“体育竞技分析”问题分析

程序设计方法学:

理解自顶向下的设计和自底向上的执行

方法论:理解并掌握一批python程序设计思维实践能力

学会编写更有设计感的程序

“体育竞技分析”问题分析:

需求:毫厘是多少,如何科学分析体育竞技比赛

输入:球员的水平

输出:可预测的比赛成绩

体育竞技分析:模拟N场比赛

计算思维:抽象+自动化

模拟:抽象比赛过程+自动化执行N场比赛

当N越大时,比赛结果分析会越科学

比赛规则:双人击球比赛:A&B,回合制,5局3胜

开始时一方先发球,直至判分,接下来胜者发球

球员只能在发球局得分,15分胜一局。

解决这个问题,我们可以采用自顶向下(解决复杂问题的有效方法)的设计方法和自底向上(逐步组建复杂系统的有效测试方法)的执行方法。

自顶向下:

基本含义:将一个总问题表达为若干个小问题组成的形式

使用同样方法进一步分解小问题

直至小问题可以用计算机简单明了的解决。

自底向上(执行)逐步组建复杂系统的有效测试方法

分单元测试,逐步组装

按照自顶向下相反的路径操作

直至系统各部分以组装的思路都经过测试和验证。

第一阶段:程序总体框架及步骤

步骤一:打印程序的介绍性信息式

步骤二:获得程序运行参数:proA(球员A能力值)、proB(球员B能力值)、n(比赛场次){从用户那里得到的数据}

步骤三:利用球员A和球员B的能力值,模拟n局比赛(计算机)

步骤四:输出球员A和球员B获胜比赛的场次及概率

我们根据自顶向下的设计,确定以下函数:

main()函数包括printInfo()(打印输出信息)、getInputs()(将获取的球员A能力值、球员B能力值、比赛场次提供给调用这个函数的main()函数)、simNGames()  (模拟n局比赛)、printSummary()(从main1函数获取比赛结果后进行输出)

我们设置的代码如下:

printInfo函数:介绍性内容,提高用户体验

def printInfo():
    print("这个程序模拟两个选手A和B的某种竞技比赛")
    print("程序运行需要A和B的能力值(以0到1之间的小数表示)")
  

getInputs()(将获取的球员A能力值、球员B能力值、比赛场次提供给调用这个函数的main()函数)

def getInputs():
    a=eval(input("请输入选手A的能力值(0-1):"))
    b=eval(input("请输入选手B的能力值(0-1):"))
    n=eval(input("模拟比赛的场次"))
    return a,b,n   #(分别返回一个元组类型,对应三个输入)

这是用户所输入的信息。

printSummary()(从main1函数获取比赛结果后进行输出)

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 main():
    printInfo()
    probA,probB,n=getInputs()
    winsA,winsB=simNGames(n,probA,probB)
    printSummary(winsA,winsB)

之后我们对模拟n局比赛的函数代码模块进行设计。要求解模拟n局比赛的函数模块,我们可以先设计模拟一局比赛的代码,之后让它们循环n次即可。在面对设计一局比赛的代码的时候,我们可以先设计比赛结束的代码。如下所示:

def gameOver(a,b):
    return a=15 or b=15

之后我们设计一局比赛的代码simOneGame():

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

设计思路如下:首先对于一局比赛来说,,初始得分全部为0,我们根据规则可知,只有在发球局才可以得分。当球员A发球的时候,面对比赛如果没有结束的话,我们要进行如下循环,如果发球的是A,当随机取得值比A的能力值小,则A加分,如果随机取得所要求的能力值比A大,则球员B发球。对于球员B发球的时候,如果随机取得能力值比球员B小,则球员B加分,如果随机取得能力值比B大,则球员A发球。当有一方球员达到15分的时候,这局比赛结束,即循环结束,之后返回球员A和球员B的得分情况。

之后我们设计n局比赛的代码simNGames():此类函数表示的是模拟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

我们在以上设计出了一局比赛的得分情况,当达到15分的时候,一局比赛结束。之后,我们设计N局比赛得分的情况,我们需要循环n局比赛,如果在调用一局比赛的simOneGame()函数之后,得分球员A的得分比球员B的大,则球员A赢一局,反之则球员B赢一局,之后返回球员A和球员B所赢的球的局数。

我们在设计过程中,首先将体育竞技分析这个大问题拆分为四个小问题,即打印介绍性信息,获得输入信息,模拟比赛结果,打印输出信息,还有总函数。我们进行逐步解决代码编写。之后,对于模拟N局比赛这个小问题里面,我们把他看成一个大问题,继续拆分为模拟一局比赛这个小问题。模拟N局比赛相当于N次模拟一局比赛,将总问题分解为模拟一局比赛并且将它循环N次。之后,我们利用规则将一局比赛的代码进行编写。即利用接口将函数联系起来,最后即可编写完成。

以上即为我们整体的代码,我们在代码段末尾调用main()函数即可运行,即输入main( )。

整体代码如下所示:

from random 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 gameOver(a,b):
    return a==15 or b==15

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 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 main():
    printInfo()
    probA,probB,n=getInputs()
    winsA,winsB=simNGames(n,probA,probB)
    printSummary(winsA,winsB)

main()

运行界面如下所示:

 举一反三:

理解自顶向下和自底向上

理解自顶向下的设计思维:分而治之

理解自底向上的执行思维:模块化集成

自顶向下是“系统思维”的简化

应用问题的扩展:

扩展比赛参数,增加对更多能力对比情况的判断

扩展比赛设计,增加对真实比赛结果的预测

扩展分析逻辑,反向推理,用胜率推算能力。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

一直再追梦

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值