Snail Race
You won’t be able to handle the fast-paced excitement of these racing . . . snails. But what they lack in speed they make up for in ASCII-art cuteness. Each snail (represented by an @ character for the shell and v for the two eyestalks) moves slowly but surely toward the finish line. Up to eight snails, each with a custom name, can race each other, leaving a slime trail in their wake. This program is good for beginners.
The Program in Action
When you run snailrace.py, the output will look like this:
Snail Race, by Al Sweigart [email protected]
@v <-- snail
How many snails will race? Max: 8
> 3
Enter snail #1's name:
> Alice
Enter snail #2's name:
> Bob
Enter snail #3's name:
> Carol
START FINISH
| |
Alice
......@v
Bob
.....@v
Carol
.......@v
--snip--
How It Works
This program makes use of two data structures, stored in two variables: snailNames is a list of strings of each snail’s name, and snailProgress is a dictionary whose keys are the snails’ names and whose values are integers representing how many spaces the snails have moved. Lines 79 to 82 read the data in these two variables to draw the snails at appropriate places on the screen.
1. """Snail Race, by Al Sweigart [email protected]
2. Fast-paced snail racing action!
3. View this code at https://nostarch.com/big-book-small-python-projects
4. Tags: short, artistic, beginner, game, multiplayer"""
5.
6. import random, time, sys
7.
8. # Set up the constants:
9. MAX_NUM_SNAILS = 8
10. MAX_NAME_LENGTH = 20
11. FINISH_LINE = 40 # (!) Try modifying this number.
12.
13. print('''Snail Race, by Al Sweigart [email protected]
14.
15. @v <-- snail
16.
17. ''')
18.
19. # Ask how many snails to race:
20. while True: # Keep asking until the player enters a number.
21. print('How many snails will race? Max:', MAX_NUM_SNAILS)
22. response = input('> ')
23. if response.isdecimal():
24. numSnailsRacing = int(response)
25. if 1 < numSnailsRacing <= MAX_NUM_SNAILS:
26. break
27. print('Enter a number between 2 and', MAX_NUM_SNAILS)
28.
29. # Enter the names of each snail:
30. snailNames = [] # List of the string snail names.
31. for i in range(1, numSnailsRacing + 1):
32. while True: # Keep asking until the player enters a valid name.
33. print('Enter snail #' + str(i) + "'s name:")
34. name = input('> ')
35. if len(name) == 0:
36. print('Please enter a name.')
37. elif name in snailNames:
38. print('Choose a name that has not already been used.')
39. else:
40. break # The entered name is acceptable.
41. snailNames.append(name)
42.
43. # Display each snail at the start line.
44. print('\n' * 40)
45. print('START' + (' ' * (FINISH_LINE - len('START')) + 'FINISH'))
46. print('|' + (' ' * (FINISH_LINE - len('|')) + '|'))
47. snailProgress = {}
48. for snailName in snailNames:
49. print(snailName[:MAX_NAME_LENGTH])
50. print('@v')
51. snailProgress[snailName] = 0
52.
53. time.sleep(1.5) # The pause right before the race starts.
54.
55. while True: # Main program loop.
56. # Pick random snails to move forward:
57. for i in range(random.randint(1, numSnailsRacing // 2)):
58. randomSnailName = random.choice(snailNames)
59. snailProgress[randomSnailName] += 1
60.
61. # Check if a snail has reached the finish line:
62. if snailProgress[randomSnailName] == FINISH_LINE:
63. print(randomSnailName, 'has won!')
64. sys.exit()
65.
66. # (!) EXPERIMENT: Add a cheat here that increases a snail's progress
67. # if it has your name.
68.
69. time.sleep(0.5) # (!) EXPERIMENT: Try changing this value.
70.
71. # (!) EXPERIMENT: What happens if you comment this line out?
72. print('\n' * 40)
73.
74. # Display the start and finish lines:
75. print('START' + (' ' * (FINISH_LINE - len('START')) + 'FINISH'))
76. print('|' + (' ' * (FINISH_LINE - 1) + '|'))
77.
78. # Display the snails (with name tags):
79. for snailName in snailNames:
80. spaces = snailProgress[snailName]
81. print((' ' * spaces) + snailName[:MAX_NAME_LENGTH])
82. print(('.' * snailProgress[snailName]) + '@v')
After entering the source code and running it a few times, try making experimental changes to it. The comments marked with (!) have suggestions for small changes you can make. On your own, you can also try to figure out how to do the following:
- Add a random “speed boost” that launches the snail four spaces ahead instead of one.
- Add a “sleep mode” that snails can randomly enter during the race. This mode causes them to stop for a few turns and
zzzto appear next to them. - Add support for ties, in case snails reach the finish line at the same time.
Exploring the Program
Try to find the answers to the following questions. Experiment with some modifications to the code and rerun the program to see what effect the changes have.
- What happens if you change
snailName[:MAX_NAME_LENGTH]on line 81 tosnailNames[0]? - What happens if you change
print('@v')on line 50 toprint('v@')?