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

Discord.py cog编写井字棋游戏时checkWinner未定义报错求助

问题原因
  • 类成员方法调用规则错误:checkWinner是你定义的help类的实例方法,Python中类内部调用自身的实例方法必须加self.前缀,你直接调用checkWinner()会被判定为找全局作用域的函数,自然会抛出未定义错误。
  • 方法定义缺失必要参数:你写的checkWinner方法作为类实例方法,第一个参数必须是实例本身self,你当前的定义缺少该参数,即便补了调用前缀也会报参数数量不匹配的错误。
  • 额外存在严重的缩进逻辑错误:你把胜负校验、换回合、提示消息的代码全部错误缩进放在了打印棋盘的for循环内部的else分支,不仅会导致逻辑重复执行多次,后续的条件判断分支也完全错位,游戏逻辑根本无法正常运行。
  • 全局变量使用不符合Cog开发规范:Discord Cog多为单实例多服务器共用,用global存储游戏状态会导致多个服务器的游戏数据串线,非常容易触发不可预期的bug。
修复方案
  1. 先修正checkWinner方法的定义,补全self参数:
# 修正后的方法定义,第一个参数必须为self
def checkWinner(self, winningConditions, mark):
    global gameOver
    for condition in winningConditions:
        if board[condition[0]] == mark and board[condition[1]] == mark and board[condition[2]] == mark:
            gameOver = True
  1. 修正checkWinner的调用语句,添加self.前缀:
    把原来的checkWinner(winningConditions, mark)改为self.checkWinner(winningConditions, mark)
  2. 修正place方法的缩进逻辑,把胜负判断、换回合的代码从for循环中移出,调整后完整的place方法参考:
@commands.command()
async def place(self, ctx: commands.Context, pos: int):
    global turn
    global player1
    global player2
    global board
    global count
    global gameOver

    if not gameOver:
        mark = ""
        if turn == ctx.author:
            if turn == player1:
                mark = ":regional_indicator_x:"
            elif turn == player2:
                mark = ":o2:"
            if 0 < pos < 10 and board[pos - 1] == ":white_large_square:" :
                board[pos - 1] = mark
                count += 1

                # 打印棋盘
                line = ""
                for x in range(len(board)):
                    if x == 2 or x == 5 or x == 8:
                        line += " " + board[x]
                        await ctx.send(line)
                        line = ""
                    else:
                        line += " " + board[x]
                
                # 校验胜负,逻辑放在for循环外
                self.checkWinner(self.winningConditions, mark)
                print(count)
                if gameOver == True:
                    await ctx.send(mark + " wins!")
                elif count >= 9:
                    gameOver = True
                    await ctx.send("It's a tie!")
                else:
                    # 交换回合
                    turn = player2 if turn == player1 else player1
                    await ctx.send(f"It is <@{turn.id}>'s turn")
            else:
                await ctx.send("Be sure to choose an integer between 1 and 9 (inclusive) and an unmarked tile.")
        else:
            await ctx.send("It is not your turn.")
    else:
        await ctx.send("Please start a new game using the !tictactoe command.")
  1. (可选优化)建议把所有全局变量替换为类的实例属性,在Cog的__init__方法中初始化,彻底避免全局污染和多服务器串数据的问题。

内容的提问来源于stack exchange,提问作者Sir Pez

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.29 13:27:01