曹操哪里跑!--Java语言实现数字华容道游戏

时间:2022-07-24
本文章向大家介绍曹操哪里跑!--Java语言实现数字华容道游戏,主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

最近这段时间《最强大脑》又开播了

但是怎么却少了经典的数字华容道游戏

心血来潮,想着手写一个解数字华容道游戏的程序

但是想解题得先有个题,就先实现了一个数字华容道

基本思路

使用一维数组表示数字华容道的游戏内容

根据用户的输入值m,随机生成一个大小为m*m大小的一维数组

一维数组内容的大小为0到m-1,其中0代表空格

考虑到随机生成的数组内容可能存在无解的情况

我是先生成了一个有序的数组,0在最后一位

然后随机移动300次,并保证生成的一维数组不是有序的

用户通过输入某个数字x,移动x和0之间的数字

并将0数字放到x的位置

每次移动数字后,都检查一遍是否已经完成

直到完成数字华容道

话不多说上代码

代码实现

你看,良好的代码注释

/**
 * 数字华容道
 *
 * @author daijiyong
 */
public class Klotski {
    /**
     * 数字华容道的大小
     */
    private Integer size;
    /**
     * 使用一维数组表示数字华容道
     */
    private int[] klotski;
    /**
     * key:数字
     * value:数字对应的索引
     */
    Map<Integer, Integer> numberIndex = new HashMap<>();
    /**
     * key:数字
     * value:数字对应坐标位置
     */
    Map<Integer, int[]> numberCoordinate = new HashMap<>();


    public Klotski() {
    }

    public Klotski(Integer size) {
        this.size = size;
        init();
    }

    /**
     * 初始化数字华容道
     * 在排序好的数字华容道的基础上随机移动300次
     * 保证生成的华容道是有解的
     */
    public void init() {
        int totalSize = (int) Math.pow(size, 2);
        klotski = new int[totalSize];

        //初始化成员属性
        for (int i = 1; i < totalSize; i++) {
            klotski[i - 1] = i;
            numberIndex.put(i, i - 1);
            numberCoordinate.put(i, getCoordinate(i));
        }
        numberIndex.put(0, totalSize - 1);
        numberCoordinate.put(0, getCoordinate(0));

        /*
         * 初始化随机移动300次
         * 并保证生成的数字华容道不是已排序好的
         */
        while (check()) {
            for (int i = 0; i < 300; i++) {
                Random random = new Random();
                move(random.nextInt((int) Math.pow(size, 2)));
            }
        }

    }

    /**
     * 移动某一个数字
     *
     * @param number 数字
     * @return 是否移动成功
     */
    public Boolean move(Integer number) {
        /*
         *如果要移动的数字是0,即空格,则返回失败
         */
        if (number == 0) {
            return false;
        }
        int[] zeroCoordinate = numberCoordinate.get(0);
        int[] currentCoordinate = numberCoordinate.get(number);
        /*
         * 如果输入的数字,不在数字华容道的范围内,则返回失败
         */
        if (zeroCoordinate == null || currentCoordinate == null) {
            return false;
        }

        if (zeroCoordinate[0] != currentCoordinate[0] && zeroCoordinate[1] != currentCoordinate[1]) {
            return false;
        }
        /*
         * 点击的数字并不在0即空格的旁边
         * 则移动点击数字到空格之间的所有数字
         * 如果点击数字跟空格不在同一个横轴或纵轴上,则移动失败
         */
        if (zeroCoordinate[0] == currentCoordinate[0]) {
            if (zeroCoordinate[1] > currentCoordinate[1]) {
                for (int i = zeroCoordinate[1] - 1; i >= currentCoordinate[1]; i--) {
                    int moveNumber = klotski[coordinate2Index(new int[]{zeroCoordinate[0], i})];
                    move(0, moveNumber);
                }
            }
            if (zeroCoordinate[1] < currentCoordinate[1]) {
                for (int i = zeroCoordinate[1] + 1; i <= currentCoordinate[1]; i++) {
                    int moveNumber = klotski[coordinate2Index(new int[]{zeroCoordinate[0], i})];
                    move(0, moveNumber);
                }
            }
        }

        if (zeroCoordinate[1] == currentCoordinate[1]) {
            if (zeroCoordinate[0] > currentCoordinate[0]) {
                for (int i = zeroCoordinate[0] - 1; i >= currentCoordinate[0]; i--) {
                    int moveNumber = klotski[coordinate2Index(new int[]{i, zeroCoordinate[1]})];
                    move(0, moveNumber);
                }
            }
            if (zeroCoordinate[0] < currentCoordinate[0]) {
                for (int i = zeroCoordinate[0] + 1; i <= currentCoordinate[0]; i++) {
                    int moveNumber = klotski[coordinate2Index(new int[]{i, zeroCoordinate[1]})];
                    move(0, moveNumber);
                }
            }
        }
        return true;
    }

    /**
     *  移动交互某两个相邻数字的位置
     *
     * @param number1 数字1 在这里就是0
     * @param number2 数字2 根0相邻的一个数字(上下左右)
     */
    private void move(Integer number1, Integer number2) {

        int indexNumber1 = numberIndex.get(number1);
        int indexNumber2 = numberIndex.get(number2);
        klotski[indexNumber1] = number2;
        klotski[indexNumber2] = number1;
        numberIndex.put(number1, indexNumber2);
        numberIndex.put(number2, indexNumber1);

        numberCoordinate.put(number1, getCoordinate(number1));
        numberCoordinate.put(number2, getCoordinate(number2));


    }

    /**
     * 将坐标数据转变为在数组中的索引下标
     *
     * @param coordinate 在二维数组中的坐标位置
     * @return 在一维数组中的索引值
     */
    private Integer coordinate2Index(int[] coordinate) {
        return (coordinate[0] - 1) * size + coordinate[1] - 1;
    }

    /**
     * 获取某个数字的坐标
     *
     * @param number 数字
     * @return 数字所在的位置表座
     */
    private int[] getCoordinate(Integer number) {
        int[] coordinate = new int[2];
        int index = numberIndex.get(number);
        coordinate[0] = (index / size) + 1;
        coordinate[1] = index % size + 1;
        return coordinate;
    }

    /**
     *  检查华容道是否已经完成
     *
     * @return 已完成或未完成
     */
    public Boolean check() {
        for (int i = 1; i < klotski.length; i++) {
            if (i != klotski[i - 1]) {
                return false;
            }
        }
        return true;
    }

    /**
     * 打印华容道的题面
     * @param str 提示语
     */
    public void println(String str) {
        for (int i = 0; i < klotski.length; i++) {
            if (i % size == 0) {
                System.out.println();
            }
            System.out.print(klotski[i] + "t");
        }
        System.out.println();
        System.out.println(str);
        System.out.println("---------------");
    }


    public void setKlotski(int[] klotski) {
        this.klotski = klotski;
    }


    public static void main(String[] args) {
        System.out.println("请输入一个大于等于3的数字,用于初始化数字华容道游戏");
        Scanner input = new Scanner(System.in);
        int size = input.nextInt();

        Klotski klotski = new Klotski(size);
        klotski.println("请开始你的表演");
        while (!klotski.check()) {
            int num = input.nextInt();
            klotski.move(num);
            if (klotski.check()) {
                klotski.println("恭喜你已逃出数字华容道");
                break;
            } else {
                klotski.println("还没完,请继续你的表演");
            }
        }
    }
}

效果图

你看,这么轻松就做出来了

你来试试下边这道题吧

文/戴先生@2020年6月7日

---end---更多精彩推荐