1.各链接
2.具体分工
王嵚:负责前端实现、博客内容指导and部分材料提供
陈荣杰:负责后端算法、博客撰写
3.PSP表格
- 王嵚
PSP2.1 | Personal Software Process Stages | 预估耗时(分钟) | 实际耗时(分钟) |
---|---|---|---|
Planning | 计划 | 60 | 90 |
·Estimate | ·估计这个任务需要多少时间 | 2600 | 2900 |
Development | 开发 | 3250 | 3960 |
·Analysis | ·需求分析 (包括学习新技术) | 1800 | 2000 |
·Design Spec | ·生成设计文档 | 90 | 60 |
·Design Review | ·设计复审 | 120 | 120 |
·Coding Standard | · 代码规范 (为目前的开发制定合适的规范) | 30 | 50 |
·Coding | ·具体编码 | 400 | 560 |
·Code Review | ·代码复审 | 450 | 720 |
·Test | ·测试(自我测试,修改代码,提交修改) | 240 | 300 |
Reporting | 报告 | 130 | 115 |
·Test Repor | ·测试报告 | 50 | 60 |
·Size Measurement | · 计算工作量 | 20 | 10 |
·Postmortem & Process Improvement Plan | ·事后总结, 并提出过程改进计划 | 20 | 10 |
合计 | 3440 | 4165 |
- 陈荣杰
PSP2.1 | Personal Software Process Stages | 预估耗时(分钟) | 实际耗时(分钟) |
---|---|---|---|
Planning | 计划 | 30 | 30 |
·Estimate | ·估计这个任务需要多少时间 | 2200 | 2600 |
Development | 开发 | 400 | 460 |
·Analysis | ·需求分析 (包括学习新技术) | 120 | 240 |
·Design Spec | ·生成设计文档 | 40 | 30 |
·Design Review | ·设计复审 | 30 | 20 |
·Coding Standard | · 代码规范 (为目前的开发制定合适的规范) | 30 | 30 |
·Coding | ·具体编码 | 1000 | 1200 |
·Code Review | ·代码复审 | 90 | 90 |
·Test | ·测试(自我测试,修改代码,提交修改) | 300 | 800 |
Reporting | 报告 | 60 | 60 |
·Test Repor | ·测试报告 | 60 | 60 |
·Size Measurement | · 计算工作量 | 20 | 20 |
·Postmortem & Process Improvement Plan | ·事后总结, 并提出过程改进计划 | 30 | 30 |
合计 | 2150 | 3130 |
4.解题思路描述与设计实现说明
网络接口的使用
根据样例的提示,调用 requests库中的get/post函数实现get/post请求,把如登录、注册等等操作所需要的请求封装成 不同函数放在一个httpfunctions.py文件下,使用时导入此文件就可以了。
具体代码如下:
def entry(account):#注册+绑定接口
url='http://api.revth.com/auth/login'
data={
"username": account["username"],
"password": account["password"]
}
headers={
"Content-Type":"application/json"
}
response=requests.post(url=url,headers=headers,data=json.dumps(data),verify=False);
print(response.text)
r = response.json()
return r
代码组织与内部实现设计(类图)
-
后端算法代码组织与内部实现设计
如果是特殊牌的话,服务器会自动识别,也就是说只要分堆就好,因此不考虑特殊牌的判别,直接对拿到的手牌进行组合,利用组合的思想对所有牌型进行比较,择取最优选择。
-
前端代码组织与内部实现设计
说明算法的关键与关键实现部分流程图
- 算法关键
- 分墩算法:对手牌进行组合,遍历一副手牌可以组成的所有情况,将当前的组合与当前的最优组合进行比较,按照等级及牌面对应权重矩阵赋权值,三墩相加再比大小,比到最后可以得出一个权值最大的组合,就选中这个组合为最优。
- 因此算法关键应该是对牌型合法的判断和判牌的策略,初始定的赋权值策略是按照牌型等级及牌面直接赋值,可在实测是产生了许多意料之外的bug,debug到自闭,后来了解到有权重矩阵的存在,摸了摸头顶,果断选择改变策略。
- 关键实现部分流程图
5.关键代码解释
- 后端:
- 先处理传入字符串,将其转化为列表类型数据,每个列表的第一个值为牌面值,第二个值为花色,方便操作,再利用组合的思想对所有牌型进行比较,择取最优牌型
def do(lll):#算法主函数,执行分墩步骤
sda = [#十三水权重矩阵,亲测可用,建议上手
[ # 1 2 3 4 5 6 7 8 9 T J Q K A JUNK
[0, 0, 0, 0, 0, 0, 1, 1, 2, 2, 4, 7, 14, 33],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]],
[ # 1 2 3 4 5 6 7 8 9 T J Q K A PAIR
[0, 46, 48, 50, 51, 54, 56, 60, 63, 68, 74, 81, 89, 97],
[0, 2, 3, 4, 4, 5, 7, 8, 10, 12, 15, 19, 24, 33],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 2, 3]],
[ # 1 2 3 4 5 6 7 8 9 T J Q K A TWO_PAIRS
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 36, 37, 38, 40, 44, 46, 49, 54, 57, 62, 64, 0],
[0, 0, 2, 3, 4, 4, 6, 7, 8, 10, 11, 13, 13, 0]],
[ # 1 2 3 4 5 6 7 8 9 T J Q K A TWO_PAIRS
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 31, 38, 39, 41, 45, 47, 50, 55, 58, 63, 65, 0],
[0, 0, 3, 4, 5, 5, 7, 8, 9, 11, 12, 14, 14, 0]],
[ # 1 2 3 4 5 6 7 8 9 T J Q K A TRIPLE
[0, 99, 99, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100],
[0, 63, 65, 69, 71, 72, 73, 73, 73, 74, 74, 75, 75, 75],
[0, 11, 12, 14, 14, 14, 14, 14, 14, 15, 15, 15, 15, 15]],
[ # 1 2 3 4 5 6 7 8 9 T J Q K A STRAIGHT
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 77, 78, 81, 83, 85, 87, 88, 90, 91, 92],
[0, 0, 0, 0, 16, 17, 20, 22, 24, 26, 28, 32, 33, 36]],
[ # 1 2 3 4 5 6 7 8 9 T J Q K A FLUSH
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 93, 93, 93, 93, 94, 95, 97, 98],
[0, 0, 0, 0, 0, 0, 36, 36, 37, 38, 40, 44, 49, 61]],
[ # 1 2 3 4 5 6 7 8 9 T J Q K A FULL_HOUSE
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 98, 98, 99, 99, 99, 100, 100, 100, 100, 100, 100, 100, 100],
[0, 64, 67, 70, 71, 73, 75, 77, 80, 82, 85, 88, 91, 94]],
[ # 1 2 3 4 5 6 7 8 9 T J Q K A FOUR_OF_A_KIND
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100],
[0, 93, 94, 95, 95, 96, 96, 96, 97, 97, 98, 98, 98, 98]],
[ # 1 2 3 4 5 6 7 8 9 T J Q K A STRAIGHT_FLUSH
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 100, 100, 100, 100, 100, 100, 100, 100, 100, 0],
[0, 0, 0, 0, 98, 98, 99, 99, 99, 99, 99, 99, 100, 0]],
[ # 1 2 3 4 5 6 7 8 9 T J Q K A ROYAL_FLUSH
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 100],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 100]]
];
card=lll
card_type=["","",""]#牌型
matrix=[[0,0,],[0,0,],[0,0,],[0,0,],[0,0,],[0,0,],[0,0,],[0,0,],[0,0,],[0,0,],[0,0,],[0,0,],[0,0,]]#拿到的牌的列表,即为牌库
dun=[[],[],[]]#分墩后存储的位置
j=0;
a=0;
max=0
for pai in card:#遍历字符串,转换需要的列表数据即拿到的牌
if pai=="*":i=4;
elif pai=="$":i=1;
elif pai == "&":
i = 2;
elif pai=="#":i=3;
if pai.isdigit():
if pai=="1":matrix[j][0]=10;matrix[j][1]=i;j=j+1;
elif pai!="0":matrix[j][0]=int(pai);matrix[j][1]=i;j=j+1;
elif pai=="J":matrix[j][0]=11;matrix[j][1]=i;j=j+1;
elif pai=="Q":matrix[j][0]=12;matrix[j][1]=i;j=j+1;
elif pai=="K":matrix[j][0]=13;matrix[j][1]=i;j=j+1;
elif pai=="A":matrix[j][0]=14;matrix[j][1]=i;j=j+1;
for i in combinations(matrix, 5):#调用combinations函数得出matrix的组合
sum=0;
test= list(i)
test_data1 = matrix.copy()#备份牌库
test = sorted(test, key=lambda x: (x[0], -x[1]))#排序,以牌面升序排序
if test[0] in test_data1:#将选出的牌从牌库中去掉以免影响后续操作
test_data1.remove(test[0])
if test[1] in test_data1:
test_data1.remove(test[1])
if test[2] in test_data1:
test_data1.remove(test[2])
if test[3] in test_data1:
test_data1.remove(test[3])
if test[4] in test_data1:
test_data1.remove(test[4])
for k in combinations(test_data1, 5):#从牌库剩余的8张牌中,抽出5张得到中墩,余下3张为后墩
test_data2=test_data1.copy()#备份
if k[0] in test_data2:#将抽出的牌从备份牌库中去掉
test_data2.remove(k[0])
if k[1] in test_data2:
test_data2.remove(k[1])
if k[2] in test_data2:
test_data2.remove(k[2])
if k[3] in test_data2:
test_data2.remove(k[3])
if k[4] in test_data1:
test_data2.remove(k[4])
pp=list(k)
test1=list(sorted(pp, key=lambda x: (x[0], -x[1])))#排序,以牌面升序排序
test2=list(sorted(test_data2,key=lambda x: (x[0], -x[1])))#排序,以牌面升序排序
list1=list(operation(test))#判断各个分墩的牌型以及此牌型中牌面最大的值,如炸弹中炸弹的牌面、两对中最大的对子牌面,返回牌型等级及牌面最大值
list2=list(operation(test1))
list3=list(ope(test2))
if list1[0] < list2[0] or list2[0] < list3[0] or list1[0] == list2[0] and list1[1] < list2[1] or list3[0] ==list2[0] and list2[1] < list3[1]or (list1[0]==list2[0]==7and list1[2]<list2[2]):#根据牌型等级及牌面最大值判断分墩是否合法,若不合法则跳过后续步骤直接下一个循环
continue
else:
value1 = sda[list1[0] - 1][2][list1[1] - 1]#从权重表中取得对应权值
value2 = sda[list2[0] - 1][1][list2[1] - 1]
value3 = sda[list3[0] - 1][0][list3[1] - 1]
sum = value1 + value2 + value3
if sum > max:#比较三墩总权值,大的留下
dun = [test2, test1, test]
max = sum
card_type[2] = get_type(list1[0])#将牌型对应名称赋值进对应墩
card_type[1] = get_type(list2[0])
card_type[0] = get_type(list3[0])
s = jiema(dun)#将处理完后的列表转换为字符串数据
s=s+["三墩牌型:"]+card_type
print(s)#输出分墩情况及牌型
return s
- 判断各个分墩的牌型以及此牌型中牌面最大的值,如炸弹中炸弹的牌面、两对中最大的对子牌面,返回牌型等级及牌面最大值
def operation(list):#判别牌型,返回牌型对应数字与此牌型中关键牌值,传入参数升序排列的列表
sum=[0,0,0];
a=[[0,0],[0,0],[0,0],[0,0],[0,0],[0,0]]#a[0]代表此位置对应牌的牌面,a[1]代表此牌面的牌有几张,可通过a[1]判断炸弹、葫芦、三条等有多张同牌面的牌型,
for list1 in list:
for count in range(5):
if a[count][0]==list1[0]:
a[count][1]=a[count][1]+1
break
elif a[count][0]==0:
a[count][0] = list1[0]
a[count][1] = a[count][1] + 1
break
count=0
if(list[0][0]+4==list[1][0]+3==list[2][0]+2==list[3][0]+1==list[4][0]):#按序排列
if list[0][1]==list[1][1]==list[2][1]==list[3][1]==list[4][1]:#同花色
sum=[10,list[4][0]]#同花顺
return sum
else:
count=0
for jojo in a:
if jojo[1]==4:
sum= [9,jojo[0]]#炸弹
return sum
elif jojo[1]==3:
if a[a.index(jojo)+1][1]==2:
sum= [8,jojo[0]]#葫芦
return sum
elif list[0][1]==list[1][1]==list[2][1]==list[3][1]==list[4][1]:
sum=[7,list[4][0],list[3][0]]#同花
return sum
elif (list[0][0] + 4 == list[1][0] + 3 == list[2][0] + 2 == list[3][0] + 1 == list[4][0]):
sum=[6,list[4][0],list[3][0]]#顺子
return sum
else :
sum=[5,jojo[0]]#三条
return sum
elif jojo[1]==2:
if a[1][1]==3:
sum= [8,a[1][0]]#葫芦
return sum
elif list[0][1] == list[1][1] == list[2][1] == list[3][1] == list[4][1]:
sum =[7, list[4][0],list[3][0]] # 同花
return sum
elif (list[0][0] + 4 == list[1][0] + 3 == list[2][0] + 2 == list[3][0] + 1 == list[4][0]):
sum = [6,list[4][0]] # 顺子
return sum
elif a[a.index(jojo)+1][1]==2:
if jojo[0]+1==a[a.index(jojo)+1][0]:
sum= [4,a[a.index(jojo)+1][0]]#连队
return sum
else:
sum=[3,a[a.index(jojo)+1][0]] #两对
return sum
elif a[a.index(jojo)+2][1]==2:
sum =[3 ,a[a.index(jojo)+2][0]] # 两对
return sum
else:
sum=[2,jojo[0]] #对子
return sum
if list[0][1] == list[1][1] == list[2][1] == list[3][1] == list[4][1]:
sum =[7 ,list[4][0] ,list[3][0]]# 同花
return sum
elif (list[0][0] + 4 == list[1][0] + 3 == list[2][0] + 2 == list[3][0] + 1 == list[4][0]):
sum = [6 ,list[4][0]] # 顺子
return sum
else:
sum = [1,list[4][0]]
return sum
if list[0][1] == list[1][1] == list[2][1] == list[3][1] == list[4][1]:
sum =[7,list[4][0]] # 同花
return sum
elif (list[0][0] + 4 == list[1][0] + 3 == list[2][0] + 2 == list[3][0] + 1 == list[4][0]):
sum = [6 ,list[4][0]] # 顺子
return sum
else:
sum = [1,list[4][0]]#散牌
return sum
return sum
def ope(list3):#求前墩的牌型,返回值与operation()相同
sum=0
if list3[0][0]==list3[1][0]==list3[2][0]:#三条
sum=[5,list3[2][0]]
return sum
elif list3[0][0]==list3[1][0]:#对子
sum=[2,list3[1][0]]
return sum
elif list3[2][0]==list3[1][0]:#对子
sum=[2,list3[1][0]]
return sum
else:
sum=[1,list3[2][0]]#散牌
return sum
- 前端:
from login_register_platform import LoginRegisterPlatform
from user_platform import UserPlatform
from record_platform import RecordPlatform
from game_platform import GamePlatform
from register_platform import RegisterPlatform
from list_platform import ListPlatform
from detail_platform import DetailPlatform
#以上是导入UI模块
from connector.sign_up import regiseterAndBind #导入注册接口
from connector.Login import entry #导入登入接口
from connector.asd import start #导入开始游戏接口
from connector.lishizhanji import paihang #导入排行榜接口
from connector.lishizhanji import see #导入历史列表接口
from connector.lishizhanji import zhanju #导入战局详情接口
from connector.Logout import chupai #导入出牌接口
from connector.division import do #导入出牌函数
from PyQt5.Qt import *
if __name__ == '__main__':
import sys
app = QApplication(sys.argv)
token = "a_random_string"
game_id = 0
card = "*1 *2 *3 *4 *5 *6 7 *8 *9 *J *Q *K"
window_login = LoginRegisterPlatform() #创建登入界面
window_login.setObjectName("Login")
window_login.setStyleSheet("#Login{border-image: url(resource/image/login.png);}")
window_register = RegisterPlatform() #创建注册界面
window_register.setObjectName("Register")
window_register.setStyleSheet("#Register{border-image: url(resource/image/login.png);}")
window_user = UserPlatform() #创建用户界面
window_user.setObjectName("User")
window_user.setStyleSheet("#User{border-image: url(resource/image/user_background.jpg);}")
window_user.head.setStyleSheet("border-image: url(resource/image/user_head.jpg)")
window_game = GamePlatform() #创建游戏界面
window_game.setObjectName("Game")
window_game.setStyleSheet("#Game{border-image: url(resource/image/record_background.jpg);}")
window_game.head.setStyleSheet("border-image: url(resource/image/user_head.jpg)")
window_record = RecordPlatform() #创建排行榜界面
window_record.setObjectName("Record")
window_record.setStyleSheet("#Record{border-image: url(resource/image/record_background.jpg);}")
window_list = ListPlatform() #创建历史战局列表界面
window_list.setObjectName("List")
window_list.setStyleSheet("#List{border-image: url(resource/image/record_background.jpg);}")
window_detail = DetailPlatform() #创建历史战局详情界面
window_detail.setObjectName("Detail")
window_detail.setStyleSheet("#Detail{border-image: url(resource/image/record_background.jpg);}")
def show_user_platform(login_text,register_text): #由登入界面跳转到用户界面的函数
global token
account = {"username": login_text, "password": register_text}
r = entry(account)
flag = r["status"]
print(flag)
if (flag == 0):
global token
data = r["data"]
token = data["token"]
QMessageBox.about(window_login, "登入结果", "登入成功")
window_user.show()
window_login.hide()
else:
QMessageBox.about(window_login, "登入结果", "登入失败,账号或密码错误")
def show_login_platform_f_r():
print("回到登入界面")
window_login.show()
window_register.hide()
def show_register_platform():
print("展示注册界面")
window_register.show()
window_login.hide()
def show_login_platform_f_u():
print("展示登入平台")
window_login.show()
window_user.hide()
def show_game_platform(): #由用户界面跳转到游戏界面的函数
window_user.hide()
window_game.show()
def show_record_platform(): #由用户界面跳转到排行榜界面的函数
print("展示排行榜平台")
window_record.show()
window_user.hide()
def show_list_platform():
print("展示历史战局列表平台")
window_list.show()
window_user.hide()
def show_detail_platform():
print("展示历史战局详情平台")
window_detail.show()
window_user.hide()
def show_user_platform_f_g(): # 由游戏界面跳转到用户界面的函数
print("展示用户平台")
window_user.show()
window_game.hide()
def show_user_platform_f_r(): #由排行榜界面跳转到用户界面的函数
print("展示用户平台")
window_user.show()
window_record.hide()
def show_user_platform_f_l():
print("展示用户平台")
window_user.show()
window_list.hide()
def show_user_platform_f_d():
print("展示用户平台")
window_user.show()
window_detail.hide()
def register(UserName,PassWord,StudentId,JwcPassWord): #注册函数
account = {"username": UserName, 'password': PassWord}
jwc = {"student_number": StudentId, "student_password": JwcPassWord}
flag = regiseterAndBind(account,jwc)
if (flag == 0):
QMessageBox.about(window_register, "注册结果", "注册成功")
window_login.show()
window_register.hide()
elif (flag == 1002):
QMessageBox.about(window_register, "注册结果", "学号已绑定")
window_login.show()
window_register.hide()
elif (flag == 1003):
QMessageBox.about(window_register, "注册结果", "教务处认证失败")
else :
QMessageBox.about(window_register, "注册结果", "注册失败")
def record_get_data(): #获取排行榜
r = paihang()
x = len(r)
window_record.tableWidget.setRowCount(x)
for i in range(0,x):
y = r[i]
idItem = QTableWidgetItem(str(y["player_id"]))
window_record.tableWidget.setItem(i,0,idItem)
nameItem = QTableWidgetItem(y["name"])
window_record.tableWidget.setItem(i, 1, nameItem)
scoreItem = QTableWidgetItem(str(y["score"]))
window_record.tableWidget.setItem(i, 2, scoreItem)
#newItem = QTableWidgetItem('张三')
#TableWidget.setItem(0, 0, newItem)
def list_get_data(player_id):
global token
print(player_id)
response = see(token,player_id)
data = response["data"]
lenth = len(data)
window_list.history_game_list.setRowCount(lenth)
for i in range(0,lenth):
now_data = data[i]
card_list = "".join(now_data["card"])
id_Item = QTableWidgetItem(str(now_data["id"]))
window_list.history_game_list.setItem(i, 0, id_Item)
card_Item = QTableWidgetItem(card_list)
window_list.history_game_list.setItem(i, 1, card_Item)
score_Item = QTableWidgetItem(str(now_data["score"]))
window_list.history_game_list.setItem(i, 2, score_Item)
timestamp_Item = QTableWidgetItem(str(now_data["timestamp"]))
window_list.history_game_list.setItem(i, 3, timestamp_Item)
def detail_get_data(game_id):
global token
response = zhanju(token,game_id)
data = response["data"]
detail = data["detail"]
lenth = len(detail)
window_detail.history_game_detail.setRowCount(lenth)
for i in range(0,lenth):
now_detail = detail[i]
card_list = "".join(now_detail["card"])
game_id_Item = QTableWidgetItem(str(data["id"]))
window_detail.history_game_detail.setItem(i,0,game_id_Item)
player_id_Item = QTableWidgetItem(str(now_detail["player_id"]))
window_detail.history_game_detail.setItem(i, 1, player_id_Item)
name_Item = QTableWidgetItem(now_detail["name"])
window_detail.history_game_detail.setItem(i, 2, name_Item)
card_Item = QTableWidgetItem(card_list)
window_detail.history_game_detail.setItem(i, 3, card_Item)
score_Item = QTableWidgetItem(str(now_detail["score"]))
window_detail.history_game_detail.setItem(i, 4, score_Item)
def start_game(): #开始游戏但是还没出牌
print("已经点击开始游戏按钮")
QMessageBox.about(window_game, "提示", "点击出牌后可再次点击开始游戏,重复点击开始游戏将导致进入多个战局而无法出牌")
global token,game_id,card
# print(token)
r = start(token)
flag = r["status"]
data = r["data"]
id = str(data["id"])
game_id = data["id"]
card = data["card"]
print(card)
if (flag == 0):
window_game.game_id.setText(id)
QMessageBox.about(window_game,"提示","成功进入战局")
else:
QMessageBox.about(window_game, "开始游戏结果", "开始游戏失败,错误状态码:" + str(flag))
def show_poker():
print("已经点击出牌按钮")
global token,game_id,card
s = do(card)
response = chupai(token,game_id,s)
c = s[0]
d = ''
type_1 = list()
for i in c:
if i == ' ':
if d[0] == '#':
d = '方块' + d
elif d[0] == '$':
d = '黑桃' + d
elif d[0] == '&':
d = '红桃' + d
elif d[0] == '*':
d = '梅花' + d
type_1.append(d)
d = ''
continue
d += i
if d[0] == '#':
d = '方块' + d
elif d[0] == '$':
d = '黑桃' + d
elif d[0] == '&':
d = '红桃' + d
elif d[0] == '*':
d = '梅花' + d
type_1.append(d)
window_game.one_poker_1.setText(type_1[0])
window_game.one_poker_2.setText(type_1[1])
window_game.one_poker_3.setText(type_1[2])
type_2 = list()
c = s[1]
d = ''
for i in c:
if i == ' ':
if d[0] == '#':
d = '方块' + d
elif d[0] == '$':
d = '黑桃' + d
elif d[0] == '&':
d = '红桃' + d
elif d[0] == '*':
d = '梅花' + d
type_2.append(d)
d = ''
continue
d += i
if d[0] == '#':
d = '方块' + d
elif d[0] == '$':
d = '黑桃' + d
elif d[0] == '&':
d = '红桃' + d
elif d[0] == '*':
d = '梅花' + d
type_2.append(d)
window_game.tow_poker_1.setText(type_2[0])
window_game.tow_poker_2.setText(type_2[1])
window_game.tow_poker_3.setText(type_2[2])
window_game.tow_poker_4.setText(type_2[3])
window_game.tow_poker_5.setText(type_2[4])
type_3 = list()
c = s[2]
d = ''
for i in c:
if i == ' ':
if d[0] == '#':
d = '方块' + d
elif d[0] == '$':
d = '黑桃' + d
elif d[0] == '&':
d = '红桃' + d
elif d[0] == '*':
d = '梅花' + d
type_3.append(d)
d = ''
continue
d += i
if d[0] == '#':
d = '方块' + d
elif d[0] == '$':
d = '黑桃' + d
elif d[0] == '&':
d = '红桃' + d
elif d[0] == '*':
d = '梅花' + d
type_3.append(d)
window_game.three_poker_1.setText(type_3[0])
window_game.three_poker_2.setText(type_3[1])
window_game.three_poker_3.setText(type_3[2])
window_game.three_poker_4.setText(type_3[3])
window_game.three_poker_5.setText(type_3[4])
flag = response["status"]
if (flag == 0):
QMessageBox.about(window_game,"提示","出牌成功可以再次开始游戏")
else:
QMessageBox.about(window_game,"提示","出牌失败")
window_login.account_password_signal.connect(show_user_platform) #登入界面中连接跳转到用户界面的函数
window_login.register_signal.connect(show_register_platform) #登入界面到注册界面的连接
window_register.return_to_login_signal.connect(show_login_platform_f_r) #注册界面回到登入界面
window_user.return_to_login_platform_signal.connect(show_login_platform_f_u) #自己看函数名
window_user.start_game_signal.connect(show_game_platform) #用户界面中连接跳转到游戏界面的函数
window_user.go_to_rank_signal.connect(show_record_platform) #用户界面中连接跳转到排行榜界面的函数
window_user.go_to_list_signal.connect(show_list_platform)
window_user.go_to_detail_signal.connect(show_detail_platform)
window_game.return_to_user_platform_signal.connect(show_user_platform_f_g) #游戏界面中连接跳转到用户界面的函数
window_record.return_to_user_platform_signal.connect(show_user_platform_f_r) #排行榜界面中连接跳转到用户界面的函数
window_list.return_to_user_signal.connect(show_user_platform_f_l)
window_detail.return_to_user_signal.connect(show_user_platform_f_d)
window_register.register_sinal.connect(register) #连接向服务器发送注册信息的函数
window_record.get_data_signal.connect(record_get_data) #更新排行榜数据
window_list.get_data_signal.connect(list_get_data) #更新历史列表数据
window_detail.get_data_signal.connect(detail_get_data) #更新战局详情列表
window_game.start_game_signal.connect(start_game) #开始游戏请求
window_game.show_poker_signal.connect(show_poker) #出牌
window_login.show()
sys.exit(app.exec_())
6.性能分析与改进
改进的思路
- 一开始定的权值策略不佳,导致容易出现葫芦拆成三条和对子,甚至偶尔会出现不合法的情况,后来苦心查阅各方资料
问大佬同学,了解到权值矩阵的存在,一用上就体会到前所未有的顺滑 - 用了权值矩阵之后,偶尔还是会有报错,多次debug后发现是在判断合不合法的条件语句出问题,后面改成判断是否不合法,相对简单一些。
- 一开始憋着一股劲,一股脑把算法敲出来,后来发现敲出来的东西bug实在太多,其实应该再开始前就先查阅资料,了解背景,然后打码的时候也得保持冷静,大脑发热万万不可
性能分析图和程序中消耗最大的函数
本次性能分析是利用pycham自带性能分析模块
由图中可以看出operation函数消耗最大,即黄色的函数块
7.单元测试
- 下图是测试用到的函数,代码比较长,限于篇幅不全展开
- 主函数代码展示
class TestDo(TestCase):
def test_best_cards_type():
card_dic = []
for i in ['*', '#', '&', '$']:
for j in ['2', '3', '4', '5', '6', '7', '8', '9', '10', 'J', 'Q', 'K', 'A']:
card_dic.append(i + j)
num = 10
while num:
cards = ""
s = copy(card_dic)
for i in range(13):
j = numpy.random.randint(0, len(s))
if i != 12:
cards += s[j] + ' '
else:
cards += s[j]
s.pop(j)
num -= 1
do(cards)
test_best_cards_type()
-
对do函数即分牌函数进行单元测试
测试数据:随机生成,不特意构造
测试思路:利用随机生成的数据对division进行测试,可完成对其实用性和可靠性检测 -
利用coverage对测试程序进行覆盖率分析
- 运行结果
- 运行结果
8.Github的代码签入记录
9.遇到的困难及解决方法
- 陈荣杰
困难描述 | 解决尝试 | 是否解决 | 有何收获 |
---|---|---|---|
排行榜、历史战局、登录注册要从服务器得到数据并展示 | 查找资料、根据十三水api上的样例来仿作、求助队友 | 是 | 第一次尝试调用网络接口,requests真的好用 |
分墩赋权值算法不够优 | 查阅资料、询问大佬 | 是 | 原来还有十三水权值矩阵这东西,真好用嘿嘿 |
如何设计算法实现最优牌型的选择 | 第一下想法是判断自己有何牌型,然后从牌型到的到小的剔除,再重新判断,后面用了组合的想法来判牌、分牌 | 是 | 学习了组合数算法,itertools库真好用 |
- 王嵚
困难描述 | 解决尝试 | 是否解决 | 有何收获 |
---|---|---|---|
实现前端的方法很多不知道用什么好 | 之前第一次个人编程作业的时候下载了pycharm 也学习了一些python,于是决定用pyqt5来完成这次作业 | 是 | 熟悉了python语法,初步掌握了pyqt5 |
熟悉的同学里没有使用相同工具的,遇到问题比较困扰 | 百度、视频教程和自己瞎试 | 是 | 锻炼了自学能力 |
10.评价队友
- 值得学习的地方
主动承担起前端大梁,儒雅随和,不紧不慢,是个好队友 - 需要改进的地方
无,挺好了
11.学习进度条
- 王嵚
第N周 | 新增代码(行) | 累计代码(行 | 本周学习耗时(小时) | 累计学习耗时(小时) | 重要成长 |
---|---|---|---|---|---|
1 | 0 | 0 | |||
2 | 500 | 500 | 20 | 20 | pyqt没学会多少python的语法倒是学了不少 |
3 | 1000 | 1500 | 30 | 50 | 实现了前端 |
- 荣杰
第N周 | 新增代码(行) | 累计代码(行 | 本周学习耗时(小时) | 累计学习耗时(小时) | 重要成长 |
---|---|---|---|---|---|
4 | 0 | 0 | 10 | 10 | 对项目的需求分析和原型设计的了解更深 |
6 | 800+ | 800+ | 5 | 15 | 十三水出牌算法的实现,以及py自带堆的学习 |