Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPhilip Withnall <philip@tecnocode.co.uk>2013-08-26 19:43:51 (GMT)
committer Philip Withnall <philip@tecnocode.co.uk>2013-08-26 19:43:51 (GMT)
commit0aa6e3fbd4641208c301a54e5da38f1f99ba2cc6 (patch)
treef4488590b2b6ab96ea62fb0cca2a3b0e0b48b882
parente77437fa53dcb0d7fe3bf0e6d0316963e5eaf8c1 (diff)
Implement MazeGame and finish the implementation of the core game
The game now works satisfactorily, but error handling hasn’t been added yet.
-rw-r--r--maze.py100
1 files changed, 83 insertions, 17 deletions
diff --git a/maze.py b/maze.py
index c1f8c07..ed833ac 100644
--- a/maze.py
+++ b/maze.py
@@ -16,23 +16,23 @@ X and Y position on an integer grid of given size where (0, 0) is the start
node and (size, size) is the finish node. This is a standard way to represent
a graph in a program.
-The next class to implement is Maze. To keep separation between the components
-in the program, it must not include any code which handles players or their
-behaviour --- that should be in the Player class.
-
-The code in the Maze class should implement a fairly standard symmetric graph,
-as explained here:
- http://en.wikipedia.org/wiki/Symmetric_graph
-There is not enough space to explain graph theory in these notes; please see
-Wikipedia for details on graphs (as distinct from data plots), reflexivity,
-graph symmetry and planarity.
-
-The graph is stored as an adjacency list, since it is a moderately sparse
-graph:
- http://en.wikipedia.org/wiki/Graph_%28abstract_data_type%29
-
-Note that the Maze class has been designed to be entirely immutable: the size
-and shape of the graph cannot be changed after the Maze has been constructed.
+
+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.
"""
import random
@@ -176,3 +176,69 @@ class Maze(object):
return self._finish_node
finish_node = property(get_finish_node)
+
+ def get_adjacents_to_node(self, node):
+ """Get a list of nodes which are adjacent to the given node.
+
+ This list may include node itself, as reflexive links are permitted.
+ If an invalid node is passed as the parameter, an empty list is
+ returned.
+ """
+ return self._links.get(node, [])
+
+
+class MazeGame(object):
+ """Command-line implementation of the maze game.
+
+ This connects the Player to the Maze and implements the input loop which
+ 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 = Player(name)
+ self._maze = Maze(size)
+
+ def __choose_next_location(self):
+ """Ask the user for the next location to move to.
+
+ The chosen location is returned as an (X, Y) tuple, which is guaranteed
+ to be a valid node in the maze. If the user chooses to exit the game,
+ None is returned.
+ """
+
+ # Get a list of the nodes conncted to the player's current location.
+ adjacent_nodes = \
+ self._maze.get_adjacents_to_node(self._player.location)
+
+ # Print out the options, numbered.
+ option = 1
+ print('You are at %s. You can move to:' % str(self._player.location))
+ for node in adjacent_nodes:
+ print(' %u) %s' % (option, str(node)))
+ option += 1
+
+ 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]
+
+ def run(self):
+ """Run the game until the player wins or quits."""
+ while self._player.location != self._maze.finish_node:
+ chosen_node = self.__choose_next_location()
+ if chosen_node is None:
+ break # quit game
+
+ self._player.location = chosen_node
+ else:
+ print('You have won, %s!' % self._player.name)
+
+
+# Run the game.
+MazeGame().run()