python初體驗 ——>>> 模擬體育競技 一、排球訓練營 1. 簡介: 模擬不同的兩個隊伍進行排球的模擬比賽。 2. 模擬原理: 通過輸入各自的能力值(Ⅰ),模擬比賽的進行( P ),最後輸出模擬的結果( O )。 P 簡介:通過產生隨機數得到每局比賽的難度,若小於能力值則表示贏得本局比賽,反之 ...
python初體驗 ——>>> 模擬體育競技
一、排球訓練營
1. 簡介: 模擬不同的兩個隊伍進行排球的模擬比賽。
2. 模擬原理: 通過輸入各自的能力值(Ⅰ),模擬比賽的進行( P ),最後輸出模擬的結果( O )。
P 簡介:通過產生隨機數得到每局比賽的難度,若小於能力值則表示贏得本局比賽,反之輸掉本局比賽。
3. 規則簡介:
① 每場比賽採用 5局3勝制。
② 前四局採用25分制,每個隊只有在贏得至少25分,且同時超過對方2分時才勝一局。
③ 決勝局(第五局)採用15分制,先獲得15分,且同時超過對方2分為勝。
4. 準備就緒,就差代碼來實現了
插入代碼之前,先對代碼做個簡單的介紹:
函數名稱 | 函數說明 |
printInfo() | 列印程式的介紹信息 |
getInputs() | 獲得用戶輸入的參數 |
printResult(n, winsA, winsB) | 輸出模擬比賽的結果 |
simNGames(n, probA, probB) | 模擬n場比賽 |
simOneGame(probA, probB) | 模擬一場比賽,包括五局,採取五局三勝制 |
simAGame(N, probA, probB) | 模擬一局比賽 |
GameOver(N, scoreA, scoreB) | 定義一局比賽的結束條件 |
好了,看看代碼吧,雖然有點長,但應該可以看懂 ^_^
1 # -*- encoding:utf-8 -*- 2 ''' 3 模擬排球競技 4 @author: bpf 5 ''' 6 # 比賽規則: 7 # 1. 採用5局3勝制 8 # 2. 前四局採用25分制,每個隊只有在贏得至少25分,且同時超過對方2分時才勝一局 9 # 3. 決勝局(第五局)採用15分制,先獲得15分,且同時超過對方2分為勝 10 11 from random import random 12 from time import time 13 def printInfo(): 14 ''' 15 function: 列印程式的介紹信息 16 ''' 17 print("{:*^70}".format("產品簡介")) 18 print("產品名稱: 排球競技模擬分析器") 19 print("產品概述: 通過輸入2個隊伍A和B的能力值(0到1之間的小數表示),能夠模擬多次2個隊伍A和B的排球競技比賽,從而得出各自的勝率!") 20 print("產品作者: 步平凡 - 04") 21 print("{:*^70}".format("模擬開始")) 22 23 def getInputs(): 24 ''' 25 function: 獲得用戶輸入的參數 26 ''' 27 probA = eval(input("請輸入隊伍A的能力值(0~1):")) 28 probB = eval(input("請輸入隊伍B的能力值(0~1):")) 29 n = eval(input("請輸入需要模擬比賽的場次數:")) 30 return probA, probB, n 31 32 def printResult(n, winsA, winsB): 33 ''' 34 function: 輸出模擬比賽的結果 35 ''' 36 print("{:*^70}".format("模擬結束")) 37 print("競技分析開始,共模擬{}場比賽。".format(n)) 38 print(">>>隊伍A獲勝{}場比賽,占比{:0.1%}".format(winsA,winsA/n)) 39 print(">>>隊伍B獲勝{}場比賽,占比{:0.1%}".format(winsB,winsB/n)) 40 41 def simNGames(n, probA, probB): 42 ''' 43 function: 模擬n場比賽 44 n: 模擬n場比賽 45 probA, probB: 分別為隊伍A和B的能力值 46 winA, winB: 隊伍A和B在一場比賽中獲勝的局數 47 winsA, winsB: 隊伍A和B贏得比賽的場數,總共n場 48 ''' 49 winsA, winsB = 0, 0 50 for _ in range(n): 51 winA, winB = simOneGame(probA, probB) 52 if winA > winB: 53 winsA += 1 54 else: 55 winsB += 1 56 return winsA, winsB 57 58 def simOneGame(probA, probB): 59 ''' 60 function: 模擬一場比賽,包括五局,採取五局三勝制 61 probA, probB: 分別為隊伍A和B的能力值 62 return: 返回隊伍A和B在本場比賽中獲勝的局數 63 scoreA, scoreB: 分別為隊伍A和B一局比賽獲得的分數 64 winA, winB: 分別為隊伍A和B一場比賽獲勝的局數 65 N: 代表本次比賽的局次 66 ''' 67 winA, winB = 0, 0 68 for N in range(5): 69 scoreA, scoreB = simAGame(N, probA, probB) 70 if scoreA > scoreB: 71 winA += 1 72 else: 73 winB += 1 74 if winA == 3 or winB == 3: 75 break 76 return winA, winB 77 78 def simAGame(N, probA, probB): 79 ''' 80 function: 模擬一局比賽 81 N: 代表本次比賽的局次 82 probA, probB: 分別為隊伍A和B的能力值 83 return: 返回隊伍A和B在本局比賽中獲得的分數 84 ''' 85 scoreA, scoreB = 0, 0 # 分別為隊伍A和B一局比賽獲得的分數 86 serving = 'A' # 發球方 87 while not GameOver(N, scoreA, scoreB): 88 if serving == 'A': 89 if random() > probA: 90 scoreB += 1 91 serving = 'B' 92 else: 93 scoreA += 1 94 else: 95 if random() > probB: 96 scoreA += 1 97 serving = 'A' 98 else: 99 scoreB += 1 100 return scoreA, scoreB 101 102 def GameOver(N, scoreA, scoreB): 103 ''' 104 function: 定義一局比賽的結束條件 105 N: 代表當前局次(第五局為決勝局) 106 return: 若比賽結束的條件成立返回真,否則為假 107 ''' 108 if N <= 4: 109 return (scoreA>=25 and scoreB>=25 and abs(scoreA-scoreB)>=2) 110 else: 111 return (scoreA>=15 and abs(scoreA-scoreB)>=2) or (scoreB>=15 and abs(scoreA-scoreB)>=2) 112 113 if __name__ == "__main__": 114 printInfo() 115 probA, probB, n = getInputs() 116 Time = time() 117 winsA, winsB = simNGames(n, probA, probB) 118 print("模擬用時: {:.1f}s".format(time()-Time)) 119 printResult(n, winsA, winsB)
5. 運行結果展示,為了查看方便,我在cmd中運行代碼
二、足球訓練基地
1. 簡介: 模擬不同的兩個隊伍進行足球的模擬比賽。
2. 模擬原理: 通過輸入各自的能力值(Ⅰ),模擬比賽的進行( P ),最後輸出模擬的結果( O )。
P 簡介:通過產生隨機數得到半場比賽的回合數,再通過產生隨機數得到每回合比賽的難度,若小於能力值則表示贏得本局比賽,反之輸掉本場比賽。
3. 規則簡介:
① 比賽分為兩半場,每場為45分鐘。
上半場: 一方挑選進攻的球門,另一方獲得開球權;
下半場: 互換攻守方向,上半場沒獲得開球權的一方獲得開球權。
②在進球後開球時,開球方為失球一方。
③ 比賽結束時得分多的球隊獲勝,如果兩隊得分相同或均未得分,比賽為平局。
4. 代碼實現
By the way, 此代碼與上述主要不同之處在於: GameOver(),其他函數都類似
函數名稱 | 函數說明 |
printInfo() | 列印程式的介紹信息 |
getInputs() | 獲得用戶輸入的參數 |
printResult(n, winsA, winsB) | 輸出模擬比賽的結果 |
simNGames(n, probA, probB) | 模擬n場比賽 |
simOneGame(probA, probB) | 模擬一場比賽,包括上半場和下半場 |
simAGame(N, probA, probB) | 模擬半場比賽 |
GameOver(N, scoreA, scoreB) | 定義半場比賽的結束條件 |
1 # -*- encoding:utf-8 -*- 2 ''' 3 模擬足球競技 4 @author: bpf 5 ''' 6 # 比賽規則: 7 # 1. 比賽分為兩場,每場為45分鐘 8 # 上半場: 一方挑選進攻的球門,另一方獲得開球權 9 # 下半場: 互換攻守方向,上半場沒獲得開球權的一方獲得開球權 10 # 2. 在進球後開球時,開球方為失球一方 11 # 3. 在沒有違反任何比賽規則時,進攻球隊得分。 12 # 4. 比賽結束時得分多的球隊獲勝,如果兩隊得分相同或均未得分,比賽為平局。 13 14 from random import random, randint 15 from time import time 16 def printInfo(): 17 ''' 18 function: 列印程式的介紹信息 19 ''' 20 print("{:*^70}".format("產品簡介")) 21 print("產品名稱: 足球競技模擬分析器") 22 print("產品概述: 通過輸入2個隊伍A和B的能力值(0到1之間的小數表示),能夠模擬多次2個隊伍A和B的排球競技比賽,從而得出各自的勝率!") 23 print("產品作者: 步平凡 - 04") 24 print("{:*^70}".format("模擬開始")) 25 26 def getInputs(): 27 ''' 28 function: 獲得用戶輸入的參數 29 ''' 30 probA = eval(input("請輸入隊伍A的能力值(0~1):")) 31 probB = eval(input("請輸入隊伍B的能力值(0~1):")) 32 n = eval(input("請輸入需要模擬比賽的場次數:")) 33 return probA, probB, n 34 35 def printResult(n, via, winsA, winsB): 36 ''' 37 function: 輸出模擬比賽的結果 38 ''' 39 print("{:*^70}".format("模擬結束")) 40 print("競技分析開始,共模擬{}場比賽。".format(n)) 41 print(">>>隊伍A獲勝{}場比賽,占比{:0.1%}".format(winsA,winsA/n)) 42 print(">>>隊伍B獲勝{}場比賽,占比{:0.1%}".format(winsB,winsB/n)) 43 print(">>>兩隊平局{}場,占比{:0.1%}".format(via,via/n)) 44 45 def simNGames(n, probA, probB): 46 ''' 47 function: 模擬n場比賽 48 n: 模擬n場比賽 49 probA, probB: 分別為隊伍A和B的能力值 50 winsA, winsB: 隊伍A和B贏得比賽的場數,總共n場 51 ''' 52 via, winsA, winsB = 0, 0, 0 53 for _ in range(n): 54 scoreA, scoreB = simOneGame(probA, probB) 55 if scoreA == scoreB: 56 via += 1 57 elif scoreA > scoreB: 58 winsA += 1 59 else: 60 winsB += 1 61 return via, winsA, winsB 62 63 def simOneGame(probA, probB): 64 ''' 65 function: 模擬一場比賽, 分上半場和下半場 66 probA, probB: 分別為隊伍A和B的能力值 67 scoreA, scoreB: 分別為隊伍A和B一場比賽的分數 68 return: 返回隊伍A和B在本場比賽中獲得的分數 69 ''' 70 winA, winB = 0, 0 71 for N in range(2): 72 scoreA, scoreB = simAGame(N, probA, probB) 73 winA += scoreA 74 winB += scoreB 75 return winA, winB 76 77 def simAGame(N, probA, probB): 78 ''' 79 function: 模擬半場比賽 80 probA, probB: 分別為隊伍A和B的能力值 81 scoreA, scoreB: 分別為隊伍A和B半場比賽的分數 82 return: 返回隊伍A和B在本半場比賽中獲得的分數 83 ''' 84 scoreA, scoreB = 0, 0 85 if N == 0: 86 serving = 'A' # 發球方 87 else: 88 serving = 'B' 89 for _ in range(gameOver()): 90 if serving == 'A': 91 if random() < probA: 92 scoreA += 1 93 serving = 'B' 94 else: 95 if random() < probB: 96 scoreB += 1 97 serving = 'A' 98 return scoreA, scoreB 99 100 def gameOver(): 101 ''' 102 function: 定義半場比賽的結束條件 103 通過randint產生一個隨機數作為半場比賽的回合數, 若達到半場比賽的回合數則結束比賽 104 return: 若比賽結束的條件成立返回真,否則為假 105 ''' 106 return randint(3, 10) 107 108 if __name__ == "__main__": 109 printInfo() 110 probA, probB, n = getInputs() 111 Time = time() 112 via, winsA, winsB = simNGames(n, probA, probB) 113 print("模擬用時: {:.1f}s".format(time()-Time)) 114 printResult(n, via, winsA, winsB)
5. 運行結果展示,為了查看方便,我仍在cmd中運行代碼
三、晉級模擬
1. 簡介: 前2次分別對於排球和足球的模擬比賽分析,比賽規則的差距 體現 在代碼上的不同,所以本次模擬分析多支隊伍進行乒乓球比賽。
2. 模擬原理: 通過輸入各自的能力值(Ⅰ),模擬比賽的進行( P ),最後輸出模擬的結果( O )。
P 簡介:通過產生隨機數得到每局比賽的難度,若小於能力值則表示贏得本局比賽,反之輸掉本局比賽。當有多個隊伍時,採取兩兩配對,但只遍歷一次,因此,本代碼功能不完善,僅供參考。
3. 規則簡介:
① 每場比賽採用回合制。
② 一名球員在一個回合中未能合法擊打時,回合結束。本回合勝方得一分、得球權。
③ 先得15分贏得一場比賽。
4. 代碼實現
本次代碼與上述不同,本次採用類的方法來實現,不過基於本人對於乒乓球不熟悉及python用法有限,本次代碼的功能有所限制,只能模擬數量為偶數的隊伍進行比賽。待技術提升,會對代碼進行改善和加強。
1 # -*- encoding:utf-8 -*- 2 ''' 3 模擬乒乓球競技 4 @author: bpf 5 ''' 6 # 比賽規則: 7 # 1. 一場比賽: 單打:採用七局四勝制 8 # 雙打淘汰賽、團體賽:採用五局三勝制 9 # 2. 一局比賽: 先得11分為勝,10平後,多得2分為勝 10 # 3. 一局比賽: 每隊發球2次後,接發球方即成為發球方,依此類推,直至該局比賽結束 11 # 或者到雙方比分都達到10分或實行輪換髮球法時,發球和接發次序仍然不變,但每人只輪發一分球 12 13 from random import random 14 from pandas import DataFrame 15 from time import time 16 class SportCompetitionAnalyze: 17 18 def PrintInfo(self): 19 ''' 20 function: 列印程式的介紹信息 21 ''' 22 print("{:*^70}".format("產品簡介")) 23 print("產品名稱: 乒乓球競技模擬分析器(採取單打淘汰賽制)") 24 print("產品概述: 通過輸入多個隊伍的能力值(0到1之間的小數表示),能夠模擬多次多個隊伍的乒乓球競技比賽,從而得出各自的勝率!") 25 print("產品作者: 步平凡 - 04") 26 print("{:*^70}".format("模擬開始")) 27 28 def GetInputs_for_Singal(self): 29 ''' 30 function: 獲得用戶輸入的參數 獲得單打各隊員的能力值 31 ''' 32 self.n = eval(input("請輸入需要模擬比賽的場數:")) 33 self.probAbilityList_Original = list(map(eval, input("(註:通過輸入的次序進行兩兩配對, 即前兩個分別為隊員A和B;以此類推。)\n\ 34 請輸入各隊員的能力值(0~1), 請用英文逗號隔開(輸入個數為2的倍數): ").split(','))) 35 self.probAbilityList = self.probAbilityList_Original 36 self.probNum = len(self.probAbilityList) 37 38 def GetInputs_for_Double(self): 39 ''' 40 function: 獲得用戶輸入的參數 獲得雙打各隊伍各隊員的能力值 41 probAbilityList: 使用各隊伍中兩隊員的平均能力值作為該隊伍的能力值 --- 雙打 42 probAbilityList_Original: 存儲原生的各隊員能力值, 後續可用 43 ''' 44 self.probAbilityList, self.probAbilityList_Original = [], [] 45 self.n = eval(input("請輸入需要模擬比賽的場數:")) 46 Original = list(map(eval, input("(註:通過輸入的次序進行四四配對, 即前四個為隊伍A和B;以此類推。)\n\ 47 請輸入各隊員的能力值(0~1), 請用英文逗號隔開(輸入個數為4的倍數): ").split(','))) 48 for i in range(0, len(Original), 2): 49 self.probAbilityList.append((Original[i] + Original[i+1])/2) 50 self.probAbilityList_Original.append(list([Original[i], Original[i+1]])) 51 self.probNum = len(self.probAbilityList) 52 53 def PrintResult(self): 54 ''' 55 function: 輸出模擬比賽的結果 56 data: 存儲每支的比賽信息 57 ''' 58 print("{:*^70}".format("模擬結束")) 59 print("競技分析結束,每組共模擬{}場比賽。".format(self.n)) 60 data = [] 61 for i in range(self.probNum): 62 tmplist = [] 63 tmplist.append(self.probAbilityList_Original[i]) # 存儲能力值 64 tmplist.append(self.probwinsList[i]) # 存儲獲勝的場數 65 tmplist.append(self.probwinsList[i]/self.n) # 存儲勝率 66 data.append(tmplist) 67 dataSheet = DataFrame(data , index=list(range(1, self.probNum+1)), columns=list(["Ability", "wins", "rate"])) 68 #dataSheet.sort_values(by="wins", inplace=True) # 對比賽勝率rate進行排序, 會混亂比賽隊伍的關係, 因此不採用 69 print(dataSheet) 70 71 def simNGames(self, GAMES, WINS): 72 ''' 73 function: 模擬n場比賽 74 probwinsList: 存儲每支隊伍贏得比賽的場數 的列表 75 winA, winB: 隊伍A和B在一場比賽中獲勝的局數 76 winsA, winsB: 隊伍A和B贏得比賽的場數,總共n場 77 ''' 78 self.probwinsList = [] 79 for i in range(0, self.probNum, 2): 80 print("隊員:", i+1, 'VS' ,i+2, "比賽中...") 81 winsA, winsB = 0, 0 82 for _ in range(self.n): 83 winA, winB = self.simOneGame(self.probAbilityList[i], self.probAbilityList[i+1], GAMES, WINS) 84 if winA > winB: 85 winsA += 1 86 else: 87 winsB += 1 88 self.probwinsList.append(winsA) 89 self.probwinsList.append(winsB) 90 91 def simOneGame(self, probA, probB, GAMES, WINS): 92 ''' 93 function: 模擬一場比賽 》》》 GAMES局 WINS勝 94 單打比賽,包括七局,採取七局四勝制 95 雙打比賽,包括五局,採取五局三勝制 96 scoreA, scoreB: 分別為隊伍A和B一局比賽的分數 97 winA, winB: 分別為隊伍A和B一場比賽贏的局數 98 return: 返回雙方贏的局數 99 ''' 100 winA, winB = 0, 0 101 for _ in range(GAMES): 102 scoreA, scoreB = self.simAGame(probA, probB) 103 if scoreA > scoreB: 104 winA += 1 105 else: 106 winB += 1 107 if winA >=WINS or winB >= WINS: 108 break 109 return winA, winB 110 111 def simAGame(self, probA, probB): 112 ''' 113 function: 模擬一局比賽 114 probA, probB: 分別為隊伍A和B的能力值 115 return: 返回隊伍A和B在本局比賽中獲得的分數 116 ''' 117 scoreA, scoreB = 0, 0 118 serving = 'A' # 發球方 119 servingNum = 2 # 每方的發球次數 120 while not self.GameOver(scoreA, scoreB): 121 if scoreA >= 10 and scoreB >= 10: 122 servingNum = 1 123 for _ in range(servingNum): 124 if random() > probA: 125 scoreB += 1 126 else: 127 scoreA += 1 128 serving = 'B' 129 for _ in range(servingNum): 130 if random() > probB: 131 scoreA += 1 132 else: 133 scoreB += 1 134 serving = 'A' 135 return scoreA, scoreB 136 137 def GameOver(self, scoreA, scoreB): 138 ''' 139 function: 定義贏得一局的條件: 先得11分為勝,10平後,多得2分為勝 140 ''' 141 if scoreA >= 11 or scoreB >= 11: 142 return (abs(scoreA-scoreB)>=2) 143 elif (scoreA == 10 and scoreB > 11) or (scoreB == 10 and scoreA > 11): 144 return (abs(scoreA-scoreB)>=2) 145 else: 146 return 0 147 148 def print_MENU(): 149 print("程式簡介:模擬乒乓球競技") 150 print("程式功能:\n\t1. 模擬多隊員進行單打比賽\n\t2. 模擬多隊伍多隊員進行雙打比賽