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;
            
        }

    }

}


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