基于JavaSwing的马踏棋盘数据结构!详细讲解!

本次文章是对实现马踏棋盘的数据结构和算法进行详细讲解,下一篇文章将把马踏棋盘编写为一个小游戏,运行界面如下图!
在这里插入图片描述

马踏棋盘介绍

所谓“马踏棋盘”问题,就是指在中国象棋的棋盘上,用马的走法走遍整个棋盘,在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!!!(把每天做到极致!!!)

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值