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

作业地址
GitHub


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

遇到的困难及解决方法

  • 困难描述

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

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

PSP表格

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

解题思路

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

设计实现

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

关键代码


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;
}

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

测试运行

性能分析

数据:2000

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

posted @ 2017-09-10 22:58  龙套1997  阅读(292)  评论(3编辑  收藏  举报