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.number_of_stools = number_of_stools
        self.number_of_cheeses = number_of_cheeses

        self.toah = TOAHModel(number_of_stools)
        self.toah.fill_first_stool(number_of_cheeses)

        self.instructions = \
        ('The objective of the game is to move the given stack of cheeses \n'
         'to the right most stool with the least amount of moves.\n'
         'To move a block of cheese from stool X to stool Y \n'
         'enter stool numbers in the format x,y\n'
         "Enter 'Info' if you wish to read this message again\n"
         "Enter 'Quit' to exit the game")

    def play_loop(self):
        """ Play Console-based game.

        @param ConsoleController self:
        @rtype: None
        """
        print(self.instructions)
        command = input("Enter a move or type Quit to exit: ")
        while command != 'Quit':
            c = command.strip().split(',')
            try:
                if command == 'Info':
                    print(self.instructions)
                elif len(c) != 2 or not (c[0].isnumeric()
                                         and c[1].isnumeric()):
                    raise IllegalMoveError
                elif not 0 < int(c[0]) <= int(self.number_of_stools):
                    print('Error ' + c[0] + ' is not within the range\n')
                elif not 0 < int(c[1]) <= int(self.number_of_stools):
                    print('Error ' + c[1] + ' is not within the range\n')
                elif not self.toah.get_top_cheese(int(c[0]) - 1):
                    print('stool ' + str(int(c[0]) - 1) + ' has No cheese!')
                else:
                    move(self.toah, int(c[0]) - 1, int(c[1]) - 1)
                    print(self.toah)
            except IllegalMoveError:
                print(
                    'Incorrect input, input must be positve #,#, Info or Quit\n'
                )
            command = input("Enter a move or type Quit to exit: ")
        print("\nYou have successfully quit the game!")
Ejemplo n.º 2
0
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)
Ejemplo n.º 3
0
    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.
        """
        def exception_handler(origin, dest, model):
            """
            Handles the exceptions

            @type origin: int
            @type dest: int
            @type model: TOAHModel
            @rtype: None|str
            """
            try:
                move(model, origin, dest)
            except IllegalMoveError:
                print("That's invalid. Choose other stools. \n")
            else:
                pass

        print("=" * 10 + "WELCOME TO THE TOUR OF ANNE HOY GAME" + "=" * 10)
        print("\n\n\nInstructions:\n-To exit the game, type '-1' when"
              "asked for the moves\n-Each stool is numbered, starting"
              "from 1")
        print("---Rules---")
        print("*Enter all information in numeral numbers")
        print("**The goal of this game is to stack all the cheeses onto the"
              " last stool")
        print(
            "***It is only possible to add cheeses on top of a larger cheese")
        print("****Only can move existing cheese on a stool")
        print("*****to EXIT type in -1 as destination")
        print("")

        model = TOAHModel(self.number_of_stools)
        model.fill_first_stool(self.number_of_cheeses)
        print(model.__str__())
        print('')
        print("Begin")
        print("")
        origin = 0
        dest = 0
        while origin != -1 and dest != -1:
            origin = int(input("Move from stool: "))
            if origin == -1:
                break
            dest = int(input("To stool: "))
            if dest == -1:
                break
            while ((origin > model.num_of_stools - 1) or (origin < 0)
                   or (dest > model.num_of_stools - 1) or (dest < 0)
                   or (len(model._stools[origin]) == 0)
                   or (len(model._stools[dest]) > 0 and
                       (model.get_top_cheese(origin).size >
                        model.get_top_cheese(dest).size))):
                exception_handler(origin, dest, model)
                origin = int(input("Move from stool: "))
                dest = int(input("To stool: "))
            move(model, origin, dest)
            print(model.__str__())
class ConsoleController:
    """ Controller for text console.
    """

    def __init__(self, number_of_cheeses, number_of_stools):
        """ Initialize a new ConsoleController self.

        @param ConsoleController self: the ConsoleController itself
        @param int number_of_cheeses: the number of cheeses
        @param int number_of_stools: the 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: the ConsoleController itself
        @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 spe instruction or if it denotes
        an invalid move (e.g. moving a cheese ontcifications given in youro 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("""
               --------Welcome to the Game of Hanoi--------
        Type two integers like x y (two integers x and y seperated by a space)
        to move a cheese from xth stool to yth stool. If the input move is
        invalid, an error message will be sent until you type a valid move.
        NO.{} represent the number of successful moves you have made.
        Type quit to exit the game.
              """)
        move_order = input('Please order a move or type quit to exit the game:')
        n = self.model.get_number_of_stools()
        while move_order != 'quit':
            try:
                from_stool = int(move_order.split()[0]) - 1
                dest_stool = int(move_order.split()[1]) - 1
                if len(move_order.split()) != 2:
                    print("Hey, dude! Please follow the format!")
                elif from_stool == -1 or dest_stool == -1:
                    print("Hey, dude! We don't have that stool!")
                else:
                    move(self.model, from_stool, dest_stool)

            except IndexError:
                if len(move_order.split()) != 2:
                    print("Hey, dude! Please follow the format!")
                elif from_stool + 1 > n or dest_stool + 1 > n:
                    print("Hey, dude! We don't have that stool")
                else:
                    print("Hey, dude! Please follow the format!")
            except IllegalMoveError:
                if from_stool == dest_stool:
                    print("Hey, dude! Origin and destination stools must "
                          "be distinct!")
                elif self.model.get_top_cheese(from_stool) is None:
                    print("Hey, dude! Can't find a cheese from an empty stool!")
                elif self.model.get_top_cheese(from_stool).size > self.model\
                        .get_top_cheese(dest_stool).size:
                    print('Hey, dude! A big cheese can not be on a small one!')
            except ValueError:
                print("Hey, dude! Don't type other characters!")

            print(self.model)
            move_order = input('NO.{} Give me a move:'.
                               format(self.model.number_of_moves()))
Ejemplo n.º 5
0
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.
        """
        inp = 0
        while inp != 'end':
            inp = input("""
            - specify the origin and destination of the cheese in the
                following format: "orig dest"
            - in that order with a space in between, be sure both are ints
            - ensure that you do not place bigger or equal cheese on
                smaller cheese
            - to exit the game type "end"
            """)
            try:
                if inp != 'end':
                    #orig, dest = inp.split(' ')[0], inp.split(' ')[1]

                    orig, dest = int(inp.split(' ')[0]), int(inp.split(' ')[1])
                    if len(self.model._stools[dest]
                           ) == 0:  # you forgot this again
                        move(self.model, orig, dest)
                        print(str(self.model))
                    # elif self.model.get_top_cheese(orig) <  self.model.get_top_cheese(dest):
                    elif (self.model.get_top_cheese(orig).size <
                          self.model.get_top_cheese(dest).size):
                        move(self.model, orig, dest)
                        print(str(self.model))
                    else:
                        print('smaller cheese please')
            except IndexError:
                print(
                    'specify the origin and destination of the cheese in the following format: "orig dest"'
                )
            else:
                'GAME OVER'