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

CS50 AI井字棋Minimax算法实现中索引类型错误求助

CS50 AI井字棋作业运行错误排查

我在完成CS50 AI课程的井字棋作业时,需要用Minimax算法实现游戏,同时编写生成可行操作及新棋盘状态的函数,但代码运行时出现以下错误:

File "c:\Users\Melisa\OneDrive\Desktop\tictactoe\tictactoe.py", line 40, in result
kopja[i][j] = player(board)
TypeError: list indices must be integers or slices, not tuple

我尝试将集合中的元组拆分作为棋盘数组的索引(i,j = action[0],action[1]),但该方案未解决问题。

我的实现代码

import copy
import math

X = "X"
O = "O"
EMPTY = None

def initial_state():
    return [[EMPTY, EMPTY, EMPTY],
            [EMPTY, EMPTY, EMPTY],
            [EMPTY, EMPTY, EMPTY]]

def player(board):
    Xc= 0
    Oc= 0
    for i in board:
        for j in i:
            if j == X:
                Xc+=1
            if j == O:
                Oc+=1
    # 先手为X
    if Xc>Oc:
        return O
    else:
        return X

def actions(board):
    possible= set()
    for i in range(0,len(board)):
        for j in range(len(board[0])):
            if board[i][j]== EMPTY:
                possible.add((i,j))
    return possible

def result(board, action):
    kopja = copy.deepcopy(board)
    i,j = action[0],action[1]

    kopja[i][j] = player(board)
    return kopja

def winner(board):
    # 手动列举所有获胜情况
    # 横向获胜:行索引变化,列索引固定为0、1、2
    for e in range(3):
        if board[e][0]==board[e][1]==board[e][2] and board[e][0] != EMPTY:
            winneri = board[0][e]
        # 对角线获胜
        if (board[0][0]==board[1][1]==board[2][2] or board[0][2]==board[1][1]==board[2][0])and board[1][1]!=EMPTY:
            winneri= board[1][1]
        else:
            winneri= None

    return winneri

def terminal(board):  
    if winner(board) == X or winner(board) == O:
        return True 
    for i in range(3):
        for j in range(3):
            if board[i][j] == EMPTY:
                return False
        return True

def utility(board):
    if winner(board)== X:
        return 1
    if winner(board)== O:
        return -1
    else:
        return 0

def maxval(board):
    if terminal(board): 
        return utility(board)
    else:
        v = float('-inf')
        for action in actions(board):
            v = max(v,minval(result(board,action)))
        return v

def minval(board):
    if terminal(board):
        return utility(board)
    else:
        v = float('inf')
        for action in actions(board):
            v = min(v,maxval(result(board,action)))
        return v

def minimax(board):
    if terminal(board):
        return None 
    else:
        listx=[]
        if player(board) == X:
            for action in actions(board):
                listx.append((minval(result(board,action)),action))
                listx.reverse()
                listi=listx
            return listi[0]

        if player(board) == O:
            listo=[]
            for action in actions(board):
                listo.append((maxval(result(board,action)),action))
                listo.reverse()
                lista=listo
            return lista[0]

课程提供的运行代码

import pygame
import sys
import time

import tictactoe as ttt

pygame.init()
size = width, height = 600, 400


black = (0, 0, 0)
white = (255, 255, 255)

screen = pygame.display.set_mode(size)

mediumFont = pygame.font.Font("OpenSans-Regular.ttf", 28)
largeFont = pygame.font.Font("OpenSans-Regular.ttf", 40)
moveFont = pygame.font.Font("OpenSans-Regular.ttf", 60)

user = None
board = ttt.initial_state()
ai_turn = False

while True:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            sys.exit()

    screen.fill(black)

    # 让用户选择玩家身份
    if user is None:

        # 绘制标题
        title = largeFont.render("Play Tic-Tac-Toe", True, white)
        titleRect = title.get_rect()
        titleRect.center = ((width / 2), 50)
        screen.blit(title, titleRect)

        # 绘制按钮
        playXButton = pygame.Rect((width / 8), (height / 2), width / 4, 50)
        playX = mediumFont.render("Play as X", True, black)
        playXRect = playX.get_rect()
        playXRect.center = playXButton.center
        pygame.draw.rect(screen, white, playXButton)
        screen.blit(playX, playXRect)

        playOButton = pygame.Rect(5 * (width / 8), (height / 2), width / 4, 50)
        playO = mediumFont.render("Play as O", True, black)
        playORect = playO.get_rect()
        playORect.center = playOButton.center
        pygame.draw.rect(screen, white, playOButton)
        screen.blit(playO, playORect)

        # 检测按钮点击
        click, _, _ = pygame.mouse.get_pressed()
        if click == 1:
            mouse = pygame.mouse.get_pos()
            if playXButton.collidepoint(mouse):
                time.sleep(0.2)
                user = ttt.X
            elif playOButton.collidepoint(mouse):
                time.sleep(0.2)
                user = ttt.O

    else:

        # 绘制游戏棋盘
        tile_size = 80
        tile_origin = (width / 2 - (1.5 * tile_size),
                       height / 2 - (1.5 * tile_size))
        tiles = []
        for i in range(3):
            row = []
            for j in range(3):
                rect = pygame.Rect(
                    tile_origin[0] + j * tile_size,
                    tile_origin[1] + i * tile_size,
                    tile_size, tile_size
                )
                pygame.draw.rect(screen, white, rect, 3)

                if board[i][j] != ttt.EMPTY:
                    move = moveFont.render(board[i][j], True, white)
                    moveRect = move.get_rect()
                    moveRect.center = rect.center
                    screen.blit(move, moveRect)
                row.append(rect)
            tiles.append(row)

        game_over = ttt.terminal(board)
        player = ttt.player(board)

        # 显示标题
        if game_over:
            winner = ttt.winner(board)
            if winner is None:
                title = f"Game Over: Tie."
            else:
                title = f"Game Over: {winner} wins."
        elif user == player:
            title = f"Play as {user}"
        else:
            title = f"Computer thinking..."
        title = largeFont.render(title, True, white)
        titleRect = title.get_rect()
        titleRect.center = ((width / 2), 30)
        screen.blit(title, titleRect)

        # AI回合处理
        if user != player and not game_over:
            if ai_turn:
                time.sleep(0.5)
                move = ttt.minimax(board)
                board = ttt.result(board, move)
                ai_turn = False
            else:
                ai_turn = True

        # 用户回合处理
        click, _, _ = pygame.mouse.get_pressed()
        if click == 1 and user == player and not game_over:
            mouse = pygame.mouse.get_pos()
            for i in range(3):
                for j in range(3):
                    if (board[i][j] == ttt.EMPTY and tiles[i][j].collidepoint(mouse)):
                        board = ttt.result(board, (i, j))

        # 游戏结束后显示重玩按钮
        if game_over:
            againButton = pygame.Rect(width / 3, height - 65, width / 3, 50)
            again = mediumFont.render("Play Again", True, black)
            againRect = again.get_rect()
            againRect.center = againButton.center
            pygame.draw.rect(screen, white, againButton)
            screen.blit(again, againRect)
            click, _, _ = pygame.mouse.get_pressed()
            if click == 1:
                mouse = pygame.mouse.get_pos()
                if againButton.collidepoint(mouse):
                    time.sleep(0.2)
                    user = None
                    board = ttt.initial_state()
                    ai_turn = False

    pygame.display.flip()

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.03 12:40:43