1.相关链接和地址
我的本次作业链接:https://www.cnblogs.com/ambition-hhn/p/11736917.html
搭档(李欣凯)作业链接:https://www.cnblogs.com/wersat/p/11768851.html
github仓库链接:https://github.com/South1999/ShisanshuiGame
2.具体分工
我负责本次作业的AI部分,写出牌的算法,我的队友负责UI部分功能实现。
3.PSP表格
PSP2.1 | Personal Software Process Stages | 预估耗时(分钟) | 实际耗时(分钟) |
---|---|---|---|
Planning | 计划 | 20(sum) | 20(sum) |
·Estimate | ·估计这个任务需要多少时间 | 20 | 20 |
Development | 开发 | 790(sum) | 1200(sum) |
·Analysis | ·需求分析 (包括学习新技术) | 180 | 200 |
·Design Spec | ·生成设计文档 | 70 | 90 |
·Design Review | ·设计复审 | 30 | 30 |
·Coding Standard | ·代码规范 | 30 | 60 |
·Design | ·具体设计 | 60 | 80 |
·Coding | ·具体编码 | 200 | 280 |
·Code Review | ·代码复审 | 40 | 60 |
·Test | ·测试 | 180 | 400 |
Reporting | 报告 | 130(sum) | 170(sum) |
·Test Repor | ·测试报告 | 40 | 60 |
·Test Repor | ·计算工作量 | 30 | 30 |
·Postmortem & Process Improvement Plan | ·事后总结, 并提出过程改进计划 | 60 | 80 |
· 合计 | 940 | 1390 |
4.解题思路描述与设计实现说明
- 网络接口的使用
- 通过使用javascript中的ajax使用接口
- 代码组织与内部实现设计
注册(很稀松平常的ajax使用......):
前端拿到牌后把牌传给后端调度算法
类图
- 说明算法的关键与关键实现部分流程图
- 算法的关键在于把十三张牌全组合,分成5,5,3三墩,给每个不同的牌型赋权值,同时记录假设当前牌全胜赢得水数,水数大的牌优先值高,其次是权值大的牌。组合用到了itertools库的combinations函数。流程图如下。
- 算法的关键在于把十三张牌全组合,分成5,5,3三墩,给每个不同的牌型赋权值,同时记录假设当前牌全胜赢得水数,水数大的牌优先值高,其次是权值大的牌。组合用到了itertools库的combinations函数。流程图如下。
5.关键代码解释
poker = poker.split(' ')
change1 = {'$': 1, '&': 2, '*': 3, '#': 4}
change2 = ['', '$', '&', '*', '#']
newpoker = []
for x in poker:
num = change1[x[0]]
if x[1] == 'A':
num += 14 * 10
elif x[1] == 'J':
num += 11 * 10
elif x[1] == 'Q':
num += 12 * 10
elif x[1] == 'K':
num += 13 * 10
else:
num += int(x[1:]) * 10
newpoker.append(num)
newpoker.sort()
for TOP in combinations(newpoker, 3):
tmp = list(newpoker[:])
for i in range(3):
tmp.remove(TOP[i])
for MID in combinations(tmp, 5):
BOT = list(tmp[:])
for j in range(5):
BOT.remove(MID[j])
这一段代码是处理拿到的十三张牌,首先用一个split函数将十三张牌分开,每张牌是一个字符串,然后把黑红梅方四种花色转化为个位数,牌的大小乘十,再加起来,这样就可以把牌转化为纯粹的数字,方便之后的处理。拿到处理过的牌后,将其排序,然后通过combinations函数进行组合,每次选出牌后,将已经选出来的牌从原来的牌集中去掉,再重复一次上述操作,最终可遍历所有牌型。
6.性能分析与改进
- 改进思路
- 因为本次从十三张牌中按5,5,3分墩,其实就是一个组合的问题,最开始我的组合是自己手写的,速度比较慢,之后我从网上查到python有求组合的函数,用了之后速度提升不少。还有排序问题,最初我是分完墩后,把每墩再分别排序,改进之后是我直接在分墩前就把牌排好序,根据combinations函数特性,得到的每墩顺序是已经排好的,省了每次每墩排序的时间。
- 性能分析图和消耗最大的函数
def Play(ID,Token,poker):
# 个位数为1是黑桃,2是红桃,3是梅花,4是方块
poker = poker.split(' ')
change1 = {'$': 1, '&': 2, '*': 3, '#': 4}
change2 = ['', '$', '&', '*', '#']
newpoker = []
for x in poker:
num = change1[x[0]]
if x[1] == 'A':
num += 14 * 10
elif x[1] == 'J':
num += 11 * 10
elif x[1] == 'Q':
num += 12 * 10
elif x[1] == 'K':
num += 13 * 10
else:
num += int(x[1:]) * 10
newpoker.append(num)
newpoker.sort()
save = []
MAX = 0 #记录最优且最理想情况全赢能获得多少水
Mscore1 = 0 #记录目前最优底墩权值分数
Mscore2 = 0 #中墩
Mscore3 = 0 #顶墩
SUM=0
for TOP in combinations(newpoker, 3):
tmp = list(newpoker[:])
for i in range(3):
tmp.remove(TOP[i])
for MID in combinations(tmp, 5):
BOT = list(tmp[:])
for j in range(5):
BOT.remove(MID[j])
score1 = 0 # 底部
val1 = 1
score2 = 0 # 钟部
val2 = 1
score3 = 0 # 顶部
val3 = 1
if Tonghuashun(BOT):
score1 = 512
val1 = 5
elif Zhadan(BOT):
score1 = 256
val = 4
elif Hulu(BOT):
score1 = 128
elif Tonghua(BOT):
score1 = 64
elif Shunzi(BOT):
score1 = 32
elif Santiao(BOT, 5):
score1 = 16
elif Liandui(BOT):
score1 = 8
elif Erdui(BOT):
score1 = 4
elif Yidui(BOT, 5):
score1 = 2
else:
score1 = 1
if Tonghuashun(MID):
score2 = 512
val2 = 10
elif Zhadan(MID):
score2 = 256
val2 = 8
elif Hulu(MID):
score2 = 128
val2 = 2
elif Tonghua(MID):
score2 = 64
elif Shunzi(MID):
score2 = 32
elif Santiao(MID, 5):
score2 = 16
elif Liandui(MID):
score2 = 8
elif Erdui(MID):
score2 = 4
elif Yidui(MID, 5):
score2 = 2
else:
score2 = 1
if Santiao(TOP, 3):
score3 = 16
elif Yidui(TOP, 3):
score3 = 2
else:
score3 = 1
if score1 >= score2 and score2 >= score3 and (val1 + val2 + val3 > MAX or (val1 + val2 + val3 == MAX and score1+score2+score3 >= SUM and score1>score2 and score2>score3) ):
save = []
temp = ''
pai = ''
for i in range(3):
temp += change2[TOP[i] % 10]
pai= str(TOP[i] // 10)
if(pai=='11'):
pai='J'
elif(pai=='12'):
pai='Q'
elif(pai=='13'):
pai='K'
elif(pai=='14'):
pai='A'
temp+=pai
if i != 2:
temp += ' '
save.append(temp)
temp = ""
for i in range(5):
temp += change2[MID[i] % 10]
pai = str(MID[i] // 10)
if(pai=='11'):
pai='J'
elif(pai=='12'):
pai='Q'
elif(pai=='13'):
pai='K'
elif(pai=='14'):
pai='A'
temp+=pai
if i != 4:
temp += ' '
save.append(temp)
temp = ""
for i in range(5):
temp += change2[BOT[i] % 10]
pai = str(BOT[i] // 10)
if(pai=='11'):
pai='J'
elif(pai=='12'):
pai='Q'
elif(pai=='13'):
pai='K'
elif(pai=='14'):
pai='A'
temp+=pai
if i != 4:
temp += ' '
save.append(temp)
MAX = val1 + val2 + val3
SUM=score1+score2+score3
Mscore1 = score1
Mscore2 = score2
Mscore3 = score3
header={
'content-type':'application/json',
'x-auth-token':str(Token)
}
data={
'id':int(ID),
'card':save
}
print(save)
response=requests.post('http://api.revth.com/game/submit',json=data,headers=header)
return response.json()
7.单元测试
测试的就是上述的Play函数,测试数据是调用api获得
拿到的牌
'&5 #3 $8 #Q *6 #5 #9 $Q #8 $5 #J #6 *10'
'&Q $6 $J #J *4 $K $2 #Q *9 *K #6 #4 #9'
'#J *7 *Q &10 #5 #8 &K &9 *A #2 #3 $7 &J'
'$9 *2 &5 &A *6 $3 *A &8 &6 #7 &10 &K *K'
'*7 *4 #6 &8 $8 $10 *5 $2 #9 #2 *3 #A *J'
打出去的牌
['$8 *10 $Q', '#3 #8 #9 #J #Q', '$5 &5 #5 *6 #6']
['*9 $J &Q', '$2 *4 $6 $K *K', '#4 #6 #9 #J #Q']
['$7 *7 *A', '&9 &10 &J *Q &K', '#2 #3 #5 #8 #J']
['$9 *K *A', '*2 $3 &6 *6 #7', '&5 &8 &10 &K &A']
['#9 $10 #A', '$2 #2 #6 $8 &8', '*3 *4 *5 *7 *J']
8.Github的代码签入记录
9.遇到的代码模块异常或结对困难及解决方法
- 问题描述
- 最开始使用requests库中的request和get函数一直显示失败,并且不知道为什么会出错
- 做过哪些尝试
- 最开始我检查url是否填写正确,然后去网上搜索request库中的request和get详细用法,后来发现我在传参数的时候,参数格式错误,最后改成正确的
- 是否解决
- 是
- 有何收获
- 之前没有接触过网络接口这方面的知识,这一次亲自写了程序利用网络接口来获取信息,对网络接口这方面的知识有了更深的了解
10.评价你的队友
- 值得学习的地方
- 我的队友非常努力,他是负责前端的内容,我知道他的工作量应该比我大,而且每天都有在学习新的内容。他善于为队友考虑,他已经把一些数据处理好,我就少了一些工作量
- 需要改进的地方
- 希望他和我可以更多的沟通,这次作业因为前端和后端用的语言不一样,导致连起来有些困难,有一些原因我觉得可能是沟通有点少,不过这方面我也需要改进。
11.学习进度条
第N周 | 新增代码(行) | 累计代码(行) | 本周学习耗时(小时) | 累计学习耗时(小时) | 重要成长 |
---|---|---|---|---|---|
1 | 0 | 0 | 3 | 3 | 对原型设计工具有一个初步了解 |
2 | 200 | 200 | 5 | 8 | 学习有关网络接口方面内容 |
3 | 350 | 550 | 5 | 13 | 尝试初步写十三水的算法 |
4 | 200 | 750 | 6 | 19 | 改进代码,改进算法 |