import curses
import random
import time
import os
class SnakeGame:
def __init__(self):
# 初始化颜色
self.init_colors()
self.min_height = 10
self.min_width = 30
if not self.show_start_screen():
raise SystemExit("游戏已取消")
# 初始化游戏参数
self.init_game()
def init_colors(self):
self.screen = curses.initscr()
curses.start_color()
curses.init_pair(1, curses.COLOR_GREEN, curses.COLOR_BLACK) # 蛇的颜色
curses.init_pair(2, curses.COLOR_RED, curses.COLOR_BLACK) # 食物的颜色
curses.init_pair(3, curses.COLOR_YELLOW, curses.COLOR_BLACK) # 分数的颜色
curses.init_pair(4, curses.COLOR_CYAN, curses.COLOR_BLACK) # 提示文字颜色
def show_start_screen(self):
self.screen.clear()
self.screen.keypad(1)
curses.noecho()
curses.curs_set(0)
height, width = self.screen.getmaxyx()
# 显示标题
title = "贪吃蛇游戏"
self.screen.addstr(height//4, (width-len(title))//2, title, curses.color_pair(3) | curses.A_BOLD)
# 显示调整窗口提示
instructions = [
"请调整窗口大小至合适大小",
f"最小要求: {self.min_width}x{self.min_height}",
"当前大小: {}x{}",
"",
"按空格键开始游戏",
"按 Q 退出游戏"
]
while True:
current_height, current_width = self.screen.getmaxyx()
# 显示指示信息
for i, text in enumerate(instructions):
if "当前大小" in text:
text = text.format(current_width, current_height)
y = height//4 + 2 + i
if y < current_height - 1: # 防止写入最后一行
self.screen.addstr(y, (width-len(text))//2, text, curses.color_pair(4))
# 检查窗口大小是否合适
size_ok = current_height >= self.min_height and current_width >= self.min_width
status = "窗口大小合适 ✓" if size_ok else "窗口太小 ✗"
status_color = curses.color_pair(1) if size_ok else curses.color_pair(2)
self.screen.addstr(height//4 + len(instructions) + 1,
(width-len(status))//2,
status,
status_color | curses.A_BOLD)
self.screen.refresh()
# 获取用户输入
key = self.screen.getch()
if key == ord(' ') and size_ok: # 空格键且窗口大小合适
return True
elif key in (ord('q'), ord('Q')): # Q键退出
return False
# 短暂延迟,降低CPU使用率
time.sleep(0.1)
def init_game(self):
# 获取当前窗口大小
self.height, self.width = self.screen.getmaxyx()
self.screen.clear()
self.screen.border(0)
# 初始化蛇的位置(在屏幕中央)
center_y = self.height // 2
center_x = self.width // 2
self.snake = [[center_y, center_x],
[center_y, center_x-1],
[center_y, center_x-2]]
# 初始化其他游戏参数
self.food = None
self.generate_food()
self.direction = curses.KEY_RIGHT
self.score = 0
self.speed = 0.1
self.paused = False
def generate_food(self):
while True:
self.food = [
random.randint(1, self.height-2),
random.randint(1, self.width-2)
]
if self.food not in self.snake:
break
def show_score(self):
score_text = f"分数: {self.score} | 按P暂停 | 按Q退出"
self.screen.addstr(0, 2, score_text, curses.color_pair(3))
def update_screen(self):
self.screen.clear()
self.screen.border(0)
# 显示蛇
for pos in self.snake:
self.screen.addch(pos[0], pos[1], '#', curses.color_pair(1))
# 显示食物
self.screen.addch(self.food[0], self.food[1], '*', curses.color_pair(2))
# 显示分数和控制说明
self.show_score()
# 如果游戏暂停,显示暂停信息
if self.paused:
pause_text = "游戏暂停中 - 按P继续"
self.screen.addstr(self.height//2, (self.width-len(pause_text))//2,
pause_text, curses.color_pair(4) | curses.A_BOLD)
self.screen.refresh()
def get_next_position(self):
head = self.snake[0].copy()
if self.direction == curses.KEY_UP:
head[0] -= 1
elif self.direction == curses.KEY_DOWN:
head[0] += 1
elif self.direction == curses.KEY_LEFT:
head[1] -= 1
elif self.direction == curses.KEY_RIGHT:
head[1] += 1
return head
def play(self):
while True:
self.update_screen()
# 获取用户输入
self.screen.timeout(100)
event = self.screen.getch()
# 处理暂停
if event in (ord('p'), ord('P')):
self.paused = not self.paused
continue
# 处理退出
if event in (ord('q'), ord('Q')):
break
# 如果游戏暂停,跳过其他处理
if self.paused:
continue
# 更新方向
if event in [curses.KEY_UP, curses.KEY_DOWN, curses.KEY_LEFT, curses.KEY_RIGHT]:
# 防止蛇反向移动
if (event == curses.KEY_UP and self.direction != curses.KEY_DOWN) or \
(event == curses.KEY_DOWN and self.direction != curses.KEY_UP) or \
(event == curses.KEY_LEFT and self.direction != curses.KEY_RIGHT) or \
(event == curses.KEY_RIGHT and self.direction != curses.KEY_LEFT):
self.direction = event
# 计算蛇的下一个位置
next_pos = self.get_next_position()
# 检查是否撞墙
if next_pos[0] in [0, self.height-1] or \
next_pos[1] in [0, self.width-1] or \
next_pos in self.snake[1:]:
break
# 移动蛇
self.snake.insert(0, next_pos)
# 检查是否吃到食物
if next_pos == self.food:
self.score += 10
self.generate_food()
# 加快游戏速度
self.speed = max(0.05, self.speed * 0.95)
else:
self.snake.pop()
time.sleep(self.speed)
def end_game(self):
curses.endwin()
print(f"游戏结束!最终得分:{self.score}")
def main():
try:
game = SnakeGame()
game.play()
game.end_game()
except SystemExit as e:
curses.endwin()
print(e)
except Exception as e:
curses.endwin()
print(f"游戏发生错误:{e}")
if __name__ == "__main__":
main()