数独问题全解

时间:2021-06-12 12:03:53

      数独是一个很多人都喜欢的游戏。对于这样的问题,我比较喜欢的解决方案是写一个程序来解决这些问题。不过这些问题显然是那种需要回溯需要优化的问题。游戏规则我就不罗嗦了,言归正传。
      首先是解决数独问题的算法。程序输入,一个9*9的输入矩阵,有数字的地方就是指定的数字,没有数字的地方输入为0。算法的主要思想如下:
      1、创建一个堆栈trackStack,用来保存用程序填入的格子的信息。
      2、查找所有的数字为0的地方,察看这些地方所有的可能选择的数量,找到最小数量的那个格子。
      3、如果找到的最小数量为0的话,表明没有数字可以填写了。从trackStack中弹出一项,重新填写这个格子可能的一个数据。重复2;
      4、如果找到的最小数量不是0的话,在格子中填入最小的可能数据,将填入的格子的信息压入堆栈trackStack。如果还有格子为空,重复2;
      5、结束。

下面是完整的程序:

 

数独问题全解using  System;
数独问题全解
using  System.Collections.Generic;
数独问题全解
using  System.Text;
数独问题全解
using  System.IO;
数独问题全解
数独问题全解
namespace  sodoku
数独问题全解数独问题全解
{
数独问题全解    
class DataItem
数独问题全解数独问题全解    
{
数独问题全解        
public int i;
数独问题全解        
public int j;
数独问题全解        
public int value ;
数独问题全解    }

数独问题全解    
class Program
数独问题全解数独问题全解    
{
数独问题全解        
static bool bContinue = true ;
数独问题全解        
static Stack<DataItem> trackStack = new Stack<DataItem>();
数独问题全解        
static void OutputResult(int[][] iData)
数独问题全解数独问题全解        
{
数独问题全解            
for(int i = 0 ; i < 9 ; i++ )
数独问题全解数独问题全解            
{
数独问题全解                Console.WriteLine();
数独问题全解                
for (int j = 0; j < 9; j++)
数独问题全解数独问题全解                
{
数独问题全解                    Console.Write(
"{0}\t", iData[i][j]);
数独问题全解                }

数独问题全解            }

数独问题全解        }

数独问题全解
数独问题全解        
static bool CheckValidInput(int[][] iData)
数独问题全解数独问题全解        
{
数独问题全解            
return true;
数独问题全解        }

数独问题全解
数独问题全解        
static int SearchMinOptions(int[][] iData)
数独问题全解数独问题全解        
{
数独问题全解            
int iMaxCount = 0;
数独问题全解            
int iRow = 0, iColumn = 0;
数独问题全解            
int iMinNum = 0;
数独问题全解
数独问题全解            
for (int i = 0; i < 9; i++)
数独问题全解数独问题全解            
{
数独问题全解                
for (int j = 0; j < 9; j++)
数独问题全解数独问题全解                
{
数独问题全解                    
if (iData[i][j] == 0)
数独问题全解数独问题全解                    
{
数独问题全解                        
int[] iFlag = new int[10];
数独问题全解                        
for (int m = 0; m < 10; m++)
数独问题全解数独问题全解                        
{
数独问题全解                            iFlag[m] 
= 0;
数独问题全解                        }

数独问题全解                        
for (int k = 0; k < 9; k++)
数独问题全解数独问题全解                        
{
数独问题全解                            iFlag[iData[i][k]] 
= 1;
数独问题全解                            iFlag[iData[k][j]] 
= 1;
数独问题全解                            iFlag[iData[i 
/ 3 * 3+ k / 3][j / 3 * 3+ k % 3]] = 1;
数独问题全解                        }

数独问题全解
数独问题全解                        
int iCount = 0;
数独问题全解                        
int iCurrMinNum = 0;
数独问题全解                        
for (int m = 1; m < 10; m++)
数独问题全解数独问题全解                        
{
数独问题全解                            
if (iFlag[m] == 1)
数独问题全解                                iCount
++;
数独问题全解                            
if (iFlag[m] == 0 && iCurrMinNum == 0)
数独问题全解数独问题全解                            
{
数独问题全解                                iCurrMinNum 
= m;
数独问题全解                            }

数独问题全解                        }

数独问题全解                        
if (iCount > iMaxCount)
数独问题全解数独问题全解                        
{
数独问题全解                            iRow 
= i;
数独问题全解                            iColumn 
= j;
数独问题全解                            iMaxCount 
= iCount;
数独问题全解                            iMinNum 
= iCurrMinNum;
数独问题全解                        }

数独问题全解                    }

数独问题全解                }

数独问题全解            }

数独问题全解
数独问题全解            
if (iMinNum == 0)
数独问题全解数独问题全解            
{
数独问题全解                
//OutputResult(iData);
数独问题全解                
//check whether finished
数独问题全解
                if( CheckFinished(iData) )
数独问题全解数独问题全解                
{
数独问题全解                    Console.WriteLine( 
"Result:" ) ;
数独问题全解                    OutputResult( iData) ;
数独问题全解                    bContinue 
= false ;
数独问题全解                    
return 0 ;
数独问题全解                }

数独问题全解                
else
数独问题全解数独问题全解                
{
数独问题全解                    
do 
数独问题全解数独问题全解                    
{
数独问题全解                        
if (trackStack.Count == 0)
数独问题全解数独问题全解                        
{
数独问题全解                            Console.WriteLine(
"Error!");
数独问题全解                            bContinue 
= false;
数独问题全解                            
return 0;
数独问题全解                        }

数独问题全解
数独问题全解                        DataItem item 
= trackStack.Pop() ;
数独问题全解                        
int[] iFlag = new int[10];
数独问题全解                        
for (int m = 0; m < 10; m++)
数独问题全解数独问题全解                        
{
数独问题全解                            iFlag[m] 
= 0;
数独问题全解                        }

数独问题全解                        
for (int k = 0; k < 9; k++)
数独问题全解数独问题全解                        
{
数独问题全解                            iFlag[iData[item.i][k]] 
= 1;
数独问题全解                            iFlag[iData[k][item.j]] 
= 1;
数独问题全解                            iFlag[iData[item.i 
/ 3 * 3+ k / 3][item.j / 3 * 3+ k % 3]] = 1;
数独问题全解                        }

数独问题全解                        
for (int m = item.value + 1; m < 10; m++)
数独问题全解数独问题全解                        
{
数独问题全解                            
if (iFlag[m] == 0 && m > item.value )
数独问题全解数独问题全解                            
{
数独问题全解                                iData[item.i][item.j] 
= m ;
数独问题全解                                item.value 
= m ;
数独问题全解                                trackStack.Push( item ) ;
数独问题全解                                
return SearchMinOptions(iData);
数独问题全解                            }

数独问题全解                        }

数独问题全解                    }
while(true ) ;
数独问题全解                }

数独问题全解            }

数独问题全解            Console.WriteLine();
数独问题全解            Console.WriteLine(
"X:{0},Y:{1},Num:{2}", iRow, iColumn,iMinNum);
数独问题全解            DataItem item2 
= new DataItem();
数独问题全解
数独问题全解            item2.i 
= iRow;
数独问题全解            item2.j 
= iColumn;
数独问题全解            item2.value 
= iMinNum;
数独问题全解
数独问题全解            trackStack.Push(item2);
数独问题全解
数独问题全解            iData[iRow][iColumn] 
= iMinNum;
数独问题全解            
return 0;
数独问题全解        }

数独问题全解        
static bool CheckFinished(int[][] iData)
数独问题全解数独问题全解        
{
数独问题全解            
bool bFinished = true;
数独问题全解            
for (int i = 0; i < 9; i++)
数独问题全解数独问题全解            
{
数独问题全解                
for (int j = 0; j < 9; j++)
数独问题全解数独问题全解                
{
数独问题全解                    
if (iData[i][j] == 0)
数独问题全解数独问题全解                    
{
数独问题全解                        bFinished 
= false;
数独问题全解                        
break;
数独问题全解                    }

数独问题全解                }

数独问题全解            }

数独问题全解
数独问题全解            
return bFinished;
数独问题全解        }

数独问题全解        
static void Main(string[] args)
数独问题全解数独问题全解        
{
数独问题全解            
string[] strAll = System.IO.File.ReadAllLines(@"D:\Test\sodoku\example.txt");
数独问题全解
数独问题全解            
int[][] iData = new int[9][] ;
数独问题全解            
for (int i = 0; i < 9; i++)
数独问题全解数独问题全解            
{
数独问题全解                iData[i] 
= new int[9];
数独问题全解            }

数独问题全解            
int iIndex = 0;
数独问题全解            
foreach (string strLine in strAll)
数独问题全解数独问题全解            
{
数独问题全解                
string[] strData = strLine.Split("\t".ToCharArray(), StringSplitOptions.RemoveEmptyEntries);
数独问题全解                
if (strData.Length != 9)
数独问题全解数独问题全解                
{
数独问题全解                    
continue;
数独问题全解                }

数独问题全解                
forint i = 0 ; i < 9 ; i ++ )
数独问题全解数独问题全解                
{
数独问题全解                    iData[iIndex][i] 
= Convert.ToInt32(strData[i]) ;
数独问题全解                }

数独问题全解
数独问题全解                iIndex 
++ ;
数独问题全解                
if( iIndex == 9 )
数独问题全解数独问题全解                
{
数独问题全解                    
break ;
数独问题全解                }

数独问题全解            }

数独问题全解
数独问题全解            
if( iIndex != 9 )
数独问题全解数独问题全解            
{
数独问题全解                Console.WriteLine( 
"Error reading file,must input 9 lines valid data!" ) ;
数独问题全解                
return ;
数独问题全解            }

数独问题全解            OutputResult( iData ) ;
数独问题全解
数独问题全解
数独问题全解            CheckValidInput(iData);
数独问题全解
数独问题全解            
do
数独问题全解数独问题全解            
{
数独问题全解                SearchMinOptions(iData);
数独问题全解                
//OutputResult(iData);
数独问题全解                
//Console.ReadLine() ;
数独问题全解
            }

数独问题全解            
while (bContinue);
数独问题全解            Console.ReadLine();
数独问题全解        }

数独问题全解    }

数独问题全解}

数独问题全解


下面是一个输入的例子:
0 6 0 0 0 5 2 0 4
0 2 0 0 1 6 0 0 3
0 5 3 0 0 4 0 0 0
2 0 0 0 7 1 9 0 8
1 0 0 9 0 0 7 4 0
4 0 9 0 6 0 0 0 0
0 1 2 6 0 0 8 0 9
0 4 7 8 2 0 1 0 5
0 0 0 0 5 0 4 0 0

      OK,上面的是我们解决数独问题的一个方法。接下来,我们需要讨论一下如何生成一个数独游戏,在生成数独游戏的过程中,我们首先需要做一些思考。对于8皇后问题,我想很多人都是知道的。其实对于我们的这个问题,其实和8皇后问题,有很大的相似的地方。仔细观察我们的数独游戏的规则,我们可以发现,如果只看一个数字,例如看2,其他的数字我们全部去掉话,这个问题不就是一个变形的8皇后问题吗?而且,我们自己观察那1到9的9个数字,其实是1-9还是A-I是没有什么差别的,这9个数字之间是相互对等的。也就是说,我们求解的目标是,一个皇后,她攻击的范围是和她同一行或者同一列或者在同一个九宫,现在有9*9的格子,里面需要放9个皇后,皇后之间不能相互攻击。我们需要计算出所有可能的皇后的解决方案。得到这些解决方案的列表以后,我们一共有9种颜色的皇后,每一种颜色的皇后都只能从刚才的得到的解决方案的列表中找到一个方案,而这9个方案放到一个相同的9*9的格子里面的时候,不能有任何的重叠。得到了这9个方案,分别将这9个方案对应一个数字。然后随机的从里面去掉一些数字。一个数独游戏就产生了。

      下面是代码,希望大家喜欢,有问题给我留言,或者邮件lujianping@china.com.cn
   

数独问题全解数独问题全解数独创建