你不去做,别人不知道你会做!送给我自己。
题设:在9*9的数独表格内输入几个数字,自动完成数独;
准备:在充分理解递归,回溯之后,完成这个题目就不难了。但是高性能完成就还是得研究。。。。
原理概要:采用栈的数据结构模型存入已经输入过得数独表格,此时应该只有几个表格有数字,我们采用一个标记数字记下这些数字位置,他们是不能进行压栈和出栈的。然后从第一个格子开始遍历。验证a[0] 是否为空,则插入1,进行验证。符合数独。继续a[1]插入1,不符合数独则插入2,符合。继续a[2]插入1,2,3,等等。直到某个数字插入9也不符合数独的规则的时候,回溯;
原理详解:
主函数:
using ch.shudu.musoft.com.cn.Models;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Runtime.Serialization.Json;
using ch.shudu.musoft.com.cn.Utils;
using System.Text;
namespace ch.shudu.musoft.com.cn.Controllers
{
public class MainController : Controller
{
//
// GET: /Main/
/// <summary>
/// 主页面
/// </summary>
/// <returns></returns>
public ActionResult Index()
{
return View();
}
/// <summary>
/// 进入数独
/// </summary>
/// <param name="json">传入的Json串</param>
/// <returns></returns>
public string count(string json)
{
Num[] numStack = JsonHelper.DataContractJsonDeserialize<Num[]>(json);
//一位数装入栈里面
Map map = ShuDuUtil.toArray(numStack);
//进入计算
while (map.top < 80)
{
for (int i = 1; i < 10; i++)
{
//如果当前栈顶是10,则压如数字 判断;否则直接判断
if (map.stack[map.top] == 10)
{
//输入第一个数为空则不用入栈直接开始
if (map.top == 0)
{
map.stack[map.top] = i;
break ;
}
else
{
map.pop();
//判断压入之后是否正确;正确就直接压一下个;不正确就清空
if (ShuDuUtil.IsRight(map.push(i)))
{
break;
}
else
{
map.pop();
map.push(10);
continue;
}
}
}
else
{
//判断当前栈是否正确;
if (ShuDuUtil.IsRight(map.stack))
{
//如果正确,在压入一个数。看看是否正确;正确就继续往后压;
if (ShuDuUtil.IsRight(map.push(i)))
{
break;
}
else
{
//如果不正确则+1继续压入;如果遍历到9还未成功,则回溯;
if (i == 9)
{
map = ShuDuUtil.Back(out i, map);
}
else
{
map.pop();
}
continue;
}
}
//当前栈如果不正确,回溯。
else
{
if (map.top == 0)
{
map.stack[map.top] = i;
continue;
}
map.pop();
i = map.stack[map.top];
}
}
}
}
//将结果拼接成串 传回去
StringBuilder resultStr = new StringBuilder();
foreach (int temp in map.stack)
{
resultStr = resultStr.Append(temp + ",");
}
return resultStr.ToString();
}
}
}
栈类:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
<pre name="code" class="csharp">using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
namespace ch.shudu.musoft.com.cn.Models
{
public class Map
{
//存数据的栈
public int[] stack{ get; set; }
//存储标记该格子是否能被改变
public int[] tag { get; set; }
//栈指针
public int top;
//构造函数
public Map()
{
top = 0;
stack = new int[81];
tag = new int[81];
}
/// <summary>
/// 出栈
/// </summary>
public int[] pop() {
if (top != 0) {
if (tag[top] == 10)
{
stack[top] = 10;
top--;
}
else
{
top--;
pop();
}
}
return stack;
}
/// <summary>
/// 入栈
/// </summary>
/// <param name="i">存入的数</param>
/// <returns></returns>
public int[] push(int i)
{
//不能超过81
if (top < 81)
{
if (tag[top + 1] == 10)
{
top++;
stack[top] = i;
}
else
{
top++;
push(i);
}
}
return stack;
}
}
}
工具类:
using ch.shudu.musoft.com.cn.Models;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
namespace ch.shudu.musoft.com.cn.Utils
{
public static class ShuDuUtil
{
/// <summary>
/// 数组转为栈
/// </summary>
/// <param name="jsonArray"></param>
/// <returns></returns>
public static Map toArray(Num[] numStack)
{
Map map = new Map();
for (int i = 0; i < numStack.Length; i++)
{
map.tag[i] = numStack[i].num;
map.stack[i] = numStack[i].num;
}
return map;
}
/// <summary>
/// 验证当前数独是否正确
/// </summary>
/// <param name="numStack"></param>
/// <returns></returns>
public static bool IsRight(int[] Stack)
{
//验证每行是否正确
List<int> listInt = new List<int>();
for(int j = 0;j<9;j++){
for (int i = 0; i < 9; i++) {
if (Stack[i+j*9] != 10) {
listInt.Add(Stack[i + j* 9]);
}
}
if (!IsEquel(listInt))
{
return false;
}
listInt.Clear();
}
//验证每列是否正确
for (int j = 0; j < 9; j++)
{
for (int i = 0; i < 9;i++ )
{
if (Stack[i * 9 + j] != 10)
{
listInt.Add(Stack[i*9+j]);
}
}
if (!IsEquel(listInt))
{
return false;
}
listInt.Clear();
}
//验证每个框框内是否正确
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
for (int k = 0; k < 3; k++) {
if (Stack[i * 3 + j*9+k] != 10)
{
listInt.Add(Stack[i * 3 + j * 9 + k]);
}
}
}
if (!IsEquel(listInt))
{
return false;
}
listInt.Clear();
}
//验证第二排
for (int i = 27; i < 34; i=i+3)
{
for (int j = 0; j < 3; j++)
{
for (int k = 0; k < 3; k++)
{
if (Stack[i + j * 9 + k] != 10)
{
listInt.Add(Stack[i + j * 9 + k]);
}
}
}
if (!IsEquel(listInt))
{
return false;
}
listInt.Clear();
}
//验证第三排
for (int i = 54; i < 61; i = i + 3)
{
for (int j = 0; j < 3; j++)
{
for (int k = 0; k < 3; k++)
{
if (Stack[i + j * 9 + k] != 10)
{
listInt.Add(Stack[i + j * 9 + k]);
}
}
}
if (!IsEquel(listInt))
{
return false;
}
listInt.Clear();
}
return true;
}
/// <summary>
/// 判断该数组集合类是否存在相同的数
/// </summary>
/// <param name="intArray"></param>
/// <returns></returns>
public static bool IsEquel(List<int> list) {
for(int i=0;i<list.Count;i++){
for(int j=0;j<list.Count;j++){
if(i != j && list[i]==list[j]){
return false;
}
}
}
return true;
}
/// <summary>
/// 回溯函数
/// </summary>
/// <param name="i"></param>
/// <param name="map"></param>
/// <returns></returns>
public static Map Back(out int i, Map map) {
if (map.tag[map.top] != 10)
{
map.top--;
i = map.stack[map.top];
map.pop();
}
else {
if (map.stack[map.top] == 9)
{
map.pop();
map = Back(out i, map);
}
else {
i = map.stack[map.top];
map.top--;
}
}
return map;
}
}
}