You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Pygame四子棋开发:回合切换函数无法交替执行问题求助

解决Pygame四子棋无法交替玩家回合的问题

看起来你遇到的核心问题是回合切换逻辑没有正确生效,我帮你拆解下问题根源,然后给出修复方案:

问题根源分析

  • 全局变量未正确引用:你在playerOne函数里设置playerOneOver = True,但这个变量在函数内是局部变量,不会修改全局的playerOneOver。因此全局的playerOneOver永远是False,程序会一直重复执行playerOne()。
  • 缺少玩家二回合结束的切换逻辑:就算playerOneOver能成功变为True,playerTwo函数执行完后没有把playerOneOver改回False,导致之后会一直执行playerTwo(),无法切回玩家一。
  • 事件处理分散:两个玩家函数里都调用pg.event.get(),会导致事件被其中一个函数“吃掉”,另一个函数无法响应输入,这也会影响回合切换的流畅性。

修复后的代码方案

我针对上述问题对代码做了修改,同时优化了部分逻辑让代码更简洁:

import pygame as pg 

# 初始化Pygame(之前遗漏了这关键一步)
pg.init()

# 窗口、颜色等基础设置
display = pg.display.set_mode((500, 500))
white = (255, 255 , 255)
black = (0, 0, 0)
red = (255, 0, 0)
blue = (0, 0, 255)

display.fill(white)
# 用简易绘制的棋盘代替图片,避免找不到文件报错(可替换回你的board.png)
pg.draw.rect(display, blue, (100, 100, 280, 240), 2)
for i in range(7):
    for j in range(6):
        pg.draw.circle(display, white, (120 + i*40, 120 + j*40), 15)

playerOneOver = False # 初始为玩家一回合

# 优化棋盘数据结构:用二维列表代替6个单独的行变量,更易维护
board = [['b' for _ in range(7)] for _ in range(6)]
# 预定义列选择区域,避免循环内重复创建
columns = [pg.Rect(105 + i*45, 70, 30, 30) for i in range(7)]

def playerOne():
    global playerOneOver  # 声明要修改全局变量
    chip_color = red

    # 显示当前轮到玩家一
    pg.draw.rect(display, chip_color, (230, 5, 20, 20))

    mouse_pressed = pg.mouse.get_pressed()
    mouse_pos = pg.mouse.get_pos()   

    # 遍历所有列,检查是否被点击
    for col_idx, col_rect in enumerate(columns):
        if col_rect.collidepoint(mouse_pos) and mouse_pressed[0]:
            # 从最下方行往上找空位置落子
            for row_idx in range(5, -1, -1):
                if board[row_idx][col_idx] == 'b':
                    board[row_idx][col_idx] = 'r'
                    pg.draw.circle(display, chip_color, (120 + col_idx*40, 120 + row_idx*40), 15)
                    playerOneOver = True  # 玩家一回合结束
                    break
            break

def playerTwo():
    global playerOneOver  # 声明要修改全局变量
    chip_color = black

    # 显示当前轮到玩家二
    pg.draw.rect(display, chip_color, (230, 5, 20, 20))

    mouse_pressed = pg.mouse.get_pressed()
    mouse_pos = pg.mouse.get_pos()   

    # 遍历所有列,检查是否被点击
    for col_idx, col_rect in enumerate(columns):
        if col_rect.collidepoint(mouse_pos) and mouse_pressed[0]:
            # 从最下方行往上找空位置落子
            for row_idx in range(5, -1, -1):
                if board[row_idx][col_idx] == 'b':
                    board[row_idx][col_idx] = 'B'
                    pg.draw.circle(display, chip_color, (120 + col_idx*40, 120 + row_idx*40), 15)
                    playerOneOver = False  # 玩家二回合结束,切回玩家一
                    break
            break

# 游戏主循环
while True:
    # 统一处理事件,避免事件被单个函数独占
    for event in pg.event.get():
        if event.type == pg.QUIT:
            pg.quit()
            exit()

    # 重绘列选择区域(清除旧的绘制痕迹)
    display.fill(white, (100, 60, 300, 40))
    for col_rect in columns:
        pg.draw.rect(display, blue, col_rect)

    # 回合切换逻辑
    if not playerOneOver:
        playerOne()
    else:
        playerTwo() 

    pg.display.flip() # 更新画面

    # 打印棋盘状态(调试用,可注释)
    for row in reversed(board):
        print(row)
    print("---")

关键修改点说明

  1. 全局变量引用:在两个玩家函数中添加global playerOneOver,确保函数内的赋值能真正修改全局变量,实现回合切换。
  2. 闭环回合切换:playerTwo函数执行完后将playerOneOver设为False,让下一轮循环切回玩家一。
  3. 统一事件处理:把pg.event.get()移到主循环中,避免事件被单个函数消费,确保所有输入都能被正确响应。
  4. 优化数据结构:用二维列表board替代6个单独的行变量,简化落子逻辑的同时让代码更易维护。
  5. 简化落子判断:通过循环从下往上查找空行,避免重复编写大量elif判断,减少冗余代码。

这样修改后,就能实现玩家一和玩家二的交替落子了,你可以测试下效果~

内容的提问来源于stack exchange,提问作者Andrew Ely

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.20 10:24:35