1、概述:马踏棋盘问题也称为骑士周游问题,这是算法设计分析比较经典的问题之一。
2、 题目要求:这里是以国际象棋的棋盘8*8的方格棋盘,现在将“马”放在任意指定的方格的方格中,按照马走棋盘的规则将马进行移动。并且要求每个方格只能进入一次,最终让“马”走遍64个方格。
3、:编写代码: 要求使用1~64来标注马移动的路径。棋盘下图所示
要解这个算法需要用到的知识点:回溯法、深度优先搜索、递归、哈马尔顿算法。。。
4、代码段
package com.yuanfeng.test; /** * @ClassName ChessAlgorithm * @Description T0D0 * @Author yuanfeng * @Date 2019/7/21 10:59 * @Version 1.0 **/ public class ChessAlgorithm { private static int X = 8; private static int Y = 8; private static int[][] chess = new int[X][Y];//定义一个棋盘 private static int x2; private static int y2; /* * * @Author yuanfeng * @Description //TODO 找到基于xy位置的下一个可走的位置 * @Date 11:02 2019/7/21 * @Param [] * @return int **/ public static int nextXY(int x1,int y1,int count) { x2 = x1; y2 = y1; switch (count) { //首先x轴右边移动两格肯定不能超过总的X-1的下标 // 并且并且向上走y是必须满足大于等于0的 // 不能超出棋盘最小的y坐标 // 最后还需要判断这个棋盘位置是否被走过,下面同理 case 0: if ((x2 + 2 <=X - 1) && (y2 - 1 >= 0) && chess[x2 + 2][y2 - 1] == 0) { x2 = x2+2; y2 = y2-1; return 1; } break; case 1: if (x2 + 2 <= X - 1 && y2 + 1 <= Y - 1 && chess[x2 + 2][y2 + 1] == 0) { x2 = x2+2; y2 = y2+1; return 1; } break; case 2: if (x2 + 1 <= X - 1 && y2 - 2 >= 0 && chess[x2 + 1][y2 - 2] == 0) { x2 = x2+1; y2 = y2-2; return 1; } break; case 3: if (x2 + 1 <= X - 1 && y2 + 2 <= Y - 1 && chess[x2 + 1][y2 + 2] == 0) { x2 = x2+1; y2 = y2+2; return 1; } break; case 4: if (x2 - 2 >= 0 && y2 - 1 >= 0 && chess[x2 - 2][y2 - 1] == 0) { x2 =x2-2; y2 = y2-1; return 1; } break; case 5: if (x2 - 2 >= 0 && y2 + 1 <= Y - 1 && chess[x2 - 2][y2 + 1] == 0) { x2 = x2-2; y2 = y2+1; return 1; } break; case 6: if (x2 - 1 >= 0 && y2 - 2 >= 0 && chess[x2 - 1][y2 - 2] == 0) { x2 = x2-1; y2 = y2-2; return 1; } break; case 7: if (x2 - 1 >= 0 && y2 + 2 <= Y - 1 && chess[x2 - 1][y2 + 2] == 0) { x2 = x2-1; y2 = y2+2; return 1; } break; default: break; } return 0; } /* * * @Author yuanfeng * @Description //TODO 深度优先遍历棋盘 * (a,b)为位置坐标 * tag是标记变量,每走一步tag+1 * @Date 11:22 2019/7/21 * @Param [a, b, tag] * @return void **/ public static int travesalChessBoard(int a, int b, int tag){ int x1 = a; int y1 = b; int flag = 0,count = 0; chess[a][b] = tag; if(X*Y == tag ){ //打印棋盘 printChess(); return 1; } flag = nextXY(x1,y1,count); while (flag == 0 && count < 7){ count++; flag = nextXY(x1,y1,count); } //找到马的下一个可走的坐标(x1,y1),如果找到flage = 1,否则为0 while (flag == 1){ if(travesalChessBoard(x1,y1,tag+1) == 1){ return 1; } x1 = a; y1 = b; count++; flag = nextXY(x1,y1,count); while (flag == 0 && count < 7){ count++; flag = nextXY(x1,y1,count); } //继续找到马的下一步可走的坐标(x2,y2),找到flage=1 if(flag == 0){ chess[a][b] = 0; } } return 0; } //打印 public static void printChess(){ int i = 0; int j = 0; for (i = 0;i<X;i++){ for (j = 0;j<Y;j++){ System.out.print("\t"+chess[i][j]); } System.out.println(); } System.out.println(); } public static void main(String[] args) { int i,j; long startTime = System.currentTimeMillis(); for (i = 0;i < X;i++) { for (j = 0; j < Y; j++) { chess[i][j] = 0; } } if(travesalChessBoard(2,2,1) == 0){ System.out.println("抱歉 骑士周游失败!"); } long stopTime = System.currentTimeMillis(); System.out.println("本次计算时间耗时:"+((stopTime-startTime)/1000)+"秒"); } }