在这个纸牌益智游戏中,您必须使用三个水桶(三升、五升和八升的水桶)在其中一个水桶中收集正好四升水。桶只能被清空、完全装满或倒入另一个桶中。例如,你可以装满一个 5 升的桶,然后把里面的东西倒入 3 升的桶,这样你就有了一个满满的 3 升桶,5 升桶里有 2 升水。
经过一些努力,你应该能解决这个难题。但是你能想出如何用最少的步数解决它吗?
当您运行waterbucket.py时,输出将如下所示:
Water Bucket Puzzle, by Al Sweigart email@protected
Try to get 4L of water into one of these
buckets:
8| |
7| |
6| |
5| | 5| |
4| | 4| |
3| | 3| | 3| |
2| | 2| | 2| |
1| | 1| | 1| |
+------+ +------+ +------+
8L 5L 3L
You can:
(F)ill the bucket
(E)mpty the bucket
(P)our one bucket into another
(Q)uit
> f
Select a bucket 8, 5, 3, or QUIT:
> 5
Try to get 4L of water into one of these
buckets:
8| |
7| |
6| |
5| | 5|WWWWWW|
4| | 4|WWWWWW|
3| | 3|WWWWWW| 3| |
2| | 2|WWWWWW| 2| |
1| | 1|WWWWWW| 1| |
+------+ +------+ +------+
8L 5L 3L
`--snip--`waterInBucket变量存储了一个代表水桶状态的字典。这个字典的关键字是字符串'8'、'5'和'3'(代表水桶),它们的值是整数(代表水桶中的水的公升数)。
第 48 到 59 行使用这个字典在屏幕上呈现水桶和水。waterDisplay列表包含'WWWWWW'(代表水)或' '(代表空气),并被传递给format()字符串方法。waterDisplay列表中的前八串填充八升桶,接下来的五串填充五升桶,最后的三串填充三升桶。
"""Water Bucket Puzzle, by Al Sweigart email@protected
A water pouring puzzle.
More info: https://en.wikipedia.org/wiki/Water_pouring_puzzle
This code is available at https://nostarch.com/big-book-small-python-programming
Tags: large, game, math, puzzle"""
import sys
print('Water Bucket Puzzle, by Al Sweigart email@protected')
GOAL = 4 # The exact amount of water to have in a bucket to win.
steps = 0 # Keep track of how many steps the player made to solve this.
# The amount of water in each bucket:
waterInBucket = {'8': 0, '5': 0, '3': 0}
while True: # Main game loop.
# Display the current state of the buckets:
print()
print('Try to get ' + str(GOAL) + 'L of water into one of these')
print('buckets:')
waterDisplay = [] # Contains strings for water or empty space.
# Get the strings for the 8L bucket:
for i in range(1, 9):
if waterInBucket['8'] < i:
waterDisplay.append(' ') # Add empty space.
else:
waterDisplay.append('WWWWWW') # Add water.
# Get the strings for the 5L bucket:
for i in range(1, 6):
if waterInBucket['5'] < i:
waterDisplay.append(' ') # Add empty space.
else:
waterDisplay.append('WWWWWW') # Add water.
# Get the strings for the 3L bucket:
for i in range(1, 4):
if waterInBucket['3'] < i:
waterDisplay.append(' ') # Add empty space.
else:
waterDisplay.append('WWWWWW') # Add water.
# Display the buckets with the amount of water in each one:
print('''
8|{7}|
7|{6}|
6|{5}|
5|{4}| 5|{12}|
4|{3}| 4|{11}|
3|{2}| 3|{10}| 3|{15}|
2|{1}| 2|{9}| 2|{14}|
1|{0}| 1|{8}| 1|{13}|
+------+ +------+ +------+
8L 5L 3L
'''.format(*waterDisplay))
# Check if any of the buckets has the goal amount of water:
for waterAmount in waterInBucket.values():
if waterAmount == GOAL:
print('Good job! You solved it in', steps, 'steps!')
sys.exit()
# Let the player select an action to do with a bucket:
print('You can:')
print(' (F)ill the bucket')
print(' (E)mpty the bucket')
print(' (P)our one bucket into another')
print(' (Q)uit')
while True: # Keep asking until the player enters a valid action.
move = input('> ').upper()
if move == 'QUIT' or move == 'Q':
print('Thanks for playing!')
sys.exit()
if move in ('F', 'E', 'P'):
break # Player has selected a valid action.
print('Enter F, E, P, or Q')
# Let the player select a bucket:
while True: # Keep asking until valid bucket entered.
print('Select a bucket 8, 5, 3, or QUIT:')
srcBucket = input('> ').upper()
if srcBucket == 'QUIT':
print('Thanks for playing!')
sys.exit()
if srcBucket in ('8', '5', '3'):
break # Player has selected a valid bucket.
# Carry out the selected action:
if move == 'F':
# Set the amount of water to the max size.
srcBucketSize = int(srcBucket)
waterInBucket[srcBucket] = srcBucketSize
steps += 1
elif move == 'E':
waterInBucket[srcBucket] = 0 # Set water amount to nothing.
steps += 1
elif move == 'P':
# Let the player select a bucket to pour into:
while True: # Keep asking until valid bucket entered.
print('Select a bucket to pour into: 8, 5, or 3')
dstBucket = input('> ').upper()
if dstBucket in ('8', '5', '3'):
break # Player has selected a valid bucket.
# Figure out the amount to pour:
dstBucketSize = int(dstBucket)
emptySpaceInDstBucket = dstBucketSize - waterInBucket[dstBucket]
waterInSrcBucket = waterInBucket[srcBucket]
amountToPour = min(emptySpaceInDstBucket, waterInSrcBucket)
# Pour out water from this bucket:
waterInBucket[srcBucket] -= amountToPour
# Put the poured out water into the other bucket:
waterInBucket[dstBucket] += amountToPour
steps += 1
elif move == 'C':
pass # If the player selected Cancel, do nothing. 在输入源代码并运行几次之后,尝试对其进行实验性的修改。你也可以自己想办法做到以下几点:
- 通过使游戏可配置来增加多样性,这样你可以为三个桶指定任何大小,为目标数量指定任何数量。
- 添加“提示”,检查每个水桶中的水量,并提供下一步要采取的措施。如果程序不知道下一步该做什么,它可以简单地显示“我不知道你下一步该做什么。也许重新开始?”
试着找出下列问题的答案。尝试对代码进行一些修改,然后重新运行程序,看看这些修改有什么影响。
- 如果把 104 行的
waterInBucket[srcBucket] = 0改成waterInBucket[srcBucket] = 1会怎么样? - 如果把第 16 行的
{'8': 0, '5': 0, '3': 0}改成{'8': 0, '5': 4, '3': 0}会怎么样? - 如果把第 16 行的
{'8': 0, '5': 0, '3': 0}改成{'8': 9, '5': 0, '3': 0}会怎么样?
