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)
示例#2
0
        print("move final " + str(m) + " took " + str(a))
        count += a
        #count += move_cheeses(model, n-m, 0, 1, 2, animate)
        #count += move_cheeses(model, m, 0, 1, 3, animate)
        #count += move_cheeses(model, n-m, 2, 0, 3, animate)
        return count


if __name__ == '__main__':
    #mod = TOAHModel(4)
    #mod.fill_first_stool(5)
    #print(tour_of_four_stools(mod,animate=True))
    #move_cheeses(mod, 8, 0, 1, 2)

    num_cheeses = 100
    delay_between_moves = 0.5
    console_animate = False

    # DO NOT MODIFY THE CODE BELOW.
    four_stools = TOAHModel(4)
    four_stools.fill_first_stool(number_of_cheeses=num_cheeses)

    tour_of_four_stools(four_stools, console_animate, delay_between_moves)

    print(four_stools.number_of_moves())
    # Leave files below to see what python_ta checks.
    # File tour_pyta.txt must be in same folder
    import python_ta

    python_ta.check_all(config="tour_pyta.txt")
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()))
class TestTOAH(unittest.TestCase):
    """Unit tests for Assignment 1."""
    def setUp(self):
        self.toah = TOAHModel(4)
        self.optimals = [
            0, 1, 3, 5, 9, 13, 17, 25, 33, 41, 49, 65, 81, 97, 113, 129, 161,
            193, 225, 257, 289, 321, 385, 449, 513, 577, 641, 705, 769, 897,
            1025, 1153, 1281, 1409, 1537, 1665, 1793, 2049, 2305, 2561, 2817,
            3073, 3329, 3585, 3841, 4097, 4609, 5121, 5633
        ]

    def test_all_cheeses(self):
        for i in range(0, len(self.optimals)):
            self.toah = TOAHModel(4)
            self.toah.fill_first_stool(i)
            tour.tour_of_four_stools(self.toah)
            self.assertEqual(self.toah.number_of_moves(), self.optimals[i])

    def test_0_cheeses(self):
        self.toah.fill_first_stool(0)
        tour.tour_of_four_stools(self.toah)
        self.assertEqual(self.toah.number_of_moves(), self.optimals[0])

    def test_1_cheeses(self):
        self.toah.fill_first_stool(1)
        tour.tour_of_four_stools(self.toah)
        self.assertEqual(self.toah.number_of_moves(), self.optimals[1])

    def test_2_cheeses(self):
        self.toah.fill_first_stool(2)
        tour.tour_of_four_stools(self.toah)
        self.assertEqual(self.toah.number_of_moves(), self.optimals[2])

    def test_3_cheeses(self):
        self.toah.fill_first_stool(3)
        tour.tour_of_four_stools(self.toah)
        self.assertEqual(self.toah.number_of_moves(), self.optimals[3])

    def test_4_cheeses(self):
        self.toah.fill_first_stool(4)
        tour.tour_of_four_stools(self.toah)
        self.assertEqual(self.toah.number_of_moves(), self.optimals[4])

    def test_5_cheeses(self):
        self.toah.fill_first_stool(5)
        tour.tour_of_four_stools(self.toah)
        self.assertEqual(self.toah.number_of_moves(), self.optimals[5])

    def test_6_cheeses(self):
        self.toah.fill_first_stool(6)
        tour.tour_of_four_stools(self.toah)
        self.assertEqual(self.toah.number_of_moves(), self.optimals[6])

    def test_7_cheeses(self):
        self.toah.fill_first_stool(7)
        tour.tour_of_four_stools(self.toah)
        self.assertEqual(self.toah.number_of_moves(), self.optimals[7])

    def test_8_cheeses(self):
        self.toah.fill_first_stool(8)
        tour.tour_of_four_stools(self.toah)
        self.assertEqual(self.toah.number_of_moves(), self.optimals[8])

    def test_9_cheeses(self):
        self.toah.fill_first_stool(9)
        tour.tour_of_four_stools(self.toah)
        self.assertEqual(self.toah.number_of_moves(), self.optimals[9])

    def test_10_cheeses(self):
        self.toah.fill_first_stool(10)
        tour.tour_of_four_stools(self.toah)
        self.assertEqual(self.toah.number_of_moves(), self.optimals[10])

    def test_11_cheeses(self):
        self.toah.fill_first_stool(11)
        tour.tour_of_four_stools(self.toah)
        self.assertEqual(self.toah.number_of_moves(), self.optimals[11])

    def test_12_cheeses(self):
        self.toah.fill_first_stool(12)
        tour.tour_of_four_stools(self.toah)
        self.assertEqual(self.toah.number_of_moves(), self.optimals[12])

    def test_13_cheeses(self):
        self.toah.fill_first_stool(13)
        tour.tour_of_four_stools(self.toah)
        self.assertEqual(self.toah.number_of_moves(), self.optimals[13])

    def test_14_cheeses(self):
        self.toah.fill_first_stool(14)
        tour.tour_of_four_stools(self.toah)
        self.assertEqual(self.toah.number_of_moves(), self.optimals[14])
示例#5
0
    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)


if __name__ == '__main__':
    NUM_CHEESES = 5
    DELAY_BETWEEN_MOVES = 0.5
    CONSOLE_ANIMATE = True

    # DO NOT MODIFY THE CODE BELOW.
    FOUR_STOOLS = TOAHModel(4)
    FOUR_STOOLS.fill_first_stool(number_of_cheeses=NUM_CHEESES)

    tour_of_four_stools(FOUR_STOOLS,
                        animate=CONSOLE_ANIMATE,
                        delay_btw_moves=DELAY_BETWEEN_MOVES)

    print(FOUR_STOOLS.number_of_moves())
    # Leave files below to see what python_ta checks.
    # File tour_pyta.txt must be in same folder
    import python_ta
    python_ta.check_all(config="tour_pyta.txt")
示例#6
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
        """

        if isinstance(number_of_cheeses, int) and isinstance(
                number_of_stools, int):
            self.number_of_cheeses = number_of_cheeses
            self.number_of_stools = number_of_stools
            self.model = TOAHModel(self.number_of_stools)
            self.model.fill_first_stool(self.number_of_cheeses)
            self.complete = self.model._stools[0][:]

        else:
            print("Please enter a NUMBER of cheeses and a NUMBER of stools")

    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.
        """

        flag = True
        player_input = ''
        orginial_stool = 0
        destination_stool = 0
        print(
            "\nThis is how you play.\n\nEnter from which stool you want to move to and its destination\nas an ordered pair, i.e. (cheese stool location, stool I want to move to), (0,1) means \nI want to move the top cheese on stool 1 to top of stool 2.\nAnd you can only stack smaller cheese on larger cheese: enter quit anytime to exit the game \nother wise we will keep playing\n"
        )
        print()
        print("here is the model of the game")
        print(self.model)

        while flag:
            if self.complete == self.model._stools[self.number_of_stools - 1]:
                print("\ncongratulations you won!!!\n")
                print("You completed the puzzel in " +
                      str(self.model.number_of_moves()) + " moves")
                flag = False
            else:
                player_input = input(
                    "please enter the ordered pair of your movement: ")
                if player_input.lower() == 'quit':
                    print('goodbye')
                    flag = False

                else:
                    r = player_input.split(',')
                    if player_input[0] != '(' or player_input[-1] != ')':
                        print(
                            '\nPlease enter the NUMBER of your source and destination stool as an ordered pair!\n'
                        )
                    else:
                        try:
                            orginial_stool = int(r[0][1:])
                            destination_stool = int(r[1][:-1])
                        except ValueError:
                            print(
                                '\nPlease enter the NUMBER of your source and destination stool\n'
                            )
                        else:
                            if orginial_stool < self.model.get_number_of_stools(
                            ) and destination_stool < self.model.get_number_of_stools(
                            ):
                                move(self.model, orginial_stool,
                                     destination_stool)
                                print(self.model)
                            else:
                                print(
                                    '\nPlease enter an appropriate stool and/or cheese\n'
                                )