1.博客与giuhub链接
(1)结对同学的博客链接:点我!!
(2)本作业的博客链接:点我!!
(3)Fork的同名仓库的Github项目地址: 点我!!
(4)UI视频链接:点击视频收获惊喜! 提取码: tx7h
2.具体分工
对于本次结对编程作业,我和搭档的分工如下:
- 雅菁负责前端,即全部UI的实现。
- 林睿负责后端,即全部算法的实现。
- 分别把各自的项目文件上传到github上并Fork对方仓库,编辑博客中各自负责的part。
3.PSP表格
PSP2.1 |
Personal Software Process Stages |
预估耗时(分钟) |
实际耗时(分钟) |
Planning |
计划 |
150 |
150 |
· Estimate |
· 估计这个任务需要多少时间 |
5040 |
5880 |
Development |
开发 |
1220 |
1320 |
· Analysis |
· 需求分析 (包括学习新技术) |
400 |
440 |
· Design Spec |
· 生成设计文档 |
120 |
120 |
· Design Review |
· 设计复审 |
60 |
120 |
· Coding Standard |
· 代码规范 (为目前的开发制定合适的规范) |
60 |
60 |
· Design |
· 具体设计 |
420 |
420 |
· Coding |
· 具体编码 |
3000 |
3360 |
· Code Review |
· 代码复审 |
300 |
300 |
· Test |
· 测试(自我测试,修改代码,提交修改) |
120 |
180 |
Reporting |
报告 |
110 |
150 |
· Test Report |
· 测试报告 |
60 |
60 |
· Size Measurement |
· 计算工作量 |
20 |
30 |
· Postmortem & Process Improvement Plan |
· 事后总结, 并提出过程改进计划 |
30 |
60 |
|
· 合计 |
5890 |
6490 |
4.解题思路描述和设计实现说明
(1)网络接口的使用
a.前端接口:前端所需要设置的接口主要包括,登录注册界面的接口、注销接口、开启战局后获取牌面的接口、排行榜的接口、历史战局的接口以及通过场号查询战局详情的接口。
- 其中开启战局、历史战绩和战局详情的接口中的"token"通过在登录界面的js中利用“localStorage.setItem("token",json.data.token);"将对应用户的token存在本地,从而实现登录后实时更新token。其中接口建立与处理获取信息的对应JS示例如下(以历史战绩界面的JS为例):
b.后端接口:后端接口部分主要用到登录,开启战局,出牌这几个接口。
- 在python中使用requests的post方法发送headers和data,将返回的json数据保存在字典中。
'''登录'''
url = 'https://api.shisanshui.rtxux.xyz/auth/login'
data = {
"username": "031702504",
"password": "123"
}
r = requests.post(url,json=data)
print(r)
result1 = r.json()
print(result1)
token = result1['data']['token']
'''开启战局'''
headers = {'x-auth-token': token}
url2='https://api.shisanshui.rtxux.xyz/game/open'
r2=requests.post(url2, headers=headers)
result2=r2.json()
print(result2)
'''出牌'''
id = str(result2["data"]["id"])
print(id)
data = {
"id": id,
"card": finalCardstr
}
print(data)
url3='https://api.shisanshui.rtxux.xyz/game/submit'
r3=requests.post(url3,json=data, headers=headers)
result3 = r3.json()
print(result3)
(2)代码组织与内部实现设计
类与类图
类名 |
说明 |
属性 |
Class CardMode |
保存一张扑克牌的信息,如花色和牌面大小 |
cardList,cardType |
Class TypeCard |
保存一组手牌的信息,前墩、中墩、后墩、牌型、待分配手牌 |
headmodul,midmodul,lastmodul,sumscore,aCardlist |
函数
函数名 |
功能 |
Def getcardList2: |
将手牌排序,依次按照牌面大小和花色降序排列 |
Def getCardList3: |
按照牌面大小将手牌从小到大保存在二维列表 |
Def getCardList4: |
按照牌面大小将手牌从大到小保存在二维列表 |
Def getHeitao: |
得到当前手牌中黑桃花色的全部手牌 |
Def getHongtao: |
得到当前手牌中红桃花色的全部手牌 |
Def getMeihua: |
得到当前手牌中梅花花色的全部手牌 |
Def getFangkuai: |
得到当前手牌中方块花色的全部手牌 |
Def SpecialCard: |
查找是否存在特殊手牌 |
Def SpecialCard: |
查找普通手牌的类型,把所有情况保存在列表 |
(3)说明算法的关键与关键实现部分流程图
算法关键是如果是普通牌型,先找到后墩中存在的所有牌型加入列表中,再依次从每一种后墩剩余的手牌中找出中墩和前墩,注意的是要求后墩>中墩>前墩,然后从大到小依次给前墩、中墩、后墩分配散牌,最后把符合要求的全部组合进行比较,得到最大的组合。
关键实现部分流程图
5.关键代码解释
(1)前端
前端中比较关键的代码有两处:
- 一是根据接口获取的数据,进行分割处理后生成相应的表单并显示出来(排行榜、历史战绩、战绩详情界面),主要通过“innerHTML+=”实现;
- 二是处理从接口中获取到的card信息,调取对应的纸牌图片并展示,用分割产生的字符串和固定字符串组成img的src路径(开启战局界面)。
分割card并调取对应牌面的部分js代码如下:
(2)后端
后端中比较关键的代码:
- 先找出所有后墩的牌型,存在CardModelList1中。再找到所有后墩对应的中墩的情况,存放在CardModelList2中。
- 判断中墩的牌型是否小于后墩,如果是则直接将一组后墩和中墩加入TypeCardList2;如果中墩牌型等于后墩牌型,需要判断最大的牌面大小,如果小于后墩则满足要求;如果中墩大于后墩或没有找到中墩的普通牌型,则直接把后墩加入TypeCardList2,说明中墩只能是散牌。(TypeCardList2是存放所有情况的手牌类的列表)
关键代码如下:
for i in TypeCardList1:#第i个情况的手牌
print("尾墩:", i.lastmodul.cardList)
i.aCardList = cardList2.copy()
for item in i.lastmodul.cardList:
i.aCardList.remove(item)
print("剩余手牌:", i.aCardList)
cardList3 = getcardList3(i.aCardList) # 从小到大的二维序列
print(cardList3)
cardList4 = getcardList4(i.aCardList) # 从大到小的二维序列
print(cardList4)
Heitao = getHeitao(i.aCardList)
print("黑桃", Heitao)
Hongtao = getHongtao(i.aCardList)
print("红桃", Hongtao)
Meihua = getMeihua(i.aCardList)
print("梅花", Meihua)
Fangkuai = getFangkuai(i.aCardList)
print("方块", Fangkuai)
CardModelList2 = nomalcard(i.aCardList, cardList3, cardList4, Heitao, Hongtao, Meihua, Fangkuai)
if CardModelList2:
for j in CardModelList2: # 第i种底墩,第j种中墩的情况
if j.cardType < i.lastmodul.cardType:
typecard = TypeCard()
typecard.lastmodul = i.lastmodul
typecard.aCardList = i.aCardList.copy()
typecard.midmodul = j
for item in j.cardList:
typecard.aCardList.remove(item)
TypeCardList2.append(typecard)
elif j.cardType == i.lastmodul.cardType:
if (j.cardList[0] % 100) < (i.lastmodul.cardList[0] % 100):
typecard = TypeCard()
typecard.lastmodul = i.lastmodul
typecard.aCardList = i.aCardList.copy()
typecard.midmodul = j
for item in j.cardList:
typecard.aCardList.remove(item)
TypeCardList2.append(typecard)
else:
typecard = TypeCard()
typecard.lastmodul = i.lastmodul
typecard.aCardList = i.aCardList.copy()
TypeCardList2.append(typecard)
else:
typecard = TypeCard()
typecard.lastmodul = i.lastmodul
typecard.aCardList = i.aCardList.copy()
TypeCardList2.append(typecard)
6.性能分析与改进
(1)改进的思路
- 前端:在战绩详情界面中,可以采用和开启战局中根据card信息调取对应牌面一样的方法,将扑克牌图片显示出来,显得更直观清晰。
- 后端:程序中消耗最大的是normalcard函数,需要找出手牌中存在的所有牌型,改进思路是如果后墩存在情况太多(如同花),就先找中墩的情况,然后回过来找剩余手牌中是否有比中墩大的后墩,可降低程序的循环消耗。
(2)性能分析图和程序中消耗最大的函数
7.单元测试
(1)项目部分单元测试代码
import random
def test():
count = 0
while (1):
list = [x for x in range(52)]
cards = [414, 314, 214, 114,
413, 313, 213, 113,
412, 312, 212, 112,
411, 311, 211, 111,
410, 310, 210, 110,
409, 309, 209, 109,
408, 308, 208, 108,
407, 307, 207, 107,
406, 306, 206, 106,
405, 305, 205, 105,
404, 304, 204, 104,
403, 303, 203, 103,
402, 302, 202, 102]
numbers = random.sample(list, 13)
testcard = []
for i in numbers:
testcard.append(cards[i])
print(testcard)
cardList3 = getcardList3(testcard)
cardList4 = getcardList4(testcard)
Heitao = getHeitao(testcard)
Hongtao = getHongtao(testcard)
Meihua = getMeihua(testcard)
Fangkuai = getFangkuai(testcard)
cardmodelList = nomalcard(testcard, cardlist3, cardlist4, heitao, hongtao, meihua, fangkuai)
print(cardmodelList)
(2)测试的函数与构造测试数据的思路:
- 单元测试的函数是消耗最大的nomalcard函数,随机生成一副手牌,打印出找到的牌型,测试函数找到的普通牌型的是否正确。
8.Github的代码签入记录
雅菁(前端)
林睿(后端)
9.遇到的代码模块异常或结对困难及解决方法
(1)前端
- 问题描述:对前端的掌握度不够,再加上没有接触过网页版界面的UI制作,Javascript简直就是魔鬼啊啊啊。导致了在写函数、接口时几乎是两眼一抹黑的状态,不知道该如何从助教的接口获取数据并处理,分分钟想撞豆腐自我了结。
- 做过的尝试:当然是百度百度百度啊,大佬们分享了很多经验方法,努力看懂并学以致用;实在看不懂或者出现bug的时候就和舍友一起讨论解决(舍友都是前端)。
- 是否解决:虽然可能还有不足,但基本上满足需求了。
- 有何收获:进一步了解了Javascript,前端有所发展。
熬夜记录也破了
(2)后端
- 问题描述:一开始想当然的按照后墩、中墩、前墩的顺序,找到最大的牌型就返回,后来发现如果后墩把最大的牌型拿走了,中墩和前墩可能就剩下散牌,而最后算分数是分别按三墩赢的水数加起来的,就需要考虑所有的情况。
- 做过哪些尝试:把每一墩符合的所有情况保存在列表中最后判断三墩加起来的最大组合。
- 是否解决:顶着超时的风险解决了。
- 有何收获:逻辑思考能力+++,代码+++。
10.评价你的队友
雅菁:
- 值得学习的地方:很有耐心,脾气很好,善于沟通,做事非常认真。
- 需要改进的地方:一起努力学代码!
林睿:
- 认真细心,能发现我的一些漏洞,还有文笔好。
- 共同提升自己的代码能力。
11.学习进度表
第N周+H5F5A1:I4A1:J5A1:J6A1:I3 |
新增代码(行) |
累计代码(行) |
本周学习耗时(小时) |
累计学习耗时(小时) |
重要成长 |
1 |
0 |
0 |
12 |
12 |
基本了解了原型图的设计理念与实现方法,掌握了墨刀的基础用法 |
2 |
412 |
412 |
20 |
32 |
构思算法,实现基本框架 |
3 |
660 |
1072 |
36 |
68 |
算法改进 |
4 |
148 |
1220 |
15 |
83 |
了解接口的使用,学习了github使用规范 |