贪吃蛇小游戏
import pygame
import random
import sys
初始化
pygame.init()
颜色定义
WHITE = (255, 255, 255)
BLACK = (0, 0, 0)
RED = (255, 0, 0)
GREEN = (0, 255, 0)
DARK_GREEN = (0, 180, 0)
YELLOW = (255, 255, 0)
BLUE = (0, 0, 255)
GRAY = (200, 200, 200)
屏幕设置
WIDTH, HEIGHT = 800, 600
BORDER = 20
screen = pygame.display.set_mode((WIDTH, HEIGHT))
pygame.display.set_caption('贪吃蛇')
游戏参数
BLOCK_SIZE = 20
BASE_SPEEDS = {
"easy": 10,
"medium": 15,
"hard": 20
}
MAX_SPEED = 30
SPEED_INCREMENT = 1
食物类型
FOOD_TYPES = {
"normal": {"color": RED, "score": 1, "speed_change": 1, "weight": 70},
"gold": {"color": YELLOW, "score": 5, "speed_change": 0, "weight": 20},
"slow": {"color": BLUE, "score": 2, "speed_change": -2, "weight": 10}
}
字体
font = pygame.font.SysFont('simhei', 36)
big_font = pygame.font.SysFont('simhei', 72)
small_font = pygame.font.SysFont('simhei', 24)
游戏区域
game_area = {
"left": BORDER,
"right": WIDTH - BORDER,
"top": BORDER,
"bottom": HEIGHT - BORDER
}
def draw_border():
"""绘制游戏边框"""
pygame.draw.rect(screen, BLACK, [0, 0, WIDTH, BORDER]) # 上
pygame.draw.rect(screen, BLACK, [0, 0, BORDER, HEIGHT]) # 左
pygame.draw.rect(screen, BLACK, [0, HEIGHT - BORDER, WIDTH, BORDER]) # 下
pygame.draw.rect(screen, BLACK, [WIDTH - BORDER, 0, BORDER, HEIGHT]) # 右
def draw_grid():
"""绘制游戏网格"""
for x in range(game_area["left"], game_area["right"], BLOCK_SIZE):
pygame.draw.line(screen, GRAY, (x, game_area["top"]), (x, game_area["bottom"]))
for y in range(game_area["top"], game_area["bottom"], BLOCK_SIZE):
pygame.draw.line(screen, GRAY, (game_area["left"], y), (game_area["right"], y))
def show_text(text, y, size="normal", color=BLACK):
"""显示文本"""
if size == "big":
font_obj = big_font
elif size == "small":
font_obj = small_font
else:
font_obj = font
surf = font_obj.render(text, True, color)
rect = surf.get_rect(center=(WIDTH / 2, y))
screen.blit(surf, rect)
def start_screen():
"""开始游戏界面"""
waiting = True
while waiting:
screen.fill(WHITE)
draw_border()
draw_grid()
show_text("贪吃蛇", HEIGHT / 2 - 100, "big")
show_text("按Enter键开始游戏", HEIGHT / 2 + 50)
show_text("使用方向键控制蛇移动", HEIGHT / 2 + 100, "small")
pygame.display.update()
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_RETURN:
waiting = False
def difficulty_screen():
"""难度选择界面"""
difficulties = ["简单", "中等", "困难"]
selected = 0
waiting = True
while waiting:
screen.fill(WHITE)
draw_border()
draw_grid()
show_text("选择难度", HEIGHT / 2 - 100, "big")
for i, diff in enumerate(difficulties):
color = GREEN if i == selected else BLACK
show_text(diff, HEIGHT / 2 + i * 50, color=color)
show_text("使用上下方向键选择,按Enter确认", HEIGHT / 2 + 200, "small")
pygame.display.update()
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_DOWN:
selected = (selected + 1) % len(difficulties)
if event.key == pygame.K_UP:
selected = (selected - 1) % len(difficulties)
if event.key == pygame.K_RETURN:
waiting = False
return ["easy", "medium", "hard"][selected]
def game_over_screen(score, high_score):
"""游戏结束界面"""
waiting = True
while waiting:
screen.fill(WHITE)
draw_border()
draw_grid()
show_text("游戏结束", HEIGHT / 2 - 150, "big", RED)
show_text(f"最终得分: {score}", HEIGHT / 2 - 50)
show_text(f"历史最高分: {high_score}", HEIGHT / 2)
show_text("按Enter键重新开始", HEIGHT / 2 + 50, "normal", GREEN)
show_text("按空格结束游戏", HEIGHT / 2 + 100, "normal", BLACK)
pygame.display.update()
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
return False
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_RETURN:
return True
if event.key == pygame.K_SPACE:
pygame.quit()
return False
def generate_food(snake):
"""生成新的食物位置,确保不与蛇身重叠"""
while True:
food_x = round(
random.randrange(game_area["left"], game_area["right"] - BLOCK_SIZE) / BLOCK_SIZE) * BLOCK_SIZE
food_y = round(
random.randrange(game_area["top"], game_area["bottom"] - BLOCK_SIZE) / BLOCK_SIZE) * BLOCK_SIZE
if [food_x, food_y] not in snake:
return food_x, food_y
def choose_food_type():
"""随机选择食物类型"""
types = list(FOOD_TYPES.keys())
weights = [FOOD_TYPES[t]["weight"] for t in types]
return random.choices(types, weights=weights)[0]
def game_loop(difficulty, high_score):
"""游戏主循环"""
# 初始化蛇
x, y = WIDTH // 2, HEIGHT // 2
dx, dy = 0, 0
snake = [[x, y]]
length = 1
speed = BASE_SPEEDS[difficulty]
grow_by = 0
score = 0
# 食物
food_x, food_y = generate_food(snake)
current_food_type = choose_food_type()
clock = pygame.time.Clock()
while True:
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_LEFT and dx == 0:
dx, dy = -BLOCK_SIZE, 0
elif event.key == pygame.K_RIGHT and dx == 0:
dx, dy = BLOCK_SIZE, 0
elif event.key == pygame.K_UP and dy == 0:
dx, dy = 0, -BLOCK_SIZE
elif event.key == pygame.K_DOWN and dy == 0:
dx, dy = 0, BLOCK_SIZE
# 移动蛇
x += dx
y += dy
# 碰撞检测
if (x < game_area["left"] or x >= game_area["right"] or
y < game_area["top"] or y >= game_area["bottom"]):
return score
# 更新蛇身
snake.append([x, y])
if grow_by > 0:
length += 1
grow_by -= 1
else:
if len(snake) > length:
del snake[0]
# 自撞检测
if [x, y] in snake[:-1]:
return score
# 绘制游戏
screen.fill(WHITE)
draw_border()
draw_grid()
# 绘制食物
pygame.draw.rect(screen, FOOD_TYPES[current_food_type]["color"],
[food_x, food_y, BLOCK_SIZE, BLOCK_SIZE])
# 绘制蛇身
for index, segment in enumerate(snake):
if index == len(snake) - 1: # 蛇头
pygame.draw.rect(screen, DARK_GREEN,
[segment[0], segment[1], BLOCK_SIZE, BLOCK_SIZE])
else: # 蛇身
pygame.draw.rect(screen, GREEN,
[segment[0], segment[1], BLOCK_SIZE, BLOCK_SIZE])
# 显示分数和最高分
show_text(f"得分: {score}", 60, color=RED)
show_text(f"最高分: {high_score}", 90, "small")
show_text(f"速度: {speed}", HEIGHT - 60, "small")
show_text(f"难度: {difficulty}", HEIGHT - 30, "small")
pygame.display.update()
# 吃食物检测
if x == food_x and y == food_y:
food_x, food_y = generate_food(snake)
current_food_type = choose_food_type()
score += FOOD_TYPES[current_food_type]["score"]
grow_by += FOOD_TYPES[current_food_type]["score"]
speed += FOOD_TYPES[current_food_type]["speed_change"]
speed = max(5, min(speed, MAX_SPEED)) # 限制速度范围
clock.tick(speed)
def main():
"""主函数"""
high_score = 0
while True:
start_screen()
difficulty = difficulty_screen()
score = game_loop(difficulty, high_score)
high_score = max(high_score, score)
if not game_over_screen(score, high_score):
break
if name == "main":
main()
if name == "main":
main()