软工第二次作业---数独

数独生成

GitHub:sudoku

解题思路:

刚刚打开这次的作业的时候,我的第一想法是这道题的关键应该就是随机吧,于是第一时间我先拿去搜索了下c++中的随机函数。的确在[http://blog.csdn.net/weeendy/article/details/53195144]这个博文中找到了我想要的随机生成数的相关的函数代码。然后再开始思考该使用什么样的方法来实现。这时候,我也发现了这次的题目和之前做过的一道代码题八皇后问题有点类似。于是也就借鉴了之前自己的算法来进行尝试。
由于数独规则有三个:一是行不同,二是列不同,三是单元格不同。所以为了对填入的数字进行规则的检查,我选择使用三个9*9的数组,通过不同的放置规则来达到更快检查的目的。

设计实现:

首先,由于肯定会多次进行检查是否合格,所以检测数字是否能正确放入棋盘中的函数肯定是要有的。其次,用于实现算法的,还有一个实现回溯的函数。还有一个进行初始化各个棋盘的函数。

代码说明:

以下此函数,是用来检测数字是否能正确放入棋盘中的。其中b是用于判断在列中是否已经存在该数字,c是判断是否在3*3的格子里存在该数字,而d是判断在行中是否存在该数字。

int judge(int x,int y,int count) {
    int z;
    if (a[x][y])//判断该位置是否已有数字
        return 0;
    else if (b[y][count - 1] == 1)//判断在第y列中是否已经存在该数字
        return 0;
    else if (d[x][count - 1] == 1)
        return 0;
    z = (x - (x % 3)) + ((y - (y % 3))/3);
    if (c[z][count - 1] == 1)
        return 0;
    a[x][y] = count;
    b[y][count - 1] = 1;
    c[z][count - 1] = 1;
    d[x][count - 1] = 1;
    return 1;
}

以下这个函数,是用来实现回溯算法的核心代码。它尝试分步的去测试每一个数字,并且我是在数字随机的情况下,以行为标准,一行一行的放入数字。如果1到9都不合格则进行回溯。(ps:这里的代码思想也是参考了一些百度上面的方法。分别是遍历数组的同时,将当前元素与数组中随机位置的元素交换,实现将数组随机排序。还有测试数独规则的时候,第三个规则,九宫格的时候参考了[http://blog.csdn.net/jiejinquanil/article/details/53463298] 这位前辈的方法。

bool recursion(int x,int y) {
    int ran_num, num[9];
    for (int i = 0; i < 9; i++) {
        num[i] = i+1;
    }
    srand((unsigned)time(0));//从网上学到的根据系统时间来生成的随机数的方法
    for (int i = 0; i < 9; i++) {
        ran_num = rand() % 9;
        swap(num[i], num[ran_num]);//使用随机函数来产生1到9的随机数
    }
    for (int i = 0; i < 9; i++) {
        int count = num[i];
        if (count == 9 && (x == 0 || y == 0)) {
            if (x == 0 && y == 0) {
                recursion(x, y + 1);
                return true;
            }
        }
        if (judge(x, y, count) == 1) {
            if (y == 8) {
                if (x == 8)//第一种情况:数独已经形成
                    return true;
                else if (recursion(x + 1, 0))//第二种情况:这一行已经遍历完了
                    return true;
            }
            else {
                if (recursion(x, y + 1))
                    return true;
            }
            a[x][y] = 0;
            b[y][count - 1] = 0;
            c[(x - (x % 3)) + ((y - (y % 3))/3)][count - 1] = 0;
            d[x][count - 1] = 0;
        }
    }
    return false;
}

测试运行:

1227270-20170910180620491-1352437088.png
1227270-20170910180626960-1393442716.png

效能分析与改进:

分析时生成的数独个数设为50000个
1227270-20170910175107569-1464100112.png
1227270-20170910180640507-341175659.png
发现了一个问题,善用百度真的可以解决很多问题

PSP 2.1表格:

PSP2.1Personal Software Process Stages预估耗时(分钟)实际耗时(分钟)
Planning计划7121245
· Estimate· 估计这个任务需要多少时间7121245
Development开发6521155
· Analysis· 需求分析 (包括学习新技术)120150
· Design Spec· 生成设计文档25
· Design Review· 设计复审 (和同事审核设计文档)1030
· Coding Standard· 代码规范 (为目前的开发制定合适的规范)1030
· Design· 具体设计100150
· Coding· 具体编码240360
· Code Review· 代码复审5070
· Test· 测试(自我测试,修改代码,提交修改)120360
Reporting报告6090
· Test Report· 测试报告3030
· Size Measurement· 计算工作量30.60
· Postmortem & Process Improvement Plan· 事后总结, 并提出过程改进计划2030
合计7121245

个人总结:

这次的代码题给我的冲击力还是很大的,因为首先是久不敲代码所带来的生疏感,二是算法上的匮乏。居然还是只能吃老本,这种情况真的是很让人难受。也让我下定决心,好好研究下算法上的知识,真的是很有必要。

转载于:https://www.cnblogs.com/qianxuanj/p/7501757.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值