今天我來學習如何經過python設計出一個用於預測比賽結果的代碼python
在預測結果以前,咱們須要進行周全的賽前分析,對於比賽中的各類做用因素進行有效分析dom
例如參賽選手的能力值,賽制規則等,這些都是做爲比賽的變量會左右比賽的結果,咱們經過自頂向下,從簡到難的方式進行一步步地分解,設計學習
下面是經過分析乒乓球比賽所設計出的代碼:spa
from random import random def printIntro(): print("這個程序模擬兩個選手A和B的某種比賽") print("程序運行須要A和B的能力值(0到1之間)") def getInputs(): a=eval(input("請輸入選手A的能力值(0-1):")) b=eval(input("請輸入選手B的能力值(0-1):")) n=eval(input("模擬比賽的場次:")) return a,b,n def simNGames(n,probA,probB): winsA,winsB=0,0 for i in range(n): scoreA,scoreB=simOneGame(probA,probB) if scoreA>scoreB: winsA+=1 else: winsB+=1 return winsA,winsB def gameOver(a,b): return a==11 or b==11 def simOneGame(probA,probB): scoreA,scoreB = 0,0 serving = 'A' while not gameOver(scoreA,scoreB): if serving == 'A': if random()<probA: scoreA+=1 else: serving='B' else: if random()<probB: scoreB+=1 else: serving='A' return scoreA,scoreB def printSummary(winsA,winsB): n=winsA+winsB print("競技分析開始,共模擬{}場比賽".format(n)) print("選手A獲勝{}場比賽,佔比{:.1%}".format(winsA,winsA/n)) print("選手B獲勝{}場比賽,佔比{:.1%}".format(winsB,winsB/n)) def main(): printIntro() probA,probB,n = getInputs() winsA,winsB = simNGames(n,probA,probB) printSummary(winsA,winsB) main()
根據以上的代碼咱們整理一下思路,這是一段經過「頂層設計」編寫出來的代碼,經過一些封裝,咱們對不一樣的動做進行解釋設計
咱們瞭解到一局乒乓球比賽的規則是,發球方發球,進行「兩球制」發球,即兩人固定輪流連續開兩球,不論勝負,誰分數先到達11分即勝利3d
因爲還有考慮最後平手時加球的狀況,但上述代碼暫不考慮,因此咱們來看看代碼的運算效果:code
輸入兩個選手的能力值,我設置爲各0.5,但結果雖較接近但仍是有些許差距,排除random()的偏差,咱們知道這是比較符合現實的一種狀況!orm
咱們再試試能力值有細微差距的狀況:blog
wow!看來僅僅只是一點點的實力差距就會有天壤之別的比賽結果……get
咱們再深刻分析,加入更多的因素,咱們知道乒乓球的賽制時單打七局四勝制,雙打則是五局三勝制,因此咱們先用如下代碼預測單打狀況:
from random import random def printIntro(): print("這個程序模擬兩個選手A和B的某種比賽") print("程序運行須要A和B的能力值(0到1之間)") def getInputs(): a=eval(input("請輸入選手A的能力值(0-1):")) b=eval(input("請輸入選手B的能力值(0-1):")) return a,b def simNGames(probA,probB): winsA,winsB=0,0 for i in range(7): scoreA,scoreB=simOneGame(probA,probB) if scoreA>scoreB: winsA+=1 if winsA==4: break else: winsB+=1 if winsB==4: break return winsA,winsB def gameOver(a,b): return a==11 or b==11 def simOneGame(probA,probB): scoreA,scoreB = 0,0 serving = 'A' while not gameOver(scoreA,scoreB): if serving == 'A': if random()<probA: scoreA+=1 else: serving='B' else: if random()<probB: scoreB+=1 else: serving='A' return scoreA,scoreB def printSummary(winsA,winsB): n=winsA+winsB print("競技分析開始,共模擬{}場比賽".format(n)) print("選手A獲勝{}場比賽,佔比{:.1%}".format(winsA,winsA/n)) print("選手B獲勝{}場比賽,佔比{:.1%}".format(winsB,winsB/n)) def main(): printIntro() probA,probB = getInputs() winsA,winsB = simNGames(probA,probB) printSummary(winsA,winsB) main()
咱們再試試結果:
咱們看到,A選手最終以4-2擊敗B選手,即便他們能力幾乎至關,也許他當下更有手感吧~
接下來是雙打時,咱們將剛剛的A/B選手抽象爲A/B隊伍,能力值爲隊伍的平均能力值。
from random import random def printIntro(): print("這個程序模擬兩個選手A和B的某種比賽") print("程序運行須要A和B的能力值(0到1之間)") def getInputs(): a=eval(input("請輸入選手A的能力值(0-1):")) b=eval(input("請輸入選手B的能力值(0-1):")) return a,b def simNGames(probA,probB): winsA,winsB=0,0 for i in range(5): scoreA,scoreB=simOneGame(probA,probB) if scoreA>scoreB: winsA+=1 if winsA==3: break else: winsB+=1 if winsB==3: break return winsA,winsB def gameOver(a,b): return a==11 or b==11 def simOneGame(probA,probB): scoreA,scoreB = 0,0 serving = 'A' while not gameOver(scoreA,scoreB): if serving == 'A': if random()<probA: scoreA+=1 else: serving='B' else: if random()<probB: scoreB+=1 else: serving='A' return scoreA,scoreB def printSummary(winsA,winsB): n=winsA+winsB print("競技分析開始,共模擬{}場比賽".format(n)) print("選手A獲勝{}場比賽,佔比{:.1%}".format(winsA,winsA/n)) print("選手B獲勝{}場比賽,佔比{:.1%}".format(winsB,winsB/n)) def main(): printIntro() probA,probB = getInputs() winsA,winsB = simNGames(probA,probB) printSummary(winsA,winsB) main()
結果:A隊伍以3-2贏得雙打比賽~
接下來咱們分析籃球賽事,咱們知道籃球是一項團隊的運動,因此左右比賽的走向的的變量更加多首先是運動員的人數較多,場上每一隊應該有5名隊員在場,場下有4-5名替補隊員,這樣加起來雙方隊伍參賽隊員將在14-20個,同時能力值有不一樣,且若精確到每一次進攻,那麼就會有進攻成功及進攻失敗,或進攻一次伴隨着搶板以後再次補籃等多種複雜狀況……因爲現實的多變性,考慮到本次只是簡單的模擬,我對現實進行理想化,只討論場上每隊主力5名隊員的能力值,並經過各值推出該隊平均能力值,因爲籃球比賽以時間做爲指標,在指定時間內得到分數最高者勝,因此咱們將其簡化爲:在必定時間內,只能有有限次的進攻次數,根據現實狀況,咱們設置爲:200次(雙方進攻總數),因而有了下面的代碼:
from random import random import time as T def printIntro(): print("這個程序模擬兩支球隊A和B的籃球比賽") print("程序運行須要A隊和B隊的能力值(0到1之間)") def getInputs(): print("如今請分別輸入A隊中上場的五位球員的能力值") a=eval(input("請輸入選手1的能力值(0-1):")) b=eval(input("請輸入選手2的能力值(0-1):")) c=eval(input("請輸入選手3的能力值(0-1):")) d=eval(input("請輸入選手4的能力值(0-1):")) e=eval(input("請輸入選手5的能力值(0-1):")) print("如今請分別輸入B隊中上場的五位球員的能力值") f=eval(input("請輸入選手6的能力值(0-1):")) g=eval(input("請輸入選手7的能力值(0-1):")) h=eval(input("請輸入選手8的能力值(0-1):")) i=eval(input("請輸入選手9的能力值(0-1):")) j=eval(input("請輸入選手10的能力值(0-1):")) meanA=(a+b+c+d+e)/5 meanB=(f+g+h+i+j)/5 print("A隊的平均能力值爲{0},B隊的平均能力值爲{1}".format(meanA,meanB)) return meanA,meanB def simOneAttack(probA,probB,): scoreA,scoreB = 0,0 serving = 'A' for i in range(200): if serving == 'A': if random()<probA: scoreA+=2 else: serving='B' else: if random()<probB: scoreB+=2 else: serving='A' print("最終A隊得分爲{0},B隊爲{1}".format(scoreA,scoreB)) print("隊伍A獲勝機率爲{:.1%}".format(scoreA/200)) print("隊伍B獲勝機率爲{:.1%}".format(scoreB/200)) print("平手機率(不加時):{:.1%}".format(1-(scoreA/200)-(scoreB/200))) return scoreA,scoreB def main(): printIntro() probA,probB = getInputs() print("競技分析開始,共模擬200次進攻") simOneAttack(probA,probB) main()
結果以下圖:
分別輸入各個隊伍主力球員的能力值,求出各隊伍平均能力值,並最終預測比賽得分爲:A:B=86:110
這是咱們預測了一次比賽的結果。
咱們繼續分析,在NBA的規則中,須要先在本土30支隊伍中經過進行82場常規賽決出8強,因而咱們對其進行變體來預測A/B兩支隊伍進行多場比賽後的結果:
from random import random import time as T def printIntro(): print("這個程序模擬兩支球隊A和B的籃球比賽") print("程序運行須要A隊和B隊的能力值(0到1之間)") def getInputs(): print("如今請分別輸入A隊中上場的五位球員的能力值") a=eval(input("請輸入選手1的能力值(0-1):")) b=eval(input("請輸入選手2的能力值(0-1):")) c=eval(input("請輸入選手3的能力值(0-1):")) d=eval(input("請輸入選手4的能力值(0-1):")) e=eval(input("請輸入選手5的能力值(0-1):")) print("如今請分別輸入B隊中上場的五位球員的能力值") f=eval(input("請輸入選手6的能力值(0-1):")) g=eval(input("請輸入選手7的能力值(0-1):")) h=eval(input("請輸入選手8的能力值(0-1):")) i=eval(input("請輸入選手9的能力值(0-1):")) j=eval(input("請輸入選手10的能力值(0-1):")) meanA=(a+b+c+d+e)/5 meanB=(f+g+h+i+j)/5 print("A隊的平均能力值爲{0},B隊的平均能力值爲{1}".format(meanA,meanB)) return meanA,meanB def simNGames(probA,probB): winsA,winsB=0,0 for i in range(82): scoreA,scoreB=simOneAttack(probA,probB) if scoreA>scoreB: winsA+=1 else: winsB+=1 print("最終A隊得分爲{0},B隊爲{1}".format(scoreA,scoreB)) return winsA,winsB def simOneAttack(probA,probB,): scoreA,scoreB = 0,0 serving = 'A' for i in range(200): if serving == 'A': if random()<probA: scoreA+=2 else: serving='B' else: if random()<probB: scoreB+=2 else: serving='A' return scoreA,scoreB def printSummary(winsA,winsB): n=winsA+winsB print("競技分析開始,共模擬{}場比賽".format(82)) print("隊伍A獲勝{}場比賽,佔比{:.1%}".format(winsA,winsA/n)) print("隊伍B獲勝{}場比賽,佔比{:.1%}".format(winsB,winsB/n)) def main(): printIntro() probA,probB = getInputs() print("競技分析開始,共模擬200次進攻") simOneAttack(probA,probB) winsA,winsB = simNGames(probA,probB) printSummary(winsA,winsB) main()
結果:
對30支隊伍進行簡化,只用44支隊伍相互角逐: