Commit ebbeaee3 authored by Anthony Jacob's avatar Anthony Jacob
Browse files

add multiple class and refactor

now able to have a real snake
parent 514830cf
Loading
Loading
Loading
Loading
+2 −1
Changes for main.py: 2 added lines, 1 removed line.
Original line number Diff line number Diff line
from pythonsnake import controller
from pythonsnake.controller import Controller


if __name__ == "__main__":
    controller = Controller()
    controller.game_menu()

pythonsnake/candy.py

0 → 100644
+55 −0
Changes for pythonsnake/candy.py: 55 added lines, 0 removed lines.
Original line number Diff line number Diff line
from random import choice
from pythonsnake.snake import Snake


class Candy:
    def __init__(self, grid_width: int, grid_height: int, snake: Snake) -> None:
        self.X = 0
        self.Y = 0
        self.random_coord(grid_width, grid_height, snake)

    def random_coord(
        self, grid_width: int, grid_height: int, snake: Snake
    ) -> None:
        found = False
        x = 0
        y = 0
        while not found:
            correct = True
            x = self.random_coord_X(grid_width, snake)
            y = self.random_coord_Y(grid_height, snake)
            # candy can be on the same line or on the same column but not at
            # the exact same place as the snake
            for snake_part in snake.coord:
                if snake_part["x"] == x and snake_part["y"] == y:
                    correct = False
                    break

            if correct:
                found = True

        self.X = x
        self.Y = y

    def random_coord_X(self, grid_width: int, snake: Snake) -> int:
        coord_to_exclude = []
        for snake_part in snake.coord:
            coord_to_exclude.append(snake_part["x"])

        return choice(
            [i for i in range(0, grid_width) if i not in coord_to_exclude]
        )

    def random_coord_Y(self, grid_height: int, snake: Snake) -> int:
        coord_to_exclude = []
        for snake_part in snake.coord:
            coord_to_exclude.append(snake_part["y"])

        return choice(
            [i for i in range(0, grid_height) if i not in coord_to_exclude]
        )

    def new_coord(
        self, grid_width: int, grid_height: int, snake: Snake
    ) -> None:
        self.random_coord(grid_width, grid_height, snake)
+31 −36
Changes for pythonsnake/controller.py: 31 added lines, 36 removed lines.
Original line number Diff line number Diff line
from pythonsnake import model, view
from pythonsnake.model import Game
from pythonsnake.terminalview import TerminalView
import keyboard
import time


def game_menu():
class Controller:
    def __init__(self) -> None:
        self.view = TerminalView()
        self.game = None

    def game_menu(self) -> None:
        while True:
        start_game(choose_mode())
            self.start_game(self.choose_mode())


def choose_mode():
    view.menu()
    def choose_mode(self) -> int:
        self.view.menu()

        choice = None
    while choice != "1" and choice != "2" and choice != "3":
        while choice != "1" and choice != "2":

            choice = input("=>")
        if choice != "1" and choice != "2" and choice != "3":
            view.menu_choice_incorrect()
            if choice != "1" and choice != "2":
                self.view.menu_choice_incorrect()

    if choice == "3":
        if choice == "2":
            exit()

        return int(choice)


def start_game(mode):
    gameState = model.Game(29)
    def start_game(self, mode: int) -> None:
        self.game = Game(50, 25)

        if mode == 1:
        start_game_terminal(gameState)
    elif mode == 2:
        start_game_UI(gameState)
            self.start_game_terminal()


def start_game_terminal(gameState):
    def start_game_terminal(self) -> None:

        keyboard.unhook_all()
    listen_escape_game(gameState)
        self.listen_escape_game()

    while not gameState.lost:
        # gameState.step() 
        view.refresh_grid(gameState.move(gameState.current_direction + " arrow"))
        listen_move(gameState)
        while not self.game.lost:
            self.view.display_grid(
                self.game.move(self.game.current_direction + " arrow")
            )
            self.listen_move()
            continue

        time.sleep(1)
        keyboard.unhook_all()

    def listen_escape_game(self) -> None:
        keyboard.on_press_key("esc", lambda _: self.game.exit_game())

def start_game_UI(game):
    pass


def listen_escape_game(gameState):
    keyboard.on_press_key("esc", lambda _: gameState.exit_game())


def listen_move(gameState):
    def listen_move(self) -> None:

        if keyboard.is_pressed("left arrow"):
        view.refresh_grid(gameState.move("left arrow"))
            self.view.display_grid(self.game.move("left arrow"))
        if keyboard.is_pressed("right arrow"):
        view.refresh_grid(gameState.move("right arrow"))
            self.view.display_grid(self.game.move("right arrow"))
        if keyboard.is_pressed("up arrow"):
        view.refresh_grid(gameState.move("up arrow"))
            self.view.display_grid(self.game.move("up arrow"))
        if keyboard.is_pressed("down arrow"):
        view.refresh_grid(gameState.move("down arrow"))
            self.view.display_grid(self.game.move("down arrow"))
+104 −51
Changes for pythonsnake/model.py: 104 added lines, 51 removed lines.
Original line number Diff line number Diff line
from copy import copy
import random
from pythonsnake.snake import Snake
from pythonsnake.candy import Candy


class Game:
    def __init__(self, grid_size) -> None:
        self.grid_size = grid_size
        self.grid = [[i for i in range(grid_size)] for j in range(grid_size)]
        self.player_coord = [0, 0]
        self.player_length = 1
    def __init__(self, grid_width: int, grid_height: int) -> None:
        self.grid_width = grid_width
        self.grid_height = grid_height
        self.snake = Snake()
        self.lost = False
        self.current_direction = "right"
        self.candy = self.new_candy()
        self.candy = Candy(grid_width, grid_height, self.snake)
        self.grid = self.init_grid(grid_width, grid_height)
        self.update_grid()

    def move(self, direction):
    def move(self, direction: str):
        # if the User is not trying to U turn, process the move
        if not self.is_U_turn(direction):

        # the snake can't make a U turn 
        if(direction == "left arrow" and self.current_direction == "right"
           or direction == "right arrow" and self.current_direction == "left"
           or direction == "up arrow" and self.current_direction == "down"
           or direction == "down arrow" and self.current_direction == "up"):
            return self
            # if the move is allowed (not off grid or snake not biting itself)
            if self.is_move_allowed(direction):
                self.current_direction = direction.replace(" arrow", "")
                self.snake.move(direction)
                if self.check_candy():
                    self.snake.eat_candy()
                    self.candy.new_coord(
                        self.grid_width, self.grid_height, self.snake
                    )

        if direction == "left arrow" and self.check_move(
            self.player_coord[0] - 1, self.player_coord[1]
        ):
            self.player_coord[0] -= 1
            self.current_direction = "left"
        elif direction == "right arrow" and self.check_move(
            self.player_coord[0] + 1, self.player_coord[1]
        ):
            self.player_coord[0] += 1
            self.current_direction = "right"
        elif direction == "up arrow" and self.check_move(
            self.player_coord[0], self.player_coord[1] - 1
        ):
            self.player_coord[1] -= 1
            self.current_direction = "up"
        elif direction == "down arrow" and self.check_move(
            self.player_coord[0], self.player_coord[1] + 1
        ):
            self.player_coord[1] += 1
            self.current_direction = "down"
                self.update_grid()
            else:
                self.lost = True

        self.check_candy()

        return self

    def exit_game(self):
        self.lost = True

    """
    check if the move is still in the grid
    check if the move is allowed in the grid
    """

    def check_move(self, coordX, coordY):
    def is_move_allowed(self, direction: str):

        snake_head = copy(self.snake.coord[0])
        if direction == "left arrow":
            snake_head["x"] -= 1
        elif direction == "right arrow":
            snake_head["x"] += 1
        elif direction == "up arrow":
            snake_head["y"] -= 1
        elif direction == "down arrow":
            snake_head["y"] += 1

        # check if next position of snake head is off grid
        if (
            coordX >= 0
            and coordX <= len(self.grid) - 1
            and coordY >= 0
            and coordY <= len(self.grid[0]) - 1
            snake_head["x"] < 0
            or snake_head["x"] >= self.grid_width
            or snake_head["y"] < 0
            or snake_head["y"] >= self.grid_height
        ):
            return False

        # check if next position of snake haed is not another snake piece
        for snake_piece in self.snake.coord:
            if (
                snake_piece["x"] == snake_head["x"]
                and snake_piece["y"] == snake_head["y"]
            ):
            return True
        else:
                return False

        return True

    def new_candy(self):
        return [random.randint(0, self.grid_size), random.randint(0, self.grid_size)]
        return [
            random.randint(0, self.grid_size),
            random.randint(0, self.grid_size),
        ]

    def check_candy(self) -> bool:
        if (
            self.snake.coord[0]["x"] == self.candy.X
            and self.snake.coord[0]["y"] == self.candy.Y
        ):
            return True

        return False

    def check_candy(self):
    def is_U_turn(self, direction: str) -> bool:
        # the User/snake can't make a U turn
        if (
            self.player_coord[0] == self.candy[0]
            and self.player_coord[1] == self.candy[1]
            direction == "left arrow"
            and self.current_direction == "right"
            or direction == "right arrow"
            and self.current_direction == "left"
            or direction == "up arrow"
            and self.current_direction == "down"
            or direction == "down arrow"
            and self.current_direction == "up"
        ):
            self.eat_candy()
            return True

    def eat_candy(self):
        self.player_length += 1
        self.candy = self.new_candy()
        return False

        """
        _summary_

        init the playing grid with format
                            column = width
        height = Y1 = line = [ [X1],[X2],[X3],[X4] ]
                        Y2     [X1],[X2],[X3],[X4]
                        Y3     [X1],[X2],[X3],[X4]
                        Y4     [X1],[X2],[X3],[X4]
        """

    def init_grid(self, grid_width: int, grid_height: int) -> None:
        return [
            [{"snake": False, "candy": False} for i in range(0, grid_width)]
            for j in range(0, grid_height)
        ]

    def update_grid(self) -> None:
        # reset grid
        for line in self.grid:
            for column in line:
                column["snake"] = False
                column["candy"] = False

        for snake_piece in self.snake.coord:
            self.grid[snake_piece["y"]][snake_piece["x"]]["snake"] = True

        self.grid[self.candy.Y][self.candy.X]["candy"] = True

pythonsnake/snake.py

0 → 100644
+42 −0
Changes for pythonsnake/snake.py: 42 added lines, 0 removed lines.
Original line number Diff line number Diff line
from copy import deepcopy


class Snake:
    def __init__(self) -> None:
        self.coord = []
        self.coord.append({"x": 0, "y": 0})
        self.piece_pending = None

    def eat_candy(self) -> None:
        self.piece_pending = {
            "x": self.coord[-1]["x"],
            "y": self.coord[-1]["y"],
        }

    def move(self, direction) -> None:
        snake_to_shift = deepcopy(self.coord)

        # move the snake head
        if direction == "left arrow":
            self.coord[0]["x"] -= 1
        elif direction == "right arrow":
            self.coord[0]["x"] += 1
        elif direction == "up arrow":
            self.coord[0]["y"] -= 1
        elif direction == "down arrow":
            self.coord[0]["y"] += 1

        # move the body
        for i, piece in enumerate(snake_to_shift):
            # except the snake head
            if i != 0:
                self.coord[i] = {
                    "x": snake_to_shift[i - 1]["x"],
                    "y": snake_to_shift[i - 1]["y"],
                }

        if self.piece_pending != None:
            self.coord.append(
                {"x": self.piece_pending["x"], "y": self.piece_pending["y"]}
            )
            self.piece_pending = None
Loading