166 lines
6.8 KiB
Markdown
166 lines
6.8 KiB
Markdown
|
## 第07课:分支和循环结构的应用
|
|||
|
|
|||
|
通过上两节课的学习,大家对Python中的分支和循环结构已经有了感性的认识。**分支和循环结构**的重要性不言而喻,它**是构造程序逻辑的基础**,对于初学者来说也是比较困难的部分。大部分初学者在学习了分支和循环结构后都能理解它们的用途和用法,但是遇到实际问题的时候又无法下手;**看懂别人的代码很容易,但是要自己写出同样的代码却又很难**。如果你也有同样的问题和困惑,千万不要沮丧,这只是因为你才刚刚开始编程之旅,**你的练习量还没有达到让你可以随心所欲的写出代码的程度**,只要加强编程练习,这个问题迟早都会解决的。下面我们就为大家讲解一些经典的案例。
|
|||
|
|
|||
|
### 经典小案例
|
|||
|
|
|||
|
#### 例子1:寻找水仙花数。
|
|||
|
|
|||
|
> **说明**:水仙花数也被称为超完全数字不变数、自恋数、自幂数、阿姆斯特朗数,它是一个3位数,该数字每个位上数字的立方之和正好等于它本身,例如:$ 153=1^3+5^3+3^3 $。
|
|||
|
|
|||
|
这个题目的关键是将一个三位数拆分为个位、十位、百位,这一点利用Python中的`//`(整除)和`%`(求模)运算符其实很容易做到,代码如下所示。
|
|||
|
|
|||
|
```Python
|
|||
|
"""
|
|||
|
找出所有水仙花数
|
|||
|
|
|||
|
Version: 0.1
|
|||
|
Author: 骆昊
|
|||
|
"""
|
|||
|
for num in range(100, 1000):
|
|||
|
low = num % 10
|
|||
|
mid = num // 10 % 10
|
|||
|
high = num // 100
|
|||
|
if num == low ** 3 + mid ** 3 + high ** 3:
|
|||
|
print(num)
|
|||
|
```
|
|||
|
|
|||
|
上面利用`//`和`%`拆分一个数的小技巧在写代码的时候还是很常用的。我们要将一个不知道有多少位的正整数进行反转,例如将`12345`变成`54321`,也可以利用这两个运算来实现,代码如下所示。
|
|||
|
|
|||
|
```Python
|
|||
|
"""
|
|||
|
正整数的反转
|
|||
|
|
|||
|
Version: 0.1
|
|||
|
Author: 骆昊
|
|||
|
"""
|
|||
|
num = int(input('num = '))
|
|||
|
reversed_num = 0
|
|||
|
while num > 0:
|
|||
|
reversed_num = reversed_num * 10 + num % 10
|
|||
|
num //= 10
|
|||
|
print(reversed_num)
|
|||
|
```
|
|||
|
|
|||
|
#### 例子2:百钱百鸡问题。
|
|||
|
|
|||
|
> **说明**:百钱百鸡是我国古代数学家[张丘建](https://baike.baidu.com/item/%E5%BC%A0%E4%B8%98%E5%BB%BA/10246238)在《算经》一书中提出的数学问题:鸡翁一值钱五,鸡母一值钱三,鸡雏三值钱一。百钱买百鸡,问鸡翁、鸡母、鸡雏各几何?翻译成现代文是:公鸡5元一只,母鸡3元一只,小鸡1元三只,用100块钱买一百只鸡,问公鸡、母鸡、小鸡各有多少只?
|
|||
|
|
|||
|
```Python
|
|||
|
"""
|
|||
|
《百钱百鸡》问题
|
|||
|
|
|||
|
Version: 0.1
|
|||
|
Author: 骆昊
|
|||
|
"""
|
|||
|
# 假设公鸡的数量为x,x的取值范围是0到20
|
|||
|
for x in range(0, 21):
|
|||
|
# 假设母鸡的数量为y,y的取值范围是0到33
|
|||
|
for y in range(0, 34):
|
|||
|
z = 100 - x - y
|
|||
|
if 5 * x + 3 * y + z // 3 == 100 and z % 3 == 0:
|
|||
|
print(f'公鸡: {x}只, 母鸡: {y}只, 小鸡: {z}只')
|
|||
|
```
|
|||
|
|
|||
|
上面使用的方法叫做**穷举法**,也称为**暴力搜索法**,这种方法通过一项一项的列举备选解决方案中所有可能的候选项并检查每个候选项是否符合问题的描述,最终得到问题的解。这种方法看起来比较笨拙,但对于运算能力非常强大的计算机来说,通常都是一个可行的甚至是不错的选择,只要问题的解存在就能够找到它。
|
|||
|
|
|||
|
#### 例子3:CRAPS赌博游戏。
|
|||
|
|
|||
|
> **说明**:CRAPS又称花旗骰,是美国拉斯维加斯非常受欢迎的一种的桌上赌博游戏。该游戏使用两粒骰子,玩家通过摇两粒骰子获得点数进行游戏。简化后的规则是:玩家第一次摇骰子如果摇出了7点或11点,玩家胜;玩家第一次如果摇出2点、3点或12点,庄家胜;玩家如果摇出其他点数则玩家继续摇骰子,如果玩家摇出了7点,庄家胜;如果玩家摇出了第一次摇的点数,玩家胜;其他点数玩家继续摇骰子,直到分出胜负。
|
|||
|
|
|||
|
```Python
|
|||
|
"""
|
|||
|
Craps赌博游戏
|
|||
|
我们设定游戏开始时玩家有1000元的赌注
|
|||
|
游戏结束的条件是玩家破产(输光所有的赌注)
|
|||
|
|
|||
|
Version: 0.1
|
|||
|
Author: 骆昊
|
|||
|
"""
|
|||
|
from random import randint
|
|||
|
|
|||
|
money = 1000
|
|||
|
while money > 0:
|
|||
|
print(f'你的总资产为: {money}元')
|
|||
|
go_on = False
|
|||
|
# 下注金额必须大于0小于等于玩家总资产
|
|||
|
while True:
|
|||
|
debt = int(input('请下注: '))
|
|||
|
if 0 < debt <= money:
|
|||
|
break
|
|||
|
# 第一次摇色子
|
|||
|
# 用1到6均匀分布的随机数模拟摇色子得到的点数
|
|||
|
first = randint(1, 6) + randint(1, 6)
|
|||
|
print(f'\n玩家摇出了{first}点')
|
|||
|
if first == 7 or first == 11:
|
|||
|
print('玩家胜!\n')
|
|||
|
money += debt
|
|||
|
elif first == 2 or first == 3 or first == 12:
|
|||
|
print('庄家胜!\n')
|
|||
|
money -= debt
|
|||
|
else:
|
|||
|
go_on = True
|
|||
|
# 第一次摇色子没有分出胜负游戏继续
|
|||
|
while go_on:
|
|||
|
go_on = False
|
|||
|
current = randint(1, 6) + randint(1, 6)
|
|||
|
print(f'玩家摇出了{current}点')
|
|||
|
if current == 7:
|
|||
|
print('庄家胜!\n')
|
|||
|
money -= debt
|
|||
|
elif current == first:
|
|||
|
print('玩家胜!\n')
|
|||
|
money += debt
|
|||
|
else:
|
|||
|
go_on = True
|
|||
|
print('你破产了, 游戏结束!')
|
|||
|
```
|
|||
|
|
|||
|
#### 例子4:斐波那契数列。
|
|||
|
|
|||
|
> **说明**:斐波那契数列(Fibonacci sequence),通常也被称作黄金分割数列,是意大利数学家莱昂纳多·斐波那契(Leonardoda Fibonacci)在《计算之书》中研究在理想假设条件下兔子成长率问题而引入的数列,因此这个数列也常被戏称为“兔子数列”。斐波那契数列的特点是数列的前两个数都是1,从第三个数开始,每个数都是它前面两个数的和,按照这个规律,斐波那契数列的前10个数是:`1, 1, 2, 3, 5, 8, 13, 21, 34, 55`。斐波那契数列在现代物理、准晶体结构、化学等领域都有直接的应用。
|
|||
|
|
|||
|
```Python
|
|||
|
"""
|
|||
|
输出斐波那契数列前20个数
|
|||
|
|
|||
|
Version: 0.1
|
|||
|
Author: 骆昊
|
|||
|
"""
|
|||
|
|
|||
|
a, b = 0, 1
|
|||
|
for _ in range(20):
|
|||
|
a, b = b, a + b
|
|||
|
print(a)
|
|||
|
```
|
|||
|
|
|||
|
#### 例子5:打印100以内的素数。
|
|||
|
|
|||
|
> **说明**:素数指的是只能被1和自身整除的正整数(不包括1)。
|
|||
|
|
|||
|
```Python
|
|||
|
"""
|
|||
|
输出100以内的素数
|
|||
|
|
|||
|
Version: 0.1
|
|||
|
Author: 骆昊
|
|||
|
"""
|
|||
|
for num in range(2, 100):
|
|||
|
# 假设num是素数
|
|||
|
is_prime = True
|
|||
|
# 在2到num-1之间找num的因子
|
|||
|
for factor in range(2, num):
|
|||
|
# 如果找到了num的因子,num就不是素数
|
|||
|
if num % factor == 0:
|
|||
|
is_prime = False
|
|||
|
break
|
|||
|
# 如果布尔值为True在num是素数
|
|||
|
if is_prime:
|
|||
|
print(num)
|
|||
|
```
|
|||
|
|
|||
|
### 简单的总结
|
|||
|
|
|||
|
还是那句话:**分支结构和循环结构非常重要**,是构造程序逻辑的基础,**一定要通过大量的练习来达到融会贯通**。刚才讲到的CRAPS赌博游戏那个例子可以作为一个标准,如果你能很顺利的完成这段代码,那么分支和循环结构的知识你就已经掌握了。
|
|||
|
|