35.骑士周游问题马踏棋游戏

img

马踏棋盘算法(骑士周游问题)

定义:将马随机放在国际象棋的8×8棋盘Board[0~7][0~7]的某个方格中,马按走棋规则进行移动。要求每个方格只进入一次,走遍棋盘上全部64个方格。

核心方法

计算出当前坐标的下一个能走的位置的集合

    /**
     * @param p
     * @return
     */
    public List<Point> next(Point p) {
        List<Point> nexts = new ArrayList<>();
        if (p.x - 2 >= 0 && p.y - 1 >= 0) {
            nexts.add(new Point(p.x - 2, p.y - 1));
        } // 左上
        if (p.x - 1 >= 0 && p.y - 2 >= 0) {
            nexts.add(new Point(p.x - 1, p.y - 2));
        } // 左上
        if (p.x - 2 >= 0 && p.y + 1 < this.Y) {
            nexts.add(new Point(p.x - 2, p.y + 1));
        }// 左下
        if (p.x - 1 >= 0 && p.y + 2 < this.Y) {
            nexts.add(new Point(p.x - 1, p.y + 2));
        } // 左下
        if (p.x + 1 < this.X && p.y + 2 < this.Y) {
            nexts.add(new Point(p.x + 1, p.y + 2));
        } // 右上
        if (p.x + 2 < this.X && p.y + 1 < this.Y) {
            nexts.add(new Point(p.x + 2, p.y + 1));
        } // 右上
        if (p.x + 2 < this.X && p.y - 1 >= 0) {
            nexts.add(new Point(p.x + 2, p.y - 1));
        } // 右下
        if (p.x + 1 < this.X && p.y - 2 >= 0) {
            nexts.add(new Point(p.x + 1, p.y - 2));
        } // 右下
        return nexts;
    }

优化思路

使用贪心思想,为了减少回溯的次数,在摆放马的下一次位置的时候,应该选择下下一次能摆放位置较少的位置。

        List<Point> points = next(new Point(x, y));
        // 使用贪心思想 每次都先选择下一步 可走步数少的先处理 可以有效减少回溯
        points.sort(new Comparator<Point>() {
            @Override
            public int compare(Point o1, Point o2) {
                return next(o1).size()-next(o2).size();
            }
        });

完成代码演示

package com.corn.algorithm.horse;


import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;

/**
 * @author : Jim Wu
 * @version 1.0
 * @function :
 * @since : 2020/8/12 15:09
 */

public class HorseGameDemo {


    public static void main(String[] args) {
        HorseGame horseGame = new HorseGame(8, 8);
        horseGame.play(0, 0, 1);
        for (int[] ints : horseGame.chess) {
            System.out.println(Arrays.toString(ints));
        }
    }
}

class HorseGame {
    int X;
    int Y;
    int[][] chess;
    boolean[][] visited;
    boolean finish;

    public HorseGame(int x, int y) {
        this.X = x;
        this.Y = y;
        this.chess = new int[x][y];
        this.visited = new boolean[x][y];
    }

    /**
     * 马其实位置
     *
     * @param x
     * @param y
     */
    public void play(int x, int y, int step) {
        // 标记步数
        chess[x][y] = step;
        // 设置该顶点已经访问
        visited[x][y] = true;
        List<Point> points = next(new Point(x, y));
        // 使用贪心思想 每次都先选择下一步 可走步数少的先处理 可以有效减少回溯
        points.sort(new Comparator<Point>() {
            @Override
            public int compare(Point o1, Point o2) {
                return next(o1).size()-next(o2).size();
            }
        });
        while (points.size() > 0) {
            // 下一个可走的顶点
            Point nextPoint = points.remove(0);
            // 如果当前位置还未走过
            if (!this.visited[nextPoint.x][nextPoint.y]) {
                // 继续走
                this.play(nextPoint.x, nextPoint.y, step + 1);
            }
        }
        // 回溯
        if (step < X * Y && !finish) {
            this.chess[x][y] = 0;
            this.visited[x][y] = false;
        } else {
            finish = true;
        }
    }

    /**
     * @param p
     * @return
     */
    public List<Point> next(Point p) {
        List<Point> nexts = new ArrayList<>();
        if (p.x - 2 >= 0 && p.y - 1 >= 0) {
            nexts.add(new Point(p.x - 2, p.y - 1));
        } // 左上
        if (p.x - 1 >= 0 && p.y - 2 >= 0) {
            nexts.add(new Point(p.x - 1, p.y - 2));
        } // 左上
        if (p.x - 2 >= 0 && p.y + 1 < this.Y) {
            nexts.add(new Point(p.x - 2, p.y + 1));
        }// 左下
        if (p.x - 1 >= 0 && p.y + 2 < this.Y) {
            nexts.add(new Point(p.x - 1, p.y + 2));
        } // 左下
        if (p.x + 1 < this.X && p.y + 2 < this.Y) {
            nexts.add(new Point(p.x + 1, p.y + 2));
        } // 右上
        if (p.x + 2 < this.X && p.y + 1 < this.Y) {
            nexts.add(new Point(p.x + 2, p.y + 1));
        } // 右上
        if (p.x + 2 < this.X && p.y - 1 >= 0) {
            nexts.add(new Point(p.x + 2, p.y - 1));
        } // 右下
        if (p.x + 1 < this.X && p.y - 2 >= 0) {
            nexts.add(new Point(p.x + 1, p.y - 2));
        } // 右下
        return nexts;
    }
}

class Point {
    int x;
    int y;

    public Point(int x, int y) {
        this.x = x;
        this.y = y;
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值