马踏棋盘算法

由于今天的马踏棋盘算法并不是使用OC编写,所以,今天的标题也就不是"使用OC....."了,下面直接开始我们的正题,还是老规矩,先上一张图:

马踏棋盘示意图.png

我们的需求是,将"马"放在任意制定的方格中,按照"马"走棋的规则将"马"进行移动。要求每个方格只能进入一次,最终使得"马"走遍棋盘的64个方格。并且将马走的步数标记出来,也就是第一步就标记为1,第二步就标记为2、依次类推,直到马走完了64个位置之后那么就算完成了,下面我们直接来看代码,因为我在代码里就已经将思路标记上了,每一句代码几乎都有详细的注释:

#define MaxRow 8//最大行
#define MaxCol 8//最大列
int chess[MaxRow][MaxCol];//棋盘二维数组

#pragma  mark -  马踏棋盘算法(骑士周游问题)
#pragma  mark -

/**
 对八种情况分析寻找下一步可以走的位置

 @param x 当前马所在棋盘位置的x坐标
 @param y 当前马所在棋盘位置的y坐标
 @param count 不考虑边缘的情况,马在任意一位置的下一个位置都可能有八种情况,count就是对这八种情况进行判断
 只要找到其中一种就返回1
 @return 找到返回1,否则返回0
 */
int nextStep(int *x ,int *y,int count) {
    switch(count)
    {
        case 1:
            if(*x + 2 <= MaxCol - 1 && *y - 1 >= 0 && chess[*x + 2][*y - 1] == 0)
            {
                *x += 2;
                *y -= 1;
                return 1;
            }
            break;
        case 2:
            if(*x + 2 <= MaxCol - 1 && *y + 1 <= MaxRow - 1 && chess[*x + 2][*y + 1] == 0)
            {
                *x += 2;
                *y += 1;
                return 1;
            }
            break;
        case 3:
            if(*x + 1 <= MaxCol - 1 && *y - 2 >= 0 && chess[*x + 1][*y - 2] == 0)
            {
                *x += 1;
                *y -= 2;
                return 1;
            }
            break;
        case 4:
            if(*x + 1 <= MaxCol - 1 && *y + 2 <= MaxRow - 1 && chess[*x + 1][*y + 2] == 0)
            {
                *x += 1;
                *y += 2;
                return 1;
            }
            break;
        case 5:
            if(*x - 2 >= 0 && *y - 1 >= 0 && chess[*x - 2][*y - 1] == 0)
            {
                *x -= 2;
                *y -= 1;
                return 1;
            }
            break;
        case 6:
            if(*x - 2 >= 0 && *y + 1 <= MaxRow - 1 && chess[*x - 2][*y + 1] == 0)
            {
                *x -= 2;
                *y += 1;
                return 1;
            }
            break;
        case 7:
            if(*x - 1 >= 0 && *y - 2 >= 0 && chess[*x - 1][*y - 2] == 0)
            {
                *x -= 1;
                *y -= 2;
                return 1;
            }
            break;
        case 8:
            if(*x - 1 >= 0 && *y + 2 <= MaxRow - 1 && chess[*x - 1][*y + 2] == 0)
            {  
                *x -= 1;  
                *y += 2;  
                return 1;  
            }  
            break;  
        default:  
            break;  
    }  
    return 0;
}



/**
 深度优先搜索

 @param x 开始搜索的x
 @param y 开始搜索的y
 @param step 第多少步
 @return 返回1表示下一步可行 0表示不可行
 */
int TraversalChessBoard(int x ,int y ,int step) {
    //临时变量记录当前位置x和y
    int x1 = x,y1 = y;
    //flag作为标记是否找到下一个位置 count为遍历的8中情况
    int flag =0,count = 1;
    //标记当前的位置已经被🐴踏过 标记为step,也就是刚刚走的是第多少步
    chess[x][y] = step;
    //当步数刚好等于棋盘的格子个数 就证明已经走完了
    if (step == MaxRow * MaxCol) {
        //成功 打印结果
        Print();
        return 1;
    }
    
    //没有走完就 寻找下一个位置并且将八种情况都走一遍
    flag = nextStep(&x1, &y1, count);
    //只要flag为0证明上一次没有找到下一步,这里我们把剩下的其他位置都走一遍
    while (flag == 0 && count < MaxRow) {
        //让走法+1
        count++;
        //让flag重新标记
        flag = nextStep(&x1, &y1, count);
    }
    
    //当找到下一个位置了之后,就从找到的位置开始继续递归寻找
    while (flag) {
        // 递归调用走向下一个位置,因为在NextStep函数中直接修改了当前位置的坐标,所以此时的x1和y1就表示下一个可走位置的坐标
        if (TraversalChessBoard(x1, y1, step+1)) {
            return 1;
        }
        //如果不是返回1,那证明刚刚的路径没法走完 我们就回溯到上一个位置去
        x1 = x;
        y1 = y;
        // 前count种可走位置的情况都判断过了,从count+1种情况继续判断
        count++;
        //没有走完就 寻找下一个位置并且将八种情况都走一遍
        flag = nextStep(&x1, &y1, count);
        //只要flag为0证明上一次没有找到下一步,这里我们把剩下的其他位置都走一遍
        while (flag == 0 && count < MaxRow) {
            //让走法+1
            count++;
            //让flag重新标记
            flag = nextStep(&x1, &y1, count);
        }
        
    }
    
    //如果八种情况都是没法找到合适的位置 那就从当前位置回退到上一个位置 返回0就行 而且将二维数组中的位置置为0 证明它没有走过
    if (0 == flag) {
        chess[x][y] = 0;
    }
    
    return 0;
}

/**
 * 打印棋盘,棋盘中每个格子的数值就是遍历的次序
 */
void Print()
{
    int i, j;
    for(i = 0; i < MaxRow; i++)
    {
        for(j = 0; j < MaxCol; j++)
        {
            printf("%2d\t", chess[i][j]);
        }
        printf("\n");
    }
    printf("\n");
}

这里我需要对第一个方法也就是nextStep这个方法进行一下说明,这个方法是用于寻找马下一步要走的位置,假如我们当前要走到1这个位置,那么x需要-1 ,y则需要-2,然后再判断一下是否跑出了棋盘的位置,接着还需要判断1这个位置是否马已经走过了,如果上面我说的几种情况都满足了,那么就说明这个位置是可以走的,就返回1,这就是这个方法大概的意思,不考虑边缘情况下,马总共有8种方式可以走,因此这里通过一个switch对8中情况进行了考虑,接着就是TraversalChessBoard这个方法了,这个方法里面我已经写上了详细的注释了,应该都能看懂了,当然,注重要的是得理解,如果不理解,也是很难看明白的

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 211,948评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,371评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,490评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,521评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,627评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,842评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,997评论 3 408
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,741评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,203评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,534评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,673评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,339评论 4 330
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,955评论 3 313
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,770评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,000评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,394评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,562评论 2 349

推荐阅读更多精彩内容

  • 最近在学习深度优先搜索算法,接触到了马踏棋盘,决定尝试一下。 涉及算法:递归,回溯法,深度优先搜索算法 题目需求:...
    凤凰城的传说阅读 1,978评论 1 4
  • 图的深度优先遍历思想 图的遍历通常有两种遍历次序方案: 深度优先遍历和广度优先遍历。深度优先遍历(DepthFir...
    AceKitty阅读 3,229评论 1 4
  • 问题定义: 将马随机放在国际象棋的Board[0~7][0~7]的某个方格中,马按走棋规则进行移动。,走遍棋盘上全...
    maskwang520阅读 622评论 0 2
  • Q0: 楼主我练了你推荐的,怎么感觉一点都不厉害啊! A0: 吾日三醒吾身 满级了吗 满宝具了吗 芙芙喂足了吗 三...
    cec21530c5dd阅读 750评论 0 0
  • 时间真快,今天周四,马上周末啦 今年于我来说,周日是新一周的开始;那么这周除了每日学习任务正常进行外,还需要读两本...
    HHzhao阅读 164评论 0 0