结对编程作业

我和队友的博客与Github链接

原型设计

我们本次设计采用了墨刀来设计

  • 游戏开始界面
  • 游戏运行界面
  • 游戏random后的界面
  • 成功完成游戏后的界面

原型设计时的困难及解决方法

在设计原型设计时我们比较苦恼的还是按钮的设计和布局吧,对于要做成什么风格的界面我们也是一时没法确定,后来经过讨论,一致同意了采用简约一些的界面,然后在界面下方还加入了random打乱功能和score计分功能,最后才有了最终版本的出现。

讨论图片

以下这张图片是我们两个人在教室奋战时候拍的

AI及原型设计实现

代码实现思路

  • 网络接口
    网络接口部分的解决方法是将题目给的json文件分析后分别将其中的信息保存到json_get.txt中,并将对应的图片的base64编码解码为pit.jpg图片
ef get_json():
    swap=[]
    response = urlopen("http://47.102.118.1:8089/api/problem?stuid=031802120").read().decode('utf-8')
    data = json.loads(response)
    photo = data["img"]
    imag = base64.b64decode(photo)
    fh = open("pit.jpg","wb")
    fh.write(imag)
    fh.close()
    js = open("json_get.txt","w")
    step = str(data["step"])
    swap=data["swap"]
    #print(swap)
    js.write(step+"\n")
    js.write("\n".join(str(i) for i in swap))
    js.close()
  • 算法流程

    • 首先就是将获取到的图片base64解码,并切割成9块进行比对
    • 将九宫格图片转化为矩阵
    • 判断有无解,并进行AI处理
    • 得出结论
  • 代码组织与内部实现设计(类图)

  • AI部分代码(一部分)

def generate_child(cur_node, end_node, hash_set, open_table, dis_fn):
    '''
    生成子节点函数
    :param cur_node:  当前节点
    :param end_node:  最终状态节点
    :param hash_set:  哈希表,用于判重
    :param open_table: OPEN表
    :param dis_fn: 距离函数
    :return: None
    '''
    if cur_node == end_node:
        heapq.heappush(open_table, end_node)
        return
    num = len(cur_node.state)
    # print("num is {}".format(num))
    for i in range(0, num):
        for j in range(0, num):
            if cur_node.state[i][j] != 9:
                continue
            for d in direction:  # 四个偏移方向
                x = i + d[0]
                y = j + d[1]
                if x < 0 or x >= num or y < 0 or y >= num:  # 越界了
                    continue
                # 记录扩展节点的个数
                global SUM_NODE_NUM
                SUM_NODE_NUM += 1

                state = copy.deepcopy(cur_node.state)  # 复制父节点的状态
                state[i][j], state[x][y] = state[x][y], state[i][j]  # 交换位置
                # print("state[i][j] is {}".format(state[i][j]))
                # print("state[x][y] is {}".format(state[x][y]))
                h = hash(str(state))  # 哈希时要先转换成字符串
                if h in hash_set:  # 重复了
                    continue
                hash_set.add(h)  # 加入哈希表
                gn = cur_node.gn + 1  # 已经走的距离函数
                hn = dis_fn(cur_node, end_node)  # 启发的距离函数
                node = State(gn, hn, state, h, cur_node)  # 新建节点
                cur_node.child.append(node)  # 加入到孩子队列
                heapq.heappush(open_table, node)  # 加入到堆中
def print_path(node):
    '''
    输出路径
    :param node: 最终的节点
    :return: None
    '''
    num = node.gn

    def show_block(block):
        for b in block:
            print(b)
            '''
            try:
                print(b.index(9))
            except ValueError:
                pass
            '''
    stack = []  # 模拟栈
    while node.par is not None:
        stack.append(node.state)
        node = node.par
    stack.append(node.state)
    count=0
    old_line = 0
    old_row = 0
    while len(stack) != 0:
        t = stack.pop()
        show_block(t)
        print(t)
        new_line = 0
        new_row = 0
        flag = 0
        for i in t:
            for j in i:
                if j == 9:
                    flag = 1
                    break
                else:
                    new_row += 1
            if flag == 0:
                new_row = 0
                new_line += 1
            else:
                break
        if count != 0:
            if new_line - old_line == -1:
                answer.append('w')
            if new_line - old_line == 1:
                answer.append('s')
            if new_row - old_row == -1:
                answer.append('a')
            if new_row - old_row == 1:
                answer.append('d')
        old_line = new_line
        old_row = new_row
        count += 1
        # print("9的坐标为[{}][{}]".format(new_line,new_row))

    return num
  • 游戏部分代码(一部分)
# 初始化
pygame.init()
mainClock = pygame.time.Clock()

# 加载图片
gameImage = pygame.image.load(r'./e_2.jpg')
gameRect = gameImage.get_rect()

# 设置窗口
windowSurface = pygame.display.set_mode((1530, 785))
pygame.display.set_caption('拼图')
clock = pygame.time.Clock()
pygame.font.SysFont('arial',32)
cellWidth = int(gameRect.width / VHNUMS)
cellHeight = int(gameRect.height / VHNUMS)

game_intro()
game_loop()

pygame.quit()
quit()
  • 性能分析
  • 测试
    我们测试时利用了接口的图片来进行测试,测试代码如下:(部分)
if __name__ == '__main__':

    NUMBER = 3
    win, temp = pictureCompare("./letter1")  # 与分割好的图片进行对比,得到目标矩阵和当前状态矩阵

    GOAL =[ [win[0], win[1], win[2]], [win[3], win[4], win[5]],[ win[6], win[7], win[8]] ]  # 得到目标矩阵

    OPEN = []
    BLOCK = [[temp[0], temp[1], temp[2]], [temp[3], temp[4], temp[5]],[ temp[6], temp[7], temp[8]]] # 原始状态

    SUM_NODE_NUM = 0
    start_t = datetime.datetime.now()
    length = A_start(BLOCK, GOAL, manhattan_dis, generate_child, time_limit=10)
    end_t = datetime.datetime.now()
    if length != -1:
        print("length =", length)
        print("time = ", (end_t - start_t).total_seconds(), "s")
        print("Nodes =", SUM_NODE_NUM)
        print("answer is :",answer)

跑出来的测试结果

代码签入记录

困难及解决方法

  • 因为是第一次和别人组队一起开发,在最开始的时候我们各自的文件的读取路径都是各写各的,后来才汇总时出现了路径问题,然后双方都采用了绝对路径后就解决了这一问题,也算是让我了解到代码规范性的重要性吧,包括注释之类的东西,没有写的话别人真的很难看懂自己的代码。
  • 在最开始的时候就遇到了问题,包括怎么从接口里面读取信息(因为确实没有做过),后面查百度才明白实现途径和爬虫差不多,就解决了问题
  • 后面在如何确认获取的图片是什么字母这一问题卡住,经过讨论,最后打算将图片分割成9块,每一块和我们的图片库进行比对,有两张及以上一样的图片碎片的话就可以确认图片的字母了,然后就可以进行后面的一系列操作

评价队友

我的队友非常优秀,其实一开始我对于代码规范性不大讲究,而且也不知道该怎么下手,后面也是在他的帮助下一步步完善了自己的代码,同时我队友的性格也和我十分合得来,总而言之,这是一次十分满意的合作

PSP和学习进度条

第N周 新增代码(行) 累计代码(行) 本周学习耗时(小时) 累计学习耗时(小时) 重要成长
1 300 300 20 20 学习了A*算法,并加以应用
2 200 500 24 44 通过完成游戏部分,对pygame及原型设计有了了解
posted @ 2020-10-19 19:55  Jitorun  阅读(124)  评论(0编辑  收藏  举报