先看看一个项目一般怎么完成的吧。要学会如何作为一个程序员来思考解决问题。
其中一个很重要的能力是问题拆解。
问题拆解就是在面对一个问题的时候,将一个大问题,拆解成多个步骤或者多个方面,逐步解决,最后完成整个问题,达到所要的结果。
这种思维在我们日常生活中也非常常见,比如:你需要洗衣服,怎么去完成洗衣服呢?
1. 把衣服放进洗衣机;2. 倒入洗衣液;3. 点击开始按钮;4. 洗衣机开始洗衣服;5. 将洗好的衣服取出晾起来。
但在编程中,我们拆解问题就需要按照代码的思维方式进行拆解。
比如:在上一关的作业练习中,葫芦娃和老爷爷猜数字的问题,我们就可以进行拆解。
当然这种拆解问题的思维并不少见。基于长期编写代码的习惯,程序员会将问题拆得更细致一些,即拆到无法再拆为止。 像这样,我会将完成一个项目的流程总结为以下三步:
明确项目目的,指的就是我们希望这个程序做什么,达到什么样的效果,之后才能更好的进行流程分析,拆解项目,最后逐步解决所有问题,逐渐完善整个项目功能。
需要注意的是,一个完美的拆解方案,应当是按照从上往下的逻辑自然拆解,难度逐渐增加。
明确项目目的
在编程界,一般是由产品经理提出项目要求,由程序员来实现。所谓的项目需求,大家可以简单的理解为项目实现效果。
我们现在需要重现一下仙剑奇侠传中的经典一战【李逍遥大战拜月教主】!
最终我们需要实现的效果如下:
用文字描述一下:在这个游戏中,李逍遥(freeLi)大战拜月教主(Boss),游戏开始后,会随机生成李逍遥与拜月教主的属性,相互攻击,直到一方的血量为 0 ,战斗采取三局两胜制,最后显示战斗结果,公布获胜者。
明确了项目目的,接下来就可以对项目进行拆解了。
逐步解决,逐渐完善
编写代码的时候,谁都不能一步到位,尤其是对一初入门的学员来说,逐步解决,逐渐完善才是做好的过程。
现按照 “难度递增,功能叠加” 的思路,将这个游戏拆解成三个版本。
版本 1.0 主要是帮助我们理清战斗逻辑,而版本 2.0 和 3.0 会涉及新的知识点。
分析流程,拆解项目
接下来,我们正式进入李逍遥大战拜月教主的主战场。
首先来看一下 1.0 版本如何实现
理清战斗逻辑
首先,根据我们上面的分析,来看一下整个项目中都有哪些基础元素。
根据这些元素,我们要做的主要有三步:
1. 规定【李逍遥】和【拜月教主】的属性;
2. 双方攻击时,失血量根据对方的攻击来进行计算;
3. 如果有一方的血量减少到 0 或 0 以下,GAME OVER。
为了保持思路的清晰,画出流程图如下:
从第一步开始,设定【李逍遥】和【拜月教主】的属性,及【血量】 和 【攻击力】。
# 自定义李逍遥的血量和攻击力
print('【李逍遥】\n 血量:100 \n 攻击力:25')
# 自定义拜月教主的血量和攻击力
print('【拜月教主】\n 血量:100 \n 攻击力: 20')
第二步,双方攻击人工计算各自的剩余血量。
# 人工计算拜月教主剩余血量 100 - 25 = 75
print('【李逍遥】向【拜月教主】发起了攻击,【拜月教主】剩余血量 75')
# 人工计算李逍遥剩余血量 100 - 20 = 80
print('【拜月教主】向【李逍遥】发起了攻击,【李逍遥】剩余血量 80')
第三步,继续攻击,人工计算各自的剩余血量。
# 人工计算拜月教主剩余血量 75 - 25 = 50
print('【李逍遥】向【拜月教主】发起了攻击,【拜月教主】剩余血量 50')
# 人工计算李逍遥剩余血量 80- 20 = 60
print('【拜月教主】向【李逍遥】发起了攻击,【李逍遥】剩余血量 60')
第四步和第五步,继续攻击,人工计算各自剩余血量。
# 第四步
# 人工计算拜月教主剩余血量 50- 25 = 25
print('【李逍遥】向【拜月教主】发起了攻击,【拜月教主】剩余血量 25')
# 人工计算李逍遥剩余血量 60 - 20 = 40
print('【拜月教主】向【李逍遥】发起了攻击,【李逍遥】剩余血量 40')
# 第五步
# 人工计算拜月教主剩余血量 25 - 25 = 0,此时拜月教主血量为 0,拜月教主死亡,游戏结束。
print('【李逍遥】向【拜月教主】发起了攻击,【拜月教主】剩余血量 0')
# 人工计算李逍遥剩余血量 40 - 20 = 20
print('【拜月教主】向【李逍遥】发起了攻击,【李逍遥】剩余血量 20')
print('【拜月教主】死了,【李逍遥】赢了')
是不是很简单,我们接下来要做的就是将几段代码拼接起来,形成一个完成的代码,然后加上一些分割线,让输出结果看起来更美观一些。
# 自定义李逍遥的血量和攻击力
print('【李逍遥】 \n 血量:100 \n 攻击力:25')
# 自定义拜月教主的血量和攻击力
print('【拜月教主】 \n 血量:100 \n 攻击力: 20')
print('-----------------------')
# 人工计算拜月教主剩余血量 100 - 25 = 75
print('【李逍遥】向【拜月教主】发起了攻击,【拜月教主】剩余血量 75')
# 人工计算李逍遥剩余血量 100- 20 = 80
print('【拜月教主】向【李逍遥】发起了攻击,【李逍遥】剩余血量 80')
print('-----------------------')
# 人工计算拜月教主剩余血量 75 - 25 = 50
print('【李逍遥】向【拜月教主】发起了攻击,【拜月教主】剩余血量 50')
# 人工计算李逍遥剩余血量 80 - 20 = 60
print('【拜月教主】向【李逍遥】发起了攻击,【李逍遥】剩余血量 60')
print('-----------------------')
# 人工计算拜月教主剩余血量 50 - 25 = 25
print('【李逍遥】向【拜月教主】发起了攻击,【拜月教主】剩余血量 25')
# 人工计算李逍遥剩余血量 60 - 20 = 40
print('【拜月教主】向【李逍遥】发起了攻击,【李逍遥】剩余血量 40')
print('-----------------------')
# 人工计算拜月教主剩余血量 25 - 25 = 0,此时拜月教主血量为 0,拜月教主死亡,游戏结束。
print('【李逍遥】向【拜月教主】发起了攻击,【拜月教主】剩余血量 0')
# 人工计算李逍遥剩余血量 40 - 20 = 20
print('【拜月教主】向【李逍遥】发起了攻击,【李逍遥】剩余血量 20')
print('-----------------------')
print('【拜月教主】死了,【李逍遥】赢了')
现在我们初步实现了项目的目的,但是我们这一下子就将全部的结果都打印出来了,速度太快了,没有丝毫的游戏快感。
为了让我们看着结果有一定的进展性,可以让打印的结果间隔出现,我需要用到一个类似 “延迟时间” 的东西。在
Python 江湖中,我们要用到两行代码。
time.sleep() 就是制作延迟效果的,让输出结果可以延迟出现,我们可以先让结果延迟 2s 出现。代码改写如下:
# 调用 time 模块
import time
# 自定义李逍遥的血量和攻击力
print('【李逍遥】 \n 血量:100 \n 攻击力:25')
# 自定义拜月教主的血量和攻击力
print('【拜月教主】 \n 血量:100 \n 攻击力: 20')
print('-----------------------')
time.sleep(2)
# 人工计算拜月教主剩余血量 100 - 25 = 75
print('【李逍遥】向【拜月教主】发起了攻击,【拜月教主】剩余血量 75')
# 人工计算李逍遥剩余血量 100 - 20 = 80
print('【拜月教主】向【李逍遥】发起了攻击,【李逍遥】剩余血量 80')
print('-----------------------')
# 人工计算拜月教主剩余血量 75 -25 = 50
print('【李逍遥】向【拜月教主】发起了攻击,【拜月教主】剩余血量 50')
# 人工计算李逍遥剩余血量 80 -20 = 60
print('【拜月教主】向【李逍遥】发起了攻击,【李逍遥】剩余血量 60')
print('-----------------------')
time.sleep(2)
# 人工计算拜月教主剩余血量 50 - 25 = 25
print('【李逍遥】向【拜月教主】发起了攻击,【拜月教主】剩余血量 25')
# 人工计算李逍遥剩余血量 60 - 20 = 40
print('【拜月教主】向【李逍遥】发起了攻击,【李逍遥】剩余血量 40')
print('-----------------------')
time.sleep(2)
# 人工计算拜月教主剩余血量 25 -25 = 0,此时拜月教主血量为 0,拜月教主死亡,游戏结束。
print('【李逍遥】向【拜月教主】发起了攻击,【拜月教主】剩余血量 0')
# 人工计算李逍遥剩余血量 40 - 20 = 20
print('【拜月教主】向【李逍遥】发起了攻击,【李逍遥】剩余血量 20')
print('-----------------------')
time.sleep(2)
print('【拜月教主】死了,【李逍遥】赢了')
Yes! 看起来不错,总算完成了项目 1.0 。
但是你有没有发现,现在的代码有一点 low 。都是 print() 函数,并且还要自己手动计算剩余血量,结局也可以自己来确定,一点也不智能。
那我们就要来进行项目升级了。
接下来要改造两个方面:
1. 【李逍遥】和【拜月教主】的属性(血量和攻击力)让计算机进行随机指定;
2. 战斗过程中血量变化让计算机来计算。
随机属性,自动 PK
这个阶段,我们主要增加【随机属性】和【自动战斗】两个功能,画出流程图:
现在问题来了,要生成随机属性,也就是随机数字,怎么实现呢?
这里有一个可以解决大部分问题的方法 — 问度娘!
可以看到度娘有很多的答案,我们可以点击第一个进去看一下。
看到度娘告诉我们的答案,想生成随机数,要使用 random 随机数模块中的 randint(a,b) 函数,括号内为 a , b 两个数字为生成随机数的范围,a 是小数字,b 是大数字。
# 多运行几次,看看结果是不是随机生成的~
# 调用 random 模块
import random
# 随机生成 1-100 范围内(含 1 和 100 )的一个整数,并赋值给变量 num
num = random.randint(1, 100)
print(num) #结果为1-100的随机一个数字
好的,既然随机数已经搞定,那么接下来我们就需要把随机数引入到项目中了。
要求:
1. 定义两个变量,用来储存【李逍遥】的血量和攻击力;
2. 血量是 100-150 之间的随机数,攻击力是 20-30 之间的随机数;
3. 打印两个变量。
# 提示:调用模块需在开头写上 import 模块名,这里需要用到 random 模块
import random
#freeLi_life为李逍遥血量,freeLi_attack为李逍遥攻击。
freeLi_life = random.randint(100,150)
freeLi_attack = random.randint(20,30)
print(xue)
print(gong) #显示结果分别为100-150,20-30之间的任意一个数字
标准的变量名最好是用英文来表达含义,如果是多个单词组成,需要用英文下划线 “ _ ” 来隔开。
江湖秘籍:对于取英文变量名,很多英语水平还停留在高考时期的同学会感到头疼,这里我推荐大家一个网站:
CODELF,输入中文就可以看到别人是怎么命名的。(CODELF网址:https://unbug.github.io/codelf/)
已经能够随机生成【李逍遥】的血量和攻击力了,下面我们要生成【拜月教主】的血量和攻击力,完成随机生成两者属性的任务。
# 导入 time 库和 random 库,也可合并写成一行:import time, random
import time
import random
# 生成随机属性
# “freeLi_life” 代表李逍遥血量
freeLi_life = random.randint(100, 150)
# “freeLi_attack” 代表李逍遥攻击
freeLi_attack = random.randint(20, 30)
# “BOSS_life” 代表拜月教主血量
BOSS_life = random.randint(100, 150)
# “BOSS_attack” 代表拜月教主攻击
BOSS_attack = random.randint(20, 30)
# 展示双方角色的属性
# freeLi_life 和 freeLi_attack 的数据类型都是整数,所以拼接时需要先用 str() 转换
print('【李逍遥】\n 血量:%s \n 攻击力:%s' % (freeLi_life, freeLi_attack))
print('------------------------')
# 暂停一秒再执行后续代码
time.sleep(1)
print('【拜月教主】\n 血量:%s \n 攻击力:%s' % (BOSS_life, BOSS_attack))
print('------------------------')
截止到目前为止,我们已经解决了随机生成属性的问题,接下来,我们就要实现 “自动 PK ”。
要怎么实现自动战斗呢?如果一头雾水的话,可以先尝试从版本 1.0 的人为战斗来寻找规律:
可以发现从 【李逍遥】 攻击【拜月教主】到【拜月教主】回击的这几行代码是重复出现的结构,除了数字是变化的,其余的一模一样。
这时,根据我们已学知识,我们应该用循环语句来解决重复劳动。
现在是【李逍遥】和【拜月教主】双方互相攻击,到底要打斗多少次,不知道,打斗多长时间也不知道,只知道,有一个的血量为 0 时,战斗结束。只知道循环的条件,因此要用的就是 while 循环了。
进一步思考:while 后面要接什么条件呢,也就是说什么条件下,战斗过程会一直持续呢?
可见 while 后面要同时满足两个条件,即这两个条件要同时为真,所以我们要用 and 来连接,用代码来表示就是:
# and 两边用()括起来,更方便大家阅读。
while (freeLi_life > 0) and (BOSS_life > 0)
执行循环的条件已经找到了,接下来就是要设置 while 循环内部的执行代码了。
根据刚才的分析,我们希望循环的内容是双方互相攻击,掉血的过程。
print('【李逍遥】向【拜月教主】发起了攻击,【拜月教主】剩余血量 XXX')
print('【拜月教主】向【李逍遥】发起了攻击,【李逍遥】剩余血量 XXX')
print('------------------------')
其中【拜月教主】剩余血量 =【拜月教主】当前血量 -【李逍遥】攻击力,【李逍遥】剩余血量 =【李逍遥】当前血量 -【拜月教主】攻击力。
我们在前面已经定义好了这四个变量,每一次攻击后, freeLi_life (李逍遥血量)与 BOSS_life(拜月教主血量)都会重新赋值,代码就是:
# 赋值语句的执行顺序是先计算等号右边,再赋值给左边的变量
freeLi_life = freeLi_life - BOSS_attack
BOSS_life = BOSS_life - freeLi_attack
好的,自动攻击的基础逻辑也已经理清楚了。我们先合并一下这之前写过的代码。
# 导入 time 库和 random 库,也可合并写成一行:import time, random
import time
import random
# 生成随机属性
# “freeLi_life” 代表李逍遥血量
freeLi_life = random.randint(100, 150)
# “freeLi_attack” 代表李逍遥攻击
freeLi_attack = random.randint(20, 30)
# “BOSS_life” 代表拜月教主血量
BOSS_life = random.randint(100, 150)
# “BOSS_attack” 代表拜月教主攻击
BOSS_attack = random.randint(20, 30)
# 展示双方角色的属性
# freeLi_life 和 freeLi_attack 的数据类型都是整数,所以拼接时需要先用 str() 转换
print('【李逍遥】 \n 血量:%s \n 攻击力:%s' % (freeLi_life, freeLi_attack))
print('------------------------')
# 暂停一秒再执行后续代码
time.sleep(1)
print('【拜月教主】\n 血量:%s \n 攻击力:%s' % (BOSS_life, BOSS_attack))
print('------------------------')
# 自动 PK 阶段
while (freeLi_life > 0) and (BOSS_life > 0):
freeLi_life = freeLi_life - BOSS_attack
BOSS_life = BOSS_life - freeLi_attack
写到这里,就只剩下补完 while 循环中的内容,也就是实时打印【李逍遥】与【拜月教主】的剩余血量。
print('【李逍遥】向【拜月教主】发起了攻击,【拜月教主】剩余血量XXX')
print('【拜月教主】向【李逍遥】发起了攻击,【李逍遥】剩余血量XXX')
print('------------------------')
合成后:
# 导入 time 库和 random 库,也可合并写成一行:import time, random
import time
import random
# 生成随机属性
# “freeLi_life” 代表李逍遥血量
freeLi_life = random.randint(100, 150)
# “freeLi_attack” 代表李逍遥攻击
freeLi_attack = random.randint(20, 30)
# “BOSS_life” 代表拜月教主血量
BOSS_life = random.randint(100, 150)
# “BOSS_attack” 代表拜月教主攻击
BOSS_attack = random.randint(20, 30)
# 展示双方角色的属性
# freeLi_life 和 freeLi_attack 的数据类型都是整数,所以拼接时需要先用 str() 转换
print('【李逍遥】 \n 血量:%s \n 攻击力:%s' % (freeLi_life, freeLi_attack))
print('------------------------')
# 暂停一秒再执行后续代码
time.sleep(1)
print('【拜月教主】 \n 血量:%s \n 攻击力:%s' % (BOSS_life, BOSS_attack))
print('------------------------')
# 自动 PK 阶段
while (freeLi_life > 0) and (BOSS_life > 0):
freeLi_life = freeLi_life - BOSS_attack
BOSS_life = BOSS_life - freeLi_attack
print('【李逍遥】向【拜月教主】发起了攻击,【拜月教主】剩余血量' + str(BOSS_life))
# freeLi_life 是整数,所以拼接时要先用 str() 转换
print('【拜月教主】向【李逍遥】发起了攻击,【李逍遥】剩余血量' + str(freeLi_life))
print('------------------------')
# 为了体现出战斗回合,这里停顿 2 秒
time.sleep(2)
2.0 版本总算完成的差不多了。
不过它还没有实现:打印出每局结果,三局两胜,并打印最终战果的功能。这就是我们在版本 3.0 要增加的功能。
我们一鼓作气,攻克最后一个难关!
打印战果,三局两胜
对比 2.0 版本,在 3.0 版本中,我们想要增加的功能是:
1、打印战果:每局战斗后,根据胜负平的结果打印出不同的提示;
2、三局两胜:双方战斗三局,胜局多的为最终赢家。
我们首先来完成战果的打印。
当【李逍遥】与【拜月教主】PK 的时候,血量都会开始递减,经过多次攻击,会出现如下结果:
根据上面图片的提示,我们可以想到的这部分代码如下:
if freeLi_life > 0 and BOSS_life <= 0:
print('【拜月教主】挂了,【李逍遥】赢了')
elif freeLi_life <= 0 and BOSS_life > 0:
print('悲催,【拜月教主】把【李逍遥】干掉了!')
else:
print('哎呀,【李逍遥】和【拜月教主】同归于尽了!')
合成后:
# 导入 time 库和 random 库,也可合并写成一行:import time, random
import time
import random
# 生成随机属性
# “freeLi_life” 代表李逍遥血量
freeLi_life = random.randint(100, 150)
# “freeLi_attack” 代表李逍遥攻击
freeLi_attack = random.randint(20, 30)
# “BOSS_life” 代表拜月教主血量
BOSS_life = random.randint(100, 150)
# “BOSS_attack” 代表拜月教主攻击
BOSS_attack = random.randint(20, 30)
# 展示双方角色的属性
# freeLi_life 和 freeLi_attack 的数据类型都是整数,所以拼接时需要先用 str() 转换
print('【李逍遥】 \n 血量:%s \n 攻击力:%s' % (freeLi_life, freeLi_attack))
print('------------------------')
# 暂停一秒再执行后续代码
time.sleep(1)
print('【拜月教主】 \n 血量:%s \n 攻击力:%s' % (BOSS_life, BOSS_attack))
print('------------------------')
# 自动 PK 阶段
while (freeLi_life > 0) and (BOSS_life > 0):
freeLi_life = freeLi_life - BOSS_attack
BOSS_life = BOSS_life - freeLi_attack
print('【李逍遥】向【拜月教主】发起了攻击,【拜月教主】剩余血量'+str(BOSS_life))
print('【拜月教主】向【李逍遥】发起了攻击,【李逍遥】剩余血量'+str(freeLi_life))
print('------------------------')
# 为了体现出战斗回合,这里停顿 2 秒
time.sleep(2)
# 打印战果
if freeLi_life > 0 and BOSS_life <= 0:
print('【拜月教主】挂了,【李逍遥】赢了')
elif freeLi_life <= 0 and BOSS_life > 0:
print('悲催,【拜月教主】把【李逍遥】干掉了!')
else:
print('哎呀,【李逍遥】和【拜月教主】同归于尽了!')
现在只剩下最后一步,三局两胜。
怎么来实现三局两胜呢?
首先来看,三局战斗也是一个可以循环的结构,且循环次数是固定的,所以要用到 for 循环。
在这里我们可以使用 for i in range( ): 的结构,我们先来回顾一下之前学过的 range() 函数。
range(a, b, c) :
a : 计数从 a 开始。不填时,默认从 0 开始,例如:range(1, 5), 表示从 1 开始生成;
b : 计数到 b 结束,但不包括 b ,例如:range(11), 表示从 0 开始生成到 11 结束,不包括 11;
c : 计数的间隔,不填时默认为 1 ,例如:range(0, 30, 5), 表示计数间隔为 5。
尝试把代码打出来吧,让战斗循环三局。(先不用统计最后的结果)
给两个提示:
1. 想清楚哪些代码要嵌套到 for 循环里,即一局战斗里包括什么信息。确定了 for 写在哪里之后,一局战斗包含的所有信息都要缩进;
2. 细节也需要留意,如局与局之间要怎么区分开来(时间间隔 & 打印局数信息)
# 导入 time 库和 random 库,也可合并写成一行:import time, random
import time
import random
for i in range(1, 4):
time.sleep(1)
# 让局与局之间有较明显的有时间间隔
print(' \n——————现在进行第' + str(i) + '局,3,2,1,go!——————') # 作为局的标记
# 生成随机属性
# “freeLi_life” 代表李逍遥血量
freeLi_life = random.randint(100, 150)
# “freeLi_attack” 代表李逍遥攻击
freeLi_attack = random.randint(20, 30)
# “BOSS_life” 代表拜月教主血量
BOSS_life = random.randint(100, 150)
# “BOSS_attack” 代表拜月教主攻击
BOSS_attack = random.randint(20, 30)
# 展示双方角色的属性
# freeLi_life 和 freeLi_attack 的数据类型都是整数,所以拼接时需要先用 str() 转换
print('【李逍遥】 \n 血量:%s \n 攻击力:%s' % (freeLi_life, freeLi_attack))
print('------------------------')
# 暂停一秒再执行后续代码
time.sleep(1)
print('【拜月教主】 \n 血量:%s \n 攻击力:%s' % (BOSS_life, BOSS_attack))
print('------------------------')
# 自动 PK 阶段
while (freeLi_life > 0) and (BOSS_life > 0):
freeLi_life = freeLi_life - BOSS_attack
BOSS_life = BOSS_life - freeLi_attack
print('【李逍遥】向【拜月教主】发起了攻击,【拜月教主】剩余血量' + str(BOSS_life))
# freeLi_life 是整数,所以拼接时要先用 str() 转换
print('【拜月教主】向【李逍遥】发起了攻击,【李逍遥】剩余血量' + str(freeLi_life))
print('------------------------')
# 为了体现出战斗回合,这里停顿 2 秒
time.sleep(2)
# 打印战果
if freeLi_life > 0 and BOSS_life <= 0:
print('【拜月教主】挂了,【李逍遥】赢了')
elif freeLi_life <= 0 and BOSS_life > 0:
print('悲催,【拜月教主】把【李逍遥】干掉了!')
else:
print('哎呀,【李逍遥】和【拜月教主】同归于尽了!')
三局比赛的效果已经完成, 现在只差 “统计三局两胜” 的结果了。
平时比赛如何记录比赛结果呢?
好比乒乓球比赛,有一方赢了一局就翻一下计分牌,让数字 + 1,最后看哪边的数字大就是哪边获胜。
既然记录得分,首先要给计算机一个空白的 “计分牌”, 用于存放【李逍遥】和【拜月教主】的每一局得分。
# 存放李逍遥赢的局数。
freeLi_score = 0
# 存放拜月教主赢的局数
BOSS_score = 0
现在我们有了空白的 “计分牌” ,那么,在什么情况下得分才会 +1 呢?当然每一局比赛完成之后,我们去增加得分。
if freeLi_life > 0 and BOSS_life <= 0:
freeLi_score = freeLi_score + 1
print('【拜月教主】挂了,【李逍遥】赢了')
elif freeLi_life <= 0 and BOSS_life > 0:
BOSS_score = BOSS_score + 1
print('悲催,【拜月教主】把【李逍遥】干掉了!')
else:
print('哎呀,【李逍遥】和【拜月教主】同归于尽了!')
接下来,我们来将【李逍遥】和【拜月教主】各自赢得局数算出来。
# 导入 time 库和 random 库,也可合并写成一行:import time, random
import time
import random
# 存放李逍遥赢的局数。
freeLi_score = 0
# 存放拜月教主赢的局数
BOSS_score = 0
for i in range(1, 4):
time.sleep(1) # 让局与局之间有较明显的有时间间隔
print(' \n——————现在进行第' + str(i) + '局,3,2,1,go!——————') # 作为局的标记
# 生成随机属性
# “freeLi_life” 代表李逍遥血量
freeLi_life = random.randint(100, 150)
# “freeLi_attack” 代表李逍遥攻击
freeLi_attack = random.randint(20, 30)
# “BOSS_life” 代表拜月教主血量
BOSS_life = random.randint(100, 150)
# “BOSS_attack” 代表拜月教主攻击
BOSS_attack = random.randint(20, 30)
# 展示双方角色的属性
# freeLi_life 和 freeLi_attack 的数据类型都是整数,所以拼接时需要先用 str() 转换
print('【李逍遥】 \n 血量:%s \n 攻击力:%s' % (freeLi_life, freeLi_attack))
print('------------------------')
# 暂停一秒再执行后续代码
time.sleep(1)
print('【拜月教主】 \n 血量:%s \n 攻击力:%s' % (BOSS_life, BOSS_attack))
print('------------------------')
# 自动 PK 阶段
while (freeLi_life > 0) and (BOSS_life > 0):
freeLi_life = freeLi_life - BOSS_attack
BOSS_life = BOSS_life - freeLi_attack
print('【李逍遥】向【拜月教主】发起了攻击,【拜月教主】剩余血量' + str(BOSS_life))
# freeLi_life 是整数,所以拼接时要先用 str() 转换
print('【拜月教主】向【李逍遥】发起了攻击,【李逍遥】剩余血量' + str(freeLi_life))
print('------------------------')
# 为了体现出战斗回合,这里停顿 2 秒
time.sleep(2)
# 打印结果
if freeLi_life > 0 and BOSS_life <= 0:
freeLi_score = freeLi_score + 1
print('【拜月教主】挂了,【李逍遥】赢了')
elif freeLi_life <= 0 and BOSS_life > 0:
BOSS_score = BOSS_score + 1
print('悲催,【拜月教主】把【李逍遥】干掉了!')
else:
print('哎呀,【李逍遥】和【拜月教主】同归于尽了!')
这样三局过后,freeLi_score 和 BOSS_score 会被赋上新的值。给你一个小技巧:
freeLi_score = freeLi_score + 1,总是这样写有点烦人,我们可以写作 freeLi_score += 1,这两个代码是等价的,都代表 “如果 if 后的条件满足,变量就 +1” 。如下:
# 打印结果
if freeLi_life > 0 and BOSS_life <= 0:
freeLi_score += 1
print('【拜月教主】挂了,【李逍遥】赢了')
elif freeLi_life <= 0 and BOSS_life > 0:
BOSS_score += 1
print('悲催,【拜月教主】把【李逍遥】干掉了!')
else:
print('哎呀,【李逍遥】和【拜月教主】同归于尽了!')
最后,再做一次判断,比较一下【李逍遥】赢得局数和【拜月教主】赢得局数。
看到上面分析情况,需要注意得是,因为你是最后需要判断三局两胜的结果,你就需要把最终结果的判断放在 for 循环的外面,不要缩进。
# 导入 time 库和 random 库,也可合并写成一行:import time, random
import time
import random
# 存放李逍遥赢的局数。
freeLi_score = 0
# 存放拜月教主赢的局数
BOSS_score = 0
for i in range(1, 4):
time.sleep(1) # 让局与局之间有较明显的有时间间隔
print(' \n——————现在进行第' + str(i) + '局,3,2,1,go!——————') # 作为局的标记
# 生成随机属性
# “freeLi_life” 代表李逍遥血量
freeLi_life = random.randint(100, 150)
# “freeLi_attack” 代表李逍遥攻击
freeLi_attack = random.randint(20, 30)
# “BOSS_life” 代表拜月教主血量
BOSS_life = random.randint(100, 150)
# “BOSS_attack” 代表拜月教主攻击
BOSS_attack = random.randint(20, 30)
# 展示双方角色的属性
# freeLi_life 和 freeLi_attack 的数据类型都是整数,所以拼接时需要先用 str() 转换
print('【李逍遥】\n 血量:%s \n 攻击力:%s' % (freeLi_life, freeLi_attack))
print('------------------------')
# 暂停一秒再执行后续代码
time.sleep(1)
print('【拜月教主】 \n 血量:%s \n 攻击力:%s' % (BOSS_life, BOSS_attack))
print('------------------------')
# 自动 PK 阶段
while (freeLi_life > 0) and (BOSS_life > 0):
freeLi_life = freeLi_life - BOSS_attack
BOSS_life = BOSS_life - freeLi_attack
print('【李逍遥】向【拜月教主】发起了攻击,【拜月教主】剩余血量' + str(BOSS_life))
# freeLi_life 是整数,所以拼接时要先用 str() 转换
print('【拜月教主】向【李逍遥】发起了攻击,【李逍遥】剩余血量' + str(freeLi_life))
print('------------------------')
# 为了体现出战斗回合,这里停顿 2 秒
time.sleep(2)
# 打印结果
if freeLi_life > 0 and BOSS_life <= 0:
freeLi_score = freeLi_score + 1
print('【拜月教主】挂了,【李逍遥】赢了')
elif freeLi_life <= 0 and BOSS_life > 0:
BOSS_score = BOSS_score + 1
print('悲催,【拜月教主】把【李逍遥】干掉了!')
else:
print('哎呀,【李逍遥】和【拜月教主】同归于尽了!')
if freeLi_score > BOSS_score:
time.sleep(1)
print('【 大战3个回合:李逍遥赢了!】')
elif BOSS_score > freeLi_score:
print('【大战3个回合:李逍遥输了!】')
else:
print('【大战3个回合:平局!】')
好了,项目已经做完了,但还是要追求尽善尽美。有个地方需要【格式化字符串】。
什么叫格式化字符串?
下面有这么两行代码,是用来展示双方角色的属性的:
print('【李逍遥】' + '血量:' + str(freeLi_life) + '攻击:' + str(freeLi_attack))
print('【拜月教主】' + '血量:' + str(BOSS_life) + '攻击:' + str(BOSS_attack))
我们在用 + 拼接字符串和变量的时候,常常需要考虑变量是什么类型的数据,如果不是字符串类型,还先需要
str() 函数转换,然后再拼接。 这里才有两个变量,就使用 【”】 开始包裹拼接,好麻烦。
Python 为我们提供了一种不同数据类型的拼接方式,使用【格式符 %】来处理。
如上图,我们看到格式符 % 后面有一个字母,这个字母用来控制数据显示的类型。【%s】就是占住这个位置,将变量转换成字符串。
那么我们项目中的代码就可以改成:
print('【李逍遥】\n 血量: %s \n 攻击力:%s' % (freeLi_life, freeLi_attack))
print('【拜月教主】\n 血量:%s \n 攻击力:%s' % (BOSS_life, BOSS_attack))
看一下,是不是代码更好读了。
# 导入 time 库和 random 库,也可合并写成一行:import time, random
import time
import random
# 存放李逍遥赢的局数。
freeLi_score = 0
# 存放拜月教主赢的局数
BOSS_score = 0
for i in range(1, 4):
time.sleep(1) # 让局与局之间有较明显的有时间间隔
print(' \n——————现在进行第' + str(i) + '局,3,2,1,go!——————') # 作为局的标记
# 生成随机属性
# “freeLi_life” 代表李逍遥血量
freeLi_life = random.randint(100, 150)
# “freeLi_attack” 代表李逍遥攻击
freeLi_attack = random.randint(20, 30)
# “BOSS_life” 代表拜月教主血量
BOSS_life = random.randint(100, 150)
# “BOSS_attack” 代表拜月教主攻击
BOSS_attack = random.randint(20, 30)
# 展示双方角色的属性
# freeLi_life 和 freeLi_attack 的数据类型都是整数,所以拼接时需要先用 str() 转换
print('【李逍遥】 \n 血量:%s \n 攻击力:%s' % (freeLi_life, freeLi_attack))
print('------------------------')
# 暂停一秒再执行后续代码
time.sleep(1)
print('【拜月教主】\n 血量:%s \n 攻击力:%s' % (BOSS_life, BOSS_attack))
print('------------------------')
# 自动 PK 阶段
while (freeLi_life > 0) and (BOSS_life > 0):
freeLi_life = freeLi_life - BOSS_attack
BOSS_life = BOSS_life - freeLi_attack
print('【李逍遥】向【拜月教主】发起了攻击,【拜月教主】剩余血量' + str(BOSS_life))
# freeLi_life 是整数,所以拼接时要先用 str() 转换
print('【拜月教主】向【李逍遥】发起了攻击,【李逍遥】剩余血量' + str(freeLi_life))
print('------------------------')
# 为了体现出战斗回合,这里停顿 2 秒
time.sleep(2)
# 打印结果
if freeLi_life > 0 and BOSS_life <= 0:
freeLi_score = freeLi_score + 1
print('【拜月教主】挂了,【李逍遥】赢了')
elif freeLi_life <= 0 and BOSS_life > 0:
BOSS_score = BOSS_score + 1
print('悲催,【拜月教主】把【李逍遥】干掉了!')
else:
print('哎呀,【李逍遥】和【拜月教主】同归于尽了!')
if freeLi_score > BOSS_score:
time.sleep(1)
print('【 大战3个回合:李逍遥赢了!】')
elif BOSS_score > freeLi_score:
print('【大战3个回合:李逍遥输了!】')
else:
print('【大战3个回合:平局!】')
代码结构是不是清爽了很多~
江湖秘籍:【%】后面的类型码用什么,取决于你希望这个【%】占住的这个位置的数据以什么类型展示出来,如果你希望它以字符串形式展示,那就写【%s】,如果你希望它以整数形式展示,那就写【%d】。
最后再来回顾一下做项目流程: