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

Dart空安全迁移问题:Connect Four游戏分数列表赋值报错

Dart空安全迁移:Connect Four游戏分数列表修复方案

我有一款未启用空安全时正常运行的Connect Four游戏,迁移到Dart空安全模式时遇到两个核心问题:

  • 原代码中scores[i] = null;无法在List<double>类型上使用,删除该语句会导致CPU在必败场景冻结
  • 改为List<double?>后,scores[i] +=/scores[i] -=操作报错,且_getBestScoreIndex方法中分数的非空判断和大小比较无法正常执行

核心修复思路

  1. 保留List<double?>类型存储分数,用null标记无效列(无法落子的列)
  2. 对有效列的分数提前初始化默认值,确保执行+=/-=时变量非null
  3. 在分数比较逻辑中明确处理null值,仅对有效分数进行判断

修改后的完整代码

int _compute(Board board, int step, int deepness, List<double?> scores) {
  for (var i = 0; i < 7; ++i) {
    final boardCopy = board.clone();
    final target = boardCopy.getColumnTarget(i);
    
    if (target == -1) {
      scores[i] = null;  // 标记无效列
      continue;
    }

    // 初始化有效列的分数为0.0(避免null导致运算符报错)
    if (scores[i] == null) {
      scores[i] = 0.0;
    }

    final coordinate = Coordinate(i, target);
    boardCopy.setBox(coordinate, player);
    
    if (boardCopy.checkWinner(coordinate, player)) {
      // 非空断言:逻辑上此处scores[i]已初始化,不可能为null
      scores[i]! += deepness / (step + 1);
      continue;
    }

    for (var j = 0; j < 7; ++j) {
      final targetJ = boardCopy.getColumnTarget(j);
      if (targetJ == -1) {
        continue;
      }

      final coordinateJ = Coordinate(j, targetJ);
      boardCopy.setBox(coordinateJ, otherPlayer);
      
      if (boardCopy.checkWinner(coordinateJ, otherPlayer)) {
        // 非空断言:同上,此处scores[i]已初始化
        scores[i]! -= deepness / (step + 1);
        continue;
      }

      if (step + 1 < deepness) {
        _compute(board, step + 1, deepness, scores);
      }
    }
  }

  return _getBestScoreIndex(scores);
}

int _getBestScoreIndex(List<double?> scores) {
  // 找到第一个有效分数的索引
  int bestScoreIndex = scores.indexWhere((s) => s != null);
  // 防御性处理:如果所有分数都是null(理论上不会出现)
  if (bestScoreIndex == -1) return 0;

  scores.asMap().forEach((index, score) {
    // 仅处理有效分数,且确保当前最佳分数非null
    if (score != null && scores[bestScoreIndex] != null) {
      final currentBest = scores[bestScoreIndex]!;
      if (score > currentBest || (score == currentBest && _random.nextBool())) {
        bestScoreIndex = index;
      }
    }
  });
  return bestScoreIndex;
}

关键修复点说明

  • 分数初始化:在处理有效列时,先检查并初始化scores[i]为0.0,避免后续运算符操作时遇到null
  • 非空断言!:在执行+=/-=时,利用逻辑判断(target != -1且已初始化)确保scores[i]非null,用!明确告知编译器此处变量不可能为null
  • 分数比较逻辑:在_getBestScoreIndex中,增加对scores[bestScoreIndex]的非空判断,仅对两个非null分数进行大小比较,避免空安全报错

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.11 01:15:52