C# 数独游戏 递归,回溯,验证是否满足数独

你不去做,别人不知道你会做!送给我自己。

题设:在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;
            
        }

    }

}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章