C# 创建数独板的蛮力算法
我正在开发的是,最初整个数独板是空的。 其中一个随机单元(81个单元中的一个)填充有随机值(1-9) 现在我想用蛮力法填充所有剩余的单元格。C# 创建数独板的蛮力算法,c#,algorithm,sudoku,C#,Algorithm,Sudoku,我正在开发的是,最初整个数独板是空的。 其中一个随机单元(81个单元中的一个)填充有随机值(1-9) 现在我想用蛮力法填充所有剩余的单元格。 从谷歌搜索后我了解到,我们应该从第一个单元格开始,用1填充它(如果它有效),然后用2填充第二个单元格(如果它有效,我们将开始检查比最后一个填充的单元格大的数字,在这种情况下是1,一旦我们达到9,我们就用1重置它) 问题是它不能正常工作 谁能把我和精确的算法联系起来。看看下面的内容。请注意,我没有运行它,因此我无法为它的声明提供担保: 代码在VB.NET中
从谷歌搜索后我了解到,我们应该从第一个单元格开始,用1填充它(如果它有效),然后用2填充第二个单元格(如果它有效,我们将开始检查比最后一个填充的单元格大的数字,在这种情况下是1,一旦我们达到9,我们就用1重置它) 问题是它不能正常工作
谁能把我和精确的算法联系起来。看看下面的内容。请注意,我没有运行它,因此我无法为它的声明提供担保: 代码在VB.NET中,但算法在C#中相同 这里有一个C版本:
由@Bill The Lizard提供的链接很好地解释了事情,而不是我上面提供的实现链接。上概述了一些算法。你所描述的听起来像是一种回溯方法。我最近在我的博客上做了一个系列,关于用C#创建数独解算器;您可能可以根据您的需要调整我提供的简单回溯算法
以下是回溯方法的一个实现:
import java.util.Random;
public class Sudoku {
public static void main(String[] args) {
Random rand = new Random();
int r = rand.nextInt(9);
int c = rand.nextInt(9);
int value = rand.nextInt(9) + 1;
Board board = new Board();
board.set(r, c, value);
System.out.println(board);
solve(board, 0);
System.out.println(board);
}
private static boolean solve(Board board, int at) {
if (at == 9*9)
return true;
int r = at / 9;
int c = at % 9;
if (board.isSet(r, c))
return solve(board, at + 1);
for (int value = 1; value <= 9; value++) {
if (board.canSet(r, c, value)) {
board.set(r, c, value);
if (solve(board, at + 1))
return true;
board.unSet(r, c);
}
}
return false;
}
static class Board {
private int[][] board = new int[9][9];
private boolean[][] rs = new boolean[9][10];
private boolean[][] cs = new boolean[9][10];
private boolean[][][] bs = new boolean[3][3][10];
public Board() {}
public boolean canSet(int r, int c, int value) {
return !isSet(r, c) && !rs[r][value] && !cs[c][value] && !bs[r/3][c/3][value];
}
public boolean isSet(int r, int c) {
return board[r][c] != 0;
}
public void set(int r, int c, int value) {
if (!canSet(r, c, value))
throw new IllegalArgumentException();
board[r][c] = value;
rs[r][value] = cs[c][value] = bs[r/3][c/3][value] = true;
}
public void unSet(int r, int c) {
if (isSet(r, c)) {
int value = board[r][c];
board[r][c] = 0;
rs[r][value] = cs[c][value] = bs[r/3][c/3][value] = false;
}
}
public String toString() {
StringBuilder ret = new StringBuilder();
for (int r = 0; r < 9; r++) {
for (int c = 0; c < 9; c++)
ret.append(board[r][c]);
ret.append("\n");
}
return ret.toString();
}
}
}
import java.util.Random;
公共级数独{
公共静态void main(字符串[]args){
Random rand=新的Random();
int r=兰特·奈克斯汀(9);
int c=兰特·奈克斯汀(9);
整数值=rand.nextInt(9)+1;
线路板=新线路板();
板组(r、c、值);
系统输出打印LN(电路板);
求解(板,0);
系统输出打印LN(电路板);
}
专用静态布尔解算(Board,int-at){
如果(at==9*9)
返回true;
int r=at/9;
int c=在%9处;
if(委员会isSet(r,c))
返回解算(板,at+1);
对于(int value=1;value这个简单的随机游走算法也应该有效(但效率低下-使用风险自负!!!):
编辑:-为无法解决的解决方案添加了修复程序
For each empty cell in grid
array = Get_Legal_Numbers_for_cell(row,col);
If (array is empty) {
Clear_All_cells()
} else {
number = Random_number_from(array);
Put_Number_in_Cell(number);
}
对于网格中的每个空单元格
数组=获取单元格(行、列)的合法编号;
If(数组为空){
清除所有单元格()
}否则{
数字=来自(数组)的随机数字;
将_编号_放入_单元格(编号);
}
编辑2
如果有人对使用基于随机搜索的数独游戏感兴趣。我使用了一种没有回溯的方法,尽管while循环可能就是它。引用我读过的一本算法书“递归中的任何东西都不能用迭代复制”
我一直在用我的眼睛来观察这一点,因为我不能理解递归方法,即使递归相对来说是理解的:
这个方法,我是在一些指导下写的,在网格检查器中有一个bug,当我发现它的时候,它现在似乎正在工作。我认为它是因为很难找到完整的工作代码。IOS SDK
#define WIDTH 9
#define HEIGHT 9
@interface ViewController ()
//- (BOOL) numberConflicts:(int)testNum;
- (BOOL) number:(int)n conflictsWithRow:(int)r;
- (BOOL) number:(int)n conflictsWithColumn:(int)c;
- (BOOL) number:(int)n conflictsWithSquareInPointX:(int)x andPointY:(int)y;
- (BOOL) number:(int)n conflictsAtGridPointX:(int)xPoint andPointY:(int)yPoint;
- (int) incrementSudokuValue:(int)v;
@end
static int sudoku[WIDTH][HEIGHT];
@implementation ViewController
- (void)viewDidLoad
{
[super viewDidLoad];
/// Initialize it
for (int x = 0; x < WIDTH; x++)
{
for (int y = 0; y < HEIGHT; y++)
{
sudoku[x][y] = 0;
}
}
///
int tries = 0;
for (int j = 0; j < HEIGHT; j++)
{
for (int i = 0; i < WIDTH; i++)
{
int num = arc4random()%9 + 1;
while ([self number:num conflictsAtGridPointX:i andPointY:j])
{
num = [self incrementSudokuValue:num];
tries++;
if (tries > 10) { //restart the column
tries = 0;
for(int count = 0; count < WIDTH; count++)
{
sudoku[count][j] = 0;
}
i = 0;
}
}
if(sudoku[i][j] == 0)
sudoku[i][j] = num;
tries = 0;
for (int y = 0; y < HEIGHT; y++)
{
for (int x = 0; x < WIDTH; x++)
{
printf("%i ", sudoku[x][y]);
}
printf("\n");
}
printf("\n");
}
}
for (int x = 0; x < WIDTH; x++)
{
for (int y = 0; y < HEIGHT; y++)
{
printf("%i ", sudoku[y][x]);
}
printf("\n"); //newline
}
// Do any additional setup after loading the view, typically from a nib.
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (BOOL) number:(int)n conflictsWithRow:(int)r;
{
for (int y = 0; y < HEIGHT; y++) {
if (sudoku[y][r] == n) {
return YES;
}
}
return NO;
}
- (BOOL) number:(int)n conflictsWithColumn:(int)c;
{
for (int x = 0; x < WIDTH; x++) {
if (sudoku[c][x] == n) {
return YES;
}
}
return NO;
}
- (BOOL) number:(int)n conflictsAtGridPointX:(int)xPoint andPointY:(int)yPoint;
{
if ([self number:n conflictsWithRow:yPoint])
{
return YES;
}
if ([self number:n conflictsWithColumn:xPoint])
{
return YES;
}
if ([self number:n conflictsWithSquareInPointX:xPoint andPointY:yPoint]) {
return YES;
}
return NO;
}
- (BOOL) number:(int)n conflictsWithSquareInPointX:(int)x andPointY:(int)y;
{
int leftX = x - (x % 3); //used to use int division
// leftX *= 3;
int topY = y - (y % 3);
// topY *= 3;
int rightX = leftX + 2;
int bottomY = topY + 2;
for(int subY = topY; subY <= bottomY; subY++) //bug was here, used < instead of less N equal to...
{
for ( int subX = leftX; subX <= rightX; subX++)
{
if (sudoku[subX][subY] == n) {
return YES;
}
}
}
NSLog(@"Testing grid at %i, %i", x/3, y/3);
NSLog(@"LeftX: %i TopY: %i", leftX, topY);
return NO;
}
- (int) incrementSudokuValue:(int)v;
{
if (v < 9) {
v++;
return v;
}
return 1;
}
#定义宽度9
#定义高度9
@界面视图控制器()
//-(BOOL)numberConflicts:(int)testNum;
-(BOOL)数:(int)n冲突(int)r;
-(BOOL)编号:(int)n冲突列:(int)c;
-(BOOL)数:(int)n与平方inpointx:(int)x和pointy:(int)y冲突;
-(BOOL)number:(int)n冲突SatGridPointX:(int)xPoint和pointy:(int)yPoint;
-(int)递增sudokuvalue:(int)v;
@结束
静态整数数独[宽度][高度];
@实现视图控制器
-(无效)viewDidLoad
{
[超级视图下载];
///初始化它
对于(int x=0;x10){//重新启动列
尝试=0;
对于(int count=0;count#define WIDTH 9
#define HEIGHT 9
@interface ViewController ()
//- (BOOL) numberConflicts:(int)testNum;
- (BOOL) number:(int)n conflictsWithRow:(int)r;
- (BOOL) number:(int)n conflictsWithColumn:(int)c;
- (BOOL) number:(int)n conflictsWithSquareInPointX:(int)x andPointY:(int)y;
- (BOOL) number:(int)n conflictsAtGridPointX:(int)xPoint andPointY:(int)yPoint;
- (int) incrementSudokuValue:(int)v;
@end
static int sudoku[WIDTH][HEIGHT];
@implementation ViewController
- (BOOL) fillGridWithNext:(int)next;
{
for (int y = 0; y < HEIGHT; y++)
{
for (int x = 0; x < WIDTH; x++)
{
if (sudoku[x][y] != 0)
{
if (x == 8 && y == 8) {
return YES;
}
continue;
}
for (int count = 0; count < (HEIGHT-1); count++)
{
if ([self number:next conflictsAtGridPointX:x andPointY:y])
{
next = [self incrementSudokuValue:next];
}
else
{
sudoku[x][y] = next;
if( [self fillGridWithNext:arc4random()%9+1])
{
return YES;
}
}
}
sudoku[x][y] = 0;
return NO;
}
}
return NO;
}
- (void)viewDidLoad
{
[super viewDidLoad];
/// Initialize it
for (int x = 0; x < WIDTH; x++)
{
for (int y = 0; y < HEIGHT; y++)
{
sudoku[x][y] = 0;
}
}
sudoku[0][0]=9;
int next;
next = (arc4random()%9)+1;
if( [self fillGridWithNext:next]) //seeded
{
NSLog(@"Solved");
}
else
{
NSLog(@"No solution");
}
for (int x = 0; x < WIDTH; x++)
{
for (int y = 0; y < HEIGHT; y++)
{
printf("%i ", sudoku[y][x]);
}
printf("\n"); //newline
}
// Do any additional setup after loading the view, typically from a nib.
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (BOOL) number:(int)n conflictsWithRow:(int)r;
{
for (int y = 0; y < HEIGHT; y++) {
if (sudoku[y][r] == n) {
return YES;
}
}
return NO;
}
- (BOOL) number:(int)n conflictsWithColumn:(int)c;
{
for (int x = 0; x < WIDTH; x++) {
if (sudoku[c][x] == n) {
return YES;
}
}
return NO;
}
- (BOOL) number:(int)n conflictsAtGridPointX:(int)xPoint andPointY:(int)yPoint;
{
if ([self number:n conflictsWithRow:yPoint])
{
return YES;
}
if ([self number:n conflictsWithColumn:xPoint])
{
return YES;
}
if ([self number:n conflictsWithSquareInPointX:xPoint andPointY:yPoint]) {
return YES;
}
return NO;
}
- (BOOL) number:(int)n conflictsWithSquareInPointX:(int)x andPointY:(int)y;
{
int leftX = x - (x % 3); //used to use int division
// leftX *= 3;
int topY = y - (y % 3);
// topY *= 3;
int rightX = leftX + 2;
int bottomY = topY + 2;
for(int subY = topY; subY <= bottomY; subY++) //bug was here, used < instead of less N equal to...
{
for ( int subX = leftX; subX <= rightX; subX++)
{
if (sudoku[subX][subY] == n) {
return YES;
}
}
}
NSLog(@"Testing grid at %i, %i", x/3, y/3);
NSLog(@"LeftX: %i TopY: %i", leftX, topY);
return NO;
}
- (int) incrementSudokuValue:(int)v;
{
if (v < 9) {
v++;
return v;
}
return 1;
}
@end