def tour_of_four_stools(model, delay_btw_moves=0.5, animate=False): """ Move a tower of cheeses from the first stool in model to the fourth. @type model: TOAHModel TOAHModel with tower of cheese on first stool and three empty stools @type delay_btw_moves: float time delay between moves if console_animate is True @type animate: bool animate the tour or not """ mock_model = TOAHModel(model.get_number_of_stools()) mock_model.fill_first_stool(model.get_number_of_cheeses()) number_cheeses = model.get_number_of_cheeses() four_stools_move(model, number_cheeses, 0, 1, 3) i = 0 move_seq = model.get_move_seq() move_times = move_seq.length() while animate: time.sleep(delay_btw_moves) ori = move_seq.get_move(i)[0] des = move_seq.get_move(i)[1] mock_model.move(ori, des) print(mock_model) i = i + 1 if i == move_times: animate = False
def play_loop(self): """ Play Console-based game. @param ConsoleController self: @rtype: None TODO: -Start by giving instructions about how to enter moves (which is up to you). Be sure to provide some way of exiting the game, and indicate that in the instructions. -Use python's built-in function input() to read a potential move from the user/player. You should print an error message if the input does not meet the specifications given in your instruction or if it denotes an invalid move (e.g. moving a cheese onto a smaller cheese). You can print error messages from this method and/or from ConsoleController.move; it's up to you. -After each valid move, use the method TOAHModel.__str__ that we've provided to print a representation of the current state of the game. """ is_int = False toah_game = TOAHModel(self.number_of_stools) toah_game.fill_first_stool(self.number_of_cheeses) print(toah_game) print("Welcome to the Tour of Anne Hoy Game.") print( "Enter a non-integer value such as a string(a) or a float(13.5) to quit the game." ) print('') run = True while run: try: cheese_origin = int( input("Choose a stool number to move the cheese from: ")) cheese_dest = int( input("Choose the stool you want to move the cheese to: ")) toah_game.move(cheese_origin, cheese_dest) print(toah_game) except IllegalMoveError: print("Invalid move. Please reenter.") print("") except IndexError: print("Invalid stool number. Please reenter.") print("") except ValueError: print("") print("Game Ended. Thank you for playing.") run = False
def move(model, origin, dest): """ Apply move from origin to destination in model. May raise an IllegalMoveError. @param TOAHModel model: model to modify @param int origin: stool number (index from 0) of cheese to move @param int dest: stool number you want to move cheese to @rtype: None """ TOAHModel.move(model, origin, dest)
class ConsoleController: """ Controller for text console. """ def __init__(self, number_of_cheeses, number_of_stools): """ Initialize a new ConsoleController self. @param ConsoleController self: @param int number_of_cheeses: @param int number_of_stools: @rtype: None """ self.model = TOAHModel(number_of_stools) self.model.fill_first_stool(number_of_cheeses) def play_loop(self): """ Play Console-based game. @param ConsoleController self: @rtype: None TODO: -Start by giving instructions about how to enter moves (which is up to you). Be sure to provide some way of exiting the game, and indicate that in the instructions. -Use python's built-in function input() to read a potential move from the user/player. You should print an error message if the input does not meet the specifications given in your instruction or if it denotes an invalid move (e.g. moving a cheese onto a smaller cheese). You can print error messages from this method and/or from ConsoleController.move; it's up to you. -After each valid move, use the method TOAHModel.__str__ that we've provided to print a representation of the current state of the game. """ while True: play = input('Please enter move: ') if play == "q": return False result = play.split() from_ = int(result[0]) to_ = int(result[1]) try: if to_ > len(self.model._stools): raise IllegalMoveError("Stool does not exist") else: self.model.move(from_, to_) except IllegalMoveError as IE: print(IE) pass print(self.model)
def play_loop(self): """ Play Console-based game. @param ConsoleController self: @rtype: None TODO: -Start by giving instructions about how to enter moves (which is up to you). Be sure to provide some way of exiting the game, and indicate that in the instructions. -Use python's built-in function input() to read a potential move from the user/player. You should print an error message if the input does not meet the specifications given in your instruction or if it denotes an invalid move (e.g. moving a cheese onto a smaller cheese). You can print error messages from this method and/or from ConsoleController.move; it's up to you. -After each valid move, use the method TOAHModel.__str__ that we've provided to print a representation of the current state of the game. """ print("Instruction: Player enter the start stool and destination stool" " at every time. \n" "Be ware you should enter the number of stool. " "i.e.'1' means first stool. Player can\n" "quit this game by enter 'E' when a messauge pop out.\n" "Be careful, " "You can't put big cheese over smaller ones! Good luck!\n" "==============================================================" "===================\n ") model = TOAHModel(self.number_of_stools) model.fill_first_stool(self.number_of_cheeses) ext = "" print(model) while ext is not "E": try: origin = int(input("Please enter the origin of movement---> ")) dest = int( input("Please enter the destination of " "movement---> ")) model.move(origin - 1, dest - 1) except IllegalMoveError as e: print(e) except ValueError: print("Please read instruction carefully," " and enter a positive integer.") finally: print(model) ext = input("Type E to exit game or any other to keep playing" "---> ") print("Game over")
def animate_hanoi(reference_model, delay): """ animate the movements in the console window one by one; delay each movement by the given <delay> @type reference_model: TOAHModel @type delay: float @rtype: None """ toah = TOAHModel(reference_model.get_number_of_stools()) toah.fill_first_stool(reference_model.get_number_of_cheeses()) for i in range(reference_model.number_of_moves()): movement = reference_model.get_move_seq().get_move(i) toah.move(movement[0], movement[1]) time.sleep(delay) print(toah)
def tour_of_four_stools(model, delay_btw_moves=0.5, animate=False): """Move a tower of cheeses from the first stool in model to the fourth. @type model: TOAHModel TOAHModel with tower of cheese on first stool and three empty stools @type delay_btw_moves: float time delay between moves if console_animate is True @type animate: bool animate the tour or not """ move_cheeses(model, model.get_number_of_cheeses(), 0, 1, 2, 3) if animate: new_model = TOAHModel(4) new_model.fill_first_stool(model.get_number_of_cheeses()) for i in range(model.number_of_moves()): new_model.move(model.get_move_seq().get_move(i)[0], model.get_move_seq().get_move(i)[1]) print(new_model) time.sleep(delay_btw_moves)
class ConsoleController: """ Controller for text console. """ def __init__(self, number_of_cheeses, number_of_stools): """ Initialize a new ConsoleController self. @param ConsoleController self: @param int number_of_cheeses: @param int number_of_stools: @rtype: None """ self.model = TOAHModel(number_of_stools) self.model.fill_first_stool(number_of_cheeses) self.number_of_stools = number_of_stools def play_loop(self): """ Play Console-based game. @param ConsoleController self: @rtype: None """ print("Instructions: To move a cheese from the first stool to " "the second, input '0 to 1' \n Enter 'ex' to exit") move_count = 1 print(self.model) move_in = input('Enter Move ' + str(move_count) + ':') while move_in != 'ex': move_in = move_in.split() if len(move_in) == 3 and move_in[1] == 'to' and \ (move_in[0].isnumeric() and move_in[2].isnumeric()): try: self.model.move(int(move_in[0]), int(move_in[-1])) move_count += 1 except IllegalMoveError as e: print(e) else: print("Invalid Input Syntax") print(self.model) move_in = input('Enter Move ' + str(move_count) + ':')
def tour_of_four_stools(model, delay_btw_moves=0.5, animate=False): """Move a tower of cheeses from the first stool in model to the fourth. @type model: TOAHModel TOAHModel with tower of cheese on first stool and three empty stools @type delay_btw_moves: float time delay between moves if CONSOLE_ANIMATE is True @type animate: bool animate the tour or not """ move_four_stools(model, model.get_number_of_cheeses(), [0, 3, 1, 2]) if animate: animate_model = TOAHModel(4) animate_model.fill_first_stool(model.get_number_of_cheeses()) move_seq = model.get_move_seq() print(animate_model) for i in range(move_seq.length()): (src_stool, dst_stool) = move_seq.get_move(i) time.sleep(delay_btw_moves) animate_model.move(src_stool, dst_stool) print(animate_model)
class GUIController: """ Graphical User Interface (GUI) controller === Attributes === @param float cheese_scale: height in pixels to scale cheese height @param root tk.Tk: tkinter root window """ def __init__(self, number_of_cheeses, number_of_stools, content_width, content_height, cheese_scale): """ Initialize a new GUIView. @param GUIController self: @param int number_of_cheeses: number of cheeses for first stool @param int number_of_stools: number of stools @param float content_width: width, in pixels, of working area @param float content_height: height, in pixels, of working area @param float cheese_scale: height in pixels for showing cheese thicknesses, and to scale cheese diameters """ self._model = TOAHModel(number_of_stools) self._stools = [] self._cheese_to_move = None self._blinking = False self._number_of_stools = number_of_stools self.cheese_scale = cheese_scale self.root = tk.Tk() canvas = tk.Canvas(self.root, background="blue", width=content_width, height=content_height) canvas.pack(expand=True, fill=tk.BOTH) self.moves_label = tk.Label(self.root) self.show_number_of_moves() self.moves_label.pack() # the dimensions of a stool are the same as a cheese that's # one size bigger than the biggest of the number_of_cheeses cheeses. for stool_ind in range(number_of_stools): width = self.cheese_scale * (number_of_cheeses + 1) x_cent = content_width * (stool_ind + 1)/(number_of_stools + 1.0) y_cent = content_height - cheese_scale / 2 stool = StoolView(width, lambda s: self.stool_clicked(s), canvas, self.cheese_scale, x_cent, y_cent) self._stools.append(stool) # Can't use self._model.fill_first_stool because we need to # use CheeseView objects instead of just Cheese objects. total_size = self.cheese_scale for sizeparam in range(1, number_of_cheeses+1): size = (number_of_cheeses + 1 - sizeparam) width = self.cheese_scale * size x_cent = content_width / (number_of_stools + 1.0) y_cent = content_height - cheese_scale / 2 - total_size cheese = CheeseView(size, width, lambda c: self.cheese_clicked(c), canvas, self.cheese_scale, x_cent, y_cent) self._model.add(cheese, 0) total_size += self.cheese_scale def cheese_clicked(self, cheese): """ React to cheese being clicked: if not in the middle of blinking then select cheese for moving, or for moving onto. @param GUIController self: @param CheeseView cheese: clicked cheese @rtype: None """ if not self._blinking: self.select_cheese(cheese) def stool_clicked(self, stool): """ React to cheese being clicked: if not in the middle of blinking then select cheese for moving, or for moving onto. @param GUIController self: @param StoolView stool: clicked stool @rtype: None """ if not self._blinking: self.select_stool(stool) def select_cheese(self, cheese): """ Select top cheese. If no cheese is selected to move, then select the cheese at top of clicked_cheese's stool (which may be clicked_cheese itself) and highlight it. If selected_cheese is already highlighted, then unhighlight it. Otherwise try to move self._cheese_to_move onto the stool that clicked_cheese is on. @param GUIController self: @param CheeseView cheese: clicked cheese @rtype: None """ stool = self._stools[self._model.get_cheese_location(cheese)] stool_index = self.stool_index(stool) cheese = self._model.get_top_cheese(stool_index) # print(stool, stool_index, cheese) if self._cheese_to_move is None: self._cheese_to_move = cheese self._cheese_to_move.highlight(True) self.root.update() elif self._cheese_to_move is cheese: self._cheese_to_move.highlight(False) self._cheese_to_move = None self.root.update() else: self.select_platform_for_move(cheese, stool_index) def select_stool(self, dest_stool): """ Initiate a move. If there is already some cheese highlighted (i.e. self._cheese_to_move is not None), unless self._cheese_to_move is on dest_stool, in which case do nothing. @param GUIController self: @type dest_stool: StoolView @rtype: None """ if self._cheese_to_move is not None: origin_stool = self._stools[ self._model.get_cheese_location(self._cheese_to_move)] dest_stool_index = self.stool_index(dest_stool) origin_stool_index = self.stool_index(origin_stool) if origin_stool_index != dest_stool_index: top_cheese = self._model.get_top_cheese(dest_stool_index) if top_cheese is None: self.select_platform_for_move(dest_stool, dest_stool_index) else: self.select_platform_for_move(top_cheese, dest_stool_index) def select_platform_for_move(self, platform, stool_index): """ Show the cheese move on screen, and update the model. Change self._cheese_to_move's coordinates so that it's on top of platform. @param GUIController self: @param PlatformView platform: @param int stool_index: @rtype: None """ if self._cheese_to_move is not None: try: from_stool = self._model.get_cheese_location( self._cheese_to_move) self._model.move(from_stool, stool_index) self._cheese_to_move.place(platform.x_center, platform.y_center - self.cheese_scale) self.show_number_of_moves() except IllegalMoveError as e: print(e) self._blinking = True for i in range(10): self._cheese_to_move.highlight(i % 2 != 0) self.root.update() time.sleep(0.1) self._blinking = False self._cheese_to_move.highlight(False) self._cheese_to_move = None self.root.update() def stool_index(self, stool): """ Return the index of stool. @param GUIController self: @param StoolView stool: @rtype: int >>> gui = GUIController(5, 4, 1024, 320, 20) >>> s = gui.get_stool(0) >>> gui.stool_index(s) == 0 True >>> gui.stool_index(s) == 1 False """ return self._stools.index(stool) def show_number_of_moves(self): """Show the number of moves so far. @param GUIController self: @rtype: None """ self.moves_label.config(text="Number of moves: " + str(self._model.number_of_moves())) def get_stool(self, i): """ Return ith stool. @param GUIController self: @param int i: @rtype: StoolView # examples not really practical here """ return self._stools[i] def get_top_cheese(self, i): """ Return the top cheese from ith stool. @param GUIController self: @param int i: @rtype: CheeseView # examples not really practical here """ return self._model.get_top_cheese(i)
class ConsoleController: """ Controller for text console. ==Attribute== @param TOAHModel model: a list version of the TOAHModel """ def __init__(self, number_of_cheeses, number_of_stools): """ Initialize a new ConsoleController self. @param ConsoleController self: @param int number_of_cheeses: @param int number_of_stools: @rtype: None """ self.model = TOAHModel(number_of_stools) self.model.fill_first_stool(number_of_cheeses) def play_loop(self): """ Play Console-based game. @param ConsoleController self: @rtype: None TODO: -Start by giving instructions about how to enter moves (which is up to you). Be sure to provide some way of exiting the game, and indicate that in the instructions. -Use python's built-in function input() to read a potential move from the user/player. You should print an error message if the input does not meet the specifications given in your instruction or if it denotes an invalid move (e.g. moving a cheese onto a smaller cheese). You can print error messages from this method and/or from ConsoleController.move; it's up to you. -After each valid move, use the method TOAHModel.__str__ that we've provided to print a representation of the current state of the game. """ print("> To move a stack, first enter which tower number it's " "currently on followed by a space and then the tower number you " "want to move the stack to. \n \n" "> The first tower is tower number 1 and each tower number" " after that goes up by one (ie. the second tower is tower" " number 2). \n \n" "> To exit the game simply type 'exit' (as an isolated word" ") in the input command. \n \n" "> The objective of the game is to move all pieces from the" " initial tower, to the last tower. \n \n" "> The game's rules are: \n \n" "1. You can never move a bigger piece on a smaller piece. \n" "2. You can only move one piece at a time \n" "3. All disks must only be moved to viable towers \n") print(self.model) move_input = input("Enter a move or command: ").split() while 'exit' not in move_input: if len(move_input) == 2 and move_input[0].isdigit() and\ move_input[1].isdigit(): try: source = int(move_input[0]) - 1 destination = int(move_input[1]) - 1 self.model.move(source, destination) print(self.model) except IllegalMoveError as error: print(error) move_input = input("Enter a move or command: ").split() else: move_input = \ input("Please enter a legal move or command: ").split()
class ConsoleController: """ Controller for text console. """ def __init__(self, number_of_cheeses, number_of_stools): """ Initialize a new ConsoleController self. @param ConsoleController self: @param int number_of_cheeses: @param int number_of_stools: @rtype: None """ self._play = True self._game = True self._model = TOAHModel(number_of_stools) self._model.fill_first_stool(number_of_cheeses) self._cheeses = number_of_cheeses self._stools = number_of_stools def print_model(self): """Prints the state of the TOAH model to the console. @param ConsoleController self: @rtype: None """ print('The model currently looks like this:') print(self._model) def move_command(self): """Procedure for handling when the user wants to move a wheel of cheese @param ConsoleController self: @rtype: None """ self._moving = True while (self._moving): source = input('Please indicate the index of the stool '\ 'you want to move from, or C to [C]ancel\n') if (source == 'C') or (source == 'c'): self._moving = False break try: source = int(source) except: print('Input is not a valid index!') continue if source >= self._stools: print('No stool exists at given index!') continue break while (self._moving): dest = input('Please indicate the index of the stool '\ 'you want to move to, or C to [C]ancel\n') if (dest == 'C') or (dest == 'c'): self._moving = False break try: dest = int(dest) except: print('Input is not a valid index!') continue if dest >= self._stools: print('No stool exists at given index!') continue try: self._model.move(source, dest) self.print_model() self._moving = False continue except IllegalMoveError as ime: print(ime) self._moving = False continue def play_loop(self): """ Play Console-based game. @param ConsoleController self: @rtype: None TODO: -Start by giving instructions about how to enter moves (which is up to you). Be sure to provide some way of exiting the game, and indicate that in the instructions. -Use python's built-in function input() to read a potential move from the user/player. You should print an error message if the input does not meet the specifications given in your instruction or if it denotes an invalid move (e.g. moving a cheese onto a smaller cheese). You can print error messages from this method and/or from ConsoleController.move; it's up to you. -After each valid move, use the method TOAHModel.__str__ that we've provided to print a representation of the current state of the game. """ print("Starting a TOAH with " + \ str(self._stools) + " number of " \ "stools and " + str(self._cheeses) + \ " number of cheeses.") print(self._model) while (self._play): self._moving = False empty = False user = input('Options: [M]ove [Q]uit [R]estart [P]rint\n') if user: if (user == 'M') or (user == 'm'): self.move_command() elif (user == 'Q') or (user == 'q'): print('Quitting...') break elif (user == 'R') or (user == 'r'): print('Restarting...') new_toah = ConsoleController(self._cheeses, self._stools) new_toah.play_loop() break elif (user == 'P') or (user == 'p'): self.print_model() else: continue else: continue