数独终局生成和求解

本文是关于软件工程基础课程的大作业,涉及数独终局的生成和求解。作业要求生成和求解最多一百万个数独终局。生成方法采用简单算法,固定首数字并随机生成其余部分,通过行列变换产生多种终局。求解方法使用回溯法,寻找可行解。数独表示为int[9][9]数组,并用面向对象的C++实现。单元测试确保代码正确性,性能分析优化了代码效率。
摘要由CSDN通过智能技术生成

软件工程基础个人大作业 数独终局生成和求解

github项目地址https://github.com/lukal-new/new-potato/tree/sudoku

一、预计开发

Personal Software Process Stages 预估耗时(分钟)
计划 60
估计任务所需时间 20
开发 1500
需求分析 30
生成设计文档 40
设计复审 40
代码规范 300
具体设计 300
具体代码 600
具体编码 600
代码复审 60
测试 300
报告 120
测试报告 120
计算工作量 30
事后总结并提出过程改进计划 120
合计 4240

二、解题思路描述

首先了解数独的规则,以下是摘自百度百科的内容。

数独(shù dú)是源自18世纪瑞士的一种数学游戏。是一种运用纸、笔进行演算的逻辑游戏。玩家需要根据9×9盘面上的已知数字,推理出所有剩余空格的数字,并满足每一行、每一列、每一个粗线宫(3*3)内的数字均含1-9,不重复 。数独盘面是个九宫,每一宫又分为九个小格。在这八十一格中给出一定的已知数字和解题条件,利用逻辑和推理,在其他的空格上填入1-9的数字。使1-9每个数字在每一行、每一列和每一宫中都只出现一次,所以又称“九宫格”。

根据题目意思,主要分为两部分。一是生成最多一百万个数独终局,并存入文件中,生成新文件要覆盖原文件。二是从某路径文件中读取最多一百万个数独,并求解存入文件中。以下内容主要描述算法和实现思路。

1.生成数独终局

数独的生成方法有很多种,比如随机法和行列变换法。但为了兼顾性能和输出时间,在此选择比较简单的一种算法。主要思路是随机生成第一行,然后从第二行开始,每一行是第一行右移3,6,1,4,7,2,5,8列的结果,这样就可以产生一个数独终局。
由于题目要求第一行第一个数字必须是固定的,我的固定数字为9,所以只用生成第一行的后八位数字。这样可以产生的数独终局个数为8!=40320种。为了达到要求的一百万种,可以将已生成的数独做行列交换,因为第一行已经固定,所以第二行和第三行可以交换,四五六行可以互换,七八九行可以互换。所以最终可以产生2!*3!*3!8!=2903040种,远超要求的一百万种。为了简化代码,只对四五六行、七八九行进行互换即可,二三行可以不用动。这样就有3!*3!*8!=1451520种,也达到了要求。
总结来说,使用的算法主要思路是,第一行的第一个数字固定为9,随机生成后8位数字,第一行右移3,6,1,4,7,2,5,8位依次得到剩下8行,可以互相交换四五六行、七八九行。最终输出每一行,可以得到题目要求的结果。

2.求解数独

求解数独的方法也有很多,比较典型的是回溯法,简单但效率比较低。回溯算法的主要思路是从根节点开始向下搜索,如该正在被搜索的节点有解,则向下继续搜索,如无解,则返回到该节点的父节点。对于数独求解问题,对所有空格,即为0的位置,可以依据全局找到可能填入的数字。从数字最少的空格开始,填入某一个数字,然后在数字第二少的空格填入数字,直到某一个空格无法填入位置,向上一个填入的空格返回,更换该空格填入的数字。
题目要求是找到一个可行解即可,所以不用搜索完所有解空间,直到找到一个可以将所有空格填入的方法,则不用继续搜索。并且可以设计合适的剪枝条件,来提高搜索效率。


三、设计实现过程

1.数独的表示形式

显而易见数独可以定义为int[9][9]这种形式。但对于终局生成来说,最多要打印1000000个数独终局,每个终局都是81个数字,如果用1000000个iint型二维数组肯定不行。所以在输出终局时要用一个足够长的字符串,包括了终局里的空格、换行符号。在此,我定义了一个长度为20000000的字符串,用来表示输出的所有数独终局。但由于这个字符串太大了,所以就作为全局变量,放在函数外面即可。
对求解数独来说,要先读取和得到的终局格式相同的文件,空格是用0表示,但要求解空格位置,就必须把读取到的字符串转化为int[9][9]的形式,才能进行求解,所以还是要在数独类中定义int[9][9]。

2.数独类的设计

由于整个程序是用c++写的,所以可以利用面向对象的封装性,把与数独有关的所有东西都封装在Sudoku类中,在主函数中对参数进行判别,定义一个类,然后调用相应的函数。
数独类里的私有变量是一个int[9][9]和两个文件指针,一个用来指向生成数独终局的文件的指针,一个用来指向求解数独存放文件的指针。
函数有一个生成数独终局函数createSudoku()函数,在这个函数外部,定义一个全局变量char[20000000],用来存放生成的终局。
class Sudoku
{
private:
char grid[9][9]h = { 0 };
FILE *resultfile1;
FILE *resultfile2;

public:
Sudoku();
~Sudoku();
void solveSudoku(string);
void createSudoku(int);
void backtrace(int );
bool isPlace(int );
};

3.函数流程
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值