поэтому я разработал приложение для игры в кости во 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, но просто... Я сделаю это позже.





Ваши виджеты перестраиваются и воссоздаются при перезагрузке. Я могу придумать 2 решения:
Это очень просто. Только случайное число недостаточно для игры в кости, случайная позиция, случайный угол также очень важны. Кстати, прежде чем бросать кости, вам нужно держать кости в углу. затем дайте место со случайным вращением. Меня не волновал дизайн доски и цвет кубиков и т.д. и т.п.
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,
),
),
),
),
],
),
),
),
);
}
}
Чтобы узнать больше об этом, узнайте, как работает управление состоянием во Flutter. Лично я использую
rxdartBehaviorSubjectдля состояния и получаю состояние с помощью пакетаget_it