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

Dart实现Minimax算法的井字棋AI出现错误决策求助

问题描述

我用Dart实现了基于Minimax算法的井字棋程序,电脑以“O”方身份尝试最大化得分,但出现错误决策。例如AI建议落子(0,2),但这并非正确决策。当前棋盘状态如下:
井字棋棋盘状态

代码实现
class Ai {
  play(state) {
    return max_Value(state);
  }


  // action参数记录到达当前状态的落子位置
  List max_Value(List state, {action}) {
    List v = [null, double.negativeInfinity];

    if (terminal(state)) {
      return [action, utility(state)];
    }

    for (var action in actions(state)) {
      if (v[1] == 1) return v;
      v = max(v, min_Value(result(state, action), action: action));
    }
    return v;
  }

  List min_Value(List state, {action}) {
    List v = [null, double.infinity];

    if (terminal(state)) {
      return [action, utility(state)];
    }

    for (var action in actions(state)) {
      if (v[1] == -1) return v;
      v = min(v, max_Value(result(state, action), action: action));
    }
    return v;
  }

  List min(List prv, List curr) {
    return prv[1] < curr[1] ? prv : curr;
  }

  List max(List prv, List curr) {
    return prv[1] > curr[1] ? prv : curr;
  }

  bool terminal(List state) {
    // 检查横向获胜
    if (state[0][0] == state[0][1] &&
        state[0][0] == state[0][2] &&
        state[0][0] != "") {
      return true;
    }
    if (state[1][0] == state[1][1] &&
        state[1][0] == state[1][2] &&
        state[1][0] != "") {
      return true;
    }
    if (state[2][0] == state[2][1] &&
        state[2][0] == state[2][2] &&
        state[2][0] != "") {
      return true;
    }

    // 检查纵向获胜
    if (state[0][0] == state[1][0] &&
        state[0][0] == state[2][0] &&
        state[0][0] != "") {
      return true;
    }
    if (state[0][1] == state[1][1] &&
        state[0][1] == state[2][1] &&
        state[0][1] != "") {
      return true;
    }
    if (state[0][2] == state[1][2] &&
        state[0][2] == state[2][2] &&
        state[0][2] != "") {
      return true;
    }

    // 检查对角线获胜
    if (state[0][0] == state[1][1] &&
        state[2][2] == state[0][0] &&
        state[0][0] != "") {
      return true;
    }

    if (state[2][0] == state[1][1] &&
        state[2][0] == state[0][2] &&
        state[2][0] != "") {
      return true;
    }

    // 检查棋盘是否填满
    for (int i = 0; i < 3; i++) {
      for (int j = 0; j < 3; j++) {
        if (state[i][j] == "") {
          return false;
        }
      }
    }
    return true;
  }

  double utility(List state) {
    String winner = "";
    // 横向判断胜者
    if (state[0][0] == state[0][1] && state[0][0] == state[0][2]) {
      winner = state[0][0];
    }
    if (state[1][0] == state[1][1] && state[1][0] == state[1][2]) {
      winner = state[1][0];
    }
    if (state[2][0] == state[2][1] && state[2][0] == state[2][2]) {
      winner = state[2][0];
    }

    // 纵向判断胜者
    if (state[0][0] == state[1][0] && state[0][0] == state[2][0]) {
      winner = state[0][0];
    }
    if (state[0][1] == state[1][1] && state[0][1] == state[2][1]) {
      winner = state[0][1];
    }
    if (state[0][2] == state[1][2] && state[0][2] == state[2][2]) {
      winner = state[0][2];
    }

    // 对角线判断胜者
    if (state[0][0] == state[1][1] && state[2][2] == state[0][0]) {
      winner = state[0][0];
    }

    if (state[2][0] == state[1][1] && state[2][0] == state[0][2]) {
      winner = state[2][0];
    }

    // 返回对应效用值
    if (winner == "O") {
      return 1;
    } else if (winner == "X") {
      return -1;
    } else {
      return 0;
    }
  }

  List actions(List state) {
    List acs = [];
    // 收集所有空位置作为可行落子
    for (int i = 0; i < 3; i++) {
      for (int j = 0; j < 3; j++) {
        if (state[i][j] == "") {
          acs.add([i, j]);
        }
      }
    }
    return acs;
  }

  List result(List state, List action) {
    // 复制当前棋盘状态
    List newState = [
      ["", "", ""],
      ["", "", ""],
      ["", "", ""]
    ];
    for (int i = 0; i < 3; i++) {
      for (int j = 0; j < 3; j++) {
        newState[i][j] = state[i][j];
      }
    }
    // 在新状态中执行落子
    newState[action[0]][action[1]] = player(state);
    return newState;
  }

  player(List state) {
    int xnum = 0;
    int onum = 0;
    // 统计双方落子数量
    for (int i = 0; i < 3; i++) {
      for (int j = 0; j < 3; j++) {
        if (state[i][j] == "X") {
          xnum++;
        } else if (state[i][j] == "O") {
          onum++;
        }
      }
    }
    // 判断当前回合玩家
    if (xnum > onum) {
      return "O";
    } else {
      return "X";
    }
  }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.11 00:35:17