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

Flutter实现国际象棋坐标训练:计时器与循环逻辑求助

解决方案

因为需要维护倒计时、分数、目标坐标这些可变状态,首先要把ChessBoard从StatelessWidget改成StatefulWidget,以下是完整的实现代码:

class BoardWhite extends StatelessWidget {
  const BoardWhite({super.key});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Chess Coordinates'),
      ),
      body: const ChessBoard(),
    );
  }
}

class ChessBoard extends StatefulWidget {
  const ChessBoard({super.key});

  @override
  State<ChessBoard> createState() => _ChessBoardState();
}

class _ChessBoardState extends State<ChessBoard> {
  int remainingTime = 30;
  int score = 0;
  String targetCoordinate = '';
  Timer? countdownTimer;

  @override
  void initState() {
    super.initState();
    // 初始化时生成第一个目标坐标并启动倒计时
    generateRandomCoordinate();
    startCountdown();
  }

  @override
  void dispose() {
    // 页面销毁时取消计时器,避免内存泄漏
    countdownTimer?.cancel();
    super.dispose();
  }

  void startCountdown() {
    countdownTimer = Timer.periodic(const Duration(seconds: 1), (timer) {
      setState(() {
        if (remainingTime > 0) {
          remainingTime--;
        } else {
          timer.cancel();
        }
      });
    });
  }

  void generateRandomCoordinate() {
    // 生成随机列(A-H)和随机行(1-8)
    final random = Random();
    final column = String.fromCharCode('A'.codeUnitAt(0) + random.nextInt(8));
    final row = random.nextInt(8) + 1;
    setState(() {
      targetCoordinate = '$column$row';
    });
  }

  void handleTileTap(String coordinate) {
    if (remainingTime <= 0) return; // 时间到了不处理点击

    if (coordinate == targetCoordinate) {
      setState(() {
        score++;
      });
      generateRandomCoordinate(); // 正确后刷新目标坐标
    }
    // 错误点击不做计分处理
  }

  @override
  Widget build(BuildContext context) {
    return Center(
      child: Column(
        mainAxisAlignment: MainAxisAlignment.center,
        children: [
          // 计时器和分数显示
          Text(
            '剩余时间: $remainingTime 秒 | 得分: $score',
            style: const TextStyle(fontSize: 18, fontWeight: FontWeight.bold),
          ),
          const SizedBox(height: 15),
          // 目标坐标显示
          Text(
            '请点击: $targetCoordinate',
            style: const TextStyle(fontSize: 24, color: Colors.blue),
          ),
          const SizedBox(height: 15),
          // 列标签
          Row(
            mainAxisAlignment: MainAxisAlignment.spaceAround,
            children: List.generate(8, (index) {
              return Container(
                width: 30,
                height: 30,
                alignment: Alignment.center,
                child: Text(
                  String.fromCharCode('A'.codeUnitAt(0) + index),
                  style: const TextStyle(fontSize: 20),
                ),
              );
            }),
          ),
          const SizedBox(height: 10),
          // 棋盘网格
          SizedBox(
            width: 300.0,
            height: 300.0,
            child: GridView.builder(
              physics: const NeverScrollableScrollPhysics(), // 禁止滚动,避免布局问题
              gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
                crossAxisCount: 8,
              ),
              itemBuilder: (context, index) {
                final row = index ~/ 8;
                final col = index % 8;
                // 转换为白方视角的坐标(行是8-1)
                final coordinate = '${String.fromCharCode('A'.codeUnitAt(0) + col)}${8 - row}';

                return GestureDetector(
                  onTap: () => handleTileTap(coordinate),
                  child: Container(
                    color: (row + col) % 2 == 0 ? Colors.white : Colors.green,
                    // 可选:给目标坐标的格子加个高亮
                    decoration: coordinate == targetCoordinate && remainingTime > 0
                        ? BoxDecoration(
                            border: Border.all(color: Colors.red, width: 2),
                          )
                        : null,
                  ),
                );
              },
            ),
          ),
        ],
      ),
    );
  }
}

关键逻辑说明

  • 状态管理:用StatefulWidget维护remainingTime(剩余时间)、score(得分)、targetCoordinate(当前目标坐标)三个核心状态,通过setState()触发UI更新,这是Flutter中更新界面的标准方式,类似C++中手动刷新UI的逻辑,但Flutter会自动处理局部重绘。
  • 倒计时实现:使用Timer.periodic每秒触发一次回调,更新剩余时间,时间归零时取消计时器。注意在dispose()中销毁计时器,避免内存泄漏。
  • 随机坐标生成:通过Random类生成0-7的随机数,转换为A-H的列和1-8的行,组合成目标坐标。
  • 点击验证:点击棋盘格子时,将格子坐标与目标坐标对比,正确则加分并生成新的目标坐标,错误则无操作;时间结束后不再响应点击。
  • UI优化:添加了禁止棋盘滚动的设置(NeverScrollableScrollPhysics),避免GridView滚动导致的布局偏移;可选给目标格子添加红色边框高亮,提升用户体验。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.09 13:05:13