C# 数独游戏(二)——数独求解

  上一篇讲了怎么构造数独,这一节讲怎么对一个被挖掉一些格子的数独矩阵(如以下矩阵)进行求解,用的是回溯法。

  

  (1)用程序求解:构造数独矩阵,随机挖掉一些空格的时候,要记录下这些空格的坐标,我们在Table类中用一个链表储存这些坐标。因为储存的这些坐标是随机产生的,所以求解之前最后排下序(排序时可以将Coord坐标类实现IComparable接口,将坐标按X,Y进行二级排序),这样回溯起来效率会快很多。依次取出链表中的坐标,往坐标的格子依次填入1~9,然后分别在行、列、3*3的小表格中检验,如果通过则继续取链表中下一个坐标,再重复一下过程,如果不能通过则回溯。

核心代码:

        public void GenerateSolutionMatrix(int finishNumber)
        {
            if (finishNumber == emptyCellList.Count)
            {
                isFinished = true;
                return;
            }

            Coord currentCoord = new Coord();
            currentCoord.X = emptyCellList[finishNumber].X;
            currentCoord.Y = emptyCellList[finishNumber].Y;

            int row = (currentCoord.X / 3) * 3 + 2;
            int column = (currentCoord.Y / 3) * 3 + 2;

            //这个要注意啊,因为产生的随机数可能一样,即一个表格被挖空了几次
            //如果对一个已处理的表格重复处理会出错
            if (table[currentCoord.X, currentCoord.Y].IsProcessed)
                GenerateSolutionMatrix(finishNumber+1);
            else
                for (int i = 1; i <= TableSize; i++)
                {  
                    if (!isFinished && ValidLine(i, currentCoord.X, TableSize) &&
                        ValidColumn(i, TableSize, currentCoord.Y) &&
                        ValidSmallTable(i, row, column))
                    {
                        //填表
                        table[currentCoord.X, currentCoord.Y].Number = i;
                        table[currentCoord.X, currentCoord.Y].IsProcessed = true;

                        GenerateSolutionMatrix(finishNumber + 1);

                        table[currentCoord.X, currentCoord.Y].IsProcessed = false;  //回溯
                    }
                }                
            } 

 

(2)验证用户的解答是否正确,这里我把用户填入的数字放到一个数组里面,然后再验证

  (注意数组里面的数字是按X坐标从小到大(相等则按Y坐标从小到大)排列的,顺序不能乱,当然在这之前储存被挖掉的格子坐标的链表emptyCellList要先排序

    这样才能与用户输入的数字一一对应)

        /// <summary>
        /// 检验解答是否正确
        /// </summary>
        /// <param name="solution">输入的数字序列</param>
        /// <returns></returns>
        public bool ValidateSolution(IEnumerable<int> solution)
        {
            if (solution.Count() != emptyCellList.Count())
                return false;

            int currentIndex = 0;
            int row, column;
            foreach (int number in solution)
            {
                row = (emptyCellList[currentIndex].X / 3) * 3 + 2;
                column = (emptyCellList[currentIndex].Y / 3) * 3 + 2;

                if (ValidLine(number, emptyCellList[currentIndex].X, TableSize) &&
                    ValidColumn(number, TableSize, emptyCellList[currentIndex].Y) &&
                    ValidSmallTable(number, row, column))
                {
                    table[emptyCellList[currentIndex].X,
                        emptyCellList[currentIndex].Y].Number = number;
                    //table[emptyCellList[currentIndex].X,
                    //    emptyCellList[currentIndex].Y].IsProcessed = true;
                }
                else
                    return false;

                currentIndex++;
            }
            return true;
        }

 

(3)测试:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace sudoku
{
    class Program
    {
        static void Main(string[] args)
        {
            Table table = new Table();
            int level = 6;  //难度为6级
            table.GenerateValidMatrix();

            Console.WriteLine("Here is the Matrix");
            table.PrintTable();

            Console.WriteLine("\nHere is the problem Matrix");
            table.GenerateProblemMatrix(level);
            table.PrintTable();


            Console.WriteLine("\nHere is the solution Matrix");
            table.GenerateSolutionMatrix(0);
            table.PrintTable();

            Console.ReadKey();
        }
    }
}

结果:

关于界面——好吧,原来自己是想把数字放到datagridview里面的,可是发现界面好丑,而且还要控制好每一个格子的颜色(这个暂时还没做控制好)

所以界面巨丑陋……对界面有好建议的朋友欢迎提出建议,当然也可对我的实现方法、代码等等提建议……

本文为原创博文,转载请注明作者博客地址:http://www.cnblogs.com/-Lei/

转载于:https://www.cnblogs.com/-Lei/archive/2012/05/10/2495192.html

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值