Snake游戏分数与最高分记录异常问题求助
Snake游戏分数记录异常问题
我正在开发一款Snake游戏,但无法正确记录当前分数(score)和最高分(high score)。每当蛇收集到食物时,只有最高分数值增长,当前分数毫无变化。我尝试过调整画布中与分数相关的代码逻辑、修改分数计数条件,但问题仍未解决。
以下是我的游戏代码:
from tkinter import * from settings import * import random import turtle import pygame as pg import keyboard from os import path global game_state class Snake: def __init__(self): self.body_size = BODY_PARTS self.coordinates = [] self.squares = [] for i in range(0, BODY_PARTS): self.coordinates.append([0, 0]) for x, y in self.coordinates: square = canvas.create_rectangle(x, y, x + SPACE_SIZE, y + SPACE_SIZE, fill=SNAKE_COLOR, tag="snake") self.squares.append(square) class Food: def __init__(self): x = random.randint(0, (GAME_WIDTH / SPACE_SIZE)-1) * SPACE_SIZE y = random.randint(0, (GAME_HEIGHT / SPACE_SIZE) - 1) * SPACE_SIZE self.coordinates = [x, y] canvas.create_oval(x, y, x + SPACE_SIZE, y + SPACE_SIZE, fill=FOOD_COLOR, tag="food") class TryAgain: def __init__(self): x = (GAME_WIDTH / SPACE_SIZE)-1 * SPACE_SIZE y = (GAME_HEIGHT / SPACE_SIZE) - 1 * SPACE_SIZE self.coordinates = [x, y] def show_title_screen(): canvas.create_text(canvas.winfo_width()/2, canvas.winfo_height()/4, font=('times new roman',70), text="SNAKE!", fill="Green", tag="title") canvas.create_text(canvas.winfo_width()/2, canvas.winfo_height()/2, font=('times new roman',22), text="Use the arrow keys to move", fill="Green", tag="title") def next_turn(snake, food): x, y = snake.coordinates[0] if direction == "up": y -= SPACE_SIZE elif direction == "down": y += SPACE_SIZE elif direction == "left": x -= SPACE_SIZE elif direction == "right": x += SPACE_SIZE snake.coordinates.insert(0, (x, y)) square = canvas.create_rectangle(x, y, x + SPACE_SIZE, y + SPACE_SIZE, fill=SNAKE_COLOR) snake.squares.insert(0, square) if x == food.coordinates[0] and y == food.coordinates[1]: global score global high_score score += 1 label.config(text="Score:{}".format(score)) if score >= high_score: high_score = score label.config(text="High Score:{}".format(high_score)) canvas.delete("food") food = Food() else: del snake.coordinates[-1] canvas.delete(snake.squares[-1]) del snake.squares[-1] if check_collisions(snake): game_over() else: window.after(SPEED, next_turn, snake, food) def change_direction(new_direction): global direction if new_direction == 'left': if direction != 'right': direction = new_direction elif new_direction == 'right': if direction != 'left': direction = new_direction elif new_direction == 'up': if direction != 'down': direction = new_direction elif new_direction == 'down': if direction != 'up': direction = new_direction def check_collisions(snake): x, y = snake.coordinates[0] if x < 0 or x >= GAME_WIDTH: return True elif y < 0 or y >= GAME_HEIGHT: return True for body_part in snake.coordinates[1:]: if x == body_part[0] and y == body_part[1]: return True return False def game_over(): canvas.delete(ALL) canvas.create_text(canvas.winfo_width()/2, canvas.winfo_height()/4, font=('times new roman',70), text="GAME OVER", fill="orange", tag="gameover") button = TryAgain() def load_data(self): self.dir = path.dirname(__dirname__) with open(path.join(self.dir, HS_FILE), 'w') as f: try: self.highscore = int(f.read()) except: self.highscore = 0 window = Tk() window.title("Snake game") window.resizable(False, False) score = 0 high_score = 0 direction = 'down' label = Label(window, text="Score:{}".format(score), font=('times new roman', 40)) label.pack() label = Label(window, text="High Score:{}".format(high_score), font=('times new roman', 40)) label.pack() canvas = Canvas(window, bg=BACKGROUND_COLOR, height=GAME_HEIGHT, width=GAME_WIDTH) canvas.pack() window.update() window_width = window.winfo_width() window_height = window.winfo_height() screen_width = window.winfo_screenwidth() screen_height = window.winfo_screenheight() x = int((screen_width/2) - (window_width/2)) y = int((screen_height/2) - (window_height/2)) window.geometry(f"{window_width}x{window_height}+{x}+{y}") show_title_screen() window.bind('<Left>', lambda event: change_direction('left')) window.bind('<Right>', lambda event: change_direction('right')) window.bind('<Up>', lambda event: change_direction('up')) window.bind('<Down>', lambda event: change_direction('down')) snake = Snake() food = Food() next_turn(snake, food) window.mainloop()
问题根源与修复方案
1. 核心问题
- Label变量覆盖:两个分数Label共用同一个
label变量,第二个Label会直接覆盖第一个,导致后续仅能更新最高分的显示,当前分数完全无法被更新。 - 分数更新逻辑冲突:收集食物时,更新当前分数后立刻用最高分文本覆盖Label,冲掉了当前分数的显示。
- 最高分持久化失效:
load_data函数定义后从未调用,且用'w'模式打开文件会清空原有内容,无法读取历史最高分。
2. 修复后的完整代码
from tkinter import * from settings import * import random from os import path global game_state class Snake: def __init__(self): self.body_size = BODY_PARTS self.coordinates = [] self.squares = [] for i in range(0, BODY_PARTS): self.coordinates.append([0, 0]) for x, y in self.coordinates: square = canvas.create_rectangle(x, y, x + SPACE_SIZE, y + SPACE_SIZE, fill=SNAKE_COLOR, tag="snake") self.squares.append(square) class Food: def __init__(self): x = random.randint(0, (GAME_WIDTH / SPACE_SIZE)-1) * SPACE_SIZE y = random.randint(0, (GAME_HEIGHT / SPACE_SIZE) - 1) * SPACE_SIZE self.coordinates = [x, y] canvas.create_oval(x, y, x + SPACE_SIZE, y + SPACE_SIZE, fill=FOOD_COLOR, tag="food") class TryAgain: def __init__(self): x = (GAME_WIDTH / SPACE_SIZE)-1 * SPACE_SIZE y = (GAME_HEIGHT / SPACE_SIZE) - 1 * SPACE_SIZE self.coordinates = [x, y] def show_title_screen(): canvas.create_text(canvas.winfo_width()/2, canvas.winfo_height()/4, font=('times new roman',70), text="SNAKE!", fill="Green", tag="title") canvas.create_text(canvas.winfo_width()/2, canvas.winfo_height()/2, font=('times new roman',22), text="Use the arrow keys to move", fill="Green", tag="title") def change_direction(new_direction): global direction if new_direction == 'left' and direction != 'right': direction = new_direction elif new_direction == 'right' and direction != 'left': direction = new_direction elif new_direction == 'up' and direction != 'down': direction = new_direction elif new_direction == 'down' and direction != 'up': direction = new_direction def check_collisions(snake): x, y = snake.coordinates[0] if x < 0 or x >= GAME_WIDTH or y < 0 or y >= GAME_HEIGHT: return True for body_part in snake.coordinates[1:]: if x == body_part[0] and y == body_part[1]: return True return False def load_data(): global high_score dir_path = path.dirname(__file__) hs_file = path.join(dir_path, HS_FILE) if path.exists(hs_file): with open(hs_file, 'r') as f: try: high_score = int(f.read()) except: high_score = 0 else: high_score = 0 def save_high_score(): global high_score dir_path = path.dirname(__file__) hs_file = path.join(dir_path, HS_FILE) with open(hs_file, 'w') as f: f.write(str(high_score)) def game_over(): save_high_score() canvas.delete(ALL) canvas.create_text(canvas.winfo_width()/2, canvas.winfo_height()/4, font=('times new roman',70), text="GAME OVER", fill="orange", tag="gameover") TryAgain() def next_turn(snake, food): x, y = snake.coordinates[0] if direction == "up": y -= SPACE_SIZE elif direction == "down": y += SPACE_SIZE elif direction == "left": x -= SPACE_SIZE elif direction == "right": x += SPACE_SIZE snake.coordinates.insert(0, (x, y)) square = canvas.create_rectangle(x, y, x + SPACE_SIZE, y + SPACE_SIZE, fill=SNAKE_COLOR) snake.squares.insert(0, square) if x == food.coordinates[0] and y == food.coordinates[1]: global score, high_score score += 1 score_label.config(text=f"Score:{score}") if score >= high_score: high_score = score high_score_label.config(text=f"High Score:{high_score}") canvas.delete("food") food = Food() else: del snake.coordinates[-1] canvas.delete(snake.squares[-1]) del snake.squares[-1] if check_collisions(snake): game_over() else: window.after(SPEED, next_turn, snake, food) # 初始化窗口 window = Tk() window.title("Snake game") window.resizable(False, False) score = 0 high_score = 0 direction = 'down' # 加载历史最高分 load_data() # 分别创建两个Label,避免变量覆盖 score_label = Label(window, text=f"Score:{score}", font=('times new roman', 40)) score_label.pack() high_score_label = Label(window, text=f"High Score:{high_score}", font=('times new roman', 40)) high_score_label.pack() canvas = Canvas(window, bg=BACKGROUND_COLOR, height=GAME_HEIGHT, width=GAME_WIDTH) canvas.pack() # 窗口居中 window.update() window_width = window.winfo_width() window_height = window.winfo_height() screen_width = window.winfo_screenwidth() screen_height = window.winfo_screenheight() x = int((screen_width/2) - (window_width/2)) y = int((screen_height/2) - (window_height/2)) window.geometry(f"{window_width}x{window_height}+{x}+{y}") show_title_screen() # 绑定方向键 window.bind('<Left>', lambda event: change_direction('left')) window.bind('<Right>', lambda event: change_direction('right')) window.bind('<Up>', lambda event: change_direction('up')) window.bind('<Down>', lambda event: change_direction('down')) # 启动游戏 snake = Snake() food = Food() next_turn(snake, food) window.mainloop()
3. 关键修改点
- 拆分两个分数Label为
score_label和high_score_label,避免变量覆盖 - 分离当前分数与最高分的更新逻辑,确保两个Label独立显示
- 修复
load_data函数,改为读取模式加载历史最高分,增加文件存在性判断 - 添加
save_high_score函数,游戏结束时自动保存当前最高分 - 清理无用导入(turtle、pygame、keyboard),简化代码结构
内容的提问来源于stack exchange,提问作者Devaki Shandha
相关产品推荐
相关产品推荐

