java实现马踏棋盘算法-------参考视频 韩顺平《java数据结构和算法》

package com.wqc.horse;

import java.awt.*;
import java.util.ArrayList;
import java.util.Comparator;

/**
 * @author 高瞻远瞩
 * @version 1.0
 * @motto 算法并不可怕, 可怕的是你不敢面对它, 加油!别浮躁~冲击大厂!!!
 * 马踏棋盘
 */
public class HorseChessBoard {
    private static int X = 10;//表示棋盘的列 col
    private static int Y = 10;//表示棋盘的行 row
    private static int[][] chessBoard = new int[Y][X];
    private static boolean isVisited[] = new boolean[Y * X];//是否被访问过 默认是false
    private static boolean finished;//标记马是否走完全部棋盘的标志 默认为false

    public static void main(String[] args) {
        int row = 4;
        int col = 2;
        horseChessBoard(chessBoard, isVisited, row - 1, col - 1, 1);
        for (int i = 0; i < chessBoard.length; i++) {
            for (int j = 0; j < chessBoard[i].length; j++) {
                System.out.print(chessBoard[i][j] + "\t");
            }
            System.out.println();
        }
    }

    /**
     * 马踏棋盘算法
     *
     * @param chessBoard 棋盘
     * @param isVisited  标记是否被访问的标志
     * @param row        马儿现在所处的行数 规定从0开始 比如row = 1  说明马儿在棋盘中的第二行
     * @param col        马儿现在所处的列数
     * @param step       步数 存放在棋盘中  从1开始 走完X*Y步表示完成
     */
    public static void horseChessBoard(int[][] chessBoard, boolean[] isVisited, int row, int col, int step) {
        //先把当前位置设置为已访问
        isVisited[row * X + col] = true;
        //设置棋盘的步数
        chessBoard[row][col] = step;
//        System.out.println("当前位置 row=" + (row + 1) + " col=" + (col + 1) + " step=" + step);
        Point curPoint = new Point(col, row);
        ArrayList<Point> next = next(curPoint);
        next.sort(new Comparator<Point>() {
            @Override
            public int compare(Point o1, Point o2) {
                return next(o1).size() - next(o2).size();
            }
        });//优化代码  对next集合所有可以走的选择中的每一个选择的的next集合大小进行排序 每次把小的放在最前面 递归可以选择最少的next集合
        //这样可以减少回溯的次数  贪心思想
        while (!next.isEmpty()) {
            Point point = next.remove(0);//取出集合的第一种可能 取走就把它从集合中删除了
            //如果当前位置没有被访问 就进行递归
            if (!isVisited[X * point.y + point.x]) {
                horseChessBoard(chessBoard, isVisited, point.y, point.x, step + 1);
            }
        }
        //当结束while循环的时候  回溯的时候进行以下判断
        if (!finished && step < X * Y) {//如果步数小于36步且没有完成 说明没有结束 将当前的步数置为0 并标记为没有访问
//            chessBoard[row][col] = 0;//把当前位置设为0
            isVisited[X * row + col] = false; //当前位置走不通了  把当前位置设为false 进行回溯 相当于悔棋
        } else {
            finished = true;//只要这一步完成 说明棋盘的所有位置都被访问过
        }
    }


    /**
     * 获取到马走下一步还有哪些选择 放在ArrayList集合中返回
     *
     * @param newPoint 传入马儿的坐标点
     * @return 返回所有情况的集合
     */
    public static ArrayList<Point> next(Point newPoint) {
        ArrayList<Point> ls = new ArrayList<>();
        Point point = new Point();
        //一共有8种情况
        if ((point.x = newPoint.x + 2) < X && (point.y = newPoint.y - 1) >= 0) {
            ls.add(new Point(point.x, point.y));
        }//0
        if ((point.x = newPoint.x + 2) < X && (point.y = newPoint.y + 1) < Y) {
            ls.add(new Point(point.x, point.y));
        }//1
        if ((point.x = newPoint.x + 1) < X && (point.y = newPoint.y + 2) < Y) {
            ls.add(new Point(point.x, point.y));
        }//2
        if ((point.x = newPoint.x - 1) >= 0 && (point.y = newPoint.y + 2) < Y) {
            ls.add(new Point(point.x, point.y));
        }//3
        if ((point.x = newPoint.x - 2) >= 0 && (point.y = newPoint.y + 1) < Y) {
            ls.add(new Point(point.x, point.y));
        }//4
        if ((point.x = newPoint.x - 2) >= 0 && (point.y = newPoint.y - 1) >= 0) {
            ls.add(new Point(point.x, point.y));
        }//5
        if ((point.x = newPoint.x - 1) >= 0 && (point.y = newPoint.y - 2) >= 0) {
            ls.add(new Point(point.x, point.y));
        }//6
        if ((point.x = newPoint.x + 1) < X && (point.y = newPoint.y - 2) >= 0) {
            ls.add(new Point(point.x, point.y));
        }//7
        return ls;
    }
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值