zoukankan      html  css  js  c++  java
  • 软件工程实践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轴坐标,但是生成随机数太费时间了,我就生成一个随机数,用数组让一个随机数定位到填入的位置。

  • 相关阅读:
    三数之和
    罗马数字与整数
    Oracle 开启或关闭归档
    Oracle RMAN scripts to delete archivelog
    Oracle check TBS usage
    Oracle kill locked sessions
    场景9 深入RAC运行原理
    场景7 Data Guard
    场景4 Data Warehouse Management 数据仓库
    场景5 Performance Management
  • 原文地址:https://www.cnblogs.com/yujohn/p/7502786.html
Copyright © 2011-2022 走看看