java根据传入参数实现独数游戏

看过很多博客和资料,都是9*9独数游戏,而且还有很多是残缺代码,这个就很恼火,自己写又要花不少时间,所以我这里这里了一份比较灵活的独数游戏,你们可以根据自己的需求生成3*3   6*6  7*7  8*8 或者 9*9 ..........等等独数游戏。

package com.odcchina.fai.util;

public class DoShudu {

    static int number = 0;
    static int limit = 0;
    /**
     * 存储数字的数组
     */
    static int[][] n = new int[number][number];
    static int[] num = null;

    public static void main(String[] args) {
        int[] numas = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
        generateSingular(10,numas);
        //输出结果
        for (int i = 0; i < number; i++) {
            for (int j = 0; j < number; j++) {
                System.out.print(n[i][j] + " ");
            }
            System.out.println();
        }
    }

    /**
     * @param numberPas 要生成的位数 6*6 7*7 8*8 9*9 。。。。。。
     * @param numPas    生成的数组,里面不能有为0的数字
     */
    public static void generateSingular(int numberPas,int[] numPas){
        number = numberPas;
        limit = numberPas - 1;
        n = new int[numberPas][numberPas];
        num = numPas;
        int code = 0;
        //生成数字
        for (int i = 0; i < number; i++) {
            //尝试填充的数字次数
            int time = 0;
            //填充数字
            for (int j = 0; j < number; j++) {
                code++;
                if(code > 50000){
                    //生成失败,重新生成
                    n = new int[number][number];
                    generateSingular(numberPas,numPas);
                    return;
                }
                //产生数字
                n[i][j] = generateNum(time);
                //如果返回值为0,则代表卡住,退回处理
                //退回处理的原则是:如果不是第一列,则先倒退到前一列,否则倒退到前一行的最后一列
                if (n[i][j] == 0) {
                    //不是第一列,则倒退一列
                    if (j > 0) {
                        j -= 2;
                        continue;
                    } else {//是第一列,则倒退到上一行的最后一列
                        i--;
                        j = limit;
                        continue;
                    }
                }
                //填充成功
                if (isCorret(i, j)) {
                    //初始化time,为下一次填充做准备
                    time = 0;
                } else { //继续填充
                    //次数增加1
                    time++;
                    //继续填充当前格
                    j--;
                }
            }
        }
    }

    /**
     *  * 是否满足行、列和3X3区域不重复的要求 * @param row 行号 * @param col 列号 * @return true代表符合要求
     */
    public static boolean isCorret(int row, int col) {
        if(number % 3 == 0){
            //3的倍数才调checkNine校验
            return (checkRow(row) & checkLine(col) & checkNine(row, col));
        }else{
            return (checkRow(row) & checkLine(col) & true);
        }
    }

    /**
     *  * 检查行是否符合要求 * @param row 检查的行号 * @return true代表符合要求
     */
    public static boolean checkRow(int row) {
        for (int j = 0; j < limit; j++) {
            if (n[row][j] == 0) {
                continue;
            }
            for (int k = j + 1; k < number; k++) {
                if (n[row][j] == n[row][k]) {
                    return false;
                }
            }
        }
        return true;
    }

    /**
     *  * 检查列是否符合要求 * @param col 检查的列号 * @return true代表符合要求
     */
    public static boolean checkLine(int col) {
        for (int j = 0; j < limit; j++) {
            if (n[j][col] == 0) {
                continue;
            }
            for (int k = j + 1; k < number; k++) {
                if (n[j][col] == n[k][col]) {
                    return false;
                }
            }
        }
        return true;
    }

    /**
     *  * 检查3X3区域是否符合要求 * @param row 检查的行号 * @param col 检查的列号 * @return true代表符合要求
     */
    public static boolean checkNine(int row, int col) {
        //获得左上角的坐标
        int j = row / 3 * 3;
        int k = col / 3 * 3;
        //循环比较
        for (int i = 0; i < limit; i++) {
            if (n[j + i / 3][k + i % 3] == 0) {
                continue;
            }
            for (int m = i + 1; m < number; m++) {
                if (n[j + i / 3][k + i % 3] == n[j + m / 3][k + m % 3]) {
                    return false;
                }
            }
        }
        return true;
    }

    /**
     *  * 产生1-N之间的随机数字 * 规则:生成的随机数字放置在数组limit-time下标的位置,
     * 随着time的增加,已经尝试过的数字将不会在取到 * 说明:即第一次次是从所有数字中随机,
     * 第二次时从前八个数字中随机,依次类推, * 这样既保证随机,也不会再重复取已经不符合要求的数字,
     * 提高程序的效率 * 这个规则是本算法的核心 * @param time 填充的次数,0代表第一次填充 * @return
     */
    public static int generateNum(int time) {
        //第一次尝试时,初始化随机数字源数组
        if (time == 0) {
            for (int i = 0; i < number; i++) {
                num[i] = i + 1;
            }
        }
        //第number次填充,表明该位置已经卡住,则返回0,由主程序处理退回
        if (time == number) {
            return 0;
        }
        //不是第一次填充
        //生成随机数字,该数字是数组的下标,取数组num中该下标对应的数字为随机数字
        int ranNum = (int) (Math.random() * (number - time));
        //把数字放置在数组倒数第time个位置,
        int temp = num[limit - time];
        num[limit - time] = num[ranNum];
        num[ranNum] = temp;
        //返回数字
        return num[limit - time];
    }
}

点击运行,成功生成独数

已连接到目标 VM, 地址: ''127.0.0.1:51558',传输: '套接字''
4 1 10 2 6 8 9 3 5 7 
10 7 9 8 3 2 5 4 6 1 
6 3 2 1 10 5 7 8 4 9 
8 4 5 7 2 10 6 9 1 3 
5 9 1 4 8 3 10 7 2 6 
3 6 7 9 1 4 2 10 8 5 
9 2 4 10 5 1 3 6 7 8 
7 8 3 5 9 6 4 1 10 2 
1 5 6 3 4 7 8 2 9 10 
2 10 8 6 7 9 1 5 3 4 
与目标 VM 断开连接, 地址为: ''127.0.0.1:51558',传输: '套接字''

进程已结束,退出代码为 0

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值