Как я могу поддерживать случайно сгенерированные значения при вызове setState? | Флаттер

поэтому я разработал приложение для игры в кости во Flutter. Я столкнулся с проблемой, из-за которой, когда вы поворачиваете экран (мобильное устройство), изменяете размер окна (рабочий стол), меняете количество кубиков или переключаете метку комбо, значение в каждом кубике сбрасывается до случайного значения. Я хочу, чтобы это происходило только при нажатии кнопки Roll. Ниже приведен код в файле die_row.dart:

class DieRow extends StatelessWidget {
  final int amount;
  final int _min = 1;
  final int _max = 6;
  final List<Die> _dice = [];
  final List<int> _dieValues = [];
  final List<Die> _diceSorted = [];
  final List<int> _dieValuesSorted = [];

  DieRow({this.amount = 2}) {
    for (int i = 0; i < amount; i++) {
      _dice.add(Die(
        portionOfScreen: amount,
        value: 1 + Random().nextInt(6),
      ));
      _dieValues.add(_dice[i].value);
    }

    for (int i = 0; i < _dice.length; i++) {
      _diceSorted.add(_dice[i]);
      _dieValuesSorted.add(_dice[i].value);
    }

    _diceSorted.sort();
    _dieValuesSorted.sort();

    print(_dieValues);
    print(_dieValuesSorted);
  }

  List<T> _rangeFrom<T>(List<T> list, int fromIndex, int toIndex) {
    List<T> result = [];
    for (int i = fromIndex; i <= toIndex; i++) //
      result.add(list[i]);
    return result;
  }

  bool _isPair(List<Die> dice) {
    if (dice.length == 1) return false;
    for (int i = 1; i < dice.length; i++) //
      if (dice[i].value != dice[i - 1].value) //
        return false;
    return true;
  }

  bool _isStraight(List<Die> dice) {
    if (dice.length == 1) return false;
    for (int i = 1; i < _dice.length; i++) //
      if (dice[i].value != dice[i - 1].value + 1) //
        return false;
    return true;
  }

  bool _isFullHouse(List<Die> diceSorted) {
    if (getGameType() != GameType.poker) return false;
    return (_isPair(_rangeFrom<Die>(diceSorted, 0, 2)) &&
            _isPair(_rangeFrom<Die>(diceSorted, 3, 4))) ||
        (_isPair(_rangeFrom<Die>(diceSorted, 0, 1)) &&
            _isPair(_rangeFrom<Die>(diceSorted, 2, 4)));
  }

  bool _isFourOfAKind(List<Die> diceSorted) {
    if (getGameType() != GameType.poker) return false;
    return _isPair(_rangeFrom(diceSorted, 0, 3)) ||
        _isPair(_rangeFrom(diceSorted, 1, 4));
  }

  List<Die> getDice() => _dice;

  List<int> getDieValues() => _dieValues;

  int getLength() => _dice.length;

  Combination getCombination() {
    switch (getGameType()) {
      case GameType.boardGame:
        if (_isPair(_dice)) //
          return Combination.pair;
        break;
      case GameType.poker:
        if (_isPair(_dice)) //
          return Combination.pair;
        if (_isFullHouse(_diceSorted)) //
          return Combination.fullHouse;
        if (_isFourOfAKind(_diceSorted)) //
          return Combination.fourOfAKind;
        if (_isStraight(_dice)) //
          return Combination.straight;
        break;
      default:
        if (_isPair(_dice)) //
          return Combination.pair;
    }
    return Combination.common;
  }

  GameType getGameType() {
    switch (amount) {
      case 1:
        return GameType.boardGame;
      case 2:
        return GameType.boardGame;
      case 5:
        return GameType.poker;
      case 6:
        return GameType.lottery;
      default:
        return GameType.custom;
    }
  }

  int getMin() => _min;

  int getMax() => _max;

  @override
  Widget build(BuildContext context) {
    return Row(
      mainAxisAlignment: MainAxisAlignment.center,
      children: _dice,
    );
  }
}

Ниже приведен файл die.dart, если это будет полезно:

class Die extends StatelessWidget implements Comparable {
  final int portionOfScreen;
  final int value;

  Die({@required this.portionOfScreen, this.value = 1});

  @override
  Widget build(BuildContext context) {
    return ConstrainedBox(
      constraints: BoxConstraints(
        maxWidth: MediaQuery.of(context).size.width / portionOfScreen,
        maxHeight: MediaQuery.of(context).size.height / 2.25,
      ),
      child: Padding(
        padding: EdgeInsets.symmetric(horizontal: 8),
        child: Image.asset(
          'assets/die$value.png',
        ),
      ),
    );
  }

  @override
  int compareTo(Object other) {
    return other is Die && this.value < other.value
        ? -1
        : other is Die && this.value > other.value
            ? 1
            : 0;
  }
}

И я понимаю, что происходит: setState вызывается, когда что-то меняется (особенно эти чертовы проставки). Я просто хочу знать альтернативный способ реализации этой функции динамического количества игральных костей, способных генерировать случайные значения. Но с настройками, которые у меня есть сейчас, setState запускает регенерацию случайных значений. Любая помощь?

Также я знаю, что я плохо реализовал методы isFullHouse и isFourOfAKind, но просто... Я сделаю это позже.

Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
0
296
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Ваши виджеты перестраиваются и воссоздаются при перезагрузке. Я могу придумать 2 решения:

  1. Создайте и используйте состояние, внешнее по отношению к вашему виджету.
  2. Если # 1 не помогает, есть пакет, который, похоже, создан для этого. Это называется Родное государство.

Чтобы узнать больше об этом, узнайте, как работает управление состоянием во Flutter. Лично я использую rxdartBehaviorSubject для состояния и получаю состояние с помощью пакета get_it

rasuru 11.12.2020 17:33

Это очень просто. Только случайное число недостаточно для игры в кости, случайная позиция, случайный угол также очень важны. Кстати, прежде чем бросать кости, вам нужно держать кости в углу. затем дайте место со случайным вращением. Меня не волновал дизайн доски и цвет кубиков и т.д. и т.п.

 import 'package:flutter/material.dart';
import 'dart:math' as math;

class DiceChange extends StatefulWidget {
  @override
  State<DiceChange> createState() => _DiceChangeState();
}

class _DiceChangeState extends State<DiceChange> {
  List<int> Dice = [
    1,
    2,
    3,
    4,
    5,
    6,
  ];

  List<int> rotate = [
    15,
    20,
    25,
    30,
    40,
    45,
    60,
    65,
    85,
    95,
    105,
    115,
    125,
    135,
    145,
    165,
  ];

  bool isRotated = false;

  int index = 0;
  int index2 = 4;
  int index3 = 6;

  int dice1Index = 0;
  int dice2Index = 0;
  int dice3Index = 0;

  void rotateBox(BuildContext context) {
    setState(() {
      dice3Index = math.Random().nextInt(Dice.length);
      dice2Index = math.Random().nextInt(Dice.length);
      dice1Index = math.Random().nextInt(Dice.length);
      index = math.Random().nextInt(rotate.length);
      index2 = math.Random().nextInt(rotate.length);
      index3 = math.Random().nextInt(rotate.length);
      isRotated = true;
    });
  }

  @override
  Widget build(BuildContext context) {
    return Card(
      color: Colors.black54,
      child: InkWell(
        onTap: () {
          rotateBox(context);
        },
        child: Container(
          height: 350,
          width: 350,
          child: Column(
            mainAxisAlignment: isRotated
                ? MainAxisAlignment.spaceEvenly
                : MainAxisAlignment.end,
            children: [
              Row(
                mainAxisAlignment: isRotated
                    ? MainAxisAlignment.spaceEvenly
                    : MainAxisAlignment.end,
                children: [
                  RotationTransition(
                    turns: AlwaysStoppedAnimation(rotate[index] / 360),
                    child: Container(
                      color: Colors.grey,
                      width: 100,
                      height: 100,
                      child: Center(
                        child: Text(
                          '${Dice[dice1Index]}',
                          textAlign: TextAlign.center,
                        ),
                      ),
                    ),
                  ),
                  RotationTransition(
                    turns: AlwaysStoppedAnimation(rotate[index2] / 360),
                    child: Container(
                      color: Colors.grey,
                      width: 100,
                      height: 100,
                      child: Center(
                        child: Text(
                          '${Dice[dice2Index]}',
                          textAlign: TextAlign.center,
                        ),
                      ),
                    ),
                  ),
                ],
              ),
              RotationTransition(
                turns: AlwaysStoppedAnimation(rotate[index3] / 360),
                child: Container(
                  color: Colors.grey,
                  width: 100,
                  height: 100,
                  child: Center(
                    child: Text(
                      '${Dice[dice3Index]}',
                      textAlign: TextAlign.center,
                    ),
                  ),
                ),
              ),
            ],
          ),
        ),
      ),
    );
  }
}

Другие вопросы по теме