各位友们,我又来了,当然还是和前面那篇文——"猜数字"有关。今年天这篇文主要是为了解决其中的一个问题。
我先把大致情况介绍一下,是这样的:在那篇文里,我想实现一个让用户自己决定退出系统的效果。想看原文的,直接点击链接进行浏览,找不到链接的,去我主页,找:《一个简单的python小例子(内附简单的知识介绍)》。
我当时的实现思路是这样的:最初只是想通过一个if判断语句进行选择“是/Yy/yes”和“否/N/n/no”来决定要不要退出该游戏。可是后来发现,这样做并没有实现预期效果,因为我最后实现的效果是,除了“是/Y/y/yes”以外的所有输入内容都会重新开始游戏。所以我就想,应该还要有一个限制,就是,如果用户输入的内容不在“是/Y/y/yes/否/N/n/no”这个范围内,会重新进行这个过程,让用户输入这里的内容。说白了,就是给这个过程加一个循环。而且这个循环还应该是while循环,因为for循环对循环的次数有明确要求,而我这个是不能限制次数的,所以不能用for循环。这样看起来问题好像解决了,但是当我把代码写好之后,又发现一个问题。这个问题就是:因为我又加了一个循环,导致原来的判断语句中的break和continue无法产生相同的效果了,因为这个时候我们要求它们必须要达到控制外层循环的目的。
看文的似乎已经开始烦了,一上来说这么多,啥也没有,不过大家不要着急,我这么做的目的也是为了照顾到看过我前两篇文的小伙伴们。
下面,直接上干货:
怎么让break和continue控制它们所在的外层循环?
首先,我们都知道:不论是直接让循环结束的break,还是跳过单次循环的continue,它们都只能控制自身所在的本层循环,无法控制外层循环。那就有人问了,如果我有这个需求时怎么办?
所以,我们不能把希望寄托于如何改造break和continue的使用方法上面,而是通过其他办法,借助这两个跳出循环的语句进行控制。
我先把原来的那个代码搬过来:
# 登陆账号和密码并进入猜数字游戏
import random
print("您一共可以输入三次账号和密码,三次以内输入正确,即可开始游戏")
for i in range(1, 4):
f = input("请输入您的账号:")
g = input("请输入您的密码:")
if f == "123456789" and g == "666666":
print("账号和密码输入正确!")
while True:
a = random.randint(1, 20)
print('猜数字游戏现在开始。\n您可以在1到20以内任选一个整数,您一共有5次机会')
for j in range(1, 6):
b = input('请输入数字:')
if b in ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "15", "16", "17", "18", "19", "20"]:
if int(b) > a:
print("大了")
elif int(b) < a:
print("小了")
else:
print('恭喜你,猜对了!')
print('正确答案是:', a)
break
else:
print('请在规定的范围内选择数字,您还剩', 5-j, '次机会')
if j == 5:
print("您的猜数字机会已经用完,谢谢您的参与!")
print('正确答案是:', a)
c = input('是否退出游戏?,是(Y/y/yes)/否(N/n/no)')
if c == '是' or c == 'Y' or c == 'y' or c == 'yes':
break
else:
continue
break
else:
print("账号或密码输入错误,请重新输入")
if i == 3:
print("您的输入次数已经用完,请重新开始游戏")
下面我再把改过之后的代码搬过来:
# 登陆账号和密码并进入猜数字游戏
import random
print("您一共可以输入三次账号和密码,三次以内输入正确,即可开始游戏")
lst1 = ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10"]
lst2 = ["11", "12", "13", "14", "15", "16", "17", "18", "19", "20"]
lst = lst1 + lst2 # 合并列表
# print(lst)
for i in range(1, 4):
f = input("请输入您的账号:")
g = input("请输入您的密码:")
if f == "123456789" and g == "666666":
print("账号和密码输入正确!")
while True:
a = random.randint(1, 20)
print('猜数字游戏现在开始。\n您可以在1到20以内任选一个整数,您一共有5次机会')
for j in range(1, 6):
b = input('请输入数字:')
if b in lst:
if int(b) > a:
print("大了")
elif int(b) < a:
print("小了")
else:
print('恭喜你,猜对了!')
print('正确答案是:', a)
break
else:
print('请在规定的范围内选择数字,您还剩', 5-j, '次机会')
if j == 5:
print("您的猜数字机会已经用完,谢谢您的参与!")
print('正确答案是:', a)
while True:
c = input('是否退出游戏?,是(Y/y/yes)/否(N/n/no)')
if c == '是' or c == 'Y' or c == 'y' or c == 'yes':
tag = 1
break
elif c == '否' or c == 'N' or c == 'n' or c == 'no':
tag = 2
break
else:
print('输入内容无效,请重新输入')
# else:
# continue
if tag == 1:
break
elif tag == 2:
continue
break
else:
print("账号或密码输入错误,请重新输入")
if i == 3:
print("您的输入次数已经用完,请重新开始游戏")
首先,大家可以观察到有两个地方发生了变化。
1.列表的书写方式,这个是考虑到了我在前面的文章里说的那个问题,就是编译器对每一行代码的书写是有限制的,每一行不能够超过120个字符(相关介绍,可以看这篇文哦:更改字符数的限制和优化代码书写方式的办法)。所以,在这里我也把这个问题顺带着解决了。
2.这个呢,就是我们本篇文重点介绍的问题,关于跳出外层循环的办法,下面我将介绍一下,它是怎么实现的(有基础的伙伴们可以直接跳过这个过程,自己去分析代码发生了什么变化,这样要比我带着你们一步一步分析效果更好)。
首先,按照前面说的,我们要加一个while循环,然后将原来的代码向后移动一个水平制表符的距离(没办法,python就是通过缩进来表示代码的逻辑关系的),
接着就是把里面的判断语句做一下更改,我们按照前面的描述,多添加一个判断语句,于是,原来的两种情况现在变成了三种情况:一是退出,二是继续,三是输入内容无效,然后重新输入。
继续看,大家会发现,原来的判断语句里除了控制循环的两兄弟是没有其他任何内容的,而现在,我们在这里多加了赋值语句,而且两种情况赋值并不相等,这么做正是为了区分。当然你赋成其他任何值都可以,但是要保证下面的一定要和上面的一致且对应。然后就是这里面都变成了break,因为这里我们不对它进行任何判断,只需要分出两条路就可以了。
再往下,就是咱们真正实现控制的结构了,细心的同学会发现:这里又有一个被我注释掉的else结构。根据python的结构特点,很容易就能够看出来这个else是和上面新加的while搭配的。至于我为什么把它注释掉,我不做解释,留给大家思考(有点像老师了哈哈)。
在这个循环下面和它并列的是两个判断语句,很明显,这个时候,我们已经退出内层循环了。然后根据判断,就很清晰了,我们按照原来的赋值进行判断,从if语句过来的就走if这条路;从elif语句过来的,就走elif(这里写成else也可以)这条路,这样我们的目的就达到了。
到这里,可能会有人问了:这不还是break和continue控制了自身所在的循环吗?这也不是控制外层循环啊。
关于这个问题,我想说的是:我在文章开始也说过了,我们不可能更改break和continue本身所具有的属性,说白了,我们要做的就是想办法让里面的循环去控制外面的循环,而且也并没有规定非要让break和continue去控制。大家很容易也都能看出来:break和continue只是起到了辅助作用,实现了效果,真正的诱因还是在内层循环的赋值语句。或者也可以这样理解:内层循环实现了一个筛选的过程,让外层循环听它的话,按照内层循环的要求进行。所以,本篇文只不过相当于介绍了一种方法来解决内层循环的break和continue无法控制外层循环的问题。
最后,我再给大家留一个小问题:怎么跳出break和continue所在的三层循环呢?
欢迎大家把你的答案留在评论区哦