一、模拟体育比赛分析(以乒乓球比赛为例)
相信大家都喜欢看各种比赛,球类、游戏等等,有比赛就有输赢,因为一些博彩项目的存在,便有人开始分析比赛队伍输赢的概率,调整赔率或是渴望靠着一场博彩一夜暴富。那么能不能利用代码来实现这个分析呢?当然可以!下面我们就来看看吧!
在写代码之前我们先将各步骤罗列出来:
(1)根据各支队伍以往的比赛成绩分析其胜率;
(2)根据相关比赛规则编写代码以判断输赢条件;
(3)根据模拟出比赛的场景,进行统计各队伍的胜率;
下面是一个规则比较简单的体育竞赛模拟的代码:
规则:两名选手进行比赛,一名选手发球,发球方若赢球则加一分,失球则换发球方,哪一方先到达15分便结束比赛。
函数名称 | 函数说明 |
printIntro()
|
声明函数,对此程序的功能进行说明 |
getInputs()
|
输入函数,供使用者输入数据进行计算分析 |
simNGames(n, probA, probB)
|
统计每一场模拟比赛的结果 |
gameOver(a,b)
|
判断比赛结束的条件 |
simOneGame(probA, probB)
|
对每一球的得失进行模拟 |
printSummary(winsA, winsB)
|
输出模拟比赛的结果 |
1 # -*- coding: utf-8 -*- 2 """ 3 Created on Sun May 12 12:26:37 2019 4 5 @author: Regan_White_Lin12 6 """ 7 8 from random import random 9 def printIntro(): #声明函数,对整个程序功能进行解释 10 print("这个程序模拟两个选手A和B的某种竞技比赛") 11 print("程序运行需要A和B的能力值(以0到1之间的小数表示)——Author's number:12") 12 def getInputs(): #输入函数,输入选手队伍的能力值以及所模拟进行的比赛场次数量 13 a = eval(input("请输入选手A的能力值(0-1): ")) 14 b = eval(input("请输入选手B的能力值(0-1): ")) 15 n = eval(input("模拟比赛的场次: ")) 16 return a, b, n 17 def simNGames(n, probA, probB): #统计对每一场模拟比赛的结果 18 winsA, winsB = 0, 0 19 for i in range(n): 20 scoreA, scoreB = simOneGame(probA, probB) 21 if scoreA > scoreB: 22 winsA += 1 23 else: 24 winsB += 1 25 return winsA, winsB 26 def gameOver(a,b): #判断比赛结束条件 27 return a==15 or b==15 28 def simOneGame(probA, probB): #对每一球的得失进行模拟 29 scoreA, scoreB = 0, 0 30 serving = "A" 31 while not gameOver(scoreA, scoreB): 32 if serving == "A": 33 if random() < probA: 34 scoreA += 1 35 else: 36 serving="B" 37 else: 38 if random() < probB: 39 scoreB += 1 40 else: 41 serving="A" 42 return scoreA, scoreB 43 def printSummary(winsA, winsB): #输出模拟的比赛结果 44 n = winsA + winsB 45 print("竞技分析开始,共模拟{}场比赛".format(n)) 46 print("选手A获胜{}场比赛,占比{:0.1%}".format(winsA, winsA/n)) 47 print("选手B获胜{}场比赛,占比{:0.1%}".format(winsB, winsB/n)) 48 def main(): #调用上方功能函数的主函数 49 printIntro() 50 probA, probB, n = getInputs() 51 winsA, winsB = simNGames(n, probA, probB) 52 printSummary(winsA, winsB) 53 main()
根据上一代码修改,得到模拟乒乓球比赛的代码:
规则:
一局比赛中,先得到11分的一方为胜方;十平后,连续得两分得一方为胜方。
一场比赛中,采用七局四胜制,七局比赛中,赢得四局比赛的一方为胜方。
1 # -*- coding: utf-8 -*- 2 """ 3 Created on Sun May 12 12:26:37 2019 4 5 @author: Regan_White_Lin12 6 """ 7 8 from random import random 9 def printIntro(): 10 print("这个程序模拟两个选手A和B的乒乓球比赛") 11 print("程序运行需要A和B的能力值(以0到1之间的小数表示)") 12 print("作者:Regan_White_Lin 12") 13 def getInputs(): 14 a = eval(input("请输入选手A的能力值(0-1): ")) 15 b = eval(input("请输入选手B的能力值(0-1): ")) 16 n = eval(input("模拟比赛的场次: ")) 17 return a, b, n 18 def simNGames(probA, probB): 19 winsA, winsB = 0, 0 20 for i in range(7): 21 scoreA, scoreB = simOneGame(probA, probB) 22 if scoreA > scoreB: 23 winsA += 1 24 else: 25 winsB += 1 26 return winsA, winsB 27 def simnGames(n,probA,probB): 28 WinsA,WinsB=0,0 29 for i in range(n): 30 winsA, winsB = simNGames(probA,probB) 31 if winsA>winsB: 32 WinsA+=1 33 else: 34 WinsB+=1 35 return WinsA,WinsB 36 def gameOver(a,b): 37 if a<11 and b<11: 38 return 0 39 elif a==11 and b<10 or b==11 and a<10: 40 return 1 41 elif a-b==2 and a>11 or b-a==2 and b>11: 42 return 1 43 def simOneGame(probA, probB): 44 scoreA, scoreB = 0, 0 45 serving = "A" 46 while not gameOver(scoreA, scoreB): 47 if serving == "A": 48 if random() < probA: 49 scoreA += 1 50 else: 51 serving="B" 52 else: 53 if random() < probB: 54 scoreB += 1 55 else: 56 serving="A" 57 return scoreA, scoreB 58 def printSummary(WinsA, WinsB): 59 n = WinsA + WinsB 60 print("竞技分析开始,共模拟{}场比赛".format(n)) 61 print("选手A获胜{}场比赛,占比{:0.1%}".format(WinsA, WinsA/n)) 62 print("选手B获胜{}场比赛,占比{:0.1%}".format(WinsB, WinsB/n)) 63 def main(): 64 printIntro() 65 probA, probB, n = getInputs() 66 WinsA, WinsB = simnGames(n, probA, probB) 67 printSummary(WinsA, WinsB) 68 main() 69 input("按下任意键退出程序......")
下一步就是将上述程序进行打包了,打包前我们要再安装pyinstaller和pywin32
安装步骤如下:
点击键盘上的"Win"键+"R"键,打开命令行窗口,输入pip install pyinstaller,同理安装pywin32也是一样的,只需将pyinstaller替换成pywin32即可,再详细的步骤可参考我的其他随笔,里面都有关于安装库函数的详细步骤,这里就不再赘述了。
安装完毕后,一样在命令行窗口中操作,输入pyinstaller -F **.py(**是要打包的程序名),点击回车键,此时会输出很多文字,等到停止输出时,在最后的地方可以找到打包完成的脚本存储位置,如下图
倒数第二行处(C:Users18129dist体育竞技分析.exe)即为打包后的脚本存储位置
找到脚本位置,打开脚本,输入数据,得出结果,效果见下图:
PS:记得在要打包的程序最后加一个input函数,否则你会发现,你输入了全部数据后,命令行窗口会直接闪退,这不是因为打包出现问题,脚本确实计算出了结果,只是因为后续没有再需要输入的数据便直接自动弹出了。
二、采用篮球规则模拟比赛,分析体育竞技规则
不同于乒乓球,篮球并没有确定分数可以结束比赛的,而是通过计时来限制选手得分,分出输赢。下面为了简便起见,我便采用一个random函数取一个随机数以决定一场比赛中的回合数,每一回合让一支队伍得到发球权,进球则得分且继续发球,否则不得分且交换发球权。
函数名称 | 函数说明 |
printIntro()
|
声明函数,对此程序的功能进行说明 |
getInputs()
|
输入函数,供使用者输入数据进行计算分析 |
simOneGame(n,probA, probB)
|
模拟每一球的得失并进行统计 |
printSummary(n, scoreA, scoreB)
|
输出模拟比赛的结果 |
闲话少说,直接上代码:
1 # -*- coding: utf-8 -*- 2 """ 3 Created on Mon May 13 20:03:51 2019 4 5 @author: Regan_White_Lin12 6 """ 7 8 import random 9 def printIntro(): 10 print("这个程序模拟两支球队A和B的篮球比赛") 11 print("程序运行需要球队A和B的能力值(以0到1之间的小数表示)") 12 print("作者:Regan_White_Lin 12") 13 def getInputs(): 14 a = eval(input("请输入球队A的能力值(0-1): ")) 15 b = eval(input("请输入球队B的能力值(0-1): ")) 16 n = random.randint(1,1000) 17 return a, b, n 18 def simOneGame(n,probA, probB): 19 scoreA, scoreB = 0, 0 20 serving = "A" 21 a=0 22 while (a<=n) or (a>n) and (scoreA==scoreB): 23 if serving == "A": 24 if random.random() < probA: 25 scoreA += 1 26 else: 27 serving="B" 28 else: 29 if random.random() < probB: 30 scoreB += 1 31 else: 32 serving="A" 33 a+=1 34 return scoreA, scoreB 35 def printSummary(n, scoreA, scoreB): 36 print("竞技分析开始,共模拟{}个回合".format(n)) 37 print("球队A获得{}分".format(scoreA)) 38 print("球队B获得{}分".format(scoreB)) 39 if scoreA>scoreB: 40 char='A' 41 else: 42 char='B' 43 print("获胜方是球队{}".format(char)) 44 def main(): 45 printIntro() 46 probA, probB, n = getInputs() 47 scoreA, scoreB = simOneGame(n,probA, probB) 48 printSummary(n, scoreA, scoreB) 49 main() 50 input("按下任意键退出程序......")
下面是测试结果:
三、采用乒乓球规则模拟多人晋级赛
模拟多人晋级赛与上面所讲述的两支队伍的模拟比赛是类似的,无非就是进行多几场,这里就不再赘述了,直接上代码:
PS:下面只是做一个例子,以四名选手为例,进行轮回赛,即任意两名选手都会进行一场比赛,规则依旧是以乒乓球规则为例,七局四胜。
1 # -*- coding: utf-8 -*- 2 """ 3 Created on Sun May 12 12:26:37 2019 4 5 @author: Regan_White_Lin12 6 """ 7 8 from random import random 9 def printIntro(): 10 print("这个程序模拟四个选手A,B,C和D的乒乓球比赛") 11 print("程序运行需要A,B,C和D的能力值(以0到1之间的小数表示)") 12 print("作者:Regan_White_Lin 12") 13 def getInputs(): 14 a = eval(input("请输入选手A的能力值(0-1): ")) 15 b = eval(input("请输入选手B的能力值(0-1): ")) 16 c = eval(input("请输入选手C的能力值(0-1): ")) 17 d = eval(input("请输入选手D的能力值(0-1): ")) 18 n = eval(input("模拟每两名选手比赛的场次: ")) 19 return a, b, c, d, n 20 def simNGames(probA, probB): 21 winsA, winsB = 0, 0 22 for i in range(7): 23 scoreA, scoreB = simOneGame(probA, probB) 24 if scoreA > scoreB: 25 winsA += 1 26 else: 27 winsB += 1 28 return winsA, winsB 29 def simnGames1(n,probA,probB): 30 WinsA,WinsB=0,0 31 for i in range(n): 32 winsA, winsB = simNGames(probA,probB) 33 if winsA>winsB: 34 WinsA+=1 35 else: 36 WinsB+=1 37 return WinsA,WinsB 38 def simnGames2(n,probA,probB,WinsA,WinsB): 39 for i in range(n): 40 winsA, winsB = simNGames(probA,probB) 41 if winsA>winsB: 42 WinsA+=1 43 else: 44 WinsB+=1 45 return WinsA,WinsB 46 def gameOver(a,b): 47 if a<11 and b<11: 48 return 0 49 elif a==11 and b<10 or b==11 and a<10: 50 return 1 51 elif a-b==2 and a>11 or b-a==2 and b>11: 52 return 1 53 def simOneGame(probA, probB): 54 scoreA, scoreB = 0, 0 55 serving = "A" 56 while not gameOver(scoreA, scoreB): 57 if serving == "A": 58 if random() < probA: 59 scoreA += 1 60 else: 61 serving="B" 62 else: 63 if random() < probB: 64 scoreB += 1 65 else: 66 serving="A" 67 return scoreA, scoreB 68 69 import operator 70 Departs = [] 71 class Department: 72 def __init__(self,num,char): 73 self.num = num 74 self.char = char 75 def main(): 76 printIntro() 77 probA, probB, probC, probD, n = getInputs() 78 WinsA, WinsB = simnGames1(n, probA, probB) 79 WinsC, WinsD = simnGames1(n, probC, probD) 80 WinsA, WinsC = simnGames2(n, probA, probC, WinsA, WinsC) 81 WinsB, WinsD = simnGames2(n, probB, probD, WinsB, WinsD) 82 WinsA, WinsD = simnGames2(n, probA, probD, WinsA, WinsD) 83 WinsB, WinsC = simnGames2(n, probB, probC, WinsB, WinsC) 84 print("竞技分析开始,共模拟{}场比赛".format(n*6)) 85 Departs.append(Department(WinsA, 'A' )) 86 Departs.append(Department(WinsB, 'B' )) 87 Departs.append(Department(WinsC, 'C' )) 88 Departs.append(Department(WinsD, 'D' )) 89 cmpfun = operator.attrgetter('num') 90 Departs.sort(key=cmpfun) 91 i=0 92 for depart in Departs: 93 i+=1 94 if i==1: 95 print("第四名:选手"+depart.char+",胜局数:"+str(depart.num)) 96 elif i==2: 97 print("第三名:选手"+depart.char+",胜局数:"+str(depart.num)) 98 elif i==3: 99 print("第二名:选手"+depart.char+",胜局数:"+str(depart.num)) 100 elif i==4: 101 print("第一名:选手"+depart.char+",胜局数:"+str(depart.num)) 102 main() 103 input("按下任意键退出程序......")
效果如下图(为了方便浏览,此程序也经过了打包处理):