数独生成算法

看到很多人写了数独终盘生成算法,于是心血来潮,自己写了一个。

一、生成规则

  1、按顺序将1~9填入宫格中;

  2、检查所在行、列及小九宫格是否存在相同数字

  3、若存在相同数字则将数字加1 ,重复第2步

  这样就得到了初始的数独终盘,如下图

  

二、打乱顺序

  1、随机交换某两行(只能是同一个九宫格内的两行)

  2、随机交换某两列(只能是同一个九宫格内的两列)

       得到终盘

       

三、去掉部分数字,这样就得到了最终的数独了(可根据难度去掉不同数量的数字)

      

上面的效果是用VBA在Excel中生成的。

下面附上JAVA代码

 

  1 import java.util.Random;
  2 
  3 public final class Sudu {
  4     static final int SIZE = 9;
  5     static final int CELL_SIZE = 3;
  6     static final int LEVEL_MAX = 10;
  7     static int[][] suduAry = new int[SIZE][SIZE];
  8     
  9     /**
 10      * 生成数独
 11      * @param level 难度级别 1~10
 12      * @return
 13      */
 14     public static int[][] generate(int level) {
 15         Random random = new Random();
16 int n = random.nextInt(9) + 1;
17 for(int i=0;i<SIZE;i++) { 18 for(int j=0;j<SIZE;j++) { 19 int p = Math.floorDiv(i, CELL_SIZE); 20 int q = Math.floorDiv(j, CELL_SIZE); 21 for(int k=0;k<SIZE;k++) { 22 if(checkColumn(n, j) && checkRow(n, i) && checkNineCells(n, p, q)) { 23 suduAry[i][j] = n; 24 break; 25 } else { 26 n = n % SIZE + 1; 27 } 28 } 29 } 30 n = n % SIZE + 1; 31 } 32 upset(); 33 maskCells(level); 34 35 return suduAry; 36 } 37 38 private static void maskCells(int level) { 39 int min, max; 40 level %= LEVEL_MAX; 41 if(level == 0) level = LEVEL_MAX; 42 43 if(level <4) { 44 min = 20; 45 max = 15; 46 } else if(level < 7) { 47 min = 40; 48 max = 10; 49 } else if(level < 10) { 50 min = 50; 51 max = 10; 52 } else { 53 min = 60; 54 max = 5; 55 } 56 57 Random random = new Random(); 58 int count = random.nextInt(max) + min; 59 for(int i=0;i<count;i++) { 60 do { 61 int n = random.nextInt(SIZE); 62 int m = random.nextInt(SIZE); 63 if(suduAry[n][m] > 0) { 64 suduAry[n][m] = 0; 65 break; 66 } 67 }while(true); 68 } 69 } 70 71 /** 72 * 随机打乱顺序 73 */ 74 private static void upset() { 75 Random random = new Random(); 76 //按行交换 77 for(int i=0;i<SIZE;i++) { 78 int n = random.nextInt(CELL_SIZE); 79 int p = random.nextInt(CELL_SIZE) * CELL_SIZE + n; 80 for(int j=0;j<SIZE;j++) { 81 int tmp = suduAry[i][j]; 82 suduAry[i][j] = suduAry[p][j]; 83 suduAry[p][j] = tmp; 84 } 85 } 86 //按列交换 87 for(int i=0;i<SIZE;i++) { 88 int n = random.nextInt(CELL_SIZE); 89 int p = random.nextInt(CELL_SIZE) * CELL_SIZE + n; 90 for(int j=0;j<SIZE;j++) { 91 int tmp = suduAry[j][i]; 92 suduAry[j][i] = suduAry[j][p]; 93 suduAry[j][p] = tmp; 94 } 95 } 96 } 97 98 /** 99 * 检查某行 100 * @param n 101 * @param row 102 * @return 103 */ 104 private static boolean checkRow(int n, int row) { 105 boolean result = true; 106 107 for(int i=0;i<SIZE;i++) { 108 if(suduAry[row][i] == n) { 109 result = false; 110 break; 111 } 112 } 113 114 return result; 115 } 116 /** 117 * 检查某列 118 * @param n 119 * @param col 120 * @return 121 */ 122 private static boolean checkColumn(int n, int col) { 123 boolean result = true; 124 for(int i=0;i<SIZE;i++) { 125 if(suduAry[i][col] == n) { 126 result = false; 127 break; 128 } 129 } 130 return result; 131 } 132 133 /** 134 * 检查小九宫格 135 * @param n 136 * @param x 137 * @param y 138 * @return 139 */ 140 private static boolean checkNineCells(int n, int x, int y) { 141 boolean result = true; 142 int sx = x * 3, sy = y * 3; 143 144 for(int i=sx; i<sx+3;i++) { 145 for(int j=sy;j<sy+3;j++) { 146 if(suduAry[i][j] == n) { 147 result = false; 148 break; 149 } 150 } 151 if(!result) break; 152 } 153 154 return result; 155 } 156 }

 

 

        

 

转载于:https://www.cnblogs.com/JasonBourn/p/7279164.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值