本次文章是对实现马踏棋盘的数据结构和算法进行详细讲解,下一篇文章将把马踏棋盘编写为一个小游戏,运行界面如下图!
马踏棋盘介绍
所谓“马踏棋盘”问题,就是指在中国象棋的棋盘上,用马的走法走遍整个棋盘,在8*8(可自定义)的方格中,每个格都要遍历,且只能遍历一次。
4399中有这个马踏棋盘的游戏,大家可以去试玩一下,会很有助于下面的阅读 链接: 4399马踏棋盘游戏.
马踏棋盘算法分析和使用原因
1.马踏棋盘问题实际上是图的深度优先搜索(DFS)应用。
2.如果使用回溯(就是深度优先搜索)来解决,加入马儿走到第X步发现已经走到了尽头,但是棋盘上的方格并没有完全遍历,那就只能回退了,查看其他的路径,就在棋盘上不停的回溯…直到找到能够完全遍历棋盘的路线。
3.分析问题思路写出相应的查询算法,并使用贪心算法进行优化。
贪心算法(又称贪婪算法)是指,在对问题求解时,总是做出在当前看来是最好的选择。也就是说,不从整体最优上加以考虑,算法得到的是在某种意义上的局部最优解。
ps:大家有些同学可能不知道为什么写出算法了还需要进行优化。原因是虽然电脑的计算能力非常强,但是当棋盘的规模很大时,每走一步都会有很多可能,马儿的路线方式非常非常的多,然而他正确的路线确可能只有那么几条甚至一条!因此电脑当电脑计算出结果时可能需要几十秒甚至几分钟!因此需要用贪心算法来减少马儿“碰壁”!!!
手把手教你使用java编写马踏棋盘
马踏棋盘解决步骤和思路分析
1.创建棋盘chessBoard,它是一个二维数组
2.将马的当前位置设置为已经访问,然后根据当前位置,计算马的下一步还能走哪些位置,并把这些位置放入到一个集合中(ArrayList),下一步最多可有八个位置能走。每走一步,就使用step+1。
3.遍历ArrayList中存放的所有位置,看看哪个可以走通。如果走通。就继续,走不通,就回溯。
4.判断马是否完成了任务,step和应该走的步数比较,如果没有达到数量则表示没有完成任务,那么就将整个棋盘置0。
注意:马不同的走法(策略),会得到不同的结果,效率也会影响(需要贪心算法优化)。
马踏棋盘代码实现
创建HorseChessboard类。
棋盘属性:棋盘规模(行,列),每个位置的遍历情况存放在visited[ ]中,判断棋盘是否全部遍历使用finished,其中行,列都是int类型,visited[ ]和finished都是boolean类型。
HorseChessboard类中除了main方法外还包含三个主要方法分别是:
public static ArrayList getNextPoints(Point nowPoint) {}
public static void traversalChessboard(int[][] chessboard,int row,int column,int step){}
public static void sort(ArrayList points){}
下面是马踏棋盘源代码:
import java.awt.*;
import java.util.*;
public class HorseChessboard {
public static int X; //棋盘的列
public static int Y; //棋盘的行
public static boolean visited[];
public static boolean finished;
public static void main(String[] args) {
X=8;
Y=8;
int row = 2;//从1开始编号,马的初始行
int column = 3;//从1开始编号,马的初始列
int [][] chessboard = new int[X][Y];
visited = new boolean[X*Y];
long start = System.currentTimeMillis();
traversalChessboard(chessboard,row-1,column-1,1);
long end = System.currentTimeMillis();
System.out.println(end-start+"毫秒");//这里输出计算机的运行时间,来查看贪心算法使用效果,可以发现只需用几毫秒,大家可以把sort()方法去掉,再运行,你就会发现这个时间需要几十秒甚至几分钟。
for(int[] rows :chessboard){
for (int step :rows){
System.out.print(step+"\t");
}
System.out.println();
}
}
/**
* 功能:得到下一个能走位置的集合
* nowPoint:当前马所处的位置
* ArrayList<Point>马可以行走的下一步的位置的集合
*/
public static ArrayList<Point> getNextPoints(Point nowPoint) {
ArrayList<Point> points = new ArrayList<Point>();
Point p = new Point();
if (((p.x = nowPoint.x - 2) >= 0) && ((p.y = nowPoint.y - 1) >= 0)) {
points.add(new Point(p));
}
if (((p.x = nowPoint.x - 1) >= 0) && ((p.y = nowPoint.y - 2) >= 0)) {
points.add(new Point(p));
}
if (((p.x = nowPoint.x + 1) < X) && ((p.y = nowPoint.y - 2) >= 0)) {
points.add(new Point(p));
}
if (((p.x = nowPoint.x + 2) < X) && ((p.y = nowPoint.y - 1) >= 0)) {
points.add(new Point(p));
}
if (((p.x = nowPoint.x + 2) < X) && ((p.y = nowPoint.y + 1) < Y)) {
points.add(new Point(p));
}
if (((p.x = nowPoint.x + 1) < X) && ((p.y = nowPoint.y + 2) < Y)) {
points.add(new Point(p));
}
if (((p.x = nowPoint.x - 1) >= 0) && ((p.y = nowPoint.y + 2) < Y)) {
points.add(new Point(p));
}
if (((p.x = nowPoint.x - 2) >= 0) && ((p.y = nowPoint.y + 1) < Y)) {
points.add(new Point(p));
}
return points;
}
/**
*完成马踏棋盘的算法
* chessboard 棋盘
* row 当前位置的行 从零开始
* column 当前位置的列 从零开始
* step 第几步 初始位置为第一步
*/
public static void traversalChessboard(int[][] chessboard,int row,int column,int step){
chessboard[row][column] = step;
visited[row*X+column] = true;
ArrayList<Point> points = getNextPoints(new Point(column,row));
sort(points);
while (!points.isEmpty()){
Point p = points.remove(0);
if(!visited[p.y*X+p.x]){
traversalChessboard(chessboard,p.y,p.x,step+1);
}
}
if(step<X*Y&&!finished){
chessboard[row][column] = 0;
visited[row*X+column] = false;
}else finished = true;
}
/***
* 贪心算法 对当前位置的points对象的下一步位置的数目,进行非递减排序
*
*/
public static void sort(ArrayList<Point> points){
points.sort(new Comparator<Point>() {
@Override
public int compare(Point p1, Point p2) {
int count1 = getNextPoints(p1).size();
int count2 = getNextPoints(p2).size();
if(count1<count2){
return -1;
}else if(count1 == count2){
return 0;
}else {
return 1;
}
}
});
}
}
运行结果如下图
进一步将马踏棋盘编写成一个类似于4399的小游戏
我将这个马踏棋盘进一步写成了类似于上面4399的小游戏。以下是我录制的程序运行视频。我的下一篇文章将对如何编写一个基于java swing的马踏棋盘游戏给大家进行分享,并附上源码,相信聪明,好看的你一定会为我点赞,谢谢大家关注 ! Make every day to its fullest!!!(把每天做到极致!!!)