數獨生成算法


看到很多人寫了數獨終盤生成算法,於是心血來潮,自己寫了一個。

一、生成規則

  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 }

 

 

        

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM