Skip to content
Commits on Source (5)
venv/
*pycache*
\ No newline at end of file
from pythonsnake.controller import Controller
if __name__ == "__main__":
controller = Controller()
controller.game_menu()
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)
from pythonsnake.model import Game
from pythonsnake.terminalview import TerminalView
import keyboard
import time
class Controller:
def __init__(self) -> None:
self.view = TerminalView()
self.game = None
def game_menu(self) -> None:
while True:
self.start_game(self.choose_mode())
def choose_mode(self) -> int:
self.view.menu()
choice = None
while choice != "1" and choice != "2":
choice = input("=>")
if choice != "1" and choice != "2":
self.view.menu_choice_incorrect()
if choice == "2":
exit()
return int(choice)
def start_game(self, mode: int) -> None:
self.game = Game(50, 25)
if mode == 1:
self.start_game_terminal()
def start_game_terminal(self) -> None:
keyboard.unhook_all()
self.listen_escape_game()
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 listen_move(self) -> None:
if keyboard.is_pressed("left arrow"):
self.view.display_grid(self.game.move("left arrow"))
if keyboard.is_pressed("right arrow"):
self.view.display_grid(self.game.move("right arrow"))
if keyboard.is_pressed("up arrow"):
self.view.display_grid(self.game.move("up arrow"))
if keyboard.is_pressed("down arrow"):
self.view.display_grid(self.game.move("down arrow"))
from copy import copy
import random
from pythonsnake.snake import Snake
from pythonsnake.candy import Candy
class Game:
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 = Candy(grid_width, grid_height, self.snake)
self.grid = self.init_grid(grid_width, grid_height)
self.update_grid()
def move(self, direction: str):
# if the User is not trying to U turn, process the move
if not self.is_U_turn(direction):
# 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
)
self.update_grid()
else:
self.lost = True
return self
def exit_game(self):
self.lost = True
"""
check if the move is allowed in the grid
"""
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 (
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 False
return True
def new_candy(self):
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 is_U_turn(self, direction: str) -> bool:
# the User/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 True
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
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
HEADER = "\033[95m"
OKBLUE = "\033[94m"
OKCYAN = "\033[96m"
OKGREEN = "\033[92m"
WARNING = "\033[93m"
FAIL = "\033[91m"
ENDC = "\033[0m"
BOLD = "\033[1m"
UNDERLINE = "\033[4m"
from pythonsnake.model import Game
from pythonsnake import terminalColor
import os
class TerminalView:
def __init__(self) -> None:
pass
def cls(self) -> None:
os.system("cls" if os.name == "nt" else "clear")
def display_grid(self, gameState: Game) -> None:
grid_to_print = ""
for Y, line in enumerate(gameState.grid):
# if first row, display the top border
if Y == 0:
grid_to_print += "_" * len(line)
grid_to_print += "\n"
for X, column in enumerate(line):
# if left border, display border
if X == 0:
grid_to_print += "|"
# display user
if column["snake"] == True:
grid_to_print += (
terminalColor.OKGREEN + "X" + terminalColor.ENDC
)
# display candy except if same coord as player
elif column["candy"] == True:
grid_to_print += (
terminalColor.OKBLUE + "O" + terminalColor.ENDC
)
else:
grid_to_print += " "
# if right border, display border
if X == len(line) - 1:
grid_to_print += "|\n"
# if last row, display the bottom border
if Y == len(gameState.grid) - 1:
grid_to_print += "\u203E" * len(line)
grid_to_print += "\n"
if gameState.lost:
grid_to_print += (
terminalColor.FAIL
+ terminalColor.BOLD
+ terminalColor.UNDERLINE
+ "Vous avez perdu !!!"
+ terminalColor.ENDC
+ "\n"
)
grid_to_print += (
terminalColor.OKCYAN
+ "pour revenir au menu, appuyer sur la touche (Esc)"
+ terminalColor.ENDC
+ "\n"
)
grid_to_print += (
terminalColor.OKBLUE
+ "Longueur: "
+ str(len(gameState.snake.coord))
+ terminalColor.ENDC
)
self.cls()
print(grid_to_print, end="\r")
def menu(self) -> None:
self.cls()
menu = (
terminalColor.OKGREEN
+ terminalColor.BOLD
+ "Bienvenue dans python Snake"
+ terminalColor.ENDC
+ "\n"
+ "que souhaitez vous faire:\n"
+ "1) jouer dans la console\n"
+ "2) Quitter\n"
)
print(menu, end="\r")
def menu_choice_incorrect(self) -> None:
print(
terminalColor.FAIL, "le choix n'est pas correct", terminalColor.ENDC
)