前几天坐在公交车上无聊,刷朋友圈看到有人晒了两道数独的题目,便好奇拿出笔做了起来,当时的题目很简单,做完之后成就感爆棚,感觉天下无不可解之数独,于是拿起手机下载数独App,直奔专家级。熟料这一题一做就是一个多小时,而且中间有一步还是靠蒙的,才勉强做出了这一题。后来又来了一题专家级,勉力强撑一个多小时以后放弃了。

这类困难的数独不能单靠简单的推导完成,需要层层排除,回来写了一个数独的求解程序。
1601using System;2using System.Text;3using System.Text.RegularExpressions;45namespace Sudoku6{7 class Sudoku8 {9 private readonly int[,] sudokuMatrix;1011 public Sudoku(string input)12 {13 //初始化9x9数字14 sudokuMatrix = new int[9, 9];15 //检查是否输入是81为数字字符串16 if (!String.IsNullOrEmpty(input) && Regex.IsMatch(input,"[0-9]{81}"))17 {18 for (int i = 0; i < 9; i++)19 {20 for (int j = 0; j < 9; j++)21 {22 sudokuMatrix[i, j] = Convert.ToInt32(input[i * 9 + j].ToString());23 }24 }25 }26 else27 {28 //...异常29 }30 }3132 /// <summary>33 /// 求解数独34 /// </summary>35 public void Solve()36 {37 int[,] emptyLocation = new int[64, 2]; //用于存储空单元格的行列,数独最大只有64个空单元格38 int cursor = -1; //游标,指示当前所在的空单元格3940 //遍历数独,寻找空单元格,若找到空单元格,检查该单元格是否有唯一值,如果有则填上唯一值,否则将空格行列记录下来41 for (int i = 0; i < 9; i++)42 {43 for (int j = 0; j < 9; j++)44 {45 if (sudokuMatrix[i,j]==0) //是否为空单元格46 {47 if (FillExclusiveNumble(i,j)) //是否有唯一值,如果有,则填入唯一值,并再次从头开始搜索48 {49 i = 0;50 j = 0;51 cursor = -1;52 }53 else //如果没有唯一值,则将空格行列号记录下来54 {55 cursor += 1;56 emptyLocation[cursor, 0] = i;57 emptyLocation[cursor, 1] = j;58 }59 }60 }61 }6263 //开始逐个空格依次尝试1-9的数字,知道所有空格都填满为止64 while (cursor>=0) //当剩余空格数大于0时65 {66 if (TryNext(emptyLocation[cursor,0],emptyLocation[cursor,1])) //尝试将当前空格内的数字加167 {68 cursor -= 1; //前往下一个空格69 }70 else //如果该空格内无法填入任意数字,则表明前面的空格所填数字有误,返回上一个空格71 {72 cursor += 1;73 }74 }75 }7677 /// <summary>78 /// 尝试在当前空格内填入更大的数字79 /// </summary>80 /// <param name="row">行</param>81 /// <param name="col">列</param>82 /// <returns></returns>83 private bool TryNext(int row,int col)84 {85 for (int i = sudokuMatrix[row,col]+1; i <=9; i++)86 {87 if (Check(row, col, i))88 {89 sudokuMatrix[row, col] = i; //如果能在当前空格内填入更大的数字,则填入该数字90 return true;91 }92 }93 sudokuMatrix[row, col] = 0; //否则将该空格内的数字改为094 return false;95 }9697 /// <summary>98 /// 根据数独规则,判断特定单元格内能否填入某数字99 /// </summary>100 /// <param name="row">行</param>101 /// <param name="col">列</param>102 /// <param name="num">尝试填入的数字</param>103 /// <returns></returns>104 private bool Check(int row,int col,int num)105 {106 for (int index = 0; index < 9; index++)107 {108 if (sudokuMatrix[row, index] == num) return false;109 if (sudokuMatrix[index, col] == num) return false;110 if (sudokuMatrix[row / 3 * 3 + index / 3, col / 3 * 3 + index % 3] == num) return false;111 }112 return true;113 }114115 /// <summary>116 /// 数独转换成字符串117 /// </summary>118 /// <returns></returns>119 public override string ToString()120 {121 StringBuilder sb = new StringBuilder();122 for (int i = 0; i < 9; i++)123 {124 for (int j = 0; j < 9; j++)125 {126 sb.Append(sudokuMatrix[i, j]); 127 }128 sb.Append("\n");129 }130 return sb.ToString();131 }132133 /// <summary>134 /// 判断空格是否有唯一值,如有则填入该唯一值135 /// </summary>136 /// <param name="row">行</param>137 /// <param name="col">列</param>138 /// <returns></returns>139 private bool FillExclusiveNumble(int row,int col)140 {141 int count = 0;142 int ExclusivleNumble = 0;143 for (int num = 1; num <= 9; num++)144 {145 if (Check(row,col,num))146 {147 count += 1;148 ExclusivleNumble = num;149 }150 }151 if (count == 1)152 {153 sudokuMatrix[row, col] = ExclusivleNumble;154 return true;155 }156 else return false;157 }158 }159}160