象棋中马的遍历

in 数据结构 with 0 comment

11385343fbf2b2117f14da63c48065380cd78ee1.jpg

问题描述

在N*N棋盘上,任意一个位置放置一个棋子马,要能选择一套合适的移动路线,按象棋中“马走日”的移动规则不重复地遍历棋盘上每一个位置点。

基本要求

起始位置坐标由用户输入任意指定,然后依次输出所遍历的每个位置坐标。

基本思路:

使用二维数组代表棋盘,用bool标记是否走过该道路

使用递归的思想,每次尝试8个方向

如果可以,继续下一次尝试,否则此次递归结束,继续下一次递归尝试

另外,棋盘行数在5个以下无解,8个以上耗时太长,建议尝试5或6

代码实现:

#include <stdio.h>
#include <stdlib.h>
#define MAX 15
bool map[MAX][MAX] = {};//棋盘,0代表可跑
int fx[8]={1,2,2,1,-1,-2,-2,-1};  //8个跳转方向 
int fy[8]={2,1,-1,-2,-2,-1,1,2}; 
int pathx[MAX*MAX] = {};//记录跑过的路径
int pathy[MAX*MAX] = {};
//棋盘较大时,尝试时间太长.这里为了方便找到一种结果后立刻返回,修改了下Move的返回值类型 
int Move(int x, int y, int n,int count){
    pathx[count] = x;
    pathy[count] = y;
    count++;
    map[x][y] = false;//跑过路径置false
    if(count==n*n){
        for (int i = 0; i < count-1;i++){
            printf("(%d,%d)-->", pathx[i], pathy[i]);
        }
        printf("(%d,%d)\n", pathx[count-1], pathy[count-1]);
        return 1;
    } 
    int tx, ty;
    for (int i = 0; i < 8;i++){//尝试八个方向
        tx = x + fx[i];
        ty = y + fy[i];
        if (!( tx < 0 || tx > n - 1 || ty < 0 || ty > n - 1|| !map[tx][ty])){
            if(Move(tx, ty, n,count)==1)return 1;
        }
    }
    map[x][y] = true;//递归恢复,继续下一次尝试
    return 0;
}
int main(){
    for (int i = 0; i < MAX; i++)
        for (int j = 0; j < MAX; j++)
            map[i][j] = true;//棋盘初始化
    Move(0, 0, 5,0);//起点为(0,0),棋盘大小5*5
    return 0;
}

样例输出:

(0,0)-->(1,2)-->(2,4)-->(4,3)-->(3,1)-->(1,0)-->(2,2)-->(0,3)-->(1,1)-->(3,0)-->(4,2)-->(3,4)-->(1,3)-->(0,1)-->(2,0)-->(4,1)-->(3,3)-->(1,4)-->(0,2)-->(2,1)-->(4,0)-->(3,2)-->(4,4)-->(2,3)-->(0,4)
Responses