数独(破解九宫图)

数独是一种比较费时费脑的游戏,一般难度的数独玩下来也得1个小时左右,本人是伪数独爱好者,碰到难点的数独需要花上若干个小时,于是偷懒写了一套破解程序,特拿出来分享,希望有人喜欢。


思路:

1、从第一个空格开始,计算出所有可能填充的数字,拿出第一个进行填充,将剩下的可能数字记录下来;

2、接着计算下一个空格所有可能的数字(在前边填充上的基础上),拿出第一个可能进行填充,将剩下的记录;

3、以此下去;

4、直到出现这样一个空格:所有的数字都没法填充(有冲突),就回到最后一次那个假设点,重新尝试其它的可能数字;

5、以此下去;

6、直到填充完所有空格。


实现代码:

  1.   [][][][] pArr = null;//存储数独数字
  2.         public SudokuService(string numStr) 
  3.         { 
  4.             string s = numStr.Replace(",",""); 
  5.             if (s.Length != 81) 
  6.             { 
  7.                 throw new Exception("初始数独错误,必须是81个数字"); 
  8.             } 
  9.             int[] numArr = newint[81]; 
  10.             for (int i = 0; i < s.Length; i++) 
  11.             { 
  12.                 numArr[i] = Convert.ToInt32(s[i].ToString()); 
  13.             } 
  14.             pArr = GetArray(numArr); 
  15.         } 
  16.         public SudokuService(int[] numArr) 
  17.         { 
  18.             if (numArr.Length != 81) 
  19.             { 
  20.                 throw new Exception("初始数独错误,必须是81个数字"); 
  21.             } 
  22.             pArr = GetArray(numArr); 
  23.         } 
  24.         /// <summary> 
  25.         /// 获取结果 
  26.         /// </summary> 
  27.         /// <returns></returns> 
  28.         public string GetResult() 
  29.         { 
  30.             FillArray(); 
  31.  
  32.             StringBuilder sb = new StringBuilder(); 
  33.             for (int m = 0; m < 3; m++) 
  34.             { 
  35.                 for (int i = 0; i < 3; i++) 
  36.                 { 
  37.                     for (int n = 0; n < 3; n++) 
  38.                     { 
  39.                         for (int j = 0; j < 3; j++) 
  40.                         { 
  41. sb.Append(pArr[m][n][i][j].Value);
  42.                         } 
  43.                     } 
  44.                     sb.Append(","); 
  45.                 } 
  46.             } 
  47.             return sb.ToString().TrimEnd(','); 
  48.         } 
  49.         /// <summary> 
  50.         /// 打印结果 
  51.         /// </summary> 
  52.         public void PrintResult() 
  53.         { 
  54.             for (int m = 0; m < 3; m++) 
  55.             { 
  56.                 if (m == 0) Console.WriteLine("".PadLeft(25,'-')); 
  57.                 for (int i = 0; i < 3; i++) 
  58.                 { 
  59.                     for (int n = 0; n < 3; n++) 
  60.                     { 
  61.                         if (n == 0) Console.Write("| "); 
  62.                         for (int j = 0; j < 3; j++) 
  63.                         { 
  64.                             var pv = pArr[m][n][i][j]; 
  65.                             if (pv.Default) Console.ForegroundColor = ConsoleColor.Red; 
  66.                             Console.Write("{0} ", pv.Value); 
  67.                             Console.ForegroundColor = ConsoleColor.White; 
  68.                         } 
  69.                         Console.Write("| "); 
  70.                     } 
  71.                     Console.WriteLine(); 
  72.                 } 
  73.                 Console.WriteLine("".PadLeft(25,'-')); 
  74.             } 
  75.         } 
  76.  
  77.         private Number[][][][] GetArray(int[] defVal) 
  78.         { 
  79.             Number[][][][] pArr = new Number[3][][][]; 
  80.             for (int m = 0; m < 3; m++) 
  81.             { 
  82.                 pArr[m] = new Number[3][][]; 
  83.                 for (int n = 0; n < 3; n++) 
  84.                 { 
  85.                     pArr[m][n] = new Number[3][]; 
  86.                     for (int i = 0; i < 3; i++) 
  87.                     { 
  88.                         pArr[m][n][i] = new Number[3]; 
  89.                         for (int j = 0; j < 3; j++) 
  90.                         { 
  91.                             pArr[m][n][i][j] = new Number() { Value = 0, Default =false }; 
  92.                         } 
  93.                     } 
  94.                 } 
  95.             } 
  96.  
  97.             int c = 0; 
  98.             for (int m = 0; m < 3; m++) 
  99.             { 
  100.                 for (int i = 0; i < 3; i++) 
  101.                 { 
  102.                     for (int n = 0; n < 3; n++) 
  103.                     { 
  104.                         for (int j = 0; j < 3; j++) 
  105.                         { 
  106.                             int val = defVal[c++]; 
  107.                             pArr[m][n][i][j].Value = val; 
  108.                             if (val > 0) 
  109.                                 pArr[m][n][i][j].Default = true
  110.                         } 
  111.                     } 
  112.                 } 
  113.             } 
  114.  
  115.             return pArr; 
  116.         } 
  117.         private void FillArray() 
  118.         { 
  119.             for (int m = 0; m < 3; m++) 
  120.             { 
  121.                 for (int n = 0; n < 3; n++) 
  122.                 { 
  123.                     for (int i = 0; i < 3; i++) 
  124.                     { 
  125.                         for (int j = 0; j < 3; j++) 
  126.                         { 
  127.                             if (pArr[m][n][i][j].Default ==false
  128.                             {//空白格 
  129.                                 var pv = GetNumber(newint[4] { m, n, i, j }); 
  130.  
  131.                                 if (!pv.Ok) 
  132.                                 { 
  133.                                     m = pv.Position[0]; 
  134.                                     n = pv.Position[1]; 
  135.                                     i = pv.Position[2]; 
  136.                                     j = pv.Position[3]; 
  137.                                     ClearAfter(pv.Position); 
  138.  
  139.                                 } 
  140.                                 pArr[m][n][i][j].Value = pv.Value; 
  141.                             } 
  142.                         } 
  143.                     }//end small 
  144.                 } 
  145.             }//end big 
  146.         } 
  147.         //清空该位置后边的空格 
  148.         private void ClearAfter(int[] pos) 
  149.         { 
  150.             int min = pos[0] * 1000 + pos[1] * 100 + pos[2] * 10 + pos[3]; 
  151.             for (int m = 0; m < 3; m++) 
  152.             { 
  153.                 for (int n = 0; n < 3; n++) 
  154.                 { 
  155.                     for (int i = 0; i < 3; i++) 
  156.                     { 
  157.                         for (int j = 0; j < 3; j++) 
  158.                         { 
  159.                             if (m * 1000 + n * 100 + i * 10 + j > min) 
  160.                             { 
  161.                                 if (pArr[m][n][i][j].Default ==false
  162.                                 { 
  163.                                     pArr[m][n][i][j].Value = 0; 
  164.                                 } 
  165.                             } 
  166.                         } 
  167.                     } 
  168.                 } 
  169.             } 
  170.         } 
  171.          
  172.         //记录每个位置的可能数字 
  173.         private List<PosValues> posVals =new List<PosValues>(); 
  174.  
  175.         //获取当前位置的可能数字 
  176.         private PosValues GetNumber(int[] pos) 
  177.         { 
  178.             List<int> nums =new List<int>(); 
  179.             for (int n = 1; n <= 9; n++) 
  180.             { 
  181.                 nums.Add(n); 
  182.             } 
  183.             //3宫格内 
  184.             for (int i = 0; i < 3; i++) 
  185.             { 
  186.                 for (int j = 0; j < 3; j++) 
  187.                 { 
  188.                     int a = pArr[pos[0]][pos[1]][i][j].Value; 
  189.                     if (a > 0 && nums.Contains(a)) 
  190.                     { 
  191.                         nums.Remove(a); 
  192.                     } 
  193.                 } 
  194.             } 
  195.             //横向 
  196.             for (int n = 0; n < 3; n++) 
  197.             { 
  198.                 for (int j = 0; j < 3; j++) 
  199.                 { 
  200.                     int a = pArr[pos[0]][n][pos[2]][j].Value; 
  201.                     if (a > 0 && nums.Contains(a)) 
  202.                     { 
  203.                         nums.Remove(a); 
  204.                     } 
  205.                 } 
  206.             } 
  207.             //纵向 
  208.             for (int m = 0; m < 3; m++) 
  209.             { 
  210.                 for (int i = 0; i < 3; i++) 
  211.                 { 
  212.                     int a = pArr[m][pos[1]][i][pos[3]].Value; 
  213.                     if (a > 0 && nums.Contains(a)) 
  214.                     { 
  215.                         nums.Remove(a); 
  216.                     } 
  217.                 } 
  218.             } 
  219.  
  220.             if (nums.Count == 0) 
  221.             { 
  222.                 if (posVals.Count == 0) 
  223.                 { 
  224.                     returnnew PosValues() 
  225.                     { 
  226.                         Value = 0 
  227.                     }; 
  228.                 } 
  229.                 var pv = posVals[posVals.Count - 1]; 
  230.  
  231.                 pv.Ok = false
  232.                 pv.Value = pv.Values[0]; 
  233.                 pv.Values.Remove(pv.Value); 
  234.                 if (pv.Values.Count == 0) 
  235.                 { 
  236.                     posVals.Remove(pv); 
  237.                 } 
  238.                 return pv; 
  239.             } 
  240.             else 
  241.             { 
  242.                 var pv = new PosValues(); 
  243.                 pv.Position = pos; 
  244.                 pv.Value = nums[0]; 
  245.                 nums.Remove(pv.Value); 
  246.                 pv.Values = nums; 
  247.                 if (nums.Count > 0) 
  248.                 { 
  249.                     posVals.Add(pv); 
  250.                 } 
  251.                 return pv; 
  252.             } 
  253.         } 
  254.     } 
  255.     public struct Number 
  256.     { 
  257.         public int Value; 
  258.         public bool Default; 
  259.     } 
  260.     public class PosValues 
  261.     { 
  262.         public int[] Position; 
  263.  
  264.         public List<int> Values; 
  265.  
  266.         public bool Ok =true
  267.  
  268.         public int Value; 
  269.     } 

调用代码:

  1. using System; 
  2. using System.Collections.Generic; 
  3.  
  4. namespace SudokuResponder 
  5.     class Program 
  6.     { 
  7.         static void Main(string[] args) 
  8.         { 
  9.             string s = "000000007,008000400,003801600,804306201,000000000,105407908,007603800,006000100,400000005"
  10.  
  11.             SudokuService service = new SudokuService(s); 
  12.             DateTime start = DateTime.Now; 
  13.             string result = service.GetResult(); 
  14.             TimeSpan span = DateTime.Now - start; 
  15.             service.PrintResult(); 
  16.  
  17.             Console.WriteLine("计算结束,用时 {0} 毫秒", span.Milliseconds); 
  18.             Console.WriteLine("press enter to exit"); 
  19.             Console.ReadLine(); 
  20.         } 
  21.     } 

posted @ 2012-07-05 11:59  yangkai_keven  阅读(998)  评论(0编辑  收藏  举报