马踏棋盘算法

作者: 再见远洋 | 来源:发表于2017-08-19 14:54 被阅读30次

由于今天的马踏棋盘算法并不是使用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这个方法了,这个方法里面我已经写上了详细的注释了,应该都能看懂了,当然,注重要的是得理解,如果不理解,也是很难看明白的,今天就介绍这么多吧,今天的文章主要用于记录,防止以后忘记了没地方看,所以写的不好,大家不要喷,有什么没看明白的可以留言或私信。非常乐意解答。

相关文章

  • 马踏棋盘java实现 详解注释

    最近对算法方面有点兴趣马踏棋盘有用到贪心算法 回溯算法 回溯是当前棋盘状态 54时下一步已经没地方了 马儿踏完整...

  • 马踏棋盘算法

    最近在学习深度优先搜索算法,接触到了马踏棋盘,决定尝试一下。 涉及算法:递归,回溯法,深度优先搜索算法 题目需求:...

  • 马踏棋盘算法

    由于今天的马踏棋盘算法并不是使用OC编写,所以,今天的标题也就不是"使用OC....."了,下面直接开始我们的正题...

  • 马踏棋盘算法

    问题定义: 将马随机放在国际象棋的Board[0~7][0~7]的某个方格中,马按走棋规则进行移动。,走遍棋盘上全...

  • 马踏棋盘(贪心算法)

    需求 将马随机放在国际象棋的Board[0~7][0~7]的某个方格中,马按走棋规则进行移动。,走遍棋盘上全部64...

  • 马踏棋盘算法2018-06-09

    /June 8,2018 Author GH //该代码用递归实现了马踏棋盘算法//反思,在实现过程中滥用全局变量...

  • 马踏棋盘(结合贪心)

    将能选择的点进行递归,不通就回溯 结合贪心算法优化将可跳转的点的下一步进行非递减排序,这样可以尽量少的回溯

  • 自学Python:马踏棋盘

    国际象棋的棋盘为8×8的方格棋盘。现将“马”放在任意指定的方格中,按照“马”走棋的规则将“马”进行移动。 要求每个...

  • 图的深度优先遍历和马踏棋盘算法

    图的深度优先遍历思想 图的遍历通常有两种遍历次序方案: 深度优先遍历和广度优先遍历。深度优先遍历(DepthFir...

  • Java基于分治算法实现的棋盘覆盖问题示例

    Java基于分治算法实现的棋盘覆盖问题示例 本文主要介绍了ava基于分治算法实现的棋盘覆盖问题,简单描述了棋盘覆盖...

网友评论

    本文标题:马踏棋盘算法

    本文链接:https://www.haomeiwen.com/subject/bjstdxtx.html