第二次结对作业
1、各种地址
2、给出具体分工
兴源做ai,我做ui和api调用。
3、psp表格
4、解题思路描述与设计实现说明
(1)网络接口的使用
思路就是把api生成的代码复制到代码上,然后有需要变量的地方(token,uid)在登陆时用正则表达式获取,有需要在ui显示出来的东西通过python自带的tkinter的label或button的text变量显示出来。
具体实现是通过python的request库来实现,下面是一个登陆的例子
url = "https://api.shisanshui.rtxux.xyz/auth/login"
headers = {
'content-type': 'application/json'
}
data = {
"username": username,
"password": password
}
dataa=str(data)
response = requests.request("POST", url, data=dataa, headers=headers)
(2)代码组织与内部实现设计(类图)
这部分是兴源实现的,文本来自兴源的博客:
(3)说明算法的关键与关键实现部分流程图
这部分是兴源实现的,文本来自兴源的博客:
- 算法的关键是进行组合和筛选
- 关键实现部分流程图
5、关键代码解释
这部分是兴源实现的,文本来自兴源的博客:
import itertools
def cmb(list0):
list1 = list0.copy()
iter1 = itertools.combinations(list1, 5)
while 1:
try:
tup0 = next(iter1)
listc = list(tup0)
list1 = list0.copy()
for i in range(5):
list1.remove(listc[i])
iter2 = itertools.combinations(list1, 5)
while 1:
try:
tup1 = next(iter2)
liste = list(tup1)
listf = list0.copy()
for i in range(5):
listf.remove(listc[i])
for i in range(5):
listf.remove(liste[i])
a = getscore(listc, 5)
b = getscore(liste, 5)
c = getscore(listf, 3)
if a > b and b > c:
listsum[1] = a + 2 * b + 3 * c
if listsum[1] > listsum[0]:
listsum[0] = listsum[1]
global lians
lians.clear()
for k in range(3):
lians.append(listf[k])
for k in range(5):
lians.append(liste[k])
for k in range(5):
lians.append(listc[k])
except StopIteration:
break
except StopIteration:
return
这段代码采用组合数的方法,即先从13张牌中随机选出5张一堆,再从剩下的8张牌中选出5张一堆,剩下3张一堆。遍历c(13,5)c(8,5)c(3,3)种所有可能的情况,再用getscore函数进行判断,选出符合规则且得分最高的组合方式。
6、性能分析与改进
这部分是兴源实现的,文本来自兴源的博客:
-
在刚开始设计AI的实现方法时,我想过使用递归的贪心算法:(1)底墩先贪心的选能够组合最大的牌型的5张牌,再递归调用自身从剩下的8张中选贪心5张最大牌型,最后剩三张。(2)然后底墩贪心选能够组合次大的牌型的5张牌,再递归调用自身从剩下的8张中选贪心5张最大牌型,最后剩三张。(3)底墩再选第三大...以此类推,直到底端是对子。(4)剩余8张选5张也类似,贪心选最大,然后次大,直到散牌。(5)最终用getscore函数给每堆打分,判断出三墩牌是否符合规则,最终分数最高的三墩牌即是要求的牌。但是这种情况下选出的牌,牌型判断变得很复杂,存在较多不确定性,对写代码实现不友好,就放弃了这种思路,改用组合数遍历所有可能的方法。即每次从13张中随机挑5张,再从剩下8张中挑5张,最后三张一堆,然后每种组合都用getscore函数给每堆打分,判断出三墩牌是否符合规则,最终分数最高的三墩牌即是要求的牌。
-
性能分析图
-
其中消耗最大的函数是组合数遍历所有可能的comb()函数(在上面关键代码处已经展示过),而消耗第二大的getscore()函数与其相差不大,因此我就展示一下getscore()函数,这个函数是用于给每一墩牌打分的。
def getscore(li, m):
listb = li.copy()
f=0
f = tonghuashun(listb)
if f > 0:
return 100 + f * 0.01
f = zhadan(listb)
if f > 0:
return 90 + f * 0.01
f = hulu(listb)
if f > 0:
return 80 + f * 0.01
f = tonghua(listb, m)
if f > 0:
return 70 + f * 0.01
f = shunzi(listb, m)
if f > 0:
return 60 + f * 0.01
f = santiao(listb)
if f > 0:
return 50 + f * 0.01
f = liandui(listb)
if f > 0:
return 40 + f * 0.01
f = liangdui(listb)
if f > 0:
return 30 + f * 0.01
f = duizi(listb, m)
if f > 0:
return 20 + f * 0.01
else:
dict1 = {}
for x in range(2, 15):
dict1[x] = 0
for r in listb:
dict1[r.num] = dict1[r.num] + 1
f = 0.1
t = 0
for i in range(14,1,-1):
if dict1[i]>0:
t =t+ i * f
f =f*0.1
return 10+t
7、单元测试
import unittest
import shisanshui
class MyTestCase(unittest.TestCase):
def test_santonghua(self):
result = shisanshui.santonghua()
self.assertEqual(result, 1)
if __name__ == '__main__':
unittest.main()
- 这是用来测试三同花的测试代码,
- 测试数据的构造思路
- 满足三同花,
- 有两个同花
- 有一个同花
- 没有同花
8、贴出GitHub的代码签入记录
9、遇到的代码模块异常或结对困难及解决方法
问题描述:在点击开始游戏按钮后,因为整个程序在while(true)循环里面,然后窗口界面就停止工作了
做过哪些尝试:在while里面增加sleep,把按钮和文本的载入放到while里面,将while循环去掉
是否解决:是
有何收获:虽然还是不知道怎么才能让他一边自己出牌一边显示,但是我用最少的时间解决了这个问题,而且题目也没说ui的这个功能要怎么设计,所以越快做完就越好啦。
10、请评价你的队友
值得学习的地方:能够独立完成当初分配的任务,不用我操心ai的部分
需要改进的地方:能做完ai我已经很满足了,硬要说改进的地方就是不要在deadline当天才完成收尾工作,能提前一两天就好了。
11、学习进度条
12、ui演示视频
https://pan.baidu.com/s/1fjkJ007D2GbNprHNU8G9_w
由于注册界面会新弹窗出来,就另外截图