#程序总体框架和步骤 #打印程序的介绍性信息式 -printInfo() #获得程序运行参数proA,proB,n -getInputs() #利用球员A和B的能力值,模拟n局比赛 -simNGames() #输出球员A和球员B的获胜场次和概率 -printSummary() import random def printInfo(): 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 printSummary(winsA,winsB): n=winsA+winsB print("竞技分析开始,共模拟{}场比赛".format(n)) print("选手A获得{}场比赛,占比{:0.1%}".format(winsA,winsA/n)) print("选手B获得{}场比赛,占比{:0.1%}".format(winsB,winsB/n)) def simNGames(n,proA,proB): #输入的是n:比赛的次数 proA:A的能力值 proB:B的能力值 winsA,winsB=0,0 for i in range(n): scoreA,scoreB=simOneGame(proA,proB) if scoreA>scoreB: winsA+=1 elif scoreA<scoreB: winsB+=1 else: continue return winsA,winsB #返回的是A赢的次数,B赢的次数 def simOneGame(proA,proB): #输入的是A和B的能力值 scoreA,scoreB=0,0 serving='A' #如果单局比赛次数少,且A和B能力相差不多,这个谁先发球因素很重要 while not gameOver(scoreA,scoreB): if serving=='A': if random.random()<=proA: scoreA+=1 else: serving='B' else: if random.random()<=proB: scoreB+=1 else: serving='A' return scoreA,scoreB #返回的是A和B单次比赛的分值 def gameOver(a,b): #输入的是a和b的分值 return a==15 or b==15 #return a==150 or b==150 # 如果分值等于15就结束比赛 # 如果次数是15次的话且serving='A',可能在A和B能力相差不多的情况下A赢 def main(): printInfo() proA,proB,n=getInputs() winsA,winsB=simNGames(n,proA,proB) printSummary(winsA,winsB) if __name__ == '__main__': main() #程序运行结果还是比较有意思的,见csdn个人博客
其实这个程序中的几个参数对于结果还是有影响的,1:单局比赛中谁先来,也就是serving先取谁的值 2:单局比赛结束的判定条件,也就是gameOver()中判定条件的次数。 这两个参数综合起来影响了结果。
比如选手A的能力是0.88,选手B的能力是0.89,但是serving为A,也就是A先来,且判定条件为15分,10万次比赛结果如下:
如结果所示,能力稍低者妥妥地赢了。不信?100万次结果如下:
结果差不多,还是能力稍低者妥妥地赢了。
我分析代码后,感觉是serving和gameover的问题。于是还是让serving='A',也就是A先手不变,但是将gameOver中的次数改为150,这样A先手的话在单次比赛中影响应该不大了。比赛10万次,结果如下:
这样,B赢了。再次改变参数,让B先手,但单局gameOver中次数还是15,比赛100万次,结果如下:
相比上图,发现B赢的更多。这说明在单局比赛中,如果B能力稍高,且占据先手优势,则赢面会较大。如果,让B先发球且单局比赛次数变多呢?10万场比赛结果如下:
发现B的优势更大了一点点。
所以,从结果来看,对于能力相差不多的人来说,比赛条件的设置着实可以隐藏真相啊!但我们是从程序编码的上帝视角来看的,而在实际生活中,谁又能看穿真相呢?或者说谁是A谁是B,观众心底也没底啊。