结对编程作业

图片华容道

具体分工

队友主要负责原型设计,代码实现,算法设计,写博客;我主要负责游戏的代码实现,算法实现,游戏运行录制,写博客,原型设计。但是有一部分算法代码写崩了,都有相互参与。

一、原型设计


设计说明:要求文字准确、样式清晰、图文并茂(多贴原型图)等。

本次作业的要求是设计一个可玩的华容道小游戏,为了这个目标,我们需要实现以下基本的几项功能:

  • 开始界面:简洁的开始界面供用户进行选择,可以根据需求进入其他分支,例如开始游戏,查看规则说明,历史记录等。

  • 游戏界面:用wsad字符表示空格图片的移动,可在游戏过程中暂停或查看提示等。

  • 结束界面:可以在结束界面查看历史记录或者再挑战一局。

  • 历史记录:展示参与本游戏的时间及步数排名。

原型设计及具体分析:

· 开始界面

  • 开始游戏
  • 规则说明
  • 历史记录
    分别跳转至相应界面

· 游戏界面

  • 撤销
  • 提示
  • 暂停
    分别跳转至相应界面

· 结束界面

  • 历史记录
  • 重新开始
    分别跳转至相应界面

· 暂停界面

  • 继续游戏
  • 重新开始
  • 规则说明

· 提示界面

· 规则说明

· 历史记录

原型模型必须采用专用的原型模型设计工具实现:如Axure Rp、Balsamiq Mockup、Prototype Composer、GUI Design Studio、Adobe设计组件等等。在博文中说明你所采用的原型开发工具。

这次原型设计,我们采用了Axure Rp进行原型模型设计。

描述结对的过程,提供非摆拍的两人在讨论、细化和使用专用原型模型工具时的结对照片。

遇到的困难及解决方法。

  • 困难描述:第一次使用原型工具,不知道该怎么操作,有点无从下手,而且平时比较少玩类似华容道的游戏,页面布局不知道怎么构思。

  • 解决尝试:利用搜索引擎搜索自己版本对应的软件看视频教程、看对应的功能,跟着一步一步学习。观察一些主流的华容道游戏,总结普遍功能部件,增加页面背景图,使其不那么单调。

  • 是否解决:解决了。

  • 有何收获:对Axure Rp的一些基本使用方法有所了解,并且这个软件的其他功能还等着我们去探索;第一次有了分工合作的经验,一起讨论,共同实现设计;对原型设计有了初步的认识,尝试美观设计,可能有些细节没有考虑周全,希望在今后的学习中能得到强化。

二、AI与原型设计实现

代码组织与内部实现设计

具体通过 GUI 实现游戏框架和游戏操作。init()函数用于初始化游戏界面,并确保能够随机生成一个可以还原的图片。通过 set_keydown_handler(keyPressEvent) 函数实现按键输入操作,也可以实现鼠标点击。具体代码如下:

class Square:
    def __init__(self,coordinage):
        self.center = coordinage
    def draw(self,canvas,board_pos):    #画出随机出来的九宫格图
        canvas.draw_image(byamax,self.center,[IMAGE_SIZE,IMAGE_SIZE],
                          [(board_pos[1]+0.5)*image_size,(board_pos[0]+0.5)*image_size],[image_size,image_size])

def init_board():
    global match_array
    global match_map
    #确保随机生成的华容道可以还原成原来的图片
    while(True):
        random.shuffle(match_array)
        if check_right():
            break
    
    for i in range(9):
        i1 = (int)(i / 3)
        i2 = i % 3
        match_map[i1][i2] = match_array[i]

    for i in range(ROWS):
        for j in range(COLS):
            idx = match_map[i][j]
            square_center = all_coordinates[idx]
            board_coordinates[i][j] = square_center
            if square_center is None:
                board[i][j] = None
            else:
                board[i][j] = Square(square_center)

def draw(canvas):
    
    flag = False

    for i in range(ROWS):
        for j in range(COLS):
            if board[i][j] is not None:
                flag = True
                board[i][j].draw(canvas,[i,j])
            
    if flag is True:
        canvas.draw_image(byamax,[WIDTH/2,WIDTH/2],[WIDTH,WIDTH],[52,width+52],[100,100])     #画出原图,便于玩家看着原图还原拼图
        canvas.draw_text('步数:'+ str(steps),[400,680],22,'white')

def keyPressEvent(key):
    global match_map
    global steps
    for i in range(ROWS):
        for j in range(COLS):
            if board[i][j] is None:
                xx = i
                yy = j
    board1 = board[xx][yy]
    board2 = match_map[xx][yy]
    if(key == Qt.Key_A and yy >= 1):
        board[xx][yy] = board[xx][yy - 1]
        board[xx][yy - 1] = board1
        match_map[xx][yy] = match_map[xx][yy - 1]
        match_map[xx][yy - 1] = board2
        steps += 1
    if(key == Qt.Key_D and yy <= 1):
        board[xx][yy] = board[xx][yy + 1]
        board[xx][yy + 1] = board1
        match_map[xx][yy] = match_map[xx][yy + 1]
        match_map[xx][yy + 1] = board2
        steps += 1
    if(key == Qt.Key_W and xx >= 1):
        board[xx][yy] = board[xx - 1][yy]
        board[xx - 1][yy] = board1
        match_map[xx][yy] = match_map[xx - 1][yy]
        match_map[xx - 1][yy] = board2
        steps += 1
    if(key == Qt.Key_S and xx <= 1):
        board[xx][yy] = board[xx + 1][yy]
        board[xx + 1][yy] = board1
        match_map[xx][yy] = match_map[xx + 1][yy]
        match_map[xx + 1][yy] = board2
        steps += 1
    frame.set_draw_handler(draw)
    flag = True
    last = -1
    for i in range(ROWS):
        for j in range(COLS):
            if last > match_map[i][j]:
                flag = False
            last = match_map[i][j]
    if flag is True:
        message = "你过关了,你的通关步数为: " + (str)(steps) + "步"
        messagebox.showinfo("提示",message)
        frame.set_canvas_background('brown')
        frame.set_draw_handler(draw)
        frame.start()

说明算法的关键与关键实现部分流程图

算法的关键:bfs + hash

贴出你认为重要的/有价值的代码片段,并解释

我认为通关挑战这个功能比较重要,这体现了AI功能,具体实现的算法是bfs + hash,通过 bfs 算法搜索华容道游戏状态,用 hash 来记录已经搜索过的状态,避免多做无用功。
bfs 算法:通过不断存储搜索到的状态,接近正确结果,花费时间较长。
hash 算法:通过将游戏图片分割成九个块,分别进行编号 1-9,然后可以按照 k (可以根据编号数量确定,3*3 图片华容道的可以直接用 10 进制)进制的方式将图片状态 hash 成一个整数,放到集合 set 里面。
但是很遗憾的是,这部分算法的代码出现 bug 了,所以这个功能并没有实现。

class Node(object):
    class Struct(object):
        def __init__(self,x,y,step,mapp,array):
            self.array = array
            self.array[0][step] = x
            self.array[1][step] = y
            self.x = x
            self.y = y
            self.step = step
            self.mapp = mapp    #用于hash
            self.hash = 0
            for i in range(3):
                for j in range(3):
                    self.hash = self.hash * 10 + mapp[i][j]
            self.temp = 0

        def swap(self,x1,y1,x2,y2):
            self.temp = self.mapp[x1][y1]
            self.mapp[x1][y1] = self.mapp[x2][y2]
            self.mapp[x2][y2] = self.temp

    def make_struct(self,x,y,step,mapp,array):
        return self.Struct(x,y,step,mapp,array)

def bfs(sx,sy,mapp):
    array = [[],[]]
    end = 12345678
    QQ = Queue()
    S = set()
    Q = Queue()
    node = Node()
    temp = node.make_struct(sx,sy,0,mapp,array)
    Q.put(temp)
    step = -1
    while Q.qsize() > 0:
        
        temp = Q.get()
        print(temp.mapp," ",temp.step)
        ttx = -1
        tty = -1
        for i in range(3):
            for j in range(3):
                if temp.mapp[i][j] == 8:
                    ttx = i
                    tty = j
        print(temp.mapp[ttx][tty])        
        i = 0
        for i in range(4):
            tx = ttx + dx[i]
            ty = tty + dy[i]
            print(tx," ",ty," ",ttx," ",tty," ",temp.mapp[tx][ty]," ",temp.mapp[ttx][tty])
            if tx > 2 or tx < 0 or ty > 2 or ty < 0:
                continue
            test = node.make_struct(tx , ty , temp.step + 1 , temp.mapp , temp.array)
            print(temp.mapp)
            test.swap(tx , ty , ttx , tty)
            print(test.mapp)
            print("HH")
            if test.hash == end:
                temp = test
                array = test.array
                step = temp.step
                break
            if test.hash in S:
                continue
            else:
                S.add(test.hash)
                Q.put(test)
        if step != -1:
            break

    print(temp.array)
    print(temp.hash)
    print(temp.mapp)
    print(temp.step)
    print(temp.x," ",temp.y)
    global steps
    global board
    steps = 0
    temp = QQ.get()
    print(temp)
    for i in range(step):
        #delay()
        print(array[0][i]," ",array[1][i])
        tp = board[array[i][0]][array[i][1]]
        board[array[0][i]][array[1][i]] = board[array[0][i + 1]][array[1][i + 1]]
        board[array[0][i + 1]][array[1][i + 1]] = tp
        steps += 1
        frame.set_draw_handler(draw)
        

    return

展示性能分析图和程序中消耗最大的函数

本程序中消耗最大的是 bfs 函数,其中不仅是时间复杂度(不断搜索状态)上消耗最大、空间复杂度(队列 Q 不断放状态进去)也是消耗最大的。

贴出Github的代码签入记录,合理记录commit信息。

遇到的代码模块异常或结对困难及解决方法。

问题描述:在编写游戏框架的时候,不知道怎么编写游戏页面,不知道怎么用 Python 代码编写 STL 和结构体,导致算法一直没办法实现。
解决尝试:查百度,百度上讲述了 GUI 的下载和运用;STL 的用法;结构体的用法。
是否解决:已经解决。
有何收获:学会了一些 GUI 的用法,在 python 上面运用 STL。

评价队友。

  • 值得学习的地方:学习态度认真,做事认真细致。
  • 需要改进的地方:没有。

提供此次结对作业的PSP和学习进度条

PSP表格

Pair software process stage 结对软件过程阶段 预估耗时(分钟) 实际耗时(分钟)
Planning 计划 60 100
Estimate 估计这个任务需要多少时间 30 30
Development 开发 500 600
Analysis 需求分析 (包括学习新技术) 100 120
Design Spec 生成设计文档 60 60
Design Review 设计复审 60 50
Coding Standard 代码规范 (为目前的开发制定合适的规范) 90 100
Design 具体设计 60 100
Coding 具体编码 300 360
Code Review 代码复审 60 30
Test 测试(自我测试,修改代码,提交修改) 100 120
Reporting 报告 30 30
Test Report 测试报告 30 60
Size Measurement 计算工作量 30 30
Postmortem & Process Improvement Plan 事后总结, 并提出过程改进计划 30 30
total 合计 1540 1820

学习进度条

第N周 新增代码(行) 累计代码(行) 本周学习耗时(小时) 累计学习耗时(小时) 重要成长
1 200 200 5 5 思考算法,决定用 bfs + hash 算法来实现 AI 部分
2 300 500 6 11 学习了 GUI 的一些函数用法
3 300 800 8 19 学习了 STL 、结构体等常在 C++ 上面用的 Python 语言用法
4 500 1300 10 29 总和运用所学的内容编写代码
posted @ 2020-10-19 22:57  GKQ  阅读(120)  评论(0编辑  收藏  举报