diff options
author | Philip 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) |
commit | 0aa6e3fbd4641208c301a54e5da38f1f99ba2cc6 (patch) | |
tree | f4488590b2b6ab96ea62fb0cca2a3b0e0b48b882 | |
parent | e77437fa53dcb0d7fe3bf0e6d0316963e5eaf8c1 (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.py | 100 |
1 files changed, 83 insertions, 17 deletions
@@ -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() |