Last active
November 28, 2025 08:11
-
-
Save elisco-latour/0937063573002db2c97e669401ca707f to your computer and use it in GitHub Desktop.
Python Snake Game - PyGame Version
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| """ | |
| SNAKE GAME - PYGAME VERSION | |
| A graphical implementation of the classic Snake game using Pygame. | |
| Controls: Arrow Keys to move, Q or ESC to quit | |
| """ | |
| import pygame | |
| import random | |
| import sys | |
| # Initialize Pygame | |
| pygame.init() | |
| # Game Constants | |
| GRID_SIZE = 15 | |
| CELL_SIZE = 30 | |
| WINDOW_WIDTH = GRID_SIZE * CELL_SIZE | |
| WINDOW_HEIGHT = GRID_SIZE * CELL_SIZE + 60 # Extra space for score | |
| FPS = 60 | |
| # Colors | |
| BLACK = (0, 0, 0) | |
| WHITE = (255, 255, 255) | |
| GREEN = (0, 255, 0) | |
| DARK_GREEN = (0, 200, 0) | |
| RED = (255, 0, 0) | |
| YELLOW = (255, 255, 0) | |
| GRAY = (128, 128, 128) | |
| # Create the game window | |
| screen = pygame.display.set_mode((WINDOW_WIDTH, WINDOW_HEIGHT)) | |
| pygame.display.set_caption("π Snake Game - Pygame") | |
| clock = pygame.time.Clock() | |
| font = pygame.font.Font(None, 24) | |
| large_font = pygame.font.Font(None, 36) | |
| class SnakeGame: | |
| """Main Snake Game class""" | |
| def __init__(self): | |
| """Initialize the game state""" | |
| self.snake_body = [[5, 5], [4, 5], [3, 5]] # Head at [5,5], body extending left | |
| self.direction = [1, 0] # Moving right [x, y] | |
| self.next_direction = [1, 0] # For buffering input | |
| self.food_pos = [self.get_random_position()] | |
| self.score = 0 | |
| self.game_running = True | |
| self.game_over = False | |
| self.move_count = 0 | |
| def get_random_position(self): | |
| """Get a random position for food that doesn't overlap with snake""" | |
| while True: | |
| pos = [random.randint(0, GRID_SIZE - 1), random.randint(0, GRID_SIZE - 1)] | |
| if pos not in self.snake_body: | |
| return pos | |
| def handle_input(self): | |
| """Handle keyboard input""" | |
| for event in pygame.event.get(): | |
| if event.type == pygame.QUIT: | |
| return "quit" | |
| if event.type == pygame.KEYDOWN: | |
| # Quit controls | |
| if event.key == pygame.K_q or event.key == pygame.K_ESCAPE: | |
| return "quit" | |
| # Restart control | |
| if event.key == pygame.K_r and self.game_over: | |
| return "restart" | |
| # Direction controls (arrow keys) | |
| if event.key == pygame.K_UP and self.direction[1] == 0: | |
| self.next_direction = [0, -1] | |
| elif event.key == pygame.K_DOWN and self.direction[1] == 0: | |
| self.next_direction = [0, 1] | |
| elif event.key == pygame.K_LEFT and self.direction[0] == 0: | |
| self.next_direction = [-1, 0] | |
| elif event.key == pygame.K_RIGHT and self.direction[0] == 0: | |
| self.next_direction = [1, 0] | |
| return "continue" | |
| def update(self): | |
| """Update game logic""" | |
| if self.game_over: | |
| return | |
| self.move_count += 1 | |
| # Update direction from buffered input | |
| self.direction = self.next_direction | |
| # Calculate new head position | |
| current_head = self.snake_body[0] | |
| new_head = [current_head[0] + self.direction[0], current_head[1] + self.direction[1]] | |
| # Check for wall collision | |
| if (new_head[0] < 0 or new_head[0] >= GRID_SIZE or | |
| new_head[1] < 0 or new_head[1] >= GRID_SIZE): | |
| self.game_over = True | |
| self.game_running = False | |
| return | |
| # Check for self collision | |
| if new_head in self.snake_body: | |
| self.game_over = True | |
| self.game_running = False | |
| return | |
| # Add new head | |
| self.snake_body.insert(0, new_head) | |
| # Check if ate food | |
| if new_head == self.food_pos[0]: | |
| self.score += 1 | |
| self.food_pos = [self.get_random_position()] | |
| # Snake grows (don't remove tail) | |
| else: | |
| # Remove tail (snake stays same length) | |
| self.snake_body.pop() | |
| def draw(self): | |
| """Draw the game""" | |
| screen.fill(BLACK) | |
| # Draw grid | |
| for x in range(0, WINDOW_WIDTH, CELL_SIZE): | |
| pygame.draw.line(screen, GRAY, (x, 60), (x, WINDOW_HEIGHT), 1) | |
| for y in range(60, WINDOW_HEIGHT, CELL_SIZE): | |
| pygame.draw.line(screen, GRAY, (0, y), (WINDOW_WIDTH, y), 1) | |
| # Draw snake | |
| for i, segment in enumerate(self.snake_body): | |
| x = segment[0] * CELL_SIZE | |
| y = segment[1] * CELL_SIZE + 60 | |
| if i == 0: | |
| # Draw head in bright green | |
| pygame.draw.rect(screen, GREEN, (x + 2, y + 2, CELL_SIZE - 4, CELL_SIZE - 4)) | |
| pygame.draw.rect(screen, WHITE, (x + 2, y + 2, CELL_SIZE - 4, CELL_SIZE - 4), 2) | |
| else: | |
| # Draw body in darker green | |
| pygame.draw.rect(screen, DARK_GREEN, (x + 3, y + 3, CELL_SIZE - 6, CELL_SIZE - 6)) | |
| pygame.draw.rect(screen, GREEN, (x + 3, y + 3, CELL_SIZE - 6, CELL_SIZE - 6), 1) | |
| # Draw food | |
| food = self.food_pos[0] | |
| food_x = food[0] * CELL_SIZE | |
| food_y = food[1] * CELL_SIZE + 60 | |
| pygame.draw.rect(screen, RED, (food_x + 2, food_y + 2, CELL_SIZE - 4, CELL_SIZE - 4)) | |
| pygame.draw.circle(screen, YELLOW, (food_x + CELL_SIZE // 2, food_y + CELL_SIZE // 2), CELL_SIZE // 4) | |
| # Draw score and info | |
| score_text = font.render(f"Score: {self.score} | Moves: {self.move_count}", True, WHITE) | |
| screen.blit(score_text, (10, 10)) | |
| if self.game_over: | |
| instructions = font.render("Arrow Keys to move | R to restart | Q or ESC to quit", True, GRAY) | |
| else: | |
| instructions = font.render("Arrow Keys to move | Q or ESC to quit", True, GRAY) | |
| screen.blit(instructions, (10, 35)) | |
| # Draw game over message | |
| if self.game_over: | |
| overlay = pygame.Surface((WINDOW_WIDTH, WINDOW_HEIGHT)) | |
| overlay.set_alpha(200) | |
| overlay.fill(BLACK) | |
| screen.blit(overlay, (0, 0)) | |
| game_over_text = large_font.render("GAME OVER!", True, RED) | |
| final_score_text = large_font.render(f"Final Score: {self.score}", True, WHITE) | |
| restart_text = font.render("Press R to restart or Q to exit", True, YELLOW) | |
| screen.blit(game_over_text, (WINDOW_WIDTH // 2 - game_over_text.get_width() // 2, | |
| WINDOW_HEIGHT // 2 - 60)) | |
| screen.blit(final_score_text, (WINDOW_WIDTH // 2 - final_score_text.get_width() // 2, | |
| WINDOW_HEIGHT // 2)) | |
| screen.blit(restart_text, (WINDOW_WIDTH // 2 - restart_text.get_width() // 2, | |
| WINDOW_HEIGHT // 2 + 60)) | |
| pygame.display.flip() | |
| def run(self): | |
| """Main game loop""" | |
| print("π Snake Game Started!") | |
| print(f"Window size: {WINDOW_WIDTH}x{WINDOW_HEIGHT}") | |
| print(f"Grid size: {GRID_SIZE}x{GRID_SIZE}") | |
| print(f"Controls: Arrow Keys to move, R to restart, Q or ESC to quit") | |
| running = True | |
| while running: | |
| input_result = self.handle_input() | |
| if input_result == "quit": | |
| if self.game_over: | |
| print(f"π₯ GAME OVER!") | |
| print(f"Final Score: {self.score}") | |
| print(f"Total Moves: {self.move_count}") | |
| running = False | |
| elif input_result == "restart": | |
| # Reset the game | |
| self.__init__() | |
| print("π Game restarted!") | |
| else: # continue | |
| self.update() | |
| self.draw() | |
| clock.tick(FPS) | |
| pygame.quit() | |
| sys.exit() | |
| if __name__ == "__main__": | |
| game = SnakeGame() | |
| game.run() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment