程序设计方法论
程序设计方法论
自顶向下和自底向上
一般来说,我们的程序设计应该采用自顶向下的设计方法,采用自底向上的执行方法。那么什么是自底向上和自顶向下呢?
自顶向下即从一个总问题开始,把他分解为很多个小问题,再去找这些个小问题的解决方法,最后把这些小问题都解决了,最终问题也就迎刃而解了。然后只需把这些小问题的解决方案拼凑起来加以整理就得到了整个问题的解决方案。
就比如我们玩游戏打BOSS,你去直接打BOSS你打不过(别问为什么打不过,问就是这样举例子比较形象。)此时官方就会为你设置三四个关卡,每通过一个关卡你就会获得BUFF加成或者BOSS就会获得debuff,这样你打完这些关卡后,再去打BOSS就会变得比较轻松了。
——————————————我是例子——————————————————
下面我们来看一个实例哈:
问题是这样的:玩家A和玩家B在擂台上进行1V1的比赛,比赛开始时,其中一个玩家的精灵先出招,接下来交替出招,直到可以判定输赢为止,这个过程称为回合。当一名玩家的招数没有命中时,回合结束。技能没有命中的玩家输掉这个回合。每回合赢的玩家先手,只有在自己先手时才能得分。率先达到10分的选手获胜。现在让你编写一个程序来模拟这个过程。
这个问题看似花里胡哨的,其实就是我们的体育竞技积分规则。
如果要模拟这个过程的话,我们必须知道的是两名玩家的胜率如何,也就是他们相对的能力值是多少,还要知道我们进行模拟的场次。我们都知道进行概率分析时,分析的场次越多结果就越向真实值靠拢,所以场次不一样得到的结果也不一样,因此需要给出模拟的场次。
我们可以试着写出这个问题的IPO:
输入:两名玩家的能力数值,模拟比赛的场次。
处理:模拟PK过程
输出:两名玩家分别获胜的概率
——————————————我是思路——————————————————
下面我们采用自顶向下的设计方法来设计程序:
step1:打印使用程序的介绍性信息
step2:获取必要的参数
step3:设计算法,利用给出的参数进行计算
step4:输出结果
step1输出一些介绍我们的信息可以给使用我们的程序的人带来非常好的体验(为了提高用户体验,必要的解析是要有的,想象一下你第一次使用自动售货机,机柜上没有贴使用方法与任何提示性信息的场景。)
顶层设计不需要我们给出具体的函数代码,只需给出函数定义即可。
def main(): print_tips()
这里我们的print_tips函数用于打印提示性文字。
step2要获取用户输入的参数,我们定义个函数用于获取输入的参数,接着上面的代码
def main(): print_tips() par_A,par_B,n=getInput()
step3要使用传入的参数来进行模拟,设计一个deal(par_A,par_B,n)函数来表示模拟过程。并用两个变量来接收函数返回值
def main(): print_tips() par_A,par_B,n=getInput() result_A,result_B=deal(par_A,par_B,n)
setp4输出结果
def main(): print_tips() par_A,par_B,n=getInput() result_A,result_B=deal(par_A,par_B,n)print_result(result_A,result_B)
到这里我们的思路就已经完成了,我们成功地将这个问题转化为了四个函数,只需把这四个函数设计出来我们的问题就解决了。
我们在每一步设计的时候需要指明每层之间的联系,即指明需要我们传入的参数。
下面我们来逐个函数的设计
————————————我是函数设计——————————————————
step1:
def print_tips(): print("这个程序用来模拟两名玩家的PK,并返回各自的胜率") print("使用时需要手动输入两名玩家的能力值(注意:能力值为0到1之间的小数)以及模拟次数")
step2:
#用于获取输入的参数 def getInput(): par_a=eval(input("请输入选手A的能力值:(输入0-1的小数)")) par_b=eval(input("请输入选手B的能力值:(输入0-1的小数)")) n=eval(input("请输入模拟的次数:")) return par_a,par_b,n
step3:
一般来说输入输出是比较基础的部分,一个程序的核心部分就是算法的设计,因此这个程序的四个函数中,核心的函数是第三步的模拟过程。
我们进行n场模拟时,实际上是进行了n次一场比赛的模拟,因此我们可以抽象出一个函数oneGame用于模拟一场比赛的输赢状况,在我们的deal函数中调用n次oneGame函数即可。
#模拟过程 def deal(par_A,par_B,n): result_A,result_B=0,0 for i in range(n): score_A,score_B=oneGame(par_A,par_B) if score_A> score_B: result_A+=1 else: result_B+=1
接下面问题的关键转化为了oneGame函数的编写
step3.plus
一场比赛结束的标志是有一方得分,我们可以使用while True的无限循环,直到有一方得分时跳出循环,那得分条件是什么呢?得分方需要先手出招而且。需要打败对方才可以取得胜利,是否打败对方取决于自身能力值和赛场上的其他因素,我们使用random库生成的随机数来模拟其他因素,如果没有打败对方则轮到对方出招
#模拟一场比赛 import random def oneGame(par_A,par_B): score_A,score_B=0,0 now="A" while True: if now=="A": if random()<par_A: score_A+=1 else: now="B" else: if random()<par_B: score_B+=1 else: now="A" if(score_B==15 or score_A==15) return score_A,score_B
step4:
最后就是输出我们的比赛结果
def print_result(result_A,result_B): n=result_A+result_B print("总共进行了{}场比赛".format(n)) print("玩家A胜场为{}场,胜率为:{}".format(result_A,result_A/n)) print("玩家B胜场为{}场,胜率为:{}".format(result_B,result_B/n))
最后把他们组合在一起就是我们完整的代码:
from random import random #介绍使用信息 def print_tips(): print("这个程序用来模拟两名玩家的PK,并返回各自的胜率") print("使用时需要手动输入两名玩家的能力值(注意:能力值为0到1之间的小数)以及模拟次数") #用于获取输入的参数 def getInput(): par_a=eval(input("请输入选手A的能力值:(输入0-1的小数)")) par_b=eval(input("请输入选手B的能力值:(输入0-1的小数)")) n=eval(input("请输入模拟的次数:")) return par_a,par_b,n #模拟过程 def deal(par_A,par_B,n): result_A,result_B=0,0 for i in range(n): score_A,score_B=oneGame(par_A,par_B) if score_A> score_B: result_A+=1 else: result_B+=1 return result_A,result_B #模拟一场比赛 def oneGame(par_A,par_B): score_A=0 score_B=0 now="A" while True: if now=="A": if random()<par_A: score_A+=1 else: now="B" else: if random()<par_B: score_B+=1 else: now="A" if score_B==10 or score_A==10: flag=True else: flag=False if flag: return score_A,score_B #输出比赛结果 def print_result(result_A,result_B): n=result_A+result_B print("总共进行了{}场比赛".format(n)) print("玩家A胜场为{}场,胜率为:{}".format(result_A,result_A/n)) print("玩家B胜场为{}场,胜率为:{}".format(result_B,result_B/n)) def main(): print_tips() pra_A,pra_B,n=getInput() result_A,result_B=deal(pra_A,pra_B,n) print_result(result_A,result_B) main()
程序的运行结果是:
我们的程序写到这里并不完善,如果用户没有输入正确的小数怎么办?
我们程序员在写一个程序的时候,写完以后还要尽可能模拟一些会让程序出错的情况,并根据不同情况做出相应的处理,让程序拥有很好的健壮性。
大家可以开动小手把这段代码进行完善,增强程序的健壮性。
今天主要是想向大家介绍一种程序设计的方法:自顶向下。
好了,那么今天你学废了吗。(:3꜂ ꜆)꜄⁾⁾
我们下次见咯̑̑ฅ( ˃̶˙ω˙˂̶ ฅ)
- 有必要澄清两个基本概念--算法和过程的关系以及关于程序设计方法论的一些看法
- 有必要澄清两个基本概念--算法和过程的关系以及关于程序设计方法论的一些看法
- 参数检验以及程序设计的方法论
- 面向对象程序设计的方法论
- 2016CCPC东北地区大学生程序设计竞赛
- 《C语言及程序设计》实践项目——枚举应用
- 网络程序设计学习总结
- 【干货】一套方法论,6个技巧,10倍提升你的知识管理效果……(亲测有效)
- [置顶] 海量数据处理程序设计技巧(附C++代码)
- 程序设计C 实验五 题目四 二维动态数组转置(0294)
- 第四章 选择结构程序设计
- 《C语言及程序设计》实践参考——用文本文件保存的学生名单
- Nginx/tengine做cache时缓存机制—存不存、存多久、用不用方法论
- 如何进入程序设计的领域
- C++程序设计实验报告(四十四)---第六周任务二
- 【C++程序设计】-继承和派生
- [.net 面向对象程序设计进阶] (9) 序列化(Serialization) (一) 二进制流序列化
- C语言程序设计---10:利用文件保存数据
- [翻译]-WinCE 程序设计 (3rd 版)--第一章 Hello Windows CE-概述
- 第一节程序设计课