Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--maze.py87
1 files changed, 64 insertions, 23 deletions
diff --git a/maze.py b/maze.py
index ed833ac..600d690 100644
--- a/maze.py
+++ b/maze.py
@@ -17,22 +17,23 @@ node and (size, size) is the finish node. This is a standard way to represent
a graph in a program.
-Finally, the MazeGame class needs to be implemented to tie together both Maze
-and Player. This class needs to implement the user interface, repeatedly asking
-the player which move they'll make, then updating the Player's location
-accordingly.
-
-Implementing this requires a method to be added to Maze to retrieve a list of
-the nodes which the player can legitimately move to from their current
-location. To avoid breaking compartmentalisation and encoding the player's
-behaviour in the Maze class, the method takes a node as a parameter rather than
-accessing the player's location directly.
-
-One language feature to note is the use of "while...else" in MazeGame.run().
-The code in the 'else' block will be executed immediately after the final
-iteration of the 'while' loop, but won't be executed if execution leaves the
-loop by executing the 'break' statement. This means the "you've won" message
-won't be printed if the user quits the game prematurely.
+In order to be a stable and robust program, the game must cope with unexpected
+or incorrect user input. What happens if the user enters a string instead of
+an integer when asked for the maze size, or for their next location? What
+happens if they press Ctrl+C (a termination signal on Linux) while the program
+is waiting for input? Try doing these things with the previous version of the
+program and see what exceptions are raised. In order to make the program more
+robust, these exceptions need to be explicitly handled.
+
+The handling code for them has been added below. Note that the maze size is
+validated twice: once when the user inputs the size, checking that it's a
+valid integer and is between the limits set to make the game fun; and once when
+the Maze object is instantiated, checking that the size doesn't violate any of
+the algorithmic constraints in the Maze implementation. To do all the checking
+on input would mean the algorithmic checks would need to be reimplemented if
+the Maze class was re-used in another program. To do all the checking in the
+Maze class would tie it too closely to this particular game by rejecting all
+maze sizes which don't fit in with this particular game.
"""
import random
@@ -76,6 +77,10 @@ class Maze(object):
The grid must be of size at least 1.
"""
def __init__(self, size):
+ # Validate the size.
+ if size < 1:
+ raise AttributeError('size must be at least 1')
+
self._links = {}
self._finish_node = (size, size)
self.__generate_maze(size)
@@ -194,8 +199,32 @@ class MazeGame(object):
handles the player's movement choices.
"""
def __init__(self):
- name = raw_input('Please enter your name: ')
- size = int(raw_input('Enter the maze size (between 5 and 20): '))
+ self._player = None
+ self._maze = None
+
+ # Get the player's name.
+ while True:
+ try:
+ name = raw_input('Please enter your name: ')
+ if name != '':
+ break
+ except KeyboardInterrupt:
+ # User pressed Ctrl+C; continue until we hit run().
+ print('')
+ return None
+
+ # Get the board size.
+ while True:
+ try:
+ size = int(raw_input('Enter the maze size (1 to 20): '))
+ if 1 <= size <= 20:
+ break
+ except ValueError:
+ continue # user entered an invalid integer
+ except KeyboardInterrupt:
+ # User pressed Ctrl+C; continue until we hit run().
+ print('')
+ return None
self._player = Player(name)
self._maze = Maze(size)
@@ -222,14 +251,26 @@ class MazeGame(object):
print(' 0) Quit game')
# Ask the user which option they want.
- chosen_option = int(raw_input('Enter the number of your choice: '))
- if chosen_option == 0:
- return None # quit the game
- else:
- return adjacent_nodes[chosen_option - 1]
+ while True:
+ try:
+ chosen_option = \
+ int(raw_input('Enter the number of your choice: '))
+ if chosen_option == 0:
+ return None # quit the game
+ elif 0 <= chosen_option - 1 < len(adjacent_nodes):
+ return adjacent_nodes[chosen_option - 1]
+ except ValueError:
+ continue # non-number entered
+ except KeyboardInterrupt:
+ print('')
+ return None # player pressed Ctrl+C, so quit
def run(self):
"""Run the game until the player wins or quits."""
+ # Check that initialisation was successful; if not, quit immediately.
+ if self._player is None or self._maze is None:
+ return # quit
+
while self._player.location != self._maze.finish_node:
chosen_node = self.__choose_next_location()
if chosen_node is None: