1.博客與giuhub鏈接與UI視頻鏈接
(1)結對同學的博客鏈接: 點我!
(2)本作業的博客鏈接:點我!!
(3)Fork的同名倉庫的Github項目地址: 點我!!!
(4)UI視頻鏈接:點擊視頻收獲驚喜! 提取碼: tx7h
2.具體分工
對於本次結對編程作業,我和搭檔的分工如下:
- 雅菁負責前端,即全部UI的實現。
- 林睿負責后端,即全部算法的實現。
- 分別把各自的項目文件上傳到github上並Fork對方倉庫,編輯博客中各自負責的part。
3.PSP表格
PSP2.1 |
Personal Software Process Stages |
預估耗時(分鍾) |
實際耗時(分鍾) |
Planning |
計划 |
60 |
30 |
· Estimate |
· 估計這個任務需要多少時間 |
3850 |
4250 |
Development |
開發 |
3740 |
4140 |
· Analysis |
· 需求分析 (包括學習新技術) |
800 |
840 |
· Design Spec |
· 生成設計文檔 |
120 |
120 |
· Design Review |
· 設計復審 |
60 |
120 |
· Coding Standard |
· 代碼規范 (為目前的開發制定合適的規范) |
60 |
60 |
· Design |
· 具體設計 |
360 |
420 |
· Coding |
· 具體編碼 |
1920 |
2100 |
· Code Review |
· 代碼復審 |
300 |
300 |
· Test |
· 測試(自我測試,修改代碼,提交修改) |
120 |
180 |
Reporting |
報告 |
110 |
150 |
· Test Report |
· 測試報告 |
60 |
60 |
· Size Measurement |
· 計算工作量 |
20 |
30 |
· Postmortem & Process Improvement Plan |
· 事后總結, 並提出過程改進計划 |
30 |
60 |
|
· 合計 |
3910 |
4320 |
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周 |
新增代碼(行) |
累計代碼(行) |
本周學習耗時(小時) |
累計學習耗時(小時) |
重要成長 |
1 |
0 |
0 |
12 |
12 |
基本了解了原型圖的設計理念與實現方法,掌握了墨刀的基礎用法 |
2 |
438 |
438 |
12 |
22 |
基本掌握html和css,開始編寫基本界面 |
3 |
545 |
983 |
18 |
40 |
基本了解Javascript,了解接口如何使用 |
4 |
762 |
1745 |
35 |
75 |
深入了解JS和接口的使用,完善所有界面的需求 |