Загрузка данных


import pygame
import random

pygame.init()

CELL = 20
COLS, ROWS = 25, 20
WIDTH, HEIGHT = COLS * CELL, ROWS * CELL
FPS = 10

BLACK  = (30,  30,  30)
GRAY   = (50,  50,  50)
WHITE  = (255, 255, 255)

P1_HEAD = (29,  158, 117)
P1_BODY = (93,  202, 165)
P2_HEAD = (55,  120, 210)
P2_BODY = (110, 170, 240)
RED     = (216,  90,  48)

screen = pygame.display.set_mode((WIDTH, HEIGHT + 50))
pygame.display.set_caption("Змейка 2 игрока")
clock = pygame.time.Clock()
font  = pygame.font.SysFont("Arial", 18)
big   = pygame.font.SysFont("Arial", 34, bold=True)
small = pygame.font.SysFont("Arial", 15)


def place_food(occupied):
    while True:
        pos = (random.randint(0, COLS - 1), random.randint(0, ROWS - 1))
        if pos not in occupied:
            return pos


def draw_snake(snake, head_color, body_color):
    for i, (x, y) in enumerate(snake):
        color = head_color if i == 0 else body_color
        rect = pygame.Rect(x * CELL + 1, y * CELL + 1, CELL - 2, CELL - 2)
        pygame.draw.rect(screen, color, rect, border_radius=4)


def draw_scene(snake1, snake2, food, score1, score2):
    screen.fill(BLACK)
    for x in range(0, WIDTH, CELL):
        pygame.draw.line(screen, GRAY, (x, 0), (x, HEIGHT))
    for y in range(0, HEIGHT, CELL):
        pygame.draw.line(screen, GRAY, (0, y), (WIDTH, y))

    fx, fy = food
    pygame.draw.circle(screen, RED,
                       (fx * CELL + CELL // 2, fy * CELL + CELL // 2), CELL // 2 - 2)

    draw_snake(snake2, P2_HEAD, P2_BODY)
    draw_snake(snake1, P1_HEAD, P1_BODY)

    pygame.draw.rect(screen, (20, 20, 20), (0, HEIGHT, WIDTH, 50))
    t1 = font.render(f"Игрок 1 (WASD): {score1}", True, P1_HEAD)
    t2 = font.render(f"Игрок 2 (стрелки): {score2}", True, P2_HEAD)
    vs = font.render("VS", True, (120, 120, 120))
    screen.blit(t1, (10, HEIGHT + 15))
    screen.blit(t2, (WIDTH - t2.get_width() - 10, HEIGHT + 15))
    screen.blit(vs, (WIDTH // 2 - vs.get_width() // 2, HEIGHT + 15))
    pygame.display.flip()


def result_screen(winner, score1, score2):
    overlay = pygame.Surface((WIDTH, HEIGHT), pygame.SRCALPHA)
    overlay.fill((0, 0, 0, 170))
    screen.blit(overlay, (0, 0))

    if winner == 0:
        msg, color = "Ничья!", WHITE
    elif winner == 1:
        msg, color = "Победил Игрок 1!", P1_HEAD
    else:
        msg, color = "Победил Игрок 2!", P2_HEAD

    t1 = big.render(msg, True, color)
    t2 = font.render(f"Счёт: Игрок 1 — {score1}    Игрок 2 — {score2}", True, (200, 200, 200))
    t3 = small.render("R — играть снова      Q — выход", True, (150, 150, 150))
    screen.blit(t1, (WIDTH // 2 - t1.get_width() // 2, HEIGHT // 2 - 60))
    screen.blit(t2, (WIDTH // 2 - t2.get_width() // 2, HEIGHT // 2))
    screen.blit(t3, (WIDTH // 2 - t3.get_width() // 2, HEIGHT // 2 + 45))
    pygame.display.flip()


def run():
    while True:
        snake1 = [(5, ROWS//2), (4, ROWS//2), (3, ROWS//2)]
        snake2 = [(COLS-6, ROWS//2), (COLS-5, ROWS//2), (COLS-4, ROWS//2)]
        dir1, next1 = (1, 0), (1, 0)
        dir2, next2 = (-1, 0), (-1, 0)
        score1, score2 = 0, 0
        speed = FPS
        food = place_food(set(snake1) | set(snake2))

        running = True
        winner = 0
        while running:
            clock.tick(speed)

            for event in pygame.event.get():
                if event.type == pygame.QUIT:
                    pygame.quit(); return
                if event.type == pygame.KEYDOWN:
                    if event.key == pygame.K_w and dir1 != (0,  1): next1 = (0, -1)
                    if event.key == pygame.K_s and dir1 != (0, -1): next1 = (0,  1)
                    if event.key == pygame.K_a and dir1 != (1,  0): next1 = (-1, 0)
                    if event.key == pygame.K_d and dir1 != (-1, 0): next1 = (1,  0)
                    if event.key == pygame.K_UP    and dir2 != (0,  1): next2 = (0, -1)
                    if event.key == pygame.K_DOWN  and dir2 != (0, -1): next2 = (0,  1)
                    if event.key == pygame.K_LEFT  and dir2 != (1,  0): next2 = (-1, 0)
                    if event.key == pygame.K_RIGHT and dir2 != (-1, 0): next2 = (1,  0)

            dir1, dir2 = next1, next2
            head1 = (snake1[0][0] + dir1[0], snake1[0][1] + dir1[1])
            head2 = (snake2[0][0] + dir2[0], snake2[0][1] + dir2[1])

            dead1 = not (0 <= head1[0] < COLS and 0 <= head1[1] < ROWS)
            dead2 = not (0 <= head2[0] < COLS and 0 <= head2[1] < ROWS)
            if head1 in set(snake1) or head1 in set(snake2): dead1 = True
            if head2 in set(snake2) or head2 in set(snake1): dead2 = True
            if head1 == head2: dead1 = dead2 = True

            if dead1 or dead2:
                if dead1 and dead2: winner = 0
                elif dead1:         winner = 2
                else:               winner = 1
                running = False
                break

            snake1.insert(0, head1)
            snake2.insert(0, head2)

            if head1 == food:
                score1 += 10
            else:
                snake1.pop()

            if head2 == food:
                score2 += 10
            else:
                snake2.pop()

            if head1 == food or head2 == food:
                food = place_food(set(snake1) | set(snake2))
                speed = min(20, FPS + (score1 + score2) // 100)

            draw_scene(snake1, snake2, food, score1, score2)

        draw_scene(snake1, snake2, food, score1, score2)
        result_screen(winner, score1, score2)

        waiting = True
        while waiting:
            for event in pygame.event.get():
                if event.type == pygame.QUIT:
                    pygame.quit(); return
                if event.type == pygame.KEYDOWN:
                    if event.key == pygame.K_r: waiting = False
                    if event.key == pygame.K_q:
                        pygame.quit(); return


run()