Greedy snake 3.0

import pygame
import random
import copy
import sys
import math
import time

初始化pygame

pygame.init()

设置屏幕大小为 650*650

screen_width, screen_height = 650, 650
screen = pygame.display.set_mode((screen_width, screen_height))
pygame.display.set_caption('贪吃蛇游戏')

颜色定义

WHITE = (255, 255, 255)
RED = (255, 0, 0)
BLACK = (0, 0, 0)
GREEN = (0, 255, 0)
GRAY = (128, 128, 128) # 第一条电脑蛇身体颜色
BLUE = (0, 0, 255) # 第二条电脑蛇身体颜色
YELLOW = (255, 255, 0) # 第二条电脑蛇眼睛颜色
BORDER_COLOR_1 = (255, 255, 0) # 闪烁边框颜色 1
BORDER_COLOR_2 = (0, 255, 255) # 闪烁边框颜色 2
BORDER_WIDTH = 3 # 边框宽度
BLINK_INTERVAL = 0.5 # 闪烁间隔时间(秒)

新定义红灰色和道具边框颜色

RED_GRAY = (200, 128, 128)
POWERUP_BORDER_COLOR_1 = (255, 128, 128)
POWERUP_BORDER_COLOR_2 = (128, 64, 64)

字体

font = pygame.font.SysFont('simhei', 40)
small_font = pygame.font.SysFont('simhei', 15) # 调整字体大小以适应 80x80 边框
timer_font = pygame.font.SysFont('simhei', 20) # 计时器字体

新增游戏结束提示字体,大小和按钮字体一致

game_over_font = pygame.font.SysFont('simhei', 40)

食物数量

FOOD_COUNT = 15

EYE_SIZE = 2 # 眼睛大小
EYE_OFFSET = 3 # 眼睛相对蛇头中心的偏移量
BODY_RADIUS = 5 # 蛇身体半径
HEAD_RADIUS = int(BODY_RADIUS * 1.6) # 蛇头半径

障碍物数量

OBSTACLE_COUNT = 5
OBSTACLE_RADIUS = 15 # 障碍物半径
TEETH_COUNT = 8 # 齿轮齿数
TOOTH_LENGTH = 5 # 齿长

新增碰撞阈值,当蛇头与障碍物中心距离小于该值时判定碰撞

COLLISION_THRESHOLD = OBSTACLE_RADIUS

道具相关参数

POWERUP_COUNT = 3
POWERUP_SIZE = 15
POWERUP_BLINK_INTERVAL = 0.3
SPEED_MULTIPLIER = 1.5
POWERUP_DURATION = 2 # 道具效果持续时间(秒)

游戏时间,单位:秒

GAME_DURATION = 60

加载封面图片

try:
cover_image = pygame.image.load('cover.jpg')
cover_image = pygame.transform.scale(cover_image, (screen_width, screen_height))
except FileNotFoundError:
print("未找到封面图片 'cover.jpg',请确保图片在正确路径下。")
cover_image = None

加载游戏结束图片

try:
game_over_image = pygame.image.load('game_over.jpg')
game_over_image = pygame.transform.scale(game_over_image, (screen_width, screen_height))
except FileNotFoundError:
print("未找到游戏结束图片 'game_over.jpg',请确保图片在正确路径下。")
game_over_image = None

加载模式选择界面图片

try:
mode_selection_image = pygame.image.load('mode_selection.jpg')
mode_selection_image = pygame.transform.scale(mode_selection_image, (screen_width, screen_height))
except FileNotFoundError:
print("未找到模式选择界面图片 'mode_selection.jpg',请确保图片在正确路径下。")
mode_selection_image = None

边框尺寸和位置

border_size = 80
border_x = screen_width - border_size - 10 # 距离右边 10 像素
border_y = 10 # 距离顶部 10 像素

def is_overlapping_with_border(pos, size):
"""
检查给定位置和大小的对象是否与分数统计边框重叠
:param pos: 对象的位置
:param size: 对象的大小(半径或边长等)
:return: 是否重叠
"""
x, y = pos
border_rect = pygame.Rect(border_x, border_y, border_size, border_size)
obj_rect = pygame.Rect(x - size, y - size, size * 2, size * 2)
return border_rect.colliderect(obj_rect)

def draw_button(text, x, y, width, height, inactive_color, active_color, action=None):
mouse = pygame.mouse.get_pos()
click = pygame.mouse.get_pressed()
current_time = time.time()
border_color = BORDER_COLOR_1 if (current_time // BLINK_INTERVAL) % 2 == 0 else BORDER_COLOR_2

if x < mouse[0] < x + width and y < mouse[1] < y + height:
    pygame.draw.rect(screen, active_color, (x, y, width, height))
    pygame.draw.rect(screen, border_color, (x, y, width, height), BORDER_WIDTH)
    if click[0] == 1 and action is not None:
        return action
else:
    pygame.draw.rect(screen, inactive_color, (x, y, width, height))
    pygame.draw.rect(screen, border_color, (x, y, width, height), BORDER_WIDTH)

text_surf = font.render(text, True, BLACK)
text_rect = text_surf.get_rect()
text_rect.center = (x + width / 2, y + height / 2)
screen.blit(text_surf, text_rect)

return False

def game_intro():
intro = True
clock = pygame.time.Clock()

while intro:
    clock.tick(15)

    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            pygame.quit()
            sys.exit()

    if cover_image:
        screen.blit(cover_image, (0, 0))
    else:
        screen.fill(WHITE)

    # 竖着显示“贪吃蛇游戏”
    title_text = "贪吃蛇游戏"
    x_pos = 30  # 文字距离左侧的距离
    y_start = 50  # 文字起始的 y 坐标
    title_rects = []
    for i, char in enumerate(title_text):
        char_surf = font.render(char, True, BLACK)
        char_rect = char_surf.get_rect(topleft=(x_pos, y_start + i * (char_surf.get_height() + 10)))
        screen.blit(char_surf, char_rect)
        title_rects.append(char_rect)

    # 计算整个标题的包围矩形
    min_x = min(rect.left for rect in title_rects)
    min_y = min(rect.top for rect in title_rects)
    max_x = max(rect.right for rect in title_rects)
    max_y = max(rect.bottom for rect in title_rects)
    title_bbox = pygame.Rect(min_x, min_y, max_x - min_x, max_y - min_y)
    title_bbox.inflate_ip(10, 10)  # 让边框比文字区域稍大

    # 获取当前时间,用于控制边框闪烁
    current_time = time.time()
    border_color = BORDER_COLOR_1 if (current_time // BLINK_INTERVAL) % 2 == 0 else BORDER_COLOR_2

    # 绘制带闪烁边框的矩形
    pygame.draw.rect(screen, border_color, title_bbox, BORDER_WIDTH)

    # 按钮位置保持不变
    start_game = draw_button("游戏开始",
                             screen_width / 2 - 100,
                             screen_height * 2 / 3,
                             200,
                             50,
                             GREEN,
                             (0, 200, 0),
                             "start")

    if start_game == "start":
        intro = False

    pygame.display.update()

def select_mode():
selecting = True
clock = pygame.time.Clock()

while selecting:
    clock.tick(15)

    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            pygame.quit()
            sys.exit()

    screen.fill(WHITE)

    # 绘制模式选择界面图片
    if mode_selection_image:
        screen.blit(mode_selection_image, (0, 0))

    # 显示模式选择提示
    mode_text = font.render("选择游戏模式", True, BLACK)
    mode_rect = mode_text.get_rect(center=(screen_width / 2, screen_height / 4))
    screen.blit(mode_text, mode_rect)

    # 生存模式按钮
    survival_mode = draw_button("生存模式",
                                screen_width / 2 - 100,
                                screen_height / 2 - 50,
                                200,
                                50,
                                GREEN,
                                (0, 200, 0),
                                "survival")

    # 自由模式按钮
    free_mode = draw_button("自由模式",
                            screen_width / 2 - 100,
                            screen_height / 2 + 50,
                            200,
                            50,
                            GREEN,
                            (0, 200, 0),
                            "free")

    if survival_mode == "survival":
        return "survival"
    elif free_mode == "free":
        return "free"

    pygame.display.update()

def get_distance(p1, p2):
return math.sqrt((p1[0] - p2[0]) ** 2 + (p1[1] - p2[1]) ** 2)

def computer_ai(snake_list, foods, obstacles, self_score, player_score, other_computer_score):
# 计算排名
scores = [self_score, player_score, other_computer_score]
rank = sorted(scores, reverse=True).index(self_score) + 1

head = snake_list[0]

closest_food = None
min_dist = float('inf')
for food in foods:
    dist = get_distance(head, food["pos"])
    if dist < min_dist:
        min_dist = dist
        closest_food = food["pos"]

if closest_food is None:
    return "up"

directions = [
    ([head[0], head[1] - 10], "up"),
    ([head[0], head[1] + 10], "down"),
    ([head[0] - 10, head[1]], "left"),
    ([head[0] + 10, head[1]], "right")
]

valid_directions = []
for new_pos, direction in directions:
    # 调整边界检查为 650
    if 0 <= new_pos[0] < 650 and 0 <= new_pos[1] < 650:
        collision = False
        # 检查是否会撞到蛇身
        for segment in snake_list[:-1]:
            if new_pos == segment:
                collision = True
                break
        # 检查是否会撞到障碍物
        for obstacle in obstacles:
            dist = get_distance(new_pos, obstacle["pos"])
            if dist < COLLISION_THRESHOLD:
                collision = True
                break
        if not collision:
            valid_directions.append((new_pos, direction))

if not valid_directions:
    return "up"

best_dir = None
min_dist = float('inf')
for new_pos, direction in valid_directions:
    dist = get_distance(new_pos, closest_food)
    if dist < min_dist:
        min_dist = dist
        best_dir = direction

# 根据排名调整策略,这里简单示例,排名第一时更保守
if rank == 1:
    # 简单示例:避开危险区域,比如靠近障碍物时更谨慎
    dangerous_directions = []
    for new_pos, direction in valid_directions:
        for obstacle in obstacles:
            dist = get_distance(new_pos, obstacle["pos"])
            if dist < COLLISION_THRESHOLD + 10:  # 加大安全距离
                dangerous_directions.append(direction)
                break
    if best_dir in dangerous_directions:
        # 选择另一个安全方向
        for new_pos, direction in valid_directions:
            if direction not in dangerous_directions:
                best_dir = direction
                break
elif rank == 3:
    # 排名最后时更激进,更倾向于冲向食物
    pass

return best_dir

def generate_food(count):
foods = []
for _ in range(count):
while True:
# 调整随机位置范围为 650
food_pos = [random.randint(15, 635), random.randint(15, 635)]
if not is_overlapping_with_border(food_pos, 13): # 食物半径为 13
break
food = {
"pos": food_pos,
"color": RED
}
foods.append(food)
return foods

生成障碍物

def generate_obstacles(count):
obstacles = []
for _ in range(count):
while True:
# 调整随机位置范围为 650
obstacle_pos = [random.randint(15 + OBSTACLE_RADIUS, 635 - OBSTACLE_RADIUS),
random.randint(15 + OBSTACLE_RADIUS, 635 - OBSTACLE_RADIUS)]
if not is_overlapping_with_border(obstacle_pos, OBSTACLE_RADIUS + TOOTH_LENGTH): # 考虑齿长
break
obstacle = {
"pos": obstacle_pos
}
obstacles.append(obstacle)
return obstacles

生成道具

def generate_powerups(count):
powerups = []
for _ in range(count):
while True:
# 调整随机位置范围为 650
powerup_pos = [random.randint(15, 635), random.randint(15, 635)]
if not is_overlapping_with_border(powerup_pos, POWERUP_SIZE):
break
powerup = {
"pos": powerup_pos,
"visible": True
}
powerups.append(powerup)
return powerups

绘制齿轮状障碍物

def draw_gear(screen, pos):
points = []
angle_step = 2 * math.pi / TEETH_COUNT
for i in range(TEETH_COUNT):
angle = i * angle_step
# 绘制内圆上的点
inner_x = pos[0] + OBSTACLE_RADIUS * math.cos(angle)
inner_y = pos[1] + OBSTACLE_RADIUS * math.sin(angle)
points.append((inner_x, inner_y))
# 绘制齿尖的点
outer_x = pos[0] + (OBSTACLE_RADIUS + TOOTH_LENGTH) * math.cos(angle + angle_step / 2)
outer_y = pos[1] + (OBSTACLE_RADIUS + TOOTH_LENGTH) * math.sin(angle + angle_step / 2)
points.append((outer_x, outer_y))
pygame.draw.polygon(screen, BLACK, points)

def draw_snake_head(screen, head_pos, body_color, eye_color, direction):
"""
绘制带有眼睛的蛇头
:param screen: 游戏屏幕
:param head_pos: 蛇头位置
:param body_color: 蛇的身体颜色
:param eye_color: 蛇的眼睛颜色
:param direction: 蛇头移动方向
"""
# 绘制蛇头,使用蛇头半径
pygame.draw.circle(screen, body_color, head_pos, HEAD_RADIUS)

# 根据移动方向确定眼睛位置
if direction == "up":
    eye1 = (head_pos[0] - EYE_OFFSET, head_pos[1] - EYE_OFFSET)
    eye2 = (head_pos[0] + EYE_OFFSET, head_pos[1] - EYE_OFFSET)
elif direction == "down":
    eye1 = (head_pos[0] - EYE_OFFSET, head_pos[1] + EYE_OFFSET)
    eye2 = (head_pos[0] + EYE_OFFSET, head_pos[1] + EYE_OFFSET)
elif direction == "left":
    eye1 = (head_pos[0] - EYE_OFFSET, head_pos[1] - EYE_OFFSET)
    eye2 = (head_pos[0] - EYE_OFFSET, head_pos[1] + EYE_OFFSET)
elif direction == "right":
    eye1 = (head_pos[0] + EYE_OFFSET, head_pos[1] - EYE_OFFSET)
    eye2 = (head_pos[0] + EYE_OFFSET, head_pos[1] + EYE_OFFSET)

# 绘制眼睛
pygame.draw.circle(screen, eye_color, eye1, EYE_SIZE)
pygame.draw.circle(screen, eye_color, eye2, EYE_SIZE)

def game_loop(game_mode):
snake_list = [[10, 10]]
direction = "right"
next_direction = "right"
player_speed = 15
player_original_speed = 15 # 玩家蛇原始速度
player_powerup_end_time = 0 # 玩家蛇道具效果结束时间
player_score = 0 # 玩家蛇分数

computer_snake = [[300, 300]]
computer_dir = "right"
computer_speed = 15
computer_original_speed = 15  # 第一条电脑蛇原始速度
computer_powerup_end_time = 0  # 第一条电脑蛇道具效果结束时间
computer_score = 0  # 第一条电脑蛇分数

computer_snake2 = [[400, 400]]
computer_dir2 = "right"
computer_speed2 = 15
computer_original_speed2 = 15  # 第二条电脑蛇原始速度
computer_powerup_end_time2 = 0  # 第二条电脑蛇道具效果结束时间
computer_score2 = 0  # 第二条电脑蛇分数

foods = generate_food(FOOD_COUNT)
obstacles = generate_obstacles(OBSTACLE_COUNT)
powerups = generate_powerups(POWERUP_COUNT)

running = True
game_over_reason = ""
clock = pygame.time.Clock()

if game_mode == "free":
    # 初始化计时器,记录游戏开始时间和结束时间
    start_time = time.time()
    end_time = start_time + GAME_DURATION
else:
    start_time = None
    end_time = None

def snake_to_food(snake):
    new_foods = []
    for segment in snake:
        new_food = {
            "pos": segment,
            "color": RED
        }
        new_foods.append(new_food)
    return new_foods

def reset_game():
    nonlocal snake_list, direction, next_direction, computer_snake, computer_dir, computer_snake2, computer_dir2, foods, obstacles, powerups, start_time, end_time, player_speed, computer_speed, computer_speed2
    nonlocal player_original_speed, player_powerup_end_time, computer_original_speed, computer_powerup_end_time, computer_original_speed2, computer_powerup_end_time2
    snake_list = [[10, 10]]
    direction = "right"
    next_direction = "right"
    player_speed = 15
    player_original_speed = 15
    player_powerup_end_time = 0

    computer_snake = [[300, 300]]
    computer_dir = "right"
    computer_speed = 15
    computer_original_speed = 15
    computer_powerup_end_time = 0

    computer_snake2 = [[400, 400]]
    computer_dir2 = "right"
    computer_speed2 = 15
    computer_original_speed2 = 15
    computer_powerup_end_time2 = 0

    foods = generate_food(FOOD_COUNT)
    obstacles = generate_obstacles(OBSTACLE_COUNT)
    powerups = generate_powerups(POWERUP_COUNT)
    if game_mode == "free":
        # 重置计时器
        start_time = time.time()
        end_time = start_time + GAME_DURATION

while running:
    current_time = time.time()

    # 检查游戏是否结束
    if game_mode == "free":
        remaining_time = end_time - current_time
        if remaining_time <= 0:
            if player_score > computer_score and player_score > computer_score2:
                game_over_reason = "玩家蛇获胜!"
            elif computer_score > player_score and computer_score > computer_score2:
                game_over_reason = "电脑蛇1获胜!"
            elif computer_score2 > player_score and computer_score2 > computer_score:
                game_over_reason = "电脑蛇2获胜!"
            else:
                game_over_reason = "平局!"
    else:
        remaining_time = None

    # 检查玩家蛇道具效果是否结束
    if current_time > player_powerup_end_time:
        player_speed = player_original_speed

    # 检查第一条电脑蛇道具效果是否结束
    if current_time > computer_powerup_end_time:
        computer_speed = computer_original_speed

    # 检查第二条电脑蛇道具效果是否结束
    if current_time > computer_powerup_end_time2:
        computer_speed2 = computer_original_speed2

    clock.tick(max(1, int(player_speed)))

    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            pygame.quit()
            sys.exit()

        if event.type == pygame.KEYDOWN:
            if event.key == pygame.K_UP:
                next_direction = "up"
            elif event.key == pygame.K_DOWN:
                next_direction = "down"
            elif event.key == pygame.K_LEFT:
                next_direction = "left"
            elif event.key == pygame.K_RIGHT:
                next_direction = "right"

    direction = next_direction

    screen.fill(WHITE)

    # 计算并显示倒计时,精确到 0.01 秒
    if game_mode == "free":
        remaining_time = max(0, end_time - current_time)
        timer_text = f"剩余时间: {remaining_time:.2f} 秒"
        timer_surf = timer_font.render(timer_text, True, BLACK)
        timer_rect = timer_surf.get_rect(center=(screen_width // 2, 20))
        screen.blit(timer_surf, timer_rect)

    # 定义分数文本和使用小字体
    score_texts = [
        f"玩家蛇: {player_score}",
        f"电脑蛇1: {computer_score}",
        f"电脑蛇2: {computer_score2}"
    ]

    # 绘制边框
    pygame.draw.rect(screen, BLACK, (border_x, border_y, border_size, border_size), 2)

    # 绘制分数文本,从上到下排列
    y_pos = border_y + 5  # 顶部内边距 5 像素
    for text in score_texts:
        score_surf = small_font.render(text, True, BLACK)
        text_rect = score_surf.get_rect(topleft=(border_x + 5, y_pos))  # 左边内边距 5 像素
        screen.blit(score_surf, text_rect)
        y_pos += score_surf.get_height() + 3  # 文本间距 3 像素

    # 绘制食物
    food_rects = []
    for food in foods:
        rect = pygame.draw.circle(screen, food["color"], food["pos"], 13, 0)
        food_rects.append({"rect": rect, "pos": food["pos"], "color": food["color"]})

    # 绘制障碍物
    for obstacle in obstacles:
        draw_gear(screen, obstacle["pos"])

    # 绘制道具
    eaten_powerups = []
    for i, powerup in enumerate(powerups):
        # 根据时间切换边框颜色
        border_color = POWERUP_BORDER_COLOR_1 if (current_time // POWERUP_BLINK_INTERVAL) % 2 == 0 else POWERUP_BORDER_COLOR_2
        x, y = powerup["pos"]
        triangle_points = [
            (x, y - POWERUP_SIZE),
            (x + POWERUP_SIZE, y + POWERUP_SIZE),
            (x - POWERUP_SIZE, y + POWERUP_SIZE)
        ]
        # 绘制道具主体
        pygame.draw.polygon(screen, RED_GRAY, triangle_points)
        # 绘制道具边框
        pygame.draw.polygon(screen, border_color, triangle_points, 2)

        # 检查玩家蛇是否吃到道具
        if get_distance(snake_list[0], powerup["pos"]) < POWERUP_SIZE:
            if current_time > player_powerup_end_time:  # 确保道具效果已结束
                player_original_speed = player_speed
                player_speed *= SPEED_MULTIPLIER
                player_powerup_end_time = current_time + POWERUP_DURATION
            eaten_powerups.append(i)

        # 检查第一条电脑蛇是否吃到道具
        if get_distance(computer_snake[0], powerup["pos"]) < POWERUP_SIZE:
            if current_time > computer_powerup_end_time:  # 确保道具效果已结束
                computer_original_speed = computer_speed
                computer_speed *= SPEED_MULTIPLIER
                computer_powerup_end_time = current_time + POWERUP_DURATION
            eaten_powerups.append(i)

        # 检查第二条电脑蛇是否吃到道具
        if get_distance(computer_snake2[0], powerup["pos"]) < POWERUP_SIZE:
            if current_time > computer_powerup_end_time2:  # 确保道具效果已结束
                computer_original_speed2 = computer_speed2
                computer_speed2 *= SPEED_MULTIPLIER
                computer_powerup_end_time2 = current_time + POWERUP_DURATION
            eaten_powerups.append(i)

    # 移除被吃掉的道具并生成新道具
    for i in sorted(eaten_powerups, reverse=True):
        if i < len(powerups):
            powerups.pop(i)
    if eaten_powerups:
        powerups.extend(generate_powerups(len(eaten_powerups)))

    # 电脑AI决策,传入障碍物参数和分数
    computer_dir = computer_ai(computer_snake, foods, obstacles, computer_score, player_score, computer_score2)
    computer_dir2 = computer_ai(computer_snake2, foods, obstacles, computer_score2, player_score, computer_score)

    # 定义电脑蛇移动方向变量
    computer_move_up = computer_dir == "up"
    computer_move_down = computer_dir == "down"
    computer_move_left = computer_dir == "left"
    computer_move_right = computer_dir == "right"

    computer_move_up2 = computer_dir2 == "up"
    computer_move_down2 = computer_dir2 == "down"
    computer_move_left2 = computer_dir2 == "left"
    computer_move_right2 = computer_dir2 == "right"

    # 绘制玩家蛇并获取矩形列表
    player_snake_rect = []
    for i, snake_point in enumerate(snake_list):
        if i == 0:
            draw_snake_head(screen, snake_point, GREEN, BLACK, direction)
        else:
            player_snake_rect_point = pygame.draw.circle(screen, GREEN, snake_point, BODY_RADIUS, 0)
            player_snake_rect.append(player_snake_rect_point)

    # 绘制第一条电脑蛇并获取矩形列表
    computer_snake_rect = []
    for i, snake_point in enumerate(computer_snake):
        if i == 0:
            draw_snake_head(screen, snake_point, GRAY, BLACK, computer_dir)
        else:
            computer_snake_rect_point = pygame.draw.circle(screen, GRAY, snake_point, BODY_RADIUS, 0)
            computer_snake_rect.append(computer_snake_rect_point)

    # 绘制第二条电脑蛇并获取矩形列表
    computer_snake_rect2 = []
    for i, snake_point in enumerate(computer_snake2):
        if i == 0:
            draw_snake_head(screen, snake_point, BLUE, YELLOW, computer_dir2)
        else:
            computer_snake_rect_point2 = pygame.draw.circle(screen, BLUE, snake_point, BODY_RADIUS, 0)
            computer_snake_rect2.append(computer_snake_rect_point2)

    # 检查玩家蛇吃食物
    eaten_indices = []
    for i, food in enumerate(food_rects):
        if food["rect"].collidepoint(snake_list[0]):  # 只检查蛇头
            if "from_snake" not in food or food["from_snake"] != "player":
                eaten_indices.append(i)
                snake_list.append([food["pos"][0], food["pos"][1]])
                player_score += 2  # 玩家蛇吃一个食物加 2 分

    # 移除被吃掉的食物并生成新食物
    for i in sorted(eaten_indices, reverse=True):
        if i < len(foods):
            foods.pop(i)
    if eaten_indices:
        foods.extend(generate_food(len(eaten_indices)))

    # 检查第一条电脑蛇吃食物
    eaten_indices = []
    for i, food in enumerate(food_rects):
        if food["rect"].collidepoint(computer_snake[0]):  # 只检查电脑蛇头
            if "from_snake" not in food or food["from_snake"] != "computer1":
                eaten_indices.append(i)
                computer_snake.append([food["pos"][0], food["pos"][1]])
                computer_score += 1  # 电脑蛇吃一个食物加 1 分

    # 移除被吃掉的食物并生成新食物
    for i in sorted(eaten_indices, reverse=True):
        if i < len(foods):
            foods.pop(i)
    if eaten_indices:
        foods.extend(generate_food(len(eaten_indices)))

    # 检查第二条电脑蛇吃食物
    eaten_indices = []
    for i, food in enumerate(food_rects):
        if food["rect"].collidepoint(computer_snake2[0]):  # 只检查电脑蛇头
            if "from_snake" not in food or food["from_snake"] != "computer2":
                eaten_indices.append(i)
                computer_snake2.append([food["pos"][0], food["pos"][1]])
                computer_score2 += 1  # 电脑蛇吃一个食物加 1 分

    # 移除被吃掉的食物并生成新食物
    for i in sorted(eaten_indices, reverse=True):
        if i < len(foods):
            foods.pop(i)
    if eaten_indices:
        foods.extend(generate_food(len(eaten_indices)))

    # 移动玩家蛇
    pos = len(snake_list) - 1
    while pos > 0:
        snake_list[pos] = copy.deepcopy(snake_list[pos - 1])
        pos -= 1

    # 根据方向移动蛇头
    if direction == "up":
        snake_list[0][1] -= 10
        if snake_list[0][1] < 0:
            snake_list[0][1] = 650
    elif direction == "down":
        snake_list[0][1] += 10
        if snake_list[0][1] > 650:
            snake_list[0][1] = 0
    elif direction == "left":
        snake_list[0][0] -= 10
        if snake_list[0][0] < 0:
            snake_list[0][0] = 650
    elif direction == "right":
        snake_list[0][0] += 10
        if snake_list[0][0] > 650:
            snake_list[0][0] = 0

    # 移动第一条电脑蛇
    pos = len(computer_snake) - 1
    while pos > 0:
        computer_snake[pos] = copy.deepcopy(computer_snake[pos - 1])
        pos -= 1

    if computer_move_up:
        computer_snake[0][1] -= 10
        if computer_snake[0][1] < 0:
            computer_snake[0][1] = 650
    if computer_move_down:
        computer_snake[0][1] += 10
        if computer_snake[0][1] > 650:
            computer_snake[0][1] = 0
    if computer_move_left:
        computer_snake[0][0] -= 10
        if computer_snake[0][0] < 0:
            computer_snake[0][0] = 650
    if computer_move_right:
        computer_snake[0][0] += 10
        if computer_snake[0][0] > 650:
            computer_snake[0][0] = 0

    # 移动第二条电脑蛇
    pos = len(computer_snake2) - 1
    while pos > 0:
        computer_snake2[pos] = copy.deepcopy(computer_snake2[pos - 1])
        pos -= 1

    if computer_move_up2:
        computer_snake2[0][1] -= 10
        if computer_snake2[0][1] < 0:
            computer_snake2[0][1] = 650
    if computer_move_down2:
        computer_snake2[0][1] += 10
        if computer_snake2[0][1] > 650:
            computer_snake2[0][1] = 0
    if computer_move_left2:
        computer_snake2[0][0] -= 10
        if computer_snake2[0][0] < 0:
            computer_snake2[0][0] = 650
    if computer_move_right2:
        computer_snake2[0][0] += 10
        if computer_snake2[0][0] > 650:
            computer_snake2[0][0] = 0

    # 检查玩家蛇与障碍物碰撞
    player_head = snake_list[0]
    for obstacle in obstacles:
        dist = get_distance(player_head, obstacle["pos"])
        if dist < COLLISION_THRESHOLD:
            new_foods = snake_to_food(snake_list)
            # 移除超出屏幕范围的食物
            new_foods = [food for food in new_foods if 0 <= food["pos"][0] < 650 and 0 <= food["pos"][1] < 650]
            # 标记这些食物为玩家蛇死亡掉落的食物
            for food in new_foods:
                food["from_snake"] = "player"
            foods.extend(new_foods)
            snake_list = [[random.randint(15, 635), random.randint(15, 635)]]
            direction = "right"
            player_speed = 15
            if game_mode == "survival":
                game_over_reason = "玩家蛇撞到障碍物,游戏结束!"
            break

    # 检查玩家蛇与其他蛇碰撞
    head_rest = player_snake_rect[0] if player_snake_rect else None
    if head_rest:
        for segment in computer_snake_rect:
            if head_rest.colliderect(segment):
                new_foods = snake_to_food(snake_list)
                # 移除超出屏幕范围的食物
                new_foods = [food for food in new_foods if 0 <= food["pos"][0] < 650 and 0 <= food["pos"][1] < 650]
                # 标记这些食物为玩家蛇死亡掉落的食物
                for food in new_foods:
                    food["from_snake"] = "player"
                foods.extend(new_foods)
                snake_list = [[random.randint(15, 635), random.randint(15, 635)]]
                direction = "right"
                player_speed = 15
                if game_mode == "survival":
                    game_over_reason = "玩家蛇撞到电脑蛇1,游戏结束!"
                break

        for segment in computer_snake_rect2:
            if head_rest.colliderect(segment):
                new_foods = snake_to_food(snake_list)
                # 移除超出屏幕范围的食物
                new_foods = [food for food in new_foods if 0 <= food["pos"][0] < 650 and 0 <= food["pos"][1] < 650]
                # 标记这些食物为玩家蛇死亡掉落的食物
                for food in new_foods:
                    food["from_snake"] = "player"
                foods.extend(new_foods)
                snake_list = [[random.randint(15, 635), random.randint(15, 635)]]
                direction = "right"
                player_speed = 15
                if game_mode == "survival":
                    game_over_reason = "玩家蛇撞到电脑蛇2,游戏结束!"
                break

    # 检查第一条电脑蛇与障碍物碰撞
    computer_head = computer_snake[0]
    for obstacle in obstacles:
        dist = get_distance(computer_head, obstacle["pos"])
        if dist < COLLISION_THRESHOLD:
            new_foods = snake_to_food(computer_snake)
            # 移除超出屏幕范围的食物
            new_foods = [food for food in new_foods if 0 <= food["pos"][0] < 650 and 0 <= food["pos"][1] < 650]
            # 标记这些食物为电脑蛇 1 死亡掉落的食物
            for food in new_foods:
                food["from_snake"] = "computer1"
            foods.extend(new_foods)
            computer_snake = [[random.randint(15, 635), random.randint(15, 635)]]
            computer_dir = "right"
            computer_speed = 15
            break

    # 检查第二条电脑蛇与障碍物碰撞
    computer_head2 = computer_snake2[0]
    for obstacle in obstacles:
        dist = get_distance(computer_head2, obstacle["pos"])
        if dist < COLLISION_THRESHOLD:
            new_foods = snake_to_food(computer_snake2)
            # 移除超出屏幕范围的食物
            new_foods = [food for food in new_foods if 0 <= food["pos"][0] < 650 and 0 <= food["pos"][1] < 650]
            # 标记这些食物为电脑蛇 2 死亡掉落的食物
            for food in new_foods:
                food["from_snake"] = "computer2"
            foods.extend(new_foods)
            computer_snake2 = [[random.randint(15, 635), random.randint(15, 635)]]
            computer_dir2 = "right"
            computer_speed2 = 15
            break

    # 检查第一条电脑蛇与其他蛇碰撞
    computer_head_rest = computer_snake_rect[0] if computer_snake_rect else None
    if computer_head_rest:
        for segment in player_snake_rect:
            if computer_head_rest.colliderect(segment):
                new_foods = snake_to_food(computer_snake)
                # 移除超出屏幕范围的食物
                new_foods = [food for food in new_foods if 0 <= food["pos"][0] < 650 and 0 <= food["pos"][1] < 650]
                # 标记这些食物为电脑蛇 1 死亡掉落的食物
                for food in new_foods:
                    food["from_snake"] = "computer1"
                foods.extend(new_foods)
                computer_snake = [[random.randint(15, 635), random.randint(15, 635)]]
                computer_dir = "right"
                computer_speed = 15
                break

        for segment in computer_snake_rect2:
            if computer_head_rest.colliderect(segment):
                new_foods = snake_to_food(computer_snake)
                # 移除超出屏幕范围的食物
                new_foods = [food for food in new_foods if 0 <= food["pos"][0] < 650 and 0 <= food["pos"][1] < 650]
                # 标记这些食物为电脑蛇 1 死亡掉落的食物
                for food in new_foods:
                    food["from_snake"] = "computer1"
                foods.extend(new_foods)
                computer_snake = [[random.randint(15, 635), random.randint(15, 635)]]
                computer_dir = "right"
                computer_speed = 15
                break

    # 检查第二条电脑蛇与其他蛇碰撞
    computer_head_rest2 = computer_snake_rect2[0] if computer_snake_rect2 else None
    if computer_head_rest2:
        for segment in player_snake_rect:
            if computer_head_rest2.colliderect(segment):
                new_foods = snake_to_food(computer_snake2)
                # 移除超出屏幕范围的食物
                new_foods = [food for food in new_foods if 0 <= food["pos"][0] < 650 and 0 <= food["pos"][1] < 650]
                # 标记这些食物为电脑蛇 2 死亡掉落的食物
                for food in new_foods:
                    food["from_snake"] = "computer2"
                foods.extend(new_foods)
                computer_snake2 = [[random.randint(15, 635), random.randint(15, 635)]]
                computer_dir2 = "right"
                computer_speed2 = 15
                break

        for segment in computer_snake_rect:
            if computer_head_rest2.colliderect(segment):
                new_foods = snake_to_food(computer_snake2)
                # 移除超出屏幕范围的食物
                new_foods = [food for food in new_foods if 0 <= food["pos"][0] < 650 and 0 <= food["pos"][1] < 650]
                # 标记这些食物为电脑蛇 2 死亡掉落的食物
                for food in new_foods:
                    food["from_snake"] = "computer2"
                foods.extend(new_foods)
                computer_snake2 = [[random.randint(15, 635), random.randint(15, 635)]]
                computer_dir2 = "right"
                computer_speed2 = 15
                break

    # 限制食物数量,避免过多
    if len(foods) > 50:
        foods = foods[:50]

    pygame.display.update()

    if game_over_reason:
        screen.fill(WHITE)
        if game_over_image:
            # 向下移动 50 像素,可按需调整
            screen.blit(game_over_image, (0, 50))
        # 使用新字体渲染游戏结束原因
        reason = game_over_font.render(game_over_reason, True, BLACK)
        # 往上调 200 像素
        reason_rect = reason.get_rect(center=(screen_width / 2, screen_height / 3 + 20 + 100 - 200))

        # 获取当前时间,用于控制边框闪烁
        current_time = time.time()
        border_color = BORDER_COLOR_1 if (current_time // BLINK_INTERVAL) % 2 == 0 else BORDER_COLOR_2

        # 绘制带闪烁边框的矩形
        border_rect = reason_rect.copy()
        border_rect.inflate_ip(10, 10)  # 让边框比文字区域稍大
        pygame.draw.rect(screen, border_color, border_rect, BORDER_WIDTH)

        screen.blit(reason, reason_rect)

        back_to_mode_selection_pressed = False
        while True:
            current_time = time.time()
            border_color = BORDER_COLOR_1 if (current_time // BLINK_INTERVAL) % 2 == 0 else BORDER_COLOR_2

            for event in pygame.event.get():
                if event.type == pygame.QUIT:
                    pygame.quit()
                    sys.exit()
                elif event.type == pygame.MOUSEBUTTONDOWN:
                    # 按钮位置往上调 100 像素,按钮文字改为返回模式选择
                    back_to_mode_selection = draw_button("返回模式选择",
                                                         screen_width / 2 - 100,
                                                         screen_height / 2 + 30 - 100,
                                                         200,
                                                         50,
                                                         GREEN,
                                                         (0, 200, 0),
                                                         "back_to_mode_selection")
                    if back_to_mode_selection == "back_to_mode_selection":
                        back_to_mode_selection_pressed = True

            if back_to_mode_selection_pressed:
                break

            # 重新绘制带闪烁边框的矩形
            pygame.draw.rect(screen, border_color, border_rect, BORDER_WIDTH)
            screen.blit(reason, reason_rect)

            # 按钮位置往上调 100 像素,按钮文字改为返回模式选择
            draw_button("返回模式选择",
                        screen_width / 2 - 100,
                        screen_height / 2 + 30 - 100,
                        200,
                        50,
                        GREEN,
                        (0, 200, 0),
                        "back_to_mode_selection")
            pygame.display.update()
        break  # 退出 game_loop 循环,回到模式选择界面

游戏主循环

while True:
game_intro()
selected_mode = select_mode()
game_loop(selected_mode)

pygame.quit()

posted @ 2025-06-18 18:17  渔樵伴夜归客  阅读(15)  评论(0)    收藏  举报