结对同学博客链接
本博客链接
github地址
UI视频链接
1. 具体分工
西西西瓜萌:UI设计、前端实现、初版算法的实现、博客撰写
雨霖铃0000:提供算法思路、改进算法的实现、算法分析测试、博客撰写
2. PSP表格
PSP2.1 | Personal Software Process Stages | 预估耗时(分钟) | 实际耗时(分钟) |
---|---|---|---|
Planning | 计划 | 20 | 15 |
Estimate | 估计这个任务需要多少时间 | 10 | 5 |
Development | 开发 | 120 | 150 |
Analysis | 需求分析 (包括学习新技术) | 180 | 150 |
Design Spec | 生成设计文档 | 60 | 50 |
Design Review | 设计复审 | 120 | 150 |
Coding Standard | 代码规范 (为目前的开发制定合适的规范) | 120 | 100 |
Design | 具体设计 | 150 | 300 |
Coding | 具体编码 | 1380 | 1060 |
Code Review | 代码复审 | 240 | 200 |
Test | 测试(自我测试,修改代码,提交修改) | 1000 | 1500 |
Reporting | 报告 | 0 | 0 |
Test Repor | 测试报告 | 60 | 50 |
Size Measurement | 计算工作量 | 20 | 20 |
Postmortem & Process Improvement Plan | 事后总结, 并提出过程改进计划 | 40 | 30 |
合计 | 3520 | 3780 |
3. 解题思路与设计实现
- 解题思路
首先,通过接口进行注册登录获取token,战局开始后取得13张扑克,通过遍历的方式找出最大的牌型,并赋予其特定的分值,当牌型一样时,分值更大的那一种排法优先,赋牌顺序为后墩、中墩、前墩。 - 网络接口的使用
- 注册
- AI
- 注册
url = "https://api.shisanshui.rtxux.xyz/auth/register"
payload = "{"username":"un","password":"pw"}"
headers = {'content-type': 'application/json'}
response = requests.request("POST", url, data=payload, headers=headers)
print(response.text)
- UI
url: "https://api.shisanshui.rtxux.xyz/auth/register",
method: "POST",
header: {
'Content-Type': 'application/json'
},
data: JSON.stringify({
"username": this.data.username,
"password": this.data.password
}),
- 登陆
- AI
url = "https://api.shisanshui.rtxux.xyz/auth/login"
payload = "{"username":"un","password":"pw"}"
headers = {'content-type': 'application/json'}
response = requests.request("POST", url, data=payload, headers=headers)
print(response.text)
- UI
url: "https://api.shisanshui.rtxux.xyz/auth/login",
method: "POST",
header: {
'Content-Type': 'application/json'
},
data: JSON.stringify({
"username": this.data.username,
"password": this.data.password
}),
- 开启战局
- AI
url = "https://api.shisanshui.rtxux.xyz/game/open"
headers = {'x-auth-token': tkk}
response = requests.request("POST", url, headers=headers)
print(response.text)
- UI
url: "https://api.shisanshui.rtxux.xyz/game/open",
method: "POST",
header: {
'X-Auth-Token': app.globalData.token
},
- 出牌
- AI
url = "https://api.shisanshui.rtxux.xyz/game/submit"
payload = "{"id":" + idd + ","card":["" + qian +"",""+ zhong +"",""+ hou +""]}"
print(payload)
headers = {
'content-type': "application/json",
'x-auth-token': tkk
}
response = requests.request("POST", url, data=payload, headers=headers)
print(response.text)
- 历史战局详情
- UI
url: "https://api.shisanshui.rtxux.xyz/history",
data: {
"player_id": this.data.id,
"limit": this.data.n1,
"page": this.data.n2
},
method: "GET",
header: {
'content-type': 'application/json',
'X-Auth-Token': app.globalData.token
},
- 历史战局列表
- UI
url: 'https://api.shisanshui.rtxux.xyz/history/'+this.data.id,
data: {
"id": this.data.id,
},
method: "GET",
header: {
'content-type': 'application/json',
'X-Auth-Token': app.globalData.token
},
- 排行榜
- UI
url: "https://api.shisanshui.rtxux.xyz/rank",
method: "GET",
-
代码组织与内部实现设计(类图)
-
说明算法的关键与关键实现部分流程图
按照牌型大小顺序来判断出牌
4. 关键代码解释
就拿取出后墩的函数third()来说
def third():
global score
init_cnt()
bubble_sort(ans_1, 1, 5)
x = 1
for i in range(1, 6):
hua[ans_1[i].flower] = hua[ans_1[i].flower] + 1
number[ans_1[i].num] = number[ans_1[i].num] + 1
x = 1
for i in range(1, 6):
if hua[i] == 5:
if ShunZi5(ans_1[1].num) == 1:
k = (9.0 + 0.9 / 9 * (ans_1[1].num - 1)) * 1.0 # 14 13 12 11 10
score += k
return k # 同花顺
x = 1
for i in range(5, 0, -1):
if number[ans_1[i].num] == 4:
x = ans_1[i].num
if number[ans_1[i].num] == 4:
k = (8.0 + 0.9 / (130 + 13) * ((ans_1[i].num - 1) * 10)) * 1.0
score += k
return k # 炸弹
x = 1
for i in range(5, 0, -1):
if number[ans_1[i].num] == 3:
x = ans_1[i].num
for j in range(5, 0, -1):
if number[ans_1[j].num] == 2:
k = (7.0 + 0.9 / (130 + 13) * ((x - 1) * 10 + ans_1[j].num - 1)) * 1.0
score += k
return k # 葫芦
x = 1
for i in range(1, 6):
if hua[i] == 5:
k = (6.0 + 0.9 / (130000 + 13000 + 1300 + 130 + 13) * (
(ans_1[5].num - 1) * 10000 + (ans_1[4].num - 1) * 1000 + (ans_1[3].num - 1) * 100 + (
ans_1[2].num - 1) * 10 + (ans_1[1].num - 1))) * 1.0
score += k
return k # 同花
x = 1
if ShunZi5(ans_1[1].num) == 1:
k = (5.0 + 0.9 / 9 * (ans_1[1].num - 1) * 1.0)
score += k
return k # 5张顺子
x = 1
for i in range(5, 0, -1):
if number[ans_1[i].num] == 3:
x = ans_1[i].num
for j in range(5, 0, -1):
if number[ans_1[j].num] == 1:
k = (4.0 + 0.9 / (1300 + 130 + 13) * ((x - 1) * 100))
score += k
return k # 三条
x = 1
for i in range(5, 0, -1):
if number[ans_1[i].num] == 2:
for j in range(5, 0, -1):
if (ans_1[i].num != ans_1[j].num) and
number[ans_1[j].num] == 2 and abs(ans_1[i].num - ans_1[j].num) == 1:
k = (3.0 + 0.9 / 10 * (ans_1[j].num - 1 - 1)) * 1.0
score += k
return k # 连对2对
x = 1
for i in range(5, 0, -1):
if number[ans_1[i].num] == 2:
for j in range(5, 0, -1):
if (ans_1[i].num != ans_1[j].num) and number[ans_1[j].num] == 2:
k = (2.0 + 0.9 / (130 + 13) * ((ans_1[i].num - 1) * 10 + ans_1[j].num - 1)) * 1.0
score += k
return k # 普通2对
x = 1
for i in range(5, 0, -1):
if number[ans_1[i].num] == 1:
x = ans_1[i].num
if number[ans_1[i].num] == 2:
k = (1.0 + 0.9 / (130 + 13) * ((ans_1[i].num - 1) * 10 + x - 1)) * 1.0
score += k
return k # 单对+3张散
k = (0.9 / (130000 + 13000 + 1300 + 130 + 13) * (
(ans_1[5].num - 1) * 10000 + (ans_1[4].num - 1) * 1000 + (ans_1[3].num - 1) * 100 + (
ans_1[2].num - 1) * 10 + ans_1[1].num - 1)) * 1.0
score += k
return k
先将未使用过的牌进行排序,在排好的序列中循环依次判断有无同花顺、 炸弹 、葫芦、 同花、顺子、三条、二对连对、普通二对、一对、散牌的牌型,牌型从大到小为:同花顺 > 炸弹 > 葫芦 > 同花 > 顺子 > 三条 > 二对连对 > 普通二对 > 一对 > 散牌,k为此牌型得到的分值,牌的大小越大,k值越大,从而得到最优的后墩牌型。
5. 性能分析与改进
-
展示性能分析图
-
程序中消耗最大的函数
由profile分析图可以看出消耗最大的函数是排序函数bubble_sort(),用于提取中墩和后墩的second()和third()中用到了冒泡排序函数,并且要在全局进行循环遍历,所以消耗也比较大。 -
改进的思路
将second()和third()两个函数中不必要的循环用if加以判断,减少排序消耗。
6. 单元测试
- 使用python的unittest模块,构建专门的单元测试类,进行部分单元测试代码
import unittest
from 13water import Card
from 13water import bubble_sort
import 13water
class Testbubble(unittest.TestCase):
def setUp(self):
pass
def tearDown(self):
pass
poker_1 = [Card(0, 0) for i in range(14)]
poker_1[1] = Card(2, 2)
poker_1[2] = Card(3, 2)
poker_1[3] = Card(4, 2)
poker_1[4] = Card(1, 3)
poker_1[5] = Card(1, 4)
poker_1[6] = Card(4, 5)
poker_1[7] = Card(1, 6)
poker_1[8] = Card(1, 7)
poker_1[9] = Card(2, 9)
poker_1[10] = Card(3, 8)
poker_1[11] = Card(4, 4)
poker_1[12] = Card(4, 8)
poker_1[13] = Card(3, 5)
bubble_sort(poker_1,1,14)
for i in range(1,14):
print(poker_1[i].num,end=" ")
if __name__ == "__main__":
unittest.main()
-
测试的函数
排序函数bubble_sort() -
构造测试数据的思路
给出13张可能遇到的牌,令bubble_sort()将其排序,只有排序正确后面才能进行正确的牌型比较。
7. Github的代码签入记录
8. 遇到的代码模块异常或结对困难及解决方法
-
遇到的代码模块异常
-
问题描述
一开始算法赋予牌型的分值和牌本身大小并无联系,导致中墩和后墩出现同种牌型时(比如都是葫芦),有可能出现中墩比后墩大的情况即“相公”。 -
做过哪些尝试
改进了分值计算的算法,使分值计算和牌面大小有关,并加入和中墩和后墩大小的比较,若中墩分值大于后墩,则中墩和后墩交换。 -
是否解决
是。 -
有何收获
在考虑墩的大小比较时要考虑全面,不仅要考虑牌型不同时的情况,也要考虑相同牌型的情况。
-
-
结对困难及解决方法
-
问题描述
一开始两人都没有非常擅长的领域,所以在UI和AI的任务分配时我们不知道怎么协调。 -
做过哪些尝试
两人都尝试着去学习和制做AI和UI部分,各取自己擅长或感兴趣的部分。 -
是否解决
是。 -
有何收获
分工搭配,干活不累!
-
9. 评价你的队友
-
值得学习的地方
基础比较好,各方面知识涉猎的都比较多一些。认真刻苦,也更善于请求他人的帮助。
-
需要改进的地方
要注意身体,熬夜到五点,七点又起来上课真的厉害了,但是对头发不好啊。
10. 学习进度条
第N周 | 新增代码(行) | 累计代码(行) | 本周学习耗时(小时) | 累积学习耗时(小时) | 重要成长 |
---|---|---|---|---|---|
1 | 99 | 99 | 18 | 18 | 熟悉Axure RP用法,了解Java的trycatch语句 |
2 | 524 | 623 | 20 | 38 | 了解wx.javascript,写了一部分前端的框架 |
3 | 1072 | 1695 | 20 | 58 | 完成UI制作和算法逻辑 |
4 | 553 | 2248 | 28 | 86 | 实现接口和部分bug的修复 |
11.心得体会
奶茶一喝,把夜熬起来,死都做不出来的最后也都能做出来的。(再次开始考虑转行了)