博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
九宫格数独--回溯法
阅读量:6825 次
发布时间:2019-06-26

本文共 1901 字,大约阅读时间需要 6 分钟。

数独顾名思义——每个数字只能出现一次。数独是一种源自18世纪末的瑞士,后在美国发展、并在日本得以发扬光大的数字谜题。数独盘面是个九宫,每一宫又分为九个小格。在这八十一格中给出一定的已知数字和解题条件,利用逻辑和推理,在其他的空格上填入1-9的数字。使1-9每个数字在每一行、每一列和每一宫中都只出现一次。 这种游戏全面考验做题者观察能力和推理能力,虽然玩法简单,但数字排列方式却千变万化,所以不少教育者认为数独是训练头脑的绝佳方式。

九宫格的游戏在很多地方都经常出现,比如手机,电脑等等,下面就以简单的一个例子来说明如何使用回溯算法来解决该类问题。下面数组代表最初给出的九宫格,
0为空格需要填的数字。
int[,] pu = new int[9, 9]
        {
        {0,0,0,7,2,8,0,0,0},
        {0,9,0,0,5,1,6,0,0},
        {0,0,0,0,6,0,0,8,2},
        {3,0,0,8,0,2,7,0,4},
        {1,7,4,0,3,0,0,2,0},
        {2,8,0,5,0,0,0,3,0},
        {0,1,0,3,0,0,2,0,0},
        {0,0,7,0,4,6,0,0,5},
        {0,0,6,1,0,0,0,4,9} };
下面使用回溯算法来解决该类问题:
1.验证函数如下:
private bool IsValid(int i, int j)
        {
            int n = pu[i,j];
            int[] query=new int[9]{0,0,0,3,3,3,6,6,6};
            
            int t, u;
            for (t = 0; t < 9; t++)
            {
                if ((t != i && pu[t, j] == n) || (t != j && pu[i, t] == n))
                    return false;
            }
            for (t = query[i]; t < query[i] + 3; t++)
            {
                for (u = query[j]; u < query[j] + 3; u++)
                {
                    if ((t != i || u != j) && pu[t, u] == n)
                        return false;
                }
            }
            return true;
        }
2.显示函数:
private void Show()
       {
           int n=0;
         
           for (var i = 0; i < 9; i++)
           {
               for (var j = 0; j < 9; j++)
               {
                   Console.Write(pu[i, j] + " ");
               }
               Console.WriteLine();
           }
           Console.WriteLine("----------------------------------------------");
       }
3.使用回溯算法求解:
private void Try(int n)
       {
           if (n == 81) {//是否已经是最后一个格子
               Show();
               return;
           }
            int i = n / 9, j = n % 9;
           if (pu[i,j] != 0) {//如果当前格子不需要填数字,就跳到下一个格子
               Try(n + 1);
               return;
           }
           for (int k = 0; k < 9; k++) {
               pu[i,j]++;//当前格子进行尝试所有解
               if (IsValid(i, j))
                   Try(n + 1);//验证通过,就继续下一个
           }
           pu[i,j] = 0;  //如果上面的单元无解,就回溯
       }
4.调用如下:
public void Test()
        {
            Show();
            Try(0);            
        }
实际在游戏中会有不同的游戏级别如:
低级:要求至少有一行或一列出题时已填上5个数据,其他可以随机安排,但是每行或每列必须有数据  
中级:要求至少有一行或一列出题时已填上4个数据,其他可以随机安排,但是每行或每列必须有数据  
高级:要求至少有一行或一列出题时已填上3个数据,其他可以随机安排,但是每行或每列必须有数据
所以实际中我们使用回溯不是很方便,我说下我的方法:
1.只要一个九宫格的任意两行,两列所在列有相同的数字,那么这两行,两列交叉后该九宫格就只剩下一格,这个格子就是前面的相同数字。
2.使用1的思想,如果一个九宫格任意两行一列,或两列一行所在行列都有相同数字,那么该九宫两行一列交叉后只剩两个格子,如果一个格子游戏已经给出
数字,剩下的格子就是该数字了。
3.一次类推,一行一列,0行1列等等。

转载于:https://www.cnblogs.com/Smily-C/p/6148071.html

你可能感兴趣的文章
df -h显示磁盘使用情况
查看>>
北京木瓜移动科技有限公司
查看>>
redis运维的一些知识点
查看>>
ZZZZ
查看>>
Win7或Windows server 2008中IIS7支持ASP+Access解决方法
查看>>
intent 图片调用问题
查看>>
div仿框架布局
查看>>
Windows 服务(附服务开发辅助工具)
查看>>
asp.net mvc的生命周期{转}
查看>>
SOLR (全文检索)
查看>>
PIGS(最大流)
查看>>
Adding Swap Files
查看>>
CentOS 配置集群机器之间SSH免密码登录
查看>>
JSP页面中taglib的uri设置
查看>>
OpenCV学习笔记——OpenCV安装
查看>>
设计模式那点事--建造者模式
查看>>
第六章 字节码执行方式--解释执行和JIT
查看>>
漫画:什么是红黑树?
查看>>
图灵简传
查看>>
LeetCode: Combinations 解题报告
查看>>