Java 如何生成一个完整的数独板?算法错误
我正在尝试生成一个完整的(即,每个单元格都有一个数字)数独板。这是为了其他与数独无关的东西,所以我不想得到一个有白色方块可以解的数独,或者任何与数独有关的东西。不知道你是否明白我的意思 我已经用java完成了这项工作:Java 如何生成一个完整的数独板?算法错误,java,algorithm,sudoku,Java,Algorithm,Sudoku,我正在尝试生成一个完整的(即,每个单元格都有一个数字)数独板。这是为了其他与数独无关的东西,所以我不想得到一个有白色方块可以解的数独,或者任何与数独有关的东西。不知道你是否明白我的意思 我已经用java完成了这项工作: private int sudokuNumberSelector(int x, int y, int[][] sudoku) { boolean valid = true; String validNumbers = new String();
private int sudokuNumberSelector(int x, int y, int[][] sudoku) {
boolean valid = true;
String validNumbers = new String();
int[] aValidNumbers;
int squarexstart = 0;
int squareystart = 0;
int b = 0; // For random numbers
Random randnum = new Random();
randnum.setSeed(new Date().getTime());
// Check numbers one by one
for(int n = 1; n < 10; n++) {
valid = true;
// Check column
for(int i = 0; i < 9; i++) {
if(sudoku[i][y] == n) {
valid = false;
}
}
// Check file
for(int j = 0; j < 9; j++) {
if(sudoku[x][j] == n) {
valid = false;
}
}
// Check square
switch (x) {
case 0: case 1: case 2: squarexstart = 0; break;
case 3: case 4: case 5: squarexstart = 3; break;
case 6: case 7: case 8: squarexstart = 6; break;
}
switch (y) {
case 0: case 1: case 2: squareystart = 0; break;
case 3: case 4: case 5: squareystart = 3; break;
case 6: case 7: case 8: squareystart = 6; break;
}
for(int i = squarexstart; i < (squarexstart + 3); i++ ) {
for(int j = squareystart; j < (squareystart + 3); j++ ) {
if(sudoku[i][j] == n) {
valid = false;
}
}
}
// If the number is valid, add it to the String
if(valid) {
validNumbers += n;
}
}
if(validNumbers.length() != 0) {
// String to int[]
aValidNumbers = fromPuzzleString(validNumbers);
// By this random number, return the valid number in its position
Log.d(TAG, "NUMBERS: " + validNumbers.length());
// Select a random number from the int[]
b = randnum.nextInt((aValidNumbers.length));
return aValidNumbers[b];
} else {
return 0;
}
}
此单元格中没有数字,因为根据数独规则,所有数字都已在列、行或正方形上
这对我来说是一场噩梦。有什么办法可以让这一切顺利进行吗?如果没有,我想我必须重做一切,就像我在做一个数独游戏一样。你必须实现一个算法
- 对于81个位置中的每一个,生成集合1到集合9
- 重复上述步骤,直到解决问题
- 解决一个位置。从集合中选择一个数字
- 从同一行、列和正方形中的所有集合中删除该数字
- 如果发生冲突,返回到已知的良好位置,并解决不同的位置
您可能必须使用递归函数才能回溯。问题是,在大多数情况下,不可能使用随机数生成完整的电路板,在无法生成下一个单元的情况下,您必须使用回溯。 我曾经写过一个数独游戏,下面是生成填充板的代码 这是单元类
public class SudokuCell implements Serializable {
private int value;
private boolean filled;
private HashSet<Integer> tried;
public SudokuCell() {
filled = false;
tried = new HashSet();
}
public boolean isFilled() {
return filled;
}
public int get() {
return value;
}
public void set(final int number) {
filled = true;
value = number;
tried.add(number);
}
public void clear() {
value = 0;
filled = false;
}
public void reset() {
clear();
tried.clear();
}
public void show() {
filled = true;
}
public void hide() {
filled = false;
}
public boolean isTried(final int number) {
return tried.contains(number);
}
public void tryNumber(final int number) {
tried.add(number);
}
public int numberOfTried() {
return tried.size();
}
}
公共类SudokuCell实现可序列化{
私有int值;
私有布尔填充;
私有哈希集;
公共SudokuCell(){
填充=假;
尝试=新HashSet();
}
公共布尔值已填充(){
填写报税表;
}
公共int get(){
返回值;
}
公共无效集(最终整数){
填充=真;
数值=数字;
已尝试。添加(编号);
}
公共空间清除(){
数值=0;
填充=假;
}
公共无效重置(){
清除();
已尝试。清除();
}
公开展览({
填充=真;
}
公共空间隐藏(){
填充=假;
}
公共布尔isTried(最终整数){
返回已尝试。包含(编号);
}
公共无效tryNumber(最终整数){
已尝试。添加(编号);
}
公共整数(){
return.size();
}
}
下面是Field类(将所有数据保存在一个对象中非常方便)
公共类SudokuField实现可序列化{
私有最终整数块大小;
私有最终int字段大小;
私有SudokuCell[]]字段;
公共SudokuField(最终整数块){
块大小=块;
fieldSize=块大小*块大小;
field=新的SudokuCell[fieldSize][fieldSize];
用于(int i=0;i 对于(int i=1;i从解决的数独开始,如下所示:
ABC DEF GHI
329 657 841 A
745 831 296 B
618 249 375 C
193 468 527 D
276 195 483 E
854 372 619 F
432 716 958 G
587 923 164 H
961 584 732 I
然后通过交换列和交换行来进行排列。如果只在以下组中进行切换ABC、DEF、GHI,那么数独仍然可以解决
置换版本(切换列):
BCA DFE IGH
293 675 184 A
457 813 629 B
186 294 537 C
931 486 752 D
762 159 348 E
548 327 961 F
324 761 895 G
875 932 416 H
619 548 273 I
BCA DFE IGH
293 675 184 A
186 294 537 C
457 813 629 B
931 486 752 D
548 327 961 F
762 159 348 E
875 932 416 H
619 548 273 I
324 761 895 G
再进行一些排列(交换行):
BCA DFE IGH
293 675 184 A
457 813 629 B
186 294 537 C
931 486 752 D
762 159 348 E
548 327 961 F
324 761 895 G
875 932 416 H
619 548 273 I
BCA DFE IGH
293 675 184 A
186 294 537 C
457 813 629 B
931 486 752 D
548 327 961 F
762 159 348 E
875 932 416 H
619 548 273 I
324 761 895 G
只要在1到9之间生成一些随机数,看看它是否适合给定的单元格[i][j]它保证每次都会生成一组新的数字,因为每个单元格编号都是基于当前系统时间随机生成的
public int sudokuNumberSelector(int i, int j, int[][] sudoku) {
while (true) {
int temp = (int) ((System.currentTimeMillis()) % 9) + 1;//Just getting some random number
while (temp < 10) {
boolean setRow = false, setColomn = false, setBlock = false;
for (int a = 0; a < 9; a++) {
if (sudoku[a][j] == temp) {
setRow = true;
break;
}
}
for (int a = 0; a < 9; a++) {
if (sudoku[i][a] == temp) {
setColomn = true;
break;
}
}
for (int a = i - (i % 3); a < i - (i % 3)+ 3; a++) {
for (int b = j - (j % 3); b < j - (j % 3)+3; b++) {
if (sudoku[a][b] == temp) {
setBlock = true;
a = 3;
b = 3;
}
}
}
if(setRow | setColomn | setBlock == false){
return temp;
}
temp++;
}
}
}
public int sudokuNumberSelector(int i,int j,int[][]数独){
while(true){
int temp=(int)((System.currentTimeMillis())%9)+1;//只是得到一些随机数
同时(温度<10){
布尔setRow=false,setColumn=false,setBlock=false;
对于(int a=0;a<9;a++){
if(数独[a][j]==temp){
setRow=true;
打破
}
}
对于(int a=0;a<9;a++){
if(数独[i][a]==temp){
setcolumn=true;
打破
}
}
对于(int a=i-(i%3);aBCA DFE IGH
293 675 184 A
186 294 537 C
457 813 629 B
931 486 752 D
548 327 961 F
762 159 348 E
875 932 416 H
619 548 273 I
324 761 895 G
public int sudokuNumberSelector(int i, int j, int[][] sudoku) {
while (true) {
int temp = (int) ((System.currentTimeMillis()) % 9) + 1;//Just getting some random number
while (temp < 10) {
boolean setRow = false, setColomn = false, setBlock = false;
for (int a = 0; a < 9; a++) {
if (sudoku[a][j] == temp) {
setRow = true;
break;
}
}
for (int a = 0; a < 9; a++) {
if (sudoku[i][a] == temp) {
setColomn = true;
break;
}
}
for (int a = i - (i % 3); a < i - (i % 3)+ 3; a++) {
for (int b = j - (j % 3); b < j - (j % 3)+3; b++) {
if (sudoku[a][b] == temp) {
setBlock = true;
a = 3;
b = 3;
}
}
}
if(setRow | setColomn | setBlock == false){
return temp;
}
temp++;
}
}
}
public class Sudoku {
//box size, and game SIZE ==> e.g. size = 3, SIZE = 9
//game will be the game
private int size, SIZE;
private int[][] game;
public Sudoku(int _size) {
size = _size;
SIZE = size*size;
game = generateGame();
}
//This will return the game
private int[][] generateGame() {
//Set everything to -1 so that it cannot be a value
int[][] g = new int[SIZE][SIZE];
for(int i = 0; i < SIZE; i++)
for(int j = 0; j < SIZE; j++)
g[i][j] = -1;
if(createGame(0, 0, g))
return g;
return null;
}
//Create the game
private boolean createGame(int x, int y, int[][] g) {
//An array of integers
Rand r = new Rand(SIZE);
//for every random num in r
for(int NUM = 0; NUM < size; NUM++) {
int num = r.get(NUM);
//if num is valid
if(isValid(x, y, g, num)) {
//next cell coordinates
int nx = (x+1)%SIZE, ny = y;
if(nx == 0) ny++;
//set this cell to num
g[x][y] = num;
//if the next cell is valid return true
if(createGame(nx, ny, g)) return true;
//otherwise return false
g[x][y] = -1;
return false;
}
}
return false;
}
private boolean isValid(int x, int y, int[][] g, int num) {
//Rows&&Cols
for(int i = 0; i < SIZE; i++)
if(g[i][y] == num || g[x][i] == num) return false;
//Box
int bx = x - x%size;, by = y - y%size;
for(int i = bx; i < bx + size; i++) {
for(int j = by; j < by + size; j++) {
if(g[i][j] == num)return false;
}
}
return true;
}
}
public class Rand {
private int rSize;
private int[] r;
public Rand(int _size) {
rSize = _size;
r = new int[size];
for(int i = 0; i < rSize; r++)r[i] = i;
for(int i = 0; i < rSize*5; r++) {
int a = (int)(Math.random()*rSize);
int b = (int)(Math.random()*rSize);
int n = r[a];
r[a] = r[b];
r[b] = n;
}
public void get(int i) {
if(i >= 0 && i < rSize) return r[i]; return -1;
}
}
SudokuGenerator g = new SudokuGenerator();
int[][] puzzle = g.generate();
SudokuSolver s = new SudokuSolver(puzzle);
s.solve();
int[][] solvedPuzzle = s.getSolvedBoard();