要求:
国际象棋的棋盘为N*N的方格棋盘,现将“马”放在任意指定的方格中,按照“马”走棋的规则将“马”进行移动。
要求每个方格只能进入一次,最终使得“马”走遍棋盘N*N个方格。
关于马的走法见下图:
主要练习的是递归的思想,伪代码如下:
DFS(int x, int y, int tag) { // 将该格子赋值为当前的步数 chess[x][y] = tag; // 保留原来数据x y 将x1 y1代入递归 int x1=x; int y1=y; // 结束条件 if (tag == 棋盘格子数){ return ture; } // 找到一个下一步可走的位置 // 直接修改x1 y1的值 flag = nextxy(x1,y1,count); while(flag == 0 && count<7){ flag = nextxy(x1,y1,++count); } while(flag){ // 步数+1 一直递归下去 直到结束条件 if (DFS(x1,y1,tag+1)){ // 然后不断地返回true 最后退出 return true; } // 以上是理想情况 // 如果上述不成功 则寻找本步的另外可走的下一步 // 注意!! 这里的x1 y1要重新赋值为x y 因为由于上述的递归 x1 y1值已经改变 x1 = x; y1 = y; count ++; flag = nextxy(x1,y1,count); while(flag == 0 && count<7){ flag = nextxy(x1,y1,++count); } } // 如果下步无路可走 则遍历失败 if (flag ==0){ // 失败则说明当前步数不成立 即最初的chess[x][y]=tag不成立 需要归零 chess[x][y] = 0; return flase; } }
咳咳,没写过几次伪代码,上述伪代码好像不够伪``有点具体了,不过无伤大雅,重要的是把思路理清了。
具体实现代码如下:
1 #include <stdio.h> 2 #include <time.h> 3 4 #define X 6 5 #define Y 6 6 7 int chess[X][Y]; 8 9 // 找到(x,y)位置的下一个可走位置 10 int nextxy(int *x, int *y ,int count) 11 { 12 switch(count) 13 { 14 case 0: 15 if (*x+2<=X-1 && *y-1>=0 && chess[*x+2][*y-1]==0){ 16 *x += 2; 17 *y -= 1; 18 return 1; 19 } 20 break; 21 case 1: 22 if (*x+2<=X-1 && *y+1<=Y-1 && chess[*x+2][*y+1]==0){ 23 *x += 2; 24 *y += 1; 25 return 1; 26 } 27 break; 28 case 2: 29 if (*x-2>=0 && *y+1<=Y-1 && chess[*x-2][*y+1]==0){ 30 *x -= 2; 31 *y += 1; 32 return 1; 33 } 34 break; 35 case 3: 36 if (*x-2>=0 && *y-1>=0 && chess[*x-2][*y-1]==0){ 37 *x -= 2; 38 *y -= 1; 39 return 1; 40 } 41 break; 42 case 4: 43 if (*x+1<=X-1 && *y-2>=0 && chess[*x+1][*y-2]==0){ 44 *x += 1; 45 *y -= 2; 46 return 1; 47 } 48 break; 49 case 5: 50 if (*x+1<=X-1 && *y+2<=Y-1 && chess[*x+1][*y+2]==0){ 51 *x += 1; 52 *y += 2; 53 return 1; 54 } 55 break; 56 case 6: 57 if (*x-1>=0 && *y+2<=Y-1 && chess[*x-1][*y+2]==0){ 58 *x -= 1; 59 *y += 2; 60 return 1; 61 } 62 break; 63 case 7: 64 if (*x-1>=0 && *y-2>=0 && chess[*x-1][*y-2]==0){ 65 *x -= 1; 66 *y -= 2; 67 return 1; 68 } 69 break; 70 default: 71 break; 72 } 73 return 0; 74 } 75 76 // 深度优先遍历棋盘 (x,y)为位置坐标 tag是标记,每走一步tag+1 77 int TraverChessBoard(int x, int y, int tag) 78 { 79 int i,j; 80 int x1=x,y1=y,flag=0,count=0; 81 chess[x][y] = tag; 82 83 if (tag == X*Y){ 84 // 打印棋盘 85 for (i=0; i<X; i++){ 86 for (j=0; j<Y; j++){ 87 printf("%2d ",chess[i][j]); 88 } 89 printf(" "); 90 } 91 printf(" "); 92 return 1; 93 } 94 95 // 找到下一个可走位置(x1,y1) 96 flag = nextxy(&x1,&y1,count); 97 while(flag == 0 && count<7 ){ 98 count ++; 99 flag = nextxy(&x1,&y1,count); 100 } 101 102 while(flag){ 103 if (TraverChessBoard(x1,y1,tag+1)){ 104 return 1; 105 } 106 107 // 找到下一个可走位置(x1,y1) 108 x1 = x; 109 y1 = y; 110 count++; 111 flag = nextxy(&x1,&y1,count); 112 while(flag == 0 && count<7){ 113 count++; 114 flag = nextxy(&x1,&y1,count); 115 } 116 } 117 118 if (flag == 0){ 119 chess[x][y] = 0; 120 } 121 return 0; 122 } 123 124 int main() 125 { 126 clock_t start,finish; 127 start = clock(); 128 if (!TraverChessBoard(2,0,1)){ 129 printf("马踏棋盘遍历失败! "); 130 } 131 finish = clock(); 132 printf(" 本次计算耗时%f秒 ",((double)finish-(double)start)/CLOCKS_PER_SEC); 133 return 0; 134 }
测试用例及结果如下:
5*5的速度较快,6*6的一般,8*8的跑了快两个小时没出来,最后放弃了