软件工程基础-个人项目-sudoku游戏

个人项目任务和要求

Github项目地址

 https://github.com/richardevan/sudokugame

PSP 表格

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

解题思路 

  数独横九竖九共八十一个格子,同时又分为9个九宫格。规则很简单——需要每一个格中的数字,都保证与其所在横排和竖排以及九宫格内无相同数字。所以我们的大概思路就是,从第一个空格开始试着填数,从 1 开始填,如果 1 不满足横排竖排九宫格无重复的话,就再填入 2 ,以此类推,直到填入一个暂时满足规则的数,中断此格,移动到下一个空格重复这个过程。如果到达某个空格发现已经无数可选了,说明前面某一格填错了,那就返回上一格,从上一格的中断处继续往 9 尝试,直到这样回朔到填错的那一格。

  这样的话,我们就可以整理出重要的步骤了:

    1. 画一个空白的屏幕格式

    def canvas_click(self, event):
        print("Click! (%d,%d)" % (event.x, event.y))
        self.canvas.focus_set()
        rsize = 512/9
        (x, y) = (0, 0)
        if event.x > rsize:
            x = int(event.x/rsize)
        if event.y > rsize:
            y = int(event.y/rsize)
        print(x, y)
        if self.current:
            (tx, ty) = self.current
            # self.canvas.itemconfig(self.handles[ty][tx][0],
            # fill=rgb(128,128,128))
        self.current = (x, y)

    def canvas_key(self, event):
        print("Clack! (%s)" % (event.char))
        if event.char.isdigit() and int(event.char) > 0 and self.current:
            (x, y) = self.current
            # self.canvas.itemconfig(self.handles[y][x][0],
            # fill=rgb(128,128,128))
            try:
                self.board.set(x, y, int(event.char))
                self.sync_board_and_canvas()
            except ValueError:
                pass

    2. 在屏幕上画一个网格

    def make_grid(self):
        c = Canvas(self, bg=rgb(128, 128, 128), width='512', height='512')
        c.pack(side='top', fill='both', expand='1')
        self.rects = [[None for x in range(9)] for y in range(9)]
        self.handles = [[None for x in range(9)] for y in range(9)]
        rsize = 512/9
        guidesize = 512/3

        for y in range(9):
            for x in range(9):
                (xr, yr) = (x*guidesize, y*guidesize)
                self.rects[y][x] = c.create_rectangle(xr, yr, xr+guidesize,
                                                      yr+guidesize, width=3)
                (xr, yr) = (x*rsize, y*rsize)
                r = c.create_rectangle(xr, yr, xr+rsize, yr+rsize)
                t = c.create_text(xr+rsize/2, yr+rsize/2, text="SUDO",
                                  font="System 15 bold")
                self.handles[y][x] = (r, t)

        self.canvas = c
        self.sync_board_and_canvas()

      然后别忘了配合空白的屏幕和网格。

    def sync_board_and_canvas(self):
        g = self.board.grid
        for y in range(9):
            for x in range(9):
                if g[y][x] != 0:
                    self.canvas.itemconfig(self.handles[y][x][1],
                                           text=str(g[y][x]))
                else:
                    self.canvas.itemconfig(self.handles[y][x][1],
text
='')

      还有做小的网格。

    def clear(self):
        self.grid = [[0 for x in range(9)] for y in range(9)]
        self.locked = []

    def get_row(self, row):
        return self.grid[row]

    def get_cols(self, col):
        return [y[col] for y in self.grid]

    def get_nearest_region(self, col, row):
        """Regions are 3x3 sections of the grid."""
        def make_index(v):
            if v <= 2:
                return 0
            elif v <= 5:
                return 3
            else:
                return 6
        return [y[make_index(col):make_index(col)+3] for y in
                self.grid[make_index(row):make_index(row)+3]]

    def set(self, col, row, v, lock=False):
        if v == self.grid[row][col] or (col, row) in self.locked:
            return
        for v2 in self.get_row(row):
            if v == v2:
                raise ValueError()
        for v2 in self.get_cols(col):
            if v == v2:
                raise ValueError()
        for y in self.get_nearest_region(col, row):
            for x in y:
                if v == x:
                    raise ValueError()
        self.grid[row][col] = v
        if lock:
            self.locked.append((col, row))

    def get(self, col, row):
        return self.grid[row][col]

    3. 轮流填入格中数字 1 到 9,还有 递归判断填入数是否符合规则

def sudogen_1(board):
    """Algorithm: enter a random number between 1-9 to each
   subgrid in the board, don't enter a duplicate random numbers.
""" board.clear() added = [0] for y in range(0, 9, 3): for x in range(0, 9, 3): if len(added) == 10: return i = 0 while i in added: i = random.randint(1, 9) try: board.set(random.randint(x, x+2), random.randint(y, y+2), i, lock=True) except ValueError: print("Board rule violation, this shouldn't happen!") added.append(i)

  对于不知道游戏或玩游戏的玩家,您可以先阅读游戏介绍。打开这个链接: https://en.wikipedia.org/wiki/Sudoku

性能优化

  1. 单元测试

    

  2. 覆盖率测试

    

 

    ncalls =为调用的数量。

    tottime =花在给定函数的总时间(不包括时间在调用子函数)。

    percall(1) =商tottime除以ncalls。

    cumtime =累计时间花在这和所有子功能(从调用到出口)。这个数字即使是递归函数也是精确的。

    percall(2) =商cumtime除以原始调用。

    文件名:株(功能)=提供每个函数的相应数据。

小结

  这次个人项目对我来说有点麻烦。因为用python的能力没那么厉害。本来,我想用C语言来完成作业。但是用C语言看起来很麻烦,很复杂,需要很长时间完成的,所以我换了一个语言就是python。用python完成作业后,我python的能力提高了。我也得到很多知识。希望这些知识能在以后帮助我。

 

posted on 2018-04-05 14:09  BIT1820161069  阅读(268)  评论(0编辑  收藏  举报