示例#1
0
    def __init__(self, master, infoPanel, intervalBar):
        """Constructor

        Parameters:
            master (tk.Tk|tk.Frame): The parent widget
        """
        self._master = master
        self._infoPanel = infoPanel
        self._infoPanel.init_window(master, self)
        self._intervalBar = intervalBar

        self._playing = True

        self._image_manager = ImageManager('images/dots/', loader=load_image)

        # Game
        counts = [10, 15, 25, 25]
        random.shuffle(counts)
        # randomly pair counts with each kind of dot
        objectives = zip(
            [BasicDot(1), BasicDot(2),
             BasicDot(4), BasicDot(3)], counts)

        self._objectives = ObjectiveManager(objectives)
        self._infoPanel.set_objectives(
            [self._objectives.get_status()[i][1] for i in range(4)])

        # Game
        dead_cells = {(2, 2), (2, 3), (2, 4), (3, 2), (3, 3), (3, 4), (4, 2),
                      (4, 3), (4, 4), (0, 7), (1, 7), (6, 7), (7, 7)}
        self._game = DotGame({ButterflyDot: 1},
                             objectives=self._objectives,
                             kinds=(1, 2, 3, 4),
                             size=(8, 8),
                             dead_cells=dead_cells)

        # The following code may be useful when you are implementing task 2:
        for i in range(0, 4):
            for j in range(0, 2):
                position = i, j
                self._game.grid[position].set_dot(ButterflyDot(3))
        self._game.grid[(7, 3)].set_dot(ButterflyDot(1))

        # Grid View
        self._grid_view = GridView(master,
                                   size=self._game.grid.size(),
                                   image_manager=self._image_manager)
        self._grid_view.pack()
        self._grid_view.draw(self._game.grid)
        self.draw_grid_borders()

        # Events
        self.bind_events()

        # Set initial score again to trigger view update automatically
        self._refresh_status()
示例#2
0
class Controller:
    def __init__(self, root, top):
        self.root = root
        self.model = Model(self)  # You pass this parameter so the model can 'see' the controller
        self.grid_v = GridView(self, top)
        self.info_b = InfoBox(self, root)

    def give_names_model(self, name):  # Passes the names to the Model Taken from the info box
        self.model.save_names(name)

    def give_names_board(self):
        # This function delivers the names, taken from the model to the score board of the InfoBox
        p1, p2 = self.model.return_p_names()
        return p1, p2

    def give_scores_board(self):
        s1, s2 = self.model.return_p_scores()
        return s1, s2

    def activate_board(self):
        # This function activates the board by calling the .activate_btns method of the GridView class
        # Also sets the first player for placing his/her symbol
        self.grid_v.activate_btns()
        self.model.set_p1_1st()

    def set_symbol(self, i, j):
        # Calls the .set_symbol method from the model and returns its results
        return self.model.set_symbol(i, j)

    def play(self):
        # This function calls the .play method from th model
        self.model.play()
        self.info_b.set_board()


    def replay_win(self):
        self.win = Replay(self)
        # self.win.no.config(command = self.root.destroy)
        # self.win.yes.config(command =
        #         lambda : [self.activate_board(), self.win.root.destroy()])

    def reset_game(self):
        # This method calls .reset_btns() and .reset_grid() methods to reset both the grids in
        # the Model and GridView classes.
        # It is also responsible for the pop-up window of the replay function
        self.grid_v.reset_btns()
        self.model.reset_grid()
        self.replay_win()
示例#3
0
    def __init__(self, master, icon=None, switch=False):
        """Constructor

        Parameters:
            master (tk.Tk|tk.Frame): The parent widget
        """
        self._master = master
        master.title(self.DEFAULT_TITLE)

        self.flag = False

        self.default_icon = tk.PhotoImage(file='images/companions/useless.gif')

        self.extra_icon = tk.PhotoImage(file='images/companions/penguin.gif')

        self.icon = icon if icon else self.default_icon

        self.default_step = 1

        self.score = 0

        self._playing = True

        self._image_manager = ImageManager('images/dots/', loader=load_image)

        menu_bar = tk.Menu(master)
        master.config(menu=menu_bar)

        file_menu = tk.Menu(menu_bar)
        menu_bar.add_cascade(label='File', menu=file_menu)
        file_menu.add_command(label='New Game', command=self.reset)
        file_menu.add_command(label='Exit Game', command=self.close)

        master.protocol('WM_DELETE_WINDOW', self.close)

        # Game
        counts = [10, 15, 25, 25]
        random.shuffle(counts)
        # randomly pair counts with each kind of dot
        objectives = zip(
            [BasicDot(1), BasicDot(2),
             BasicDot(4), BasicDot(3)], counts)

        self._objectives = ObjectiveManager(objectives)

        dead_cells = {(2, 2), (2, 3), (2, 4), (3, 2), (3, 3), (3, 4), (4, 2),
                      (4, 3), (4, 4), (0, 7), (1, 7), (6, 7), (7, 7)}
        self.dot_game = DotGame({BasicDot: 1},
                                objectives=self._objectives,
                                kinds=(1, 2, 3, 4),
                                size=(8, 8),
                                dead_cells=dead_cells)
        self.companion_game = CompanionGame(
            {
                BasicDot: 43,
                CompanionDot: 9,
                WildcardDot: 6
            },
            BuffaloCompanion(),
            objectives=self._objectives,
            kinds=(1, 2, 3, 4),
            size=(8, 8),
            dead_cells=dead_cells)

        # Game
        self._game = self.companion_game if switch else self.dot_game
        if self.FIRST:
            reply = askquestion(
                type=messagebox.YESNO,
                title='Select Model',
                message=
                'Would you like to start a new game with "Companion Dot"?')
            if reply == messagebox.YES:
                showinfo('"Companion Dot" Model',
                         'Enjoy the game with "Companion Dot"!')
                self.icon = self.extra_icon
                self._game = self.companion_game
                self._master.title('Dots & Co - "Companion Dot"')
            else:
                showinfo('New Game', 'Enjoy the basic game!')
                self._game = self.dot_game
            self.FIRST = False

        # The following code may be useful when you are implementing task 2:
        # for i in range(0, 4):
        #     for j in range(0, 2):
        #         position = i, j
        #         self._game.grid[position].set_dot(BasicDot(3))
        # self._game.grid[(7, 3)].set_dot(BasicDot(1))

        # InfoPanel
        self.info_panel = InfoPanel(master)
        self.info_panel.set_default_icon(self.icon)
        self.info_panel.decrease_remaining_moves_and_increase_score(
            self._game.get_moves(), self._game.get_score())
        self.info_panel.set_objectives(self._image_manager,
                                       self._objectives.get_status())
        self.info_panel.pack()

        # IntervalBar
        self.interval_bar = IntervalBar(master)
        self.interval_bar.draw_step(self.default_step)
        self.interval_bar.pack()

        # Grid View
        self._grid_view = GridView(master,
                                   size=self._game.grid.size(),
                                   image_manager=self._image_manager)
        self._grid_view.pack()
        self._grid_view.draw(self._game.grid)
        self.draw_grid_borders()

        # Events
        self.bind_events()

        # Set initial score again to trigger view update automatically
        self._refresh_status()
示例#4
0
class DotsApp:
    """Top level GUI class for simple Dots & Co game"""
    DEFAULT_TITLE = 'Dots & Co'
    FIRST = True

    def __init__(self, master, icon=None, switch=False):
        """Constructor

        Parameters:
            master (tk.Tk|tk.Frame): The parent widget
        """
        self._master = master
        master.title(self.DEFAULT_TITLE)

        self.flag = False

        self.default_icon = tk.PhotoImage(file='images/companions/useless.gif')

        self.extra_icon = tk.PhotoImage(file='images/companions/penguin.gif')

        self.icon = icon if icon else self.default_icon

        self.default_step = 1

        self.score = 0

        self._playing = True

        self._image_manager = ImageManager('images/dots/', loader=load_image)

        menu_bar = tk.Menu(master)
        master.config(menu=menu_bar)

        file_menu = tk.Menu(menu_bar)
        menu_bar.add_cascade(label='File', menu=file_menu)
        file_menu.add_command(label='New Game', command=self.reset)
        file_menu.add_command(label='Exit Game', command=self.close)

        master.protocol('WM_DELETE_WINDOW', self.close)

        # Game
        counts = [10, 15, 25, 25]
        random.shuffle(counts)
        # randomly pair counts with each kind of dot
        objectives = zip(
            [BasicDot(1), BasicDot(2),
             BasicDot(4), BasicDot(3)], counts)

        self._objectives = ObjectiveManager(objectives)

        dead_cells = {(2, 2), (2, 3), (2, 4), (3, 2), (3, 3), (3, 4), (4, 2),
                      (4, 3), (4, 4), (0, 7), (1, 7), (6, 7), (7, 7)}
        self.dot_game = DotGame({BasicDot: 1},
                                objectives=self._objectives,
                                kinds=(1, 2, 3, 4),
                                size=(8, 8),
                                dead_cells=dead_cells)
        self.companion_game = CompanionGame(
            {
                BasicDot: 43,
                CompanionDot: 9,
                WildcardDot: 6
            },
            BuffaloCompanion(),
            objectives=self._objectives,
            kinds=(1, 2, 3, 4),
            size=(8, 8),
            dead_cells=dead_cells)

        # Game
        self._game = self.companion_game if switch else self.dot_game
        if self.FIRST:
            reply = askquestion(
                type=messagebox.YESNO,
                title='Select Model',
                message=
                'Would you like to start a new game with "Companion Dot"?')
            if reply == messagebox.YES:
                showinfo('"Companion Dot" Model',
                         'Enjoy the game with "Companion Dot"!')
                self.icon = self.extra_icon
                self._game = self.companion_game
                self._master.title('Dots & Co - "Companion Dot"')
            else:
                showinfo('New Game', 'Enjoy the basic game!')
                self._game = self.dot_game
            self.FIRST = False

        # The following code may be useful when you are implementing task 2:
        # for i in range(0, 4):
        #     for j in range(0, 2):
        #         position = i, j
        #         self._game.grid[position].set_dot(BasicDot(3))
        # self._game.grid[(7, 3)].set_dot(BasicDot(1))

        # InfoPanel
        self.info_panel = InfoPanel(master)
        self.info_panel.set_default_icon(self.icon)
        self.info_panel.decrease_remaining_moves_and_increase_score(
            self._game.get_moves(), self._game.get_score())
        self.info_panel.set_objectives(self._image_manager,
                                       self._objectives.get_status())
        self.info_panel.pack()

        # IntervalBar
        self.interval_bar = IntervalBar(master)
        self.interval_bar.draw_step(self.default_step)
        self.interval_bar.pack()

        # Grid View
        self._grid_view = GridView(master,
                                   size=self._game.grid.size(),
                                   image_manager=self._image_manager)
        self._grid_view.pack()
        self._grid_view.draw(self._game.grid)
        self.draw_grid_borders()

        # Events
        self.bind_events()

        # Set initial score again to trigger view update automatically
        self._refresh_status()

    def close(self):
        if self.can_close():
            self._master.destroy()

    def can_close(self):
        reply = askquestion(type=messagebox.YESNO,
                            title='Confirm Exit',
                            message='Are you sure you want to quit?')
        if reply == messagebox.YES:
            return True
        else:
            return False

    def draw_grid_borders(self):
        """Draws borders around the game grid"""

        borders = list(self._game.grid.get_borders())

        # this is a hack that won't work well for multiple separate clusters
        outside = max(borders, key=lambda border: len(set(border)))

        for border in borders:
            self._grid_view.draw_border(border, fill=border != outside)

    def bind_events(self):
        """Binds relevant events"""
        self._grid_view.on('start_connection', self._drag)
        self._grid_view.on('move_connection', self._drag)
        self._grid_view.on('end_connection', self._drop)

        self._game.on('reset', self._refresh_status)
        self._game.on('complete', self._drop_complete)

        self._game.on('connect', self._connect)
        self._game.on('undo', self._undo)

    def _animation_step(self, step_name):
        """Runs for each step of an animation

        Parameters:
            step_name (str): The name (type) of the step
        """
        print(step_name)
        self._refresh_status()
        self.draw_grid()

    def animate(self, steps, callback=lambda: None):
        """Animates some steps (i.e. from selecting some dots, activating companion, etc.

        Parameters:
            steps (generator): Generator which yields step_name (str) for each step in the animation
        """

        if steps is None:
            steps = (None for _ in range(1))

        animation = create_animation(self._master,
                                     steps,
                                     delays=ANIMATION_DELAYS,
                                     delay=DEFAULT_ANIMATION_DELAY,
                                     step=self._animation_step,
                                     callback=callback)
        animation()

    def _drop(self, position):  # pylint: disable=unused-argument
        """Handles the dropping of the dragged connection

        Parameters:
            position (tuple<int, int>): The position where the connection was
                                        dropped
        """
        if not self._playing:
            return

        if self._game.is_resolving():
            return

        self._grid_view.clear_dragged_connections()
        self._grid_view.clear_connections()

        self.animate(self._game.drop())

    def _connect(self, start, end):
        """Draws a connection from the start point to the end point

        Parameters:
            start (tuple<int, int>): The position of the starting dot
            end (tuple<int, int>): The position of the ending dot
        """

        if self._game.is_resolving():
            return
        if not self._playing:
            return
        self._grid_view.draw_connection(
            start, end, self._game.grid[start].get_dot().get_kind())

    def _undo(self, positions):
        """Removes all the given dot connections from the grid view

        Parameters:
            positions (list<tuple<int, int>>): The dot connects to remove
        """
        for _ in positions:
            self._grid_view.undo_connection()

    def _drag(self, position):
        """Attempts to connect to the given position, otherwise draws a dragged
        line from the start

        Parameters:
            position (tuple<int, int>): The position to drag to
        """

        if self._game.is_resolving():
            return
        if not self._playing:
            return

        tile_position = self._grid_view.xy_to_rc(position)

        if tile_position is not None:
            cell = self._game.grid[tile_position]
            dot = cell.get_dot()

            if dot and self._game.connect(tile_position):
                self._grid_view.clear_dragged_connections()
                return

        kind = self._game.get_connection_kind()

        if not len(self._game.get_connection_path()):
            return

        start = self._game.get_connection_path()[-1]

        if start:
            self._grid_view.draw_dragged_connection(start, position, kind)

    @staticmethod
    def remove(*_):
        """Deprecated in 1.1.0"""
        raise DeprecationWarning("Deprecated in 1.1.0")

    def draw_grid(self):
        """Draws the grid"""
        self._grid_view.draw(self._game.grid)

    def reset(self):
        """Resets the game"""
        # raise NotImplementedError()
        if self._playing:
            reply = askquestion(type=messagebox.YESNO,
                                title='Now Playing',
                                message='Are you sure you want to restart?')
            if reply == messagebox.YES:
                self.select_model()
            else:
                pass
        else:
            self.select_model()

    def select_model(self):
        reply = askquestion(
            type=messagebox.YESNOCANCEL,
            title='Select Model',
            message='Would you like to start a new game with "Companion Dot"?')
        if reply == messagebox.YES:
            showinfo('"Companion Dot" Model',
                     'Enjoy the game with "Companion Dot"!')
            self.restart(True)
            # self.restart_o()
            self._master.title('Dots & Co - "Companion Dot"')
        elif reply == messagebox.NO:
            showinfo('New Game', 'Enjoy the basic game!')
            self.restart()
        else:
            pass

    def restart(self, flag=False):
        self.info_panel.destroy()
        self.interval_bar.destroy()
        self._grid_view.destroy()
        if flag:
            self.__init__(self._master, self.extra_icon, True)
        else:
            self.__init__(self._master)

    def check_game_over(self):
        """Checks whether the game is over and shows an appropriate message box if so"""
        state = self._game.get_game_state()

        if state == self._game.GameState.WON:
            showinfo("Game Over!", "You won!!!")
            self._playing = False
        elif state == self._game.GameState.LOST:
            showinfo(
                "Game Over!",
                f"You didn't reach the objective(s) in time. You connected {self._game.get_score()} points"
            )
            self._playing = False

    def _drop_complete(self):
        """Handles the end of a drop animation"""

        # Useful for when implementing a companion
        # if self._game.companion.is_fully_charged():
        #     self._game.companion.reset()
        #     steps = self._game.companion.activate(self._game)
        #     self._refresh_status()
        #
        #     return self.animate(steps)

        # Need to check whether the game is over
        # raise NotImplementedError()  # no mercy for stooges
        print(self._game.get_game_state())
        if self.flag:
            if self._game.companion.is_fully_charged():
                self._game.companion.reset()
                showinfo('Ultimate Skill!!!!', 'BOOM SHAKALAKA!!!!!!!')
                self._game.companion.activate(self._game)
            self.interval_bar.draw_step(self._game.companion.get_charge() + 1)
            self.flag = False
        self.check_game_over()
        if not self._playing:
            print('ok')

    def _refresh_status(self):
        """Handles change in game status"""

        # Normally, this should raise the following error:
        # raise NotImplementedError()
        # But so that the game can work prior to this method being implemented,
        # we'll just print some information
        # Sometimes I believe Python ignores all my comments :(
        score = self._game.get_score()
        print("Score is now {}.".format(score))
        if self.score < score:
            if type(self._game) is type(self.dot_game):
                self.basic_progress()
            else:
                self.companion_progress()
            self.score = score
            self.info_panel.decrease_remaining_moves_and_increase_score(
                self._game.get_moves(), score)
            self.info_panel.refresh_objectives(self._objectives.get_status())

    def basic_progress(self):
        self.default_step += 1
        if self.default_step > 6:
            self.default_step = 1
        self.interval_bar.draw_step(self.default_step)

    def companion_progress(self):
        if self._game.companion.get_charge() < 6:
            self.interval_bar.draw_step(self._game.companion.get_charge() + 1)
        else:
            self.interval_bar.draw_step(self._game.companion.get_charge())
            self.flag = True
示例#5
0
 def get_grid_view_with_parameters(
     cls, grid_size: int, location_probability: float, model_type: Type
 ) -> GridView:
     grid = cls._get_grid(grid_size, location_probability, model_type)
     return GridView(grid)
示例#6
0
文件: a3.py 项目: dazhuoge/pythonGame
class DotsApp:
    """Top level GUI class for simple Dots & Co game"""

    def __init__(self, master):
        """Constructor

        Parameters:
            master (tk.Tk|tk.Frame): The parent widget
        """
        self._master = master

        self._playing = True

        self._image_manager = ImageManager('images/dots/', loader=load_image)

        # Game
        counts = [10, 15, 25, 25]
        random.shuffle(counts)
        # randomly pair counts with each kind of dot
        objectives = zip([BasicDot(1), BasicDot(2), BasicDot(4), BasicDot(3)], counts)

        self._objectives = ObjectiveManager(objectives)

        # Game
        dead_cells = {(2, 2), (2, 3), (2, 4),
                      (3, 2), (3, 3), (3, 4),
                      (4, 2), (4, 3), (4, 4),
                      (0, 7), (1, 7), (6, 7), (7, 7)}
        self._game = DotGame({BasicDot: 1}, objectives=self._objectives, kinds=(1, 2, 3, 4), size=(8, 8),
                             dead_cells=dead_cells)

        # The following code may be useful when you are implementing task 2:
        # for i in range(0, 4):
        #     for j in range(0, 2):
        #         position = i, j
        #         self._game.grid[position].set_dot(BasicDot(3))
        # self._game.grid[(7, 3)].set_dot(BasicDot(1))

        # Grid View
        self._grid_view = GridView(master, size=self._game.grid.size(), image_manager=self._image_manager)
        self._grid_view.pack()
        self._grid_view.draw(self._game.grid)
        self.draw_grid_borders()

        # Events
        self.bind_events()

        # Set initial score again to trigger view update automatically
        self._refresh_status()

    def draw_grid_borders(self):
        """Draws borders around the game grid"""

        borders = list(self._game.grid.get_borders())

        # this is a hack that won't work well for multiple separate clusters
        outside = max(borders, key=lambda border: len(set(border)))

        for border in borders:
            self._grid_view.draw_border(border, fill=border != outside)

    def bind_events(self):
        """Binds relevant events"""
        self._grid_view.on('start_connection', self._drag)
        self._grid_view.on('move_connection', self._drag)
        self._grid_view.on('end_connection', self._drop)

        self._game.on('reset', self._refresh_status)
        self._game.on('complete', self._drop_complete)

        self._game.on('connect', self._connect)
        self._game.on('undo', self._undo)

    def _animation_step(self, step_name):
        """Runs for each step of an animation
        
        Parameters:
            step_name (str): The name (type) of the step    
        """
        print(step_name)
        self._refresh_status()
        self.draw_grid()

    def animate(self, steps, callback=lambda: None):
        """Animates some steps (i.e. from selecting some dots, activating companion, etc.
        
        Parameters:
            steps (generator): Generator which yields step_name (str) for each step in the animation
        """

        if steps is None:
            steps = (None for _ in range(1))

        animation = create_animation(self._master, steps,
                                     delays=ANIMATION_DELAYS, delay=DEFAULT_ANIMATION_DELAY,
                                     step=self._animation_step, callback=callback)
        animation()

    def _drop(self, position):  # pylint: disable=unused-argument
        """Handles the dropping of the dragged connection

        Parameters:
            position (tuple<int, int>): The position where the connection was
                                        dropped
        """
        if not self._playing:
            return

        if self._game.is_resolving():
            return

        self._grid_view.clear_dragged_connections()
        self._grid_view.clear_connections()

        self.animate(self._game.drop())

    def _connect(self, start, end):
        """Draws a connection from the start point to the end point

        Parameters:
            start (tuple<int, int>): The position of the starting dot
            end (tuple<int, int>): The position of the ending dot
        """

        if self._game.is_resolving():
            return
        if not self._playing:
            return
        self._grid_view.draw_connection(start, end,
                                        self._game.grid[start].get_dot().get_kind())

    def _undo(self, positions):
        """Removes all the given dot connections from the grid view

        Parameters:
            positions (list<tuple<int, int>>): The dot connects to remove
        """
        for _ in positions:
            self._grid_view.undo_connection()

    def _drag(self, position):
        """Attempts to connect to the given position, otherwise draws a dragged
        line from the start

        Parameters:
            position (tuple<int, int>): The position to drag to
        """

        if self._game.is_resolving():
            return
        if not self._playing:
            return

        tile_position = self._grid_view.xy_to_rc(position)

        if tile_position is not None:
            cell = self._game.grid[tile_position]
            dot = cell.get_dot()

            if dot and self._game.connect(tile_position):
                self._grid_view.clear_dragged_connections()
                return

        kind = self._game.get_connection_kind()

        if not len(self._game.get_connection_path()):
            return

        start = self._game.get_connection_path()[-1]

        if start:
            self._grid_view.draw_dragged_connection(start, position, kind)

    @staticmethod
    def remove(*_):
        """Deprecated in 1.1.0"""
        raise DeprecationWarning("Deprecated in 1.1.0")

    def draw_grid(self):
        """Draws the grid"""
        self._grid_view.draw(self._game.grid)

    def reset(self):
        """Resets the game"""
        raise NotImplementedError()

    def check_game_over(self):
        """Checks whether the game is over and shows an appropriate message box if so"""
        state = self._game.get_game_state()

        if state == self._game.GameState.WON:
            showinfo("Game Over!", "You won!!!")
            self._playing = False
        elif state == self._game.GameState.LOST:
            showinfo("Game Over!",
                     f"You didn't reach the objective(s) in time. You connected {self._game.get_score()} points")
            self._playing = False

    def _drop_complete(self):
        """Handles the end of a drop animation"""

        # Useful for when implementing a companion
        # if self._game.companion.is_fully_charged():
        #     self._game.companion.reset()
        #     steps = self._game.companion.activate(self._game)
        #     self._refresh_status()
        #
        #     return self.animate(steps)

        # Need to check whether the game is over
        raise NotImplementedError()  # no mercy for stooges

    def _refresh_status(self):
        """Handles change in score"""

        # Normally, this should raise the following error:
        # raise NotImplementedError()
        # But so that the game can work prior to this method being implemented,
        # we'll just print some information
        # Sometimes I believe Python ignores all my comments :(
        score = self._game.get_score()
        print("Score is now {}.".format(score))
示例#7
0
文件: game.py 项目: ayberkt/2048
class Grid(object):

    def __init__(self):
        self.matrix = [ [2, 0, 2, 0],
                        [0, 0, 0, 8],
                        [0, 2, 0, 0],
                        [0, 0, 2, 4]]

        self.score = 0

        print "Play with WASD!"

    def begin(self):
        '''Start the game.'''
        self.grid_view = GridView(self)
        self.grid_view.initUI(self.matrix)
        self.grid_view.mainloop()

    def get_column(self, nth):
        '''Get column at index.'''
        column = []
        for row in self.matrix:
            column.append(row[nth])
        return column

    def set_column(self, nth, column):
        '''Replace a column at index "nth".'''
        for i in range(4):
            self.matrix[i][nth] = column[i]

    def insert_random_num(self):
        '''Insert a random number to the grid.'''
        x = randint(0, 3)
        y = randint(0, 3)

        while not self.matrix[y][x] == 0:
            x = randint(0, 3)
            y = randint(0, 3)

        self.matrix[y][x] = 2

    def control_state(self):
        print "Score: " + str(self.score)
        self.insert_random_num()
        self.grid_view.layout_matrix(self.matrix)

    def slide(self, direction):
        ''' Apply the corresponding shift to a column or row.
        Columns are treated as rows thus sliding a row up is
        same as shifting it left.
        u for up, r for right, l for left, d for down '''
        if direction == "up":
            for i in range(4):
                column = self.get_column(i)
                column = self.shift(column, "left")
                self.set_column(i, column)
        elif direction == "right":
            for i in range(4):
                row = self.matrix[i]
                row = self.shift(row, "right")
                self.matrix[i] = row
        elif direction == "down":
            for i in range(4):
                column = self.get_column(i)
                column = self.shift(column, "right")
                self.set_column(i, column)
        elif direction == "left":
            for i in range(4):
                row = self.matrix[i]
                row = self.shift(row, "left")
                self.matrix[i] = row
        self.control_state()

    def shift(self, array, direction):
        '''Shift an array left or right specified with the "direction" arg.
        If the input array is [2, 2, 4, 8] the result would be equal 
        to [4, 4, 8] after a left-shift is applied.'''

        # Direction should be specified as either left or right.
        assert(direction == 'left' or direction == 'right')

        if sum(array) == 0: return array

        if direction == 'right': array = array[::-1]

        array = filter(lambda x: x != 0, array)

        for index in range(1, len(array)):
            if array[index - 1] == array[index]:
                array[index - 1] += array[index]
                self.score += array[index - 1]
                array[index] = 0
        array = filter(lambda x: x != 0, array)

        while len(array) < 4:
            array.append(0)

        if direction == 'left': return array
        
        if direction == 'right': return array[::-1]

    def matrix_str(self):
        '''Create a string representation of the matrix
        in the current state. This method is to be used
        for debugging purposes.'''
        matrix_str = ""
        for row in self.matrix:
            row_str = ""
            for num in row:
                if num == 0:
                    row_str += " . "
                else:
                    row_str += " " + str(num) + " "
            row_str += "\n"
            matrix_str += row_str
        return matrix_str
示例#8
0
文件: game.py 项目: ayberkt/2048
 def begin(self):
     '''Start the game.'''
     self.grid_view = GridView(self)
     self.grid_view.initUI(self.matrix)
     self.grid_view.mainloop()
示例#9
0
    def __init__(self, master):
        """Constructor

        Parameters:
            master (tk.Tk|tk.Frame): The parent widget
        """
        pygame.init()
        self._master = master
        master.title('Dots')
        self._playing = True
        self._over = None
        self._player = 'None'
        self._scores = {}
        self._steps = 0
        self._image_manager = ImageManager('images/dots/', loader=load_image)

        # InfoPanel
        self._info = InfoPanel(master)
        self._info.pack(fill=tk.BOTH, expand=1)

        # Login
        top = tk.Toplevel()
        top.title('Login')
        tk.Label(top, text='Welcome to the Dots & Co game!').pack()
        frame = tk.Frame(top)
        frame.pack(side=tk.BOTTOM)
        tk.Label(frame, text="Name: ").pack(side=tk.LEFT)
        entry = tk.Entry(frame, width=20)
        entry.pack(side=tk.LEFT)

        def record(*args):
            self._player = entry.get()
            if self.read_score() == None:
                self.save_score()
            top.destroy()

        tk.Button(frame, text="Start!", command=record).pack(side=tk.RIGHT)
        top.bind('<Return>', record)

        # Menu
        menubar = tk.Menu(master)
        master.config(menu=menubar)
        filemenu = tk.Menu(menubar)
        menubar.add_cascade(label='File', menu=filemenu)
        newgame = tk.Menu(menubar)
        filemenu.add_cascade(label='New Game', menu=newgame)
        newgame.add_command(label='With a Companion',
                            command=self.with_companion)
        newgame.add_command(label='Without a Companion',
                            command=self.without_companion)
        filemenu.add_command(label='Exit', command=self.exit)
        master.protocol("WM_DELETE_WINDOW", self.exit)

        # Game
        counts = [10, 15, 25, 25]
        random.shuffle(counts)
        # randomly pair counts with each kind of dot
        objectives = zip(
            [BasicDot(1), BasicDot(2),
             BasicDot(4), BasicDot(3)], counts)

        self._objectives = ObjectiveManager(list(objectives))
        self._info.set_objectives(list(objectives))

        self._dead_cells = {(2, 2), (2, 3), (2, 4), (3, 2), (3, 3), (3, 4),
                            (4, 2), (4, 3), (4, 4), (0, 7), (1, 7), (6, 7),
                            (7, 7)}
        self._companion = EskimoCompanion()
        self._game = CompanionGame(
            {
                TurtleDot: 1,
                CompanionDot: 4,
                BasicDot: 11
            },
            objectives=self._objectives,
            companion=self._companion,
            kinds=(1, 2, 3, 4),
            size=(8, 8),
            dead_cells=self._dead_cells)

        # Grid View
        self._grid_view = GridView(self._master,
                                   size=self._game.grid.size(),
                                   image_manager=self._image_manager)
        self._grid_view.pack()
        self._grid_view.draw(self._game.grid)
        self.draw_grid_borders()

        # Events
        self.bind_events()

        # Set initial score again to trigger view update automatically
        self._refresh_status()

        self.read_score()
示例#10
0
class DotsApp(object):
    """Top level GUI class for simple Dots & Co game"""
    def __init__(self, master):
        """Constructor

        Parameters:
            master (tk.Tk|tk.Frame): The parent widget
        """
        pygame.init()
        self._master = master
        master.title('Dots')
        self._playing = True
        self._over = None
        self._player = 'None'
        self._scores = {}
        self._steps = 0
        self._image_manager = ImageManager('images/dots/', loader=load_image)

        # InfoPanel
        self._info = InfoPanel(master)
        self._info.pack(fill=tk.BOTH, expand=1)

        # Login
        top = tk.Toplevel()
        top.title('Login')
        tk.Label(top, text='Welcome to the Dots & Co game!').pack()
        frame = tk.Frame(top)
        frame.pack(side=tk.BOTTOM)
        tk.Label(frame, text="Name: ").pack(side=tk.LEFT)
        entry = tk.Entry(frame, width=20)
        entry.pack(side=tk.LEFT)

        def record(*args):
            self._player = entry.get()
            if self.read_score() == None:
                self.save_score()
            top.destroy()

        tk.Button(frame, text="Start!", command=record).pack(side=tk.RIGHT)
        top.bind('<Return>', record)

        # Menu
        menubar = tk.Menu(master)
        master.config(menu=menubar)
        filemenu = tk.Menu(menubar)
        menubar.add_cascade(label='File', menu=filemenu)
        newgame = tk.Menu(menubar)
        filemenu.add_cascade(label='New Game', menu=newgame)
        newgame.add_command(label='With a Companion',
                            command=self.with_companion)
        newgame.add_command(label='Without a Companion',
                            command=self.without_companion)
        filemenu.add_command(label='Exit', command=self.exit)
        master.protocol("WM_DELETE_WINDOW", self.exit)

        # Game
        counts = [10, 15, 25, 25]
        random.shuffle(counts)
        # randomly pair counts with each kind of dot
        objectives = zip(
            [BasicDot(1), BasicDot(2),
             BasicDot(4), BasicDot(3)], counts)

        self._objectives = ObjectiveManager(list(objectives))
        self._info.set_objectives(list(objectives))

        self._dead_cells = {(2, 2), (2, 3), (2, 4), (3, 2), (3, 3), (3, 4),
                            (4, 2), (4, 3), (4, 4), (0, 7), (1, 7), (6, 7),
                            (7, 7)}
        self._companion = EskimoCompanion()
        self._game = CompanionGame(
            {
                TurtleDot: 1,
                CompanionDot: 4,
                BasicDot: 11
            },
            objectives=self._objectives,
            companion=self._companion,
            kinds=(1, 2, 3, 4),
            size=(8, 8),
            dead_cells=self._dead_cells)

        # Grid View
        self._grid_view = GridView(self._master,
                                   size=self._game.grid.size(),
                                   image_manager=self._image_manager)
        self._grid_view.pack()
        self._grid_view.draw(self._game.grid)
        self.draw_grid_borders()

        # Events
        self.bind_events()

        # Set initial score again to trigger view update automatically
        self._refresh_status()

        self.read_score()
        # mixer not working under Ubuntu
        # pygame.mixer.Sound('Sounds/start.wav').play()

    def draw_grid_borders(self):
        """Draws borders around the game grid"""

        borders = list(self._game.grid.get_borders())

        # this is a hack that won't work well for multiple separate clusters
        outside = max(borders, key=lambda border: len(set(border)))

        for border in borders:
            self._grid_view.draw_border(border, fill=border != outside)

    def bind_events(self):
        """Binds relevant events"""
        self._grid_view.on('start_connection', self._drag)
        self._grid_view.on('move_connection', self._drag)
        self._grid_view.on('end_connection', self._drop)

        self._game.on('reset', self._refresh_status)
        self._game.on('complete', self._drop_complete)

        self._game.on('connect', self._connect)
        self._game.on('undo', self._undo)

    def _animation_step(self, step_name):
        """Runs for each step of an animation

        Parameters:
            step_name (str): The name (type) of the step
        """
        self._refresh_status()
        self.draw_grid()

    def animate(self, steps, callback=lambda: None):
        """Animates some steps (i.e. from selecting some dots, activating companion, etc.
        
        Parameters:
            steps (generator): Generator which yields step_name (str) for each step in the animation
        """
        if steps is None:
            steps = (None for _ in range(1))

        animation = create_animation(self._master,
                                     steps,
                                     delays=ANIMATION_DELAYS,
                                     delay=DEFAULT_ANIMATION_DELAY,
                                     step=self._animation_step,
                                     callback=callback)
        animation()

    def _drop(self, position):  # pylint: disable=unused-argument
        """Handles the dropping of the dragged connection

        Parameters:
            position (tuple<int, int>): The position where the connection was
                                        dropped
        """
        if not self._playing:
            return

        if self._game.is_resolving():
            return

        self._grid_view.clear_dragged_connections()
        self._grid_view.clear_connections()

        self.animate(self._game.drop())

        # drop_sound = pygame.mixer.Sound('Sounds/drop.wav')
        # drop_sound.play()

    def _connect(self, start, end):
        """Draws a connection from the start point to the end point

        Parameters:
            start (tuple<int, int>): The position of the starting dot
            end (tuple<int, int>): The position of the ending dot
        """
        if self._game.is_resolving():
            return
        if not self._playing:
            return
        self._grid_view.draw_connection(
            start, end, self._game.grid[start].get_dot().get_kind())

    def _undo(self, positions):
        """Removes all the given dot connections from the grid view

        Parameters:
            positions (list<tuple<int, int>>): The dot connects to remove
        """
        for _ in positions:
            self._grid_view.undo_connection()

    def _drag(self, position):
        """Attempts to connect to the given position, otherwise draws a dragged
        line from the start

        Parameters:
            position (tuple<int, int>): The position to drag to
        """
        if self._game.is_resolving():
            return
        if not self._playing:
            return

        tile_position = self._grid_view.xy_to_rc(position)

        if tile_position is not None:
            cell = self._game.grid[tile_position]
            dot = cell.get_dot()

            if dot and self._game.connect(tile_position):
                self._grid_view.clear_dragged_connections()
                return

        kind = self._game.get_connection_kind()

        if not len(self._game.get_connection_path()):
            return

        start = self._game.get_connection_path()[-1]

        if start:
            self._grid_view.draw_dragged_connection(start, position, kind)

    def draw_grid(self):
        """Draws the grid"""
        self._grid_view.draw(self._game.grid)

    def with_companion(self):
        """Sets the companion for the new game with a companion and resets"""
        self._companion = EskimoCompanion()
        self.reset()

    def without_companion(self):
        """Cancels the companion for the new game witout a companion and resets"""
        self._companion = None
        self.reset()

    def reset(self):
        """Resets the game"""
        self._playing = True
        self._steps = 0
        self._game.reset()
        self._objectives.reset()
        self._refresh_status()
        self._info.reset_bar()
        # start_sound = pygame.mixer.Sound('Sounds/start.wav')
        # start_sound.play()
        if self._over is not None:
            self._info.after_cancel(self._animation)

        if self._companion:
            img = tk.PhotoImage(file='images/companions/eskimo.png')
            self._info.set_companion(img)
            self._game = CompanionGame(
                {
                    TurtleDot: 1,
                    CompanionDot: 4,
                    BasicDot: 11
                },
                objectives=self._objectives,
                companion=self._companion,
                kinds=(1, 2, 3, 4),
                size=(8, 8),
                dead_cells=self._dead_cells)
        if not self._companion:
            img = tk.PhotoImage(file='images/companions/useless.gif')
            self._info.set_companion(img)
            self._game = DotGame({BasicDot: 1},
                                 objectives=self._objectives,
                                 kinds=(1, 2, 3, 4),
                                 size=(8, 8),
                                 dead_cells=self._dead_cells)
            self._info.set_bar(0)

        self._grid_view.draw(self._game.grid)
        self.bind_events()

    def exit(self):
        """Checks if the user wants to exit and closes the application if so"""
        reply = messagebox.askokcancel('Verify exit', 'Really quit?')
        if reply:
            self._master.destroy()

    def change_win(self):
        """Shows an animation when the user wins"""
        self._over = not self._over
        if self._over:
            img = tk.PhotoImage(file='images/win1.gif')
            self._info.set_companion(img)
        else:
            img = tk.PhotoImage(file='images/win2.gif')
            self._info.set_companion(img)
        self._animation = self._info.after(800, self.change_win)

    def change_lose(self):
        """Shows an animation when the user loses"""
        self._over = not self._over
        if self._over:
            img = tk.PhotoImage(file='images/gameover1.png')
            self._info.set_companion(img)
        else:
            img = tk.PhotoImage(file='images/gameover2.png')
            self._info.set_companion(img)
        self._animation = self._info.after(800, self.change_lose)

    def check_game_over(self):
        """Checks whether the game is over and shows an appropriate message box if so"""
        state = self._game.get_game_state()

        if state == self._game.GameState.WON:
            # Shows the animation and plays sound effects
            self._over = True
            self.change_win()
            # pygame.mixer.Sound('Sounds/success.wav').play()
            # Saves the best score
            if self._player == 'None':
                self.save_score()
            elif self._game.get_score() > self.read_score():
                self.save_score()
            # Shows the user's highest ranking and the top 3 players
            ranking = sorted(self._scores,
                             key=self._scores.__getitem__,
                             reverse=True)
            position = ranking.index(self._player) + 1
            top = ''
            for name in ranking[:3]:
                top += "{0}--{1}   ".format(name, self._scores.get(name))
            messagebox.showinfo(
                "Game Over!",
                "You won!!!\nYour best socre: {0}. Your highest ranking: {1}.\n Top 3: "
                .format(self.read_score(), position) + top)
            self._playing = False

        elif state == self._game.GameState.LOST:
            self._over = True
            self.change_lose()
            # pygame.mixer.Sound('Sounds/lose.wav').play()
            messagebox.showinfo(
                "Game Over!",
                f"You didn't reach the objective(s) in time. You connected {self._game.get_score()} points"
            )
            self._playing = False

    def read_score(self):
        """(int) Returns the user's former best score.
        Returns None if the user plays the game for the first time

        Precondition:
            The user's name does not consist ','
        """
        f = open('score.txt', 'r')
        lines = f.readlines()
        for l in lines:
            if l:
                s = l.split(',')
                self._scores[s[0]] = int(s[1])
        score = self._scores.get(self._player)
        f.close
        return score

    def save_score(self):
        """Saves the user's score"""
        self._scores[self._player] = self._game.get_score()
        result = ''
        for n in self._scores:
            line = str(n) + "," + str(self._scores[n]) + "\n"
            result += line
        f = open('score.txt', 'w')
        f.write(result)
        f.close

    def _drop_complete(self):
        """Handles the end of a drop animation"""
        if not self._companion:
            self._steps += 1
            step = self._steps % 6
            if step == 0:
                self._info.reset_bar()
            self._info.set_bar(step)

        if self._companion:
            charge = self._game.companion.get_charge()
            for i in range(charge):
                self._info.set_bar(i)
            if self._game.companion.is_fully_charged():
                # pygame.mixer.Sound('Sounds/companion.wav').play()
                steps = self._game.companion.activate(self._game)
                self._grid_view.draw(self._game.grid)
                self._game.companion.reset()
                self._info.reset_bar()
                self.check_game_over()
                return self.animate(steps)

        self._grid_view.draw(self._game.grid)
        self.check_game_over()

    def _refresh_status(self):
        """Handles change in objectives, remaining moves, and score."""
        status = self._objectives.get_status()
        self._info.set_objectives(status)

        moves = self._game.get_moves()
        self._info.set_moves(moves)

        score = self._game.get_score()
        self._info.set_score(score)
示例#11
0
    def __init__(self, master):
        """Constructor

        Parameters:
            master (tk.Tk|tk.Frame): The parent widget
        """
        self._master = master
        self._master.title('Dot')
        self._playing = True
        self._image_manager = ImageManager('images/dots/', loader=load_image)

        # initialize pygame
        pygame.init()

        # load background music
        pygame.mixer.music.load('bgm2.ogg')
        pygame.mixer.music.play(-1, 0.0)
        pygame.mixer.music.set_volume(0.3)

        # create an instance of InfoPanel
        self.info_panel = InfoPanel(master)
        self.info_panel.pack()

        # create an instance of IntervalBar
        self.interval_bar = IntervalBar(master)
        self.interval_bar.pack()

        # create an instance of ActionBar
        self.action_bar = ActionBar(master)
        self.action_bar.pack(side=tk.BOTTOM)

        # add command to two button
        self.action_bar.companion_charge().config(command=self.com_button)
        self.action_bar.colour_remove().config(command=self.colour_activate)

        # File menu
        menubar = tk.Menu(self._master)
        # tell master what it's menu is
        self._master.config(menu=menubar)
        filemenu = tk.Menu(menubar)
        menubar.add_cascade(label="File", menu=filemenu)
        filemenu.add_command(label="New Game(companion)",
                             command=self.reset_with_com)
        filemenu.add_command(label="New Game(no-companion)",
                             command=self.reset_without_com)
        filemenu.add_command(label="Exit", command=self.exit)

        # Game
        counts = [10, 15, 25, 25]
        random.shuffle(counts)
        # randomly pair counts with each kind of dot
        objectives = zip(
            [BasicDot(1), BasicDot(2),
             BasicDot(4), BasicDot(3)], counts)
        self._objectives = ObjectiveManager(list(objectives))
        # show the objectives
        self._obj = self.info_panel.set_object()
        self._obj.draw(self._objectives.get_status())

        # Game
        dead_cells = {(2, 2), (2, 3), (2, 4), (3, 2), (3, 3), (3, 4), (4, 2),
                      (4, 3), (4, 4), (0, 7), (1, 7), (6, 7), (7, 7)}
        self._game = CompanionGame({
            BasicDot: 1,
            CompanionDot: 1
        },
                                   companion=EskimoCompanion(),
                                   objectives=self._objectives,
                                   kinds=(1, 2, 3, 4),
                                   size=(8, 8),
                                   dead_cells=dead_cells)

        # show the remaining moves
        moves = self.info_panel.remain_moves()
        moves.config(text=str(self._game.get_moves()))
        # show the scores
        scores = self.info_panel.set_scores()
        scores.config(text=str(self._game.get_score()))

        # control the reset type(with/without companion)
        self._play_with_com = True

        # Grid View
        self._grid_view = GridView(master,
                                   size=self._game.grid.size(),
                                   image_manager=self._image_manager)
        self._grid_view.pack()
        self._grid_view.draw(self._game.grid)
        self.draw_grid_borders()

        # Events
        self.bind_events()

        # Set initial score again to trigger view update automatically
        self._refresh_status()
示例#12
0
class DotsApp:
    """Top level GUI class for simple Dots & Co game"""
    def __init__(self, master):
        """Constructor

        Parameters:
            master (tk.Tk|tk.Frame): The parent widget
        """
        self._master = master
        self._master.title('Dot')
        self._playing = True
        self._image_manager = ImageManager('images/dots/', loader=load_image)

        # initialize pygame
        pygame.init()

        # load background music
        pygame.mixer.music.load('bgm2.ogg')
        pygame.mixer.music.play(-1, 0.0)
        pygame.mixer.music.set_volume(0.3)

        # create an instance of InfoPanel
        self.info_panel = InfoPanel(master)
        self.info_panel.pack()

        # create an instance of IntervalBar
        self.interval_bar = IntervalBar(master)
        self.interval_bar.pack()

        # create an instance of ActionBar
        self.action_bar = ActionBar(master)
        self.action_bar.pack(side=tk.BOTTOM)

        # add command to two button
        self.action_bar.companion_charge().config(command=self.com_button)
        self.action_bar.colour_remove().config(command=self.colour_activate)

        # File menu
        menubar = tk.Menu(self._master)
        # tell master what it's menu is
        self._master.config(menu=menubar)
        filemenu = tk.Menu(menubar)
        menubar.add_cascade(label="File", menu=filemenu)
        filemenu.add_command(label="New Game(companion)",
                             command=self.reset_with_com)
        filemenu.add_command(label="New Game(no-companion)",
                             command=self.reset_without_com)
        filemenu.add_command(label="Exit", command=self.exit)

        # Game
        counts = [10, 15, 25, 25]
        random.shuffle(counts)
        # randomly pair counts with each kind of dot
        objectives = zip(
            [BasicDot(1), BasicDot(2),
             BasicDot(4), BasicDot(3)], counts)
        self._objectives = ObjectiveManager(list(objectives))
        # show the objectives
        self._obj = self.info_panel.set_object()
        self._obj.draw(self._objectives.get_status())

        # Game
        dead_cells = {(2, 2), (2, 3), (2, 4), (3, 2), (3, 3), (3, 4), (4, 2),
                      (4, 3), (4, 4), (0, 7), (1, 7), (6, 7), (7, 7)}
        self._game = CompanionGame({
            BasicDot: 1,
            CompanionDot: 1
        },
                                   companion=EskimoCompanion(),
                                   objectives=self._objectives,
                                   kinds=(1, 2, 3, 4),
                                   size=(8, 8),
                                   dead_cells=dead_cells)

        # show the remaining moves
        moves = self.info_panel.remain_moves()
        moves.config(text=str(self._game.get_moves()))
        # show the scores
        scores = self.info_panel.set_scores()
        scores.config(text=str(self._game.get_score()))

        # control the reset type(with/without companion)
        self._play_with_com = True

        # Grid View
        self._grid_view = GridView(master,
                                   size=self._game.grid.size(),
                                   image_manager=self._image_manager)
        self._grid_view.pack()
        self._grid_view.draw(self._game.grid)
        self.draw_grid_borders()

        # Events
        self.bind_events()

        # Set initial score again to trigger view update automatically
        self._refresh_status()

    def draw_grid_borders(self):
        """Draws borders around the game grid"""

        borders = list(self._game.grid.get_borders())

        # this is a hack that won't work well for multiple separate clusters
        outside = max(borders, key=lambda border: len(set(border)))

        for border in borders:
            self._grid_view.draw_border(border, fill=border != outside)

    def bind_events(self):
        """Binds relevant events"""
        self._grid_view.on('start_connection', self._drag)
        self._grid_view.on('move_connection', self._drag)
        self._grid_view.on('end_connection', self._drop)

        self._game.on('reset', self._refresh_status)
        self._game.on('complete', self._drop_complete)

        self._game.on('connect', self._connect)
        self._game.on('undo', self._undo)

    def _animation_step(self, step_name):
        """Runs for each step of an animation
        
        Parameters:
            step_name (str): The name (type) of the step    
        """

        # add sound effect
        sound = pygame.mixer.Sound('boble1.wav')
        sound.play()

        print(step_name)
        self._refresh_status()
        self.draw_grid()

    def animate(self, steps, callback=lambda: None):
        """Animates some steps (i.e. from selecting some dots, activating companion, etc.
        
        Parameters:
            steps (generator): Generator which yields step_name (str) for each step in the animation
        """

        if steps is None:
            steps = (None for _ in range(1))

        animation = create_animation(self._master,
                                     steps,
                                     delays=ANIMATION_DELAYS,
                                     delay=DEFAULT_ANIMATION_DELAY,
                                     step=self._animation_step,
                                     callback=callback)
        animation()

    def _drop(self, position):  # pylint: disable=unused-argument
        """Handles the dropping of the dragged connection

        Parameters:
            position (tuple<int, int>): The position where the connection was
                                        dropped
        """
        if not self._playing:
            return

        if self._game.is_resolving():
            return

        self._grid_view.clear_dragged_connections()
        self._grid_view.clear_connections()

        self.animate(self._game.drop())

    def _connect(self, start, end):
        """Draws a connection from the start point to the end point

        Parameters:
            start (tuple<int, int>): The position of the starting dot
            end (tuple<int, int>): The position of the ending dot
        """

        # add sound effect when two connects
        sound = pygame.mixer.Sound('cartoon-boing.ogg')
        sound.play()

        if self._game.is_resolving():
            return
        if not self._playing:
            return
        self._grid_view.draw_connection(
            start, end, self._game.grid[start].get_dot().get_kind())

    def _undo(self, positions):
        """Removes all the given dot connections from the grid view

        Parameters:
            positions (list<tuple<int, int>>): The dot connects to remove
        """
        for _ in positions:
            self._grid_view.undo_connection()

    def _drag(self, position):
        """Attempts to connect to the given position, otherwise draws a dragged
        line from the start

        Parameters:
            position (tuple<int, int>): The position to drag to
        """

        if self._game.is_resolving():
            return
        if not self._playing:
            return

        tile_position = self._grid_view.xy_to_rc(position)

        if tile_position is not None:
            cell = self._game.grid[tile_position]
            dot = cell.get_dot()

            if dot and self._game.connect(tile_position):
                self._grid_view.clear_dragged_connections()
                return

        kind = self._game.get_connection_kind()

        if not len(self._game.get_connection_path()):
            return

        start = self._game.get_connection_path()[-1]

        if start:
            self._grid_view.draw_dragged_connection(start, position, kind)

    @staticmethod
    def remove(*_):
        """Deprecated in 1.1.0"""
        raise DeprecationWarning("Deprecated in 1.1.0")

    def draw_grid(self):
        """Draws the grid"""
        self._grid_view.draw(self._game.grid)

    def reset_without_com(self):
        """Resets the game"""

        # initialize pygame
        pygame.init()
        # load background music
        pygame.mixer.music.load('bgm2.ogg')
        pygame.mixer.music.play(-1, 0.0)
        pygame.mixer.music.set_volume(0.3)

        counts = [10, 15, 25, 25]
        random.shuffle(counts)
        # randomly pair counts with each kind of dot
        objectives = zip(
            [BasicDot(1), BasicDot(2),
             BasicDot(4), BasicDot(3)], counts)
        self._objectives = ObjectiveManager(list(objectives))

        dead_cells = {(2, 2), (2, 3), (2, 4), (3, 2), (3, 3), (3, 4), (4, 2),
                      (4, 3), (4, 4), (0, 7), (1, 7), (6, 7), (7, 7)}
        self._game = DotGame({BasicDot: 1},
                             objectives=self._objectives,
                             kinds=(1, 2, 3, 4),
                             size=(8, 8),
                             dead_cells=dead_cells)

        # reset the game(score, move)
        self._game.reset()
        # reset the score
        scores = self.info_panel.set_scores()
        scores.config(text=str(self._game.get_score()))
        # reset the move
        moves = self.info_panel.remain_moves()
        moves.config(text=str(self._game.get_moves()))

        # reset the objectives
        self._obj.draw(self._objectives.get_status())

        # reset the grid
        self.draw_grid()

        # reset the interval bar
        self.interval_bar.progress_bar(0)
        self.interval_bar.com_charge_bar_reset()

        # player choose to play without companion
        self._play_with_com = False
        # reset the companion charge button as disable
        self.action_bar.companion_charge().config(state='disable')
        # reset the color remover button
        self.action_bar.colour_remove().config(state='normal')

    def reset_with_com(self):
        # initialize pygame
        pygame.init()
        # load background music
        pygame.mixer.music.load('bgm2.ogg')
        pygame.mixer.music.play(-1, 0.0)
        pygame.mixer.music.set_volume(0.3)

        counts = [10, 15, 25, 25]
        random.shuffle(counts)
        # randomly pair counts with each kind of dot
        objectives = zip(
            [BasicDot(1), BasicDot(2),
             BasicDot(4), BasicDot(3)], counts)
        self._objectives = ObjectiveManager(list(objectives))

        # reset the objectives
        self._obj.draw(self._objectives.get_status())

        dead_cells = {(2, 2), (2, 3), (2, 4), (3, 2), (3, 3), (3, 4), (4, 2),
                      (4, 3), (4, 4), (0, 7), (1, 7), (6, 7), (7, 7)}
        self._game = CompanionGame({
            BasicDot: 1,
            CompanionDot: 1
        },
                                   companion=EskimoCompanion(),
                                   objectives=self._objectives,
                                   kinds=(1, 2, 3, 4),
                                   size=(8, 8),
                                   dead_cells=dead_cells)
        # reset the game(score, move)
        self._game.reset()

        # reset the grid
        self.draw_grid()

        # reset the score
        scores = self.info_panel.set_scores()
        scores.config(text=str(self._game.get_score()))
        # reset the move
        moves = self.info_panel.remain_moves()
        moves.config(text=str(self._game.get_moves()))

        # reset the interval bar
        self.interval_bar.progress_bar(0)
        self._game.companion.reset()
        # reset the companion bar
        self.interval_bar.com_charge_bar_reset()
        # reset the companion charge button
        self.action_bar.companion_charge().config(state='normal')
        # reset the color remover button
        self.action_bar.colour_remove().config(state='normal')

    def check_game_over(self):
        """Checks whether the game is over and shows an appropriate message box if so"""
        state = self._game.get_game_state()

        if state == self._game.GameState.WON:
            # load the gamewin music
            pygame.mixer.music.load('breaking slient.ogg')
            pygame.mixer.music.play()
            showinfo("Game Over!", "You won!!!")
            self._playing = False
        elif state == self._game.GameState.LOST:
            # load the gameover music
            pygame.mixer.music.load('gameOver.wav')
            pygame.mixer.music.play()
            showinfo(
                "Game Over!",
                f"You didn't reach the objective(s) in time. You connected {self._game.get_score()} points"
            )

            self._playing = False

    def _drop_complete(self):
        """Handles the end of a drop animation"""

        # Need to check whether the game is over
        # check whether the game is over
        self.check_game_over()

    def _refresh_status(self):
        """Handles change in score"""

        # Normally, this should raise the following error:
        # raise NotImplementedError()
        # But so that the game can work prior to this method being implemented,
        # we'll just print some information
        # Sometimes I believe Python ignores all my comments :(

        # show the remaining objectives using get_status() function
        self._obj.draw(self._objectives.get_status())

        # show the interval bar(max==6)
        bar_num = (20 - self._game.get_moves()) % 6
        self.interval_bar.progress_bar(bar_num)

        # show the current score
        scores = self.info_panel.set_scores()
        scores.config(text=str(self._game.get_score()))

        # show the remaining moves
        moves = self.info_panel.remain_moves()
        moves.config(text=str(self._game.get_moves()))

        # if player choose to play without companion, then undo the following part
        if self._play_with_com == True:
            charge_num = self._game.companion.get_charge()
            for i in range(charge_num):
                self.interval_bar.com_charge_bar(i)
            # reset the companion when fully-charged
            if self._game.companion.is_fully_charged():
                self._game.companion.reset()
                steps = self._game.companion.activate(self._game)
                self._refresh_status()
                return self.animate(steps)

        score = self._game.get_score()
        print("Score is now {}.".format(score))

    # exit function
    def exit(self):
        """Ask exit or not when click exit button"""

        ans = messagebox.askokcancel('Verify exit', 'Really exit?')
        if ans:
            # close the game window
            self._master.destroy()

    def com_button(self):
        """Immediately activates the companion"""

        # set the button disabled after first use
        self.action_bar.companion_charge().config(state='disable')
        # charge the companion dot for 6 times to activate the companion
        self._game.companion.charge(6)
        charge_num = self._game.companion.get_charge()
        # change the interval bar
        for i in range(charge_num):
            self.interval_bar.com_charge_bar(i)
        self._game.companion.reset()
        steps = self._game.companion.activate(self._game)
        self._refresh_status()
        return self.animate(steps)

    def colour_activate(self):
        """Immediately activates (& removes) all dots of a random kind (colour)"""

        # set the button disabled after first use
        self.action_bar.colour_remove().config(state='disable')
        # generate a random kind
        kind = random.randint(1, 4)
        dead_cells = {(2, 2), (2, 3), (2, 4), (3, 2), (3, 3), (3, 4), (4, 2),
                      (4, 3), (4, 4), (0, 7), (1, 7), (6, 7), (7, 7)}
        # create a set to save all the positions to be activated
        to_activate = set()
        for i in range(0, 8):
            for j in range(0, 8):
                # generate a random position
                position = (i, j)
                # the position is not in dead_cells and its kind is the random kind
                if position not in dead_cells and self._game.grid[
                        position].get_dot().get_kind() == kind:
                    # add the position into set
                    to_activate.add(position)
        # activate all the position in set
        steps = self._game.activate_all(to_activate)
        return self.animate(steps)
示例#13
0
 def __init__(self, root, top):
     self.root = root
     self.model = Model(self)  # You pass this parameter so the model can 'see' the controller
     self.grid_v = GridView(self, top)
     self.info_b = InfoBox(self, root)