软件工程实践2017第二次作业【数独】

作业地址
GitHub



在初看到题目时我是又惊又喜,喜是应该我从小就很喜欢玩数独,惊是因为题目看起来难度不小,但是如果太简单又能学到什么呢?在做作业的过程中我遇到了很多困难,也学到了很多。

遇到的困难及解决方法

  • 困难描述

    我这次使用的是C#语言,由于以前写算法多是使用C和C++,C#用来写界面,用C写算法对我来说难度不小,有很多函数不懂,很多情况不知道怎么处理,性能也很差。
  • 做过哪些尝试

    首先我是想到用回溯法生成数独,网络上也有很多人用这种方法,看了一些C++写的,然后想着自己也写写看。
  • 是否解决
    在写的过程中,我发现自己写的性能很差,但是修改了很久没有改变,我只好暴力求解。
  • 有所收获
    感觉经过这几天自己特别努力地在学习,学习了各种知识,自己的综合学习能力也有所提升。

PSP表格

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

解题思路

刚拿到题目的时候,我想到可以用回溯法做,一行一行的填过去,但是想了一下一行一行地填效率是否太低了,又想到要判断没有九宫格都有数字有些麻烦,就想到不如我一个一个九宫格填过去,每次填一个数字,填九次就填完了,同时还不用验证一个九宫格里是否有重复的数字,只要比较行和列就可以了。

设计实现

程序里有两个类,一个是Map,是数独有关的类,里面有三个函数,另一个是Program类,执行程序的类,里面有五个函数。
流程图:
1011927-20170916101310032-332648956.png

关键代码


static bool Fill(int s, int d, ref Map a,ref int count)//将数字随机填入九宫格(fill the Nine Patch with each number)
{

          int i, j, m, n;

          Random ran = new Random(Guid.NewGuid().GetHashCode());

          for (j = 0; j < 6; j++)

          {

                i = ran.Next(0, 9);//随机生成一个九宫格中的位置(randomly generate the position to fill in Nine Patch)

                m = Yp[s] + yp[i];

                n = Xp[s] + xp[i];

                if (a.sdk[m, n] == 0 && a.x[n] == 0 && a.y[m] == 0)//判断是否可以填入数字(determine if the number can be filled in)

                {

                    count++;//每次填入时count+1(count + 1 every time you fill in)

                    a.sdk[m, n] = d;

                    a.y[m] = 1;

                    a.x[n] = 1;

                    a.m[s] = 1;

                    return true;

                }

          }

          return false;

}

我把数独分成九个九宫格,利用随机数生成九宫格的位置,填入数字,利用一个count,如果反复填入过多,那就跳出循环。


 while (a.m[s] == 0)

 {

      if (!Fill(s, d, ref a,ref count))

       {

              if (count > 500) return;//count大于500时跳出循环(drop the loop when count>500)

              s=Back(s, d, ref a);

              continue;

         }
}

static int Back(int s, int d, ref Map a)//当一个九宫格填不下去时,回到上一个九宫格(when you can't put the number in this Nine Patch,go back to the previous one)
{

          int i, m, n;

          if (s == 0) return s;

          else s--;

          a.m[s] = 0;

          for (i = 0; i < 9; i++)

          {

                m = Yp[s] + yp[i];

                n = Xp[s] + xp[i];

                if (a.sdk[m, n] == d)

                {

                    a.sdk[m, n] = 0;

                    a.y[m] = 0;

                    a.x[n] = 0;

                    return s;

                  }

            }

            return s;
}

当一个九宫格无处可填的时候,回到上一个九宫格再随机填。

测试运行

1011927-20170916101750047-2040316874.png

1011927-20170916101802547-561502621.png

性能分析

数据:2000
1011927-20170916111152235-1990403598.png

1011927-20170916111301375-737999319.png

1011927-20170916111350438-956239758.png

占比最多的函数是填入九宫格Fill函数,最多的是生成随机数填入,我本来想用两个随机数,一个生成填入的x轴坐标,一个生成填入的y轴坐标,但是生成随机数太费时间了,我就生成一个随机数,用数组让一个随机数定位到填入的位置。

转载于:https://www.cnblogs.com/yujohn/p/7502786.html

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值