Flutter随机灯光变色、状态记录与按键验证实现问题咨询
解决方案:实现随机亮灯与按键验证功能
核心问题分析
randomLights方法数组越界错误:直接对空数组ans使用下标赋值会触发异常,需先添加元素。- 未维护亮灯状态:状态类中未保存选中灯光ID和对应颜色,无法驱动UI更新。
- 全局变量滥用:计时器等全局变量易导致状态混乱,应移至状态类内部。
- 重复代码冗余:8个按钮与灯光组件代码重复,可通过循环生成简化。
- 按键验证逻辑缺失:未判断玩家点击的按钮是否对应亮灯。
修改后的完整代码
import 'dart:math'; import 'package:flutter/material.dart'; import 'globals.dart' as globals; void main() { runApp(const MyApp()); } class MyApp extends StatelessWidget { const MyApp({Key? key}) : super(key: key); @override Widget build(BuildContext context) { return MaterialApp( debugShowCheckedModeBanner: false, home: const LBulb(), ); } } class LBulb extends StatefulWidget { const LBulb({super.key}); @override State<LBulb> createState() => _LBulbState(); } class _LBulbState extends State<LBulb> { final Stopwatch _stopwatchD = Stopwatch(); final Stopwatch _stopwatchR = Stopwatch(); int _gameVersion = 0; List<int> _selectedLights = []; List<Color> _lightColors = List.filled(8, Colors.white); @override void initState() { _gameVersion = _oneOrThree(); super.initState(); } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( backgroundColor: Colors.blue[600]?.withOpacity(0.5), ), body: Container( decoration: const BoxDecoration( image: DecorationImage( image: AssetImage("assets/images/background2.png"), fit: BoxFit.cover), ), child: Column( crossAxisAlignment: CrossAxisAlignment.center, children: [ const SizedBox(height: 60), const Text( "请点击对应亮灯的按钮", textAlign: TextAlign.center, style: TextStyle( color: Colors.black, fontSize: 40, fontWeight: FontWeight.bold, fontFamily: 'Alkatra'), ), const SizedBox(height: 30), Center( child: Container( height: 500, width: 810, decoration: BoxDecoration( color: Colors.white, borderRadius: BorderRadius.circular(100), boxShadow: [ BoxShadow( color: Colors.black.withOpacity(0.5), offset: const Offset(7.0, 7.0), blurRadius: 10.0, ), ], ), child: screenBuilding( distance: 310.0, // 主按钮 centerButton: GestureDetector( onTapDown: (details) { _stopwatchD.start(); // 随机选灯并更新颜色 setState(() { _selectedLights = _randomLights(_gameVersion); _lightColors = List.filled(8, Colors.white); for (int lightId in _selectedLights) { _lightColors[lightId - 1] = Colors.green; } }); }, onTapUp: (details) { _stopwatchD.stop(); globals.detectionTime = _stopwatchD.elapsed; globals.detectionTimes[globals.numOfTurn] = globals.detectionTime; _stopwatchD.reset(); globals.detectionTime = const Duration(seconds: 0); globals.numOfTurn++; print(globals.detectionTimes); _stopwatchR.start(); }, child: Container( height: 20, width: 20, decoration: const BoxDecoration( color: Colors.black, borderRadius: BorderRadius.circular(500)), ), ), // 灯光对应的按钮 buttonsFirstRow: List.generate(8, (index) { int lightId = index + 1; return TextButton( onPressed: () => _onLightButtonPressed(lightId), child: Container( height: 20, width: 20, decoration: const BoxDecoration( color: Colors.black, borderRadius: BorderRadius.circular(500)), ), ); }), // 第一组4个灯光 buttonsSecondRowHalf1: List.generate(4, (index) { int lightId = index + 1; return TextButton( onPressed: () => _onLightButtonPressed(lightId), child: Container( height: 20, width: 20, decoration: BoxDecoration( color: _lightColors[index], borderRadius: BorderRadius.circular(500), border: Border.all(width: 3)), ), ); }), // 第二组4个灯光 buttonsSecondRowHalf2: List.generate(4, (index) { int lightId = index + 5; return TextButton( onPressed: () => _onLightButtonPressed(lightId), child: Container( height: 20, width: 20, decoration: BoxDecoration( color: _lightColors[index + 4], borderRadius: BorderRadius.circular(500), border: Border.all(width: 3)), ), ); }), ), ), ), ], ), ), ); } void _onLightButtonPressed(int lightId) { if (_selectedLights.contains(lightId)) { // 正确按键,停止响应计时器 _stopwatchR.stop(); globals.responseTime = _stopwatchR.elapsed; globals.responseTimes[globals.numOfTurn - 1] = globals.responseTime; _stopwatchR.reset(); print("按键正确!响应时间: ${globals.responseTime}"); // 重置状态,准备下一轮 setState(() { _lightColors = List.filled(8, Colors.white); _selectedLights.clear(); _gameVersion = _oneOrThree(); }); } else { print("按键错误,请点击亮灯对应的按钮"); } } int _oneOrThree() { final rand = Random(); return [1, 3][rand.nextInt(2)]; } List<int> _randomLights(int version) { final rand = Random(); List<int> availableLights = List.generate(8, (index) => index + 1); List<int> selected = []; if (version == 1) { selected.add(availableLights[rand.nextInt(availableLights.length)]); } else { for (int i = 0; i < 3; i++) { int randomIndex = rand.nextInt(availableLights.length); selected.add(availableLights[randomIndex]); availableLights.removeAt(randomIndex); } } return selected; } }
关键修改说明
- 状态管理优化:将计时器、选中灯光、灯光颜色移至状态类内部,避免全局变量状态混乱。
- 修复随机选灯方法:通过
add和removeAt操作数组,解决空数组下标赋值异常。 - 动态生成组件:用
List.generate循环生成按钮与灯光组件,减少重复代码。 - 按键验证逻辑:判断点击的按钮ID是否在选中列表中,正确则停止计时器并重置状态,错误则提示。
- UI实时更新:主按钮按下时通过
setState更新灯光颜色,确保UI同步刷新。
内容的提问来源于stack exchange,提问作者מאי כהן
相关产品推荐
相关产品推荐

