结对编程作业

李秋杰博客链接:https://www.cnblogs.com/lqj666/
林必涵博客链接:https://www.cnblogs.com/kikikkii/
GitHub项目地址:https://github.com/kikikkii/CooperateWork
具体分工

原型设计 AI实现 游戏界面代码 游戏操作代码 游戏测试
林必涵
李秋杰

1.原型设计

这次作业设计主要采用了QT的界面设计工具
QT设计界面
实际效果
实际效果
组件:
start按钮:获取题目并初始化gridlayout布局

gridlayout布局控件:存放题目的图片,提供游戏的操作控制功能和游戏逻辑(胜利条件)

help按钮:请求提示,给出题目的解

Tips标签:显示题目的解

9个Label放在gridlayout控件内,显示题目图片的九宫格

设计说明:

大致的思路:

先将本地的图片(所有可能的图片)分为九宫格的样式,并编上1-9的序号,然后将从网络上获取的题目均等的切为九宫格,然后和本地的图片库进行匹配
最后将题目中的图片也编上序号,放入九宫格内。

结对过程,讨论问题时的照片

遇到的困难及解决方法

1.UI设计问题

一开始打算用tkinter,但是之后用发现QTDesigner可以直接转为python于是就果断转pyqt了,但是pyqt也用的不熟练,消息的传递研究了很久,按键响应也
研究了很久

2.控件的研究

选择什么样的控件才能更好的展示和进行游戏控制

3.设计完成后发现要加一个新的窗口,放不下所有的控件

重新设计了所有的控件布局,并且换了一个更大的窗口
收获:以后一定要先设计再写代码

4.图片的路径问题

很多文件一开始保存的的都是直接放在当前路径下,导致后期将各种模块组合再一起时,导包经常出问题,代码的管理也不是很规范

2.AI设计及原型设计实现

网络接口的使用

  网络接口使用python的requests库来获取题目信息

UML类图

算法关建

算法使用的是A*算法,经典的8数码问题,无解前返回-1,有解返回操作序列的字符串

import collections
import itertools
import heapq

class Solution(object):
    def __init__(self,blocks,zero_column,zero_row):
        super().__init__()
        self.board = []
        self.zero_column = 0
        self.zero_row =0
        
        self.zero_column = zero_column
        self.zero_row = zero_row
        t = 0
        for i in blocks:
            self.board.append([])
            for j in i:
                tmp = j.number
                self.board[t].append(tmp)
            t += 1
        self.zero_num = self.board[zero_row][zero_column]
        
    def slidingPuzzle(self):
        board = self.board
        R, C = len(board), len(board[0])
        #board[self.zero_row][self.zero_column] = 0
        start = tuple(itertools.chain(*board))
        #target = tuple([*range(1, R * C)] + [0])
        target = tuple([*range(1, R * C + 1)])
        target_wrong = tuple([*range(0, R*C-3)] + [R*C-3, R*C-1, R*C-2])
        operations = ""
        pq = [(0, 0, start, start.index(self.zero_num),operations)]
        cost = {start: 0}
        

        expected = {(C*r+c+1) % (R*C+1) : (r, c)
                    for r in range(R) for c in range(C)}
        def heuristic(board):
            ans = 0
            for r in range(R):
                for c in range(C):
                    val = board[C*r + c]
                    #if val == self.zero_num: continue
                    er, ec = expected[val]
                    ans += abs(r - er) + abs(c - ec)
            return ans

        while pq:
            #f = estimated distance (priority)
            #g = actual distance travelled (depth)
            f, g, board, zero, ops = heapq.heappop(pq)
            if board == target: return ops
            if board == target_wrong: return "-1"
            if f > cost[board]: continue

            for delta in (-1, 1, -C, C):
                tops = ops
                if delta == -1:
                    tops += "a"
                elif delta == 1:
                    tops += "d"
                elif delta == -C:
                    tops += "w"
                elif delta == C:
                    tops += "s"
                nei = zero + delta
                if abs(zero // C - nei // C) + abs(zero % C - nei % C) != 1:
                    continue
                if 0 <= nei < R*C:
                    board2 = list(board)
                    board2[zero], board2[nei] = board2[nei], board2[zero]
                    board2t = tuple(board2)
                    ncost = g + 1 + heuristic(board2t)
                    if ncost < cost.get(board2t, float('inf')):
                        cost[board2t] = ncost
                        heapq.heappush(pq, (ncost, g+1, board2t, nei, tops))

        return "-1"

流程图

代码性能分析

单元测试代码

# -*- coding: utf-8 -*-

# Form implementation generated from reading ui file 'C:\Users\lbh\Desktop\SoftwareProject\CooperateWork\UI\Huarong.ui'
#
# Created by: PyQt5 UI code generator 5.15.1
#
# WARNING: Any manual changes made to this file will be lost when pyuic5 is
# run again.  Do not edit this file unless you know what you are doing.
#这里仅为测试UI用,没什么其他用处
import sys
from PyQt5 import QtCore, QtGui, QtWidgets


class Ui_Dialog(object):
    def setupUi(self, Dialog):
        Dialog.setObjectName("Dialog")
        Dialog.resize(966, 665)
        self.Gamestart = QtWidgets.QPushButton(Dialog)
        self.Gamestart.setGeometry(QtCore.QRect(160, 430, 111, 61))
        self.Gamestart.setObjectName("Gamestart")
        self.gridLayoutWidget = QtWidgets.QWidget(Dialog)
        self.gridLayoutWidget.setGeometry(QtCore.QRect(160, 60, 341, 321))
        self.gridLayoutWidget.setObjectName("gridLayoutWidget")
        self.gridLayout = QtWidgets.QGridLayout(self.gridLayoutWidget)
        self.gridLayout.setContentsMargins(0, 0, 0, 0)
        self.gridLayout.setObjectName("gridLayout")
        self.pciture1 = QtWidgets.QLabel(self.gridLayoutWidget)
        self.pciture1.setText("")
        self.pciture1.setScaledContents(True)
        self.pciture1.setObjectName("pciture1")
        self.gridLayout.addWidget(self.pciture1, 0, 0, 1, 1)
        self.picture2 = QtWidgets.QLabel(self.gridLayoutWidget)
        self.picture2.setText("")
        self.picture2.setScaledContents(True)
        self.picture2.setObjectName("picture2")
        self.gridLayout.addWidget(self.picture2, 0, 1, 1, 1)
        self.picture8 = QtWidgets.QLabel(self.gridLayoutWidget)
        self.picture8.setText("")
        self.picture8.setScaledContents(True)
        self.picture8.setObjectName("picture8")
        self.gridLayout.addWidget(self.picture8, 2, 1, 1, 1)
        self.picture5 = QtWidgets.QLabel(self.gridLayoutWidget)
        self.picture5.setText("")
        self.picture5.setScaledContents(True)
        self.picture5.setObjectName("picture5")
        self.gridLayout.addWidget(self.picture5, 1, 1, 1, 1)
        self.picture4 = QtWidgets.QLabel(self.gridLayoutWidget)
        self.picture4.setText("")
        self.picture4.setScaledContents(True)
        self.picture4.setObjectName("picture4")
        self.gridLayout.addWidget(self.picture4, 1, 0, 1, 1)
        self.picture7 = QtWidgets.QLabel(self.gridLayoutWidget)
        self.picture7.setText("")
        self.picture7.setScaledContents(True)
        self.picture7.setObjectName("picture7")
        self.gridLayout.addWidget(self.picture7, 2, 0, 1, 1)
        self.picture10 = QtWidgets.QLabel(self.gridLayoutWidget)
        self.picture10.setText("")
        self.picture10.setScaledContents(True)
        self.picture10.setObjectName("picture10")
        self.gridLayout.addWidget(self.picture10, 2, 2, 1, 1)
        self.picture6 = QtWidgets.QLabel(self.gridLayoutWidget)
        self.picture6.setText("")
        self.picture6.setScaledContents(True)
        self.picture6.setObjectName("picture6")
        self.gridLayout.addWidget(self.picture6, 1, 2, 1, 1)
        self.picture3 = QtWidgets.QLabel(self.gridLayoutWidget)
        self.picture3.setText("")
        self.picture3.setScaledContents(True)
        self.picture3.setObjectName("picture3")
        self.gridLayout.addWidget(self.picture3, 0, 2, 1, 1)
        self.tips = QtWidgets.QLabel(Dialog)
        self.tips.setGeometry(QtCore.QRect(610, 90, 130, 130))
        sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Preferred)
        sizePolicy.setHorizontalStretch(0)
        sizePolicy.setVerticalStretch(0)
        sizePolicy.setHeightForWidth(self.tips.sizePolicy().hasHeightForWidth())
        self.tips.setSizePolicy(sizePolicy)
        self.tips.setMaximumSize(QtCore.QSize(400, 400))
        self.tips.setBaseSize(QtCore.QSize(400, 400))
        self.tips.setAlignment(QtCore.Qt.AlignLeading|QtCore.Qt.AlignLeft|QtCore.Qt.AlignTop)
        self.tips.setObjectName("tips")

        self.retranslateUi(Dialog)
        QtCore.QMetaObject.connectSlotsByName(Dialog)

    def retranslateUi(self, Dialog):
        _translate = QtCore.QCoreApplication.translate
        Dialog.setWindowTitle(_translate("Dialog", "Dialog"))
        self.Gamestart.setText(_translate("Dialog", "start"))
        self.tips.setText(_translate("Dialog", "提示:"))
if __name__ == "__main__":
  app = QtWidgets.QApplication(sys.argv) # 创建一个QApplication,也就是你要开发的软件app
  MainWindow = QtWidgets.QMainWindow()  # 创建一个QMainWindow,用来装载你需要的各种组件、控件
  ui = Ui_Dialog()            # ui是你创建的ui类的实例化对象
  ui.setupUi(MainWindow)         # 执行类中的setupUi方法,方法的参数是第二步中创建的QMainWindow
  MainWindow.show()            # 执行QMainWindow的show()方法,显示这个QMainWindow
  sys.exit(app.exec_())   

github代码签入



评价队友

值得学习的地方:队友的代码能力较强能较好的实现功能代码的编写。
需要改进的地方:心态要调整好

psp表格与学习进度条

PSP2.1 Personal Software
Process Stages
预估耗时
(分钟)
实际耗时
(分钟)
Planning 计划
· Estimate · 估计这个任务需要多少时间 10 10
Development 开发
· Analysis · 需求分析 (包括学习新技术) 800 1000
· Design Spec · 生成设计文档 200 260
· Design Review · 设计复审 30 55
· Coding Standard · 代码规范 (为目前的开发
制定合适的规范)
20 40
· Design · 具体设计 120 90
· Coding · 具体编码 160 200
· Code Review · 代码复审 60 60
· Test · 测试(自我测试,修改
代码,提交修改)
30 50
Reporting 报告
· Test Repor · 测试报告 70 70
· Size Measurement · 计算工作量 10 20
· Postmortem & Process
Improvement Plan
· 事后总结, 并提出过程改
进计划
30 30
· 合计 1530 1875
第N周 新增代码(行) 累计代码(行) 本周学习耗时(小时) 累计学习耗时(小时) 重要成长
1 0 0 5 5 了解qtqtdesigner
2 20 20 10 17 熟悉qtqtdesigner的使用,并使用qtqtdesigner完成原型设计
3 100 120 8 25 了解A算法,运用A算法求最优解法
4 0 0 5 30 熟悉github的仓库管理和git的操作
posted @ 2020-10-19 20:01  L2020  阅读(122)  评论(0编辑  收藏  举报