如何修复Pygame井字棋游戏屏幕运行异常、无法正常执行的问题
代码问题根源定位
- 落子操作与棋盘状态完全脱节:鼠标点击仅在屏幕临时绘制X,从未将对应网格位置写入
board二维数组,导致胜利检测逻辑永远读不到实际落子数据,无法触发对局结束判断,同时重复点击同一格子会出现多层重叠的X标记。 - 绘制锚点错误:
blit渲染文字时默认将文字表面的左上角对齐传入坐标,而代码传入的是格子中心点,会导致X/O标记偏移到相邻格子,无法正常落在目标区域。 - 渲染流程缺失清屏步骤:每轮游戏循环没有先填充纯色底色重绘网格,直接在旧画面上叠加绘制按钮和文字,长时间运行后屏幕会因多层内容残留出现模糊、重影。
- 函数返回值不完整:
check_win遍历完所有获胜判定条件后,没有默认返回False的兜底逻辑,可能引发隐性类型判断错误。 - 对局逻辑缺失:已编写的电脑落子、控制台输入取位置等函数完全没有和Pygame窗口流程适配,既会造成控制台输入和窗口操作的冲突,也无法实现人机交互的完整流程。
修复后可运行代码
import sys, pygame from pygame.locals import * import random def setup_board(width=860, height=640): """初始化井字棋棋盘,返回屏幕对象、宽高尺寸""" size = width, height screen = pygame.display.set_mode(size) screen.fill('white') # 绘制垂直网格线 pygame.draw.line(screen, 'black', (width/3, 0), (width/3, height), 3) pygame.draw.line(screen, 'black', (2*width/3, 0), (2*width/3, height), 3) # 绘制水平网格线 pygame.draw.line(screen, 'black', (0, height/3), (width, height/3), 3) pygame.draw.line(screen, 'black', (0, 2*height/3), (width, 2*height/3), 3) return screen, width, height def get_board_position(x, y): """根据鼠标坐标换算对应的棋盘网格行、列,以及单格宽高""" dw, dl = 860//3, 640//3 col = x // dw row = y // dl # 处理点在窗口边缘的越界情况 row = min(row, 2) col = min(col, 2) return int(row), int(col), dw, dl def get_draw_position(row, col): """根据网格行列号换算标记的绘制中心点""" dw, dl = 860//3, 640//3 center_x = col * dw + dw/2 center_y = row * dl + dl/2 return center_x, center_y def get_computer_move(board): """电脑获取第一个空闲网格位置""" for row in range(3): for col in range(3): if board[row][col] == '': return row, col # 无空位时返回None return None def check_win(board, mark): """检测指定标记的获胜状态,无获胜时返回False""" # 检测行获胜 for row in range(3): if board[row][0] == board[row][1] == board[row][2] == mark: return True # 检测列获胜 for col in range(3): if board[0][col] == board[1][col] == board[2][col] == mark: return True # 检测对角线获胜 if board[0][0] == board[1][1] == board[2][2] == mark: return True if board[2][0] == board[1][1] == board[0][2] == mark: return True return False def check_draw(board): """检测是否平局""" for row in range(3): for col in range(3): if board[row][col] == '': return False return True # 初始化Pygame基础配置 pygame.init() pygame.display.set_caption("人机对战井字棋") font = pygame.font.SysFont('arial', 110) small_font = pygame.font.SysFont('arial', 30) screen, width, height = setup_board() clock = pygame.time.Clock() # 预渲染标记素材 x_render = font.render("X", False, "blue") o_render = font.render("O", False, "red") quit_text = small_font.render("Quit!", False, "red") # 计算标记的半宽高,实现居中对齐 x_w, x_h = x_render.get_size() o_w, o_h = o_render.get_size() # 游戏全局状态 active_game = True board = [['' ,'', ''], ['', '', ''],['', '', '']] player_turn = True while active_game: # 每帧重绘干净背景和网格 screen.fill('white') pygame.draw.line(screen, 'black', (width/3, 0), (width/3, height), 3) pygame.draw.line(screen, 'black', (2*width/3, 0), (2*width/3, height), 3) pygame.draw.line(screen, 'black', (0, height/3), (width, height/3), 3) pygame.draw.line(screen, 'black', (0, 2*height/3), (width, 2*height/3), 3) # 绘制退出按钮 quit_rect = pygame.draw.rect(screen, 'gray', (50, 50, 80, 40), 2) screen.blit(quit_text, (55, 55)) # 绘制棋盘上已有的所有标记 for row in range(3): for col in range(3): mark = board[row][col] center_x, center_y = get_draw_position(row, col) if mark == 'X': # 居中对齐绘制X screen.blit(x_render, (center_x - x_w/2, center_y - x_h/2)) if mark == 'O': # 居中对齐绘制O screen.blit(o_render, (center_x - o_w/2, center_y - o_h/2)) # 事件检测 for event in pygame.event.get(): if event.type == pygame.QUIT: pygame.quit() sys.exit() elif event.type == MOUSEBUTTONUP: ex, ey = event.pos # 退出按钮点击检测 if quit_rect.collidepoint(ex, ey): pygame.quit() sys.exit() # 玩家回合的落子检测 if player_turn: row, col, _, _ = get_board_position(ex, ey) # 仅当目标格子为空时落子 if board[row][col] == '': board[row][col] = 'X' player_turn = False # 电脑自动回合落子 if not player_turn and active_game: pygame.time.wait(500) # 模拟电脑思考延迟 comp_move = get_computer_move(board) if comp_move: c_row, c_col = comp_move board[c_row][c_col] = 'O' player_turn = True # 对局结束状态检测 if check_win(board, 'X'): win_text = small_font.render("玩家获胜!", False, "blue") screen.blit(win_text, (300, 300)) pygame.display.flip() pygame.time.wait(3000) active_game = False if check_win(board, 'O'): win_text = small_font.render("电脑获胜!", False, "red") screen.blit(win_text, (300, 300)) pygame.display.flip() pygame.time.wait(3000) active_game = False if check_draw(board): draw_text = small_font.render("平局!", False, "green") screen.blit(draw_text, (350, 300)) pygame.display.flip() pygame.time.wait(3000) active_game = False pygame.display.flip() clock.tick(60) pygame.quit()
内容的提问来源于stack exchange,提问作者compscie111
相关产品推荐
相关产品推荐

