【问题标题】:GridView of Random Colored Cards随机色卡的 GridView
【发布时间】:2021-07-16 05:42:26
【问题描述】:

我正在通过 Flutter 开发一个基本的配色游戏。规则很简单,根据用户选择的难度级别,随机生成的颜色框被带到屏幕上,每个颜色都以网格形式放置。用户必须点击的颜色和剩余时间信息将显示在屏幕的上角。每次正确点击后,网格中的所有颜色都会随机重新分配。当时间结束时,显示用户在游戏中收到的分数,并提供返回主屏幕。

但是,当我尝试在点击后随机重新分配卡片的颜色时,它只显示一种颜色,并且没有任何变化。我该如何解决这个问题?

截图

代码如下:

import 'dart:math';
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';

class MyGame extends StatefulWidget {
  final difficulty;
  final matrix;
  MyGame({Key key, this.difficulty, this.matrix}) : super(key: key);
  @override
  _MyGameState createState() =>
      _MyGameState(difficulty: this.difficulty, matrix: this.matrix);
}

class _MyGameState extends State<MyGame> {
  var difficulty;
  var matrix;
  _MyGameState({this.difficulty, this.matrix});
  int _points = 0;
  int _counter = 100;
  Timer _timer;
  void _startTimer() {
    _counter = 100;
    if (_timer != null) {
      _timer.cancel();
    }
    _timer = Timer.periodic(Duration(seconds: 1), (timer) {
      setState(() {
        if (_counter > 0) {
          _counter--;
        } else {
          _timer.cancel();

          showDialog(
            context: context,
            builder: (BuildContext context) {
              return AlertDialog();
            },
          );
        }
      });
    });
  }

  /*RANDOM COLORS */
  Random random = Random();
  int colorindex = 0;
  void changeIndex() {
    setState(() => colorindex = random.nextInt(Colors.primaries.length));
  }

  Color getrandom = Colors.primaries[Random().nextInt(Colors.primaries.length)];
  Color selection = Colors.primaries[Random().nextInt(Colors.primaries.length)];

  @override
  void initState() {
    _startTimer();
    changeIndex();
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
          elevation: 0.0,
          title: Text(
            '$difficulty',
            style: TextStyle(
              color: Colors.white,
              fontSize: 32.0,
              fontWeight: FontWeight.w700,
            ),
          ),
          centerTitle: true,
          backgroundColor: Colors.transparent),
      backgroundColor: Colors.primaries[colorindex],
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            Padding(
              padding: const EdgeInsets.fromLTRB(64, 114, 64, 0),
              child: Column(children: [
                Column(
                  children: [
                    Row(
                      mainAxisAlignment: MainAxisAlignment.spaceBetween,
                      children: [
                        Expanded(
                          child: Card(
                            shape: RoundedRectangleBorder(
                                borderRadius: BorderRadius.circular(15.0)),
                            elevation: 25.0,
                            child: SizedBox(
                              width: 124,
                              child: Padding(
                                padding: const EdgeInsets.all(8.0),
                                child: Column(
                                  children: <Widget>[
                                    Text(
                                      '$_counter',
                                      style: TextStyle(fontSize: 24),
                                    ),
                                    Text(
                                      "Seconds Left",
                                      style: TextStyle(fontSize: 12),
                                    ),
                                  ],
                                ),
                              ),
                            ),
                          ),
                        ),
                        Expanded(
                          child: Card(
                            shape: RoundedRectangleBorder(
                                borderRadius: BorderRadius.circular(15.0)),
                            elevation: 25.0,
                            child: SizedBox(
                              width: 124,
                              child: Padding(
                                padding: const EdgeInsets.all(8.0),
                                child: Column(
                                  children: [
                                    Text(
                                      '$_points',
                                      style: TextStyle(fontSize: 24),
                                    ),
                                    Text("Score",
                                        style: TextStyle(fontSize: 12)),
                                  ],
                                ),
                              ),
                            ),
                          ),
                        ),
                      ],
                    )
                  ],
                ),
                Card(
                  shape: RoundedRectangleBorder(
                      borderRadius: BorderRadius.circular(15.0)),
                  child: Padding(
                    padding: const EdgeInsets.all(12.0),
                    child: Column(
                      children: [
                        Row(
                          mainAxisAlignment: MainAxisAlignment.spaceBetween,
                          children: [
                            Text("Pick this!"),
                            Icon(Icons.play_arrow_outlined),
                            Card(
                                child: SizedBox(
                                  width: 50,
                                  height: 50,
                                ),
                                color: getrandom)
                          ],
                        )
                      ],
                    ),
                  ),
                  elevation: 25.0,
                )
              ]),
            ),
            Expanded(
              child: Padding(
                padding: const EdgeInsets.fromLTRB(48, 26, 48, 52),
                child: Card(
                  color: Colors.white,
                  shape: RoundedRectangleBorder(
                    borderRadius: BorderRadius.circular(15.0),
                  ),
                  elevation: 25.0,
                  child: Padding(
                    padding: const EdgeInsets.all(8.0),
                    child: Center(
                      child: GridView.builder(
                        physics: NeverScrollableScrollPhysics(),
                        shrinkWrap: true,
                        gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
                          crossAxisCount: matrix,
                          childAspectRatio: 1.0,
                          mainAxisSpacing: 1.0,
                          crossAxisSpacing: 1.0,
                        ),
                        itemCount: matrix * matrix,
                        itemBuilder: (context, index) {
                          return GestureDetector(
                            onTap: () {
                              if (selection == getrandom) {
                                HapticFeedback.vibrate();
                                _points++;
                                changeIndex(); // 1) It does not change colors on tap
                              }
                            },
                            child: Card(
                              clipBehavior: Clip.antiAlias,
                              child: Container(
                                color: selection, // 2) Not initialized randomly
                                //P.S: If I use Colors.primaries[Random().nextInt(Colors.primaries.length)]
                                //instead of selection. It works but conflicts with timer, changes every seconds
                              ),
                            ),
                          );
                        },
                      ),
                    ),
                  ),
                ),
              ),
            ),
          ],
        ),
      ),
    );
  }
}

【问题讨论】:

    标签: android flutter dart


    【解决方案1】:

    你需要...

    1. 请勿在initState() 中调用setState(...)
    2. 随机化每个网格颜色。参考_gridColors
    3. 每个正确答案的答案颜色随机化。参考_answer
    4. 单独的倒计时小部件。参考CountdownCard

    样品...

    class MyGame extends StatefulWidget {
      const MyGame({
        required this.difficulty,
        required this.matrix,
        Key? key,
      }) : super(key: key);
    
      final String difficulty;
      final int matrix;
    
      @override
      _MyGameState createState() => _MyGameState();
    }
    
    class _MyGameState extends State<MyGame> {
      final List<Color> _gridColors = <Color>[];
      final Random _random = Random();
    
      late Color _answer;
    
      int _points = 0;
    
      @override
      void initState() {
        super.initState();
        _initColors();
      }
    
      ///
      void _initColors() {
        _gridColors.clear();
        _answer = _randomColor;
        _gridColors.add(_answer);
    
        while (_gridColors.length < widget.matrix * widget.matrix) {
          final Color gridColor = _randomColor;
    
          if (!_gridColors.contains(gridColor)) {
            _gridColors.add(gridColor);
          }
        }
    
        _gridColors.shuffle();
      }
    
      ///
      void _changeIndex() => setState(_initColors);
    
      ///
      Color get _randomColor =>
          Colors.primaries[_random.nextInt(Colors.primaries.length)];
    
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          backgroundColor: _answer,
          appBar: _buildAppBar(),
          body: Center(
            child: Column(
              mainAxisAlignment: MainAxisAlignment.center,
              children: [
                Padding(
                  padding: const EdgeInsets.fromLTRB(64, 114, 64, 0),
                  child: Column(children: [
                    Row(
                      mainAxisAlignment: MainAxisAlignment.spaceBetween,
                      children: [
                        Expanded(
                          child: Card(
                            shape: RoundedRectangleBorder(
                              borderRadius: BorderRadius.circular(15.0),
                            ),
                            elevation: 25.0,
                            child: CountdownCard(() {
                              showDialog(
                                context: context,
                                builder: (BuildContext context) {
                                  return AlertDialog();
                                },
                              );
                            }),
                          ),
                        ),
                        Expanded(
                          child: Card(
                            shape: RoundedRectangleBorder(
                              borderRadius: BorderRadius.circular(15.0),
                            ),
                            elevation: 25.0,
                            child: SizedBox(
                              width: 124,
                              child: Padding(
                                padding: const EdgeInsets.all(8.0),
                                child: Column(
                                  children: [
                                    Text(
                                      _points.toString(),
                                      style: const TextStyle(fontSize: 24),
                                    ),
                                    const Text(
                                      "Score",
                                      style: TextStyle(fontSize: 12),
                                    ),
                                  ],
                                ),
                              ),
                            ),
                          ),
                        ),
                      ],
                    ),
                    Card(
                      shape: RoundedRectangleBorder(
                        borderRadius: BorderRadius.circular(15.0),
                      ),
                      child: Padding(
                        padding: const EdgeInsets.all(12.0),
                        child: Column(
                          children: [
                            Row(
                              mainAxisAlignment: MainAxisAlignment.spaceBetween,
                              children: [
                                const Text("Pick this!"),
                                const Icon(Icons.play_arrow_outlined),
                                Card(
                                  child: const SizedBox(
                                    width: 50,
                                    height: 50,
                                  ),
                                  color: _answer,
                                ),
                              ],
                            ),
                          ],
                        ),
                      ),
                      elevation: 25.0,
                    ),
                  ]),
                ),
                Expanded(
                  child: Padding(
                    padding: const EdgeInsets.fromLTRB(48, 26, 48, 52),
                    child: Card(
                      color: Colors.white,
                      shape: RoundedRectangleBorder(
                        borderRadius: BorderRadius.circular(15.0),
                      ),
                      elevation: 25.0,
                      child: Padding(
                        padding: const EdgeInsets.all(8.0),
                        child: Center(
                          child: GridView.builder(
                            physics: NeverScrollableScrollPhysics(),
                            shrinkWrap: true,
                            gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
                              crossAxisCount: widget.matrix,
                              childAspectRatio: 1.0,
                              mainAxisSpacing: 1.0,
                              crossAxisSpacing: 1.0,
                            ),
                            itemCount: _gridColors.length,
                            itemBuilder: (context, index) {
                              return GestureDetector(
                                onTap: () {
                                  if (_gridColors[index] == _answer) {
                                    HapticFeedback.vibrate();
                                    _points++;
                                    _changeIndex();
                                  }
                                },
                                child: Card(
                                  clipBehavior: Clip.antiAlias,
                                  child: Container(
                                    color: _gridColors[index],
                                  ),
                                ),
                              );
                            },
                          ),
                        ),
                      ),
                    ),
                  ),
                ),
              ],
            ),
          ),
        );
      }
    
      ///
      AppBar _buildAppBar() => AppBar(
            elevation: 0.0,
            title: Text(
              widget.difficulty,
              style: const TextStyle(
                color: Colors.white,
                fontSize: 32.0,
                fontWeight: FontWeight.w700,
              ),
            ),
            centerTitle: true,
            backgroundColor: Colors.transparent,
          );
    }
    
    class CountdownCard extends StatefulWidget {
      CountdownCard(this.onTime);
    
      final VoidCallback onTime;
    
      @override
      _CountdownCardState createState() => _CountdownCardState();
    }
    
    class _CountdownCardState extends State<CountdownCard> {
      late Timer _timer;
      late int _counter;
    
      @override
      void initState() {
        super.initState();
        _startTimer();
      }
    
      @override
      Widget build(BuildContext context) {
        return SizedBox(
          width: 124,
          child: Padding(
            padding: const EdgeInsets.all(8.0),
            child: Column(
              children: <Widget>[
                Text(
                  _counter.toString(),
                  style: const TextStyle(fontSize: 24),
                ),
                const Text(
                  'Seconds Left',
                  style: TextStyle(fontSize: 12),
                ),
              ],
            ),
          ),
        );
      }
    
      ///
      void _startTimer() {
        _counter = 100;
    
        _timer = Timer.periodic(
          const Duration(seconds: 1),
          (Timer timer) {
            if (_counter > 0) {
              setState(() => _counter--);
              return;
            }
    
            _timer.cancel();
            widget.onTime();
          },
        );
      }
    }
    

    【讨论】:

      猜你喜欢
      • 2014-09-08
      • 2016-09-23
      • 2018-03-18
      • 1970-01-01
      • 2018-03-22
      • 1970-01-01
      • 1970-01-01
      • 2012-08-02
      • 1970-01-01
      相关资源
      最近更新 更多