import 'package:flutter/material.dart'; import 'package:super_tic_tac_toe/game.dart'; import 'package:super_tic_tac_toe/state.dart'; import 'package:super_tic_tac_toe/util.dart'; class SuperGame extends StatefulWidget { const SuperGame({super.key}); @override State createState() => _SuperGameState(); } class _SuperGameState extends State { TTCState turn = TTCState.x; List> data = Util.emptyBoardSuper; TTCState subGameWinner(int index) => Util.checkWin(data[index]); List get subGameWinners => data.map(Util.checkWin).toList(); bool subGameEnded(int i) => subGameWinner(i) != TTCState.empty; TTCState get winner => Util.checkWin(subGameWinners); bool gameEnded() => winner != TTCState.empty; int nextPlay = -1; void _swapTurn() => turn = Util.nextTurn(turn); bool _checkValidChoice(List game, int index) => game[index] == TTCState.empty; void Function(int) subGameCellOnTapCallback(int subGame) { return (int i) { if (!_checkValidChoice(data[subGame], i)) { showDialog( context: context, builder: (context) => AlertDialog( content: Text("${data[subGame][i].name.toUpperCase()}" " already claimed " "[${i % 3}, ${(i / 3).floor()}]"), actions: [ ElevatedButton( onPressed: () => Navigator.pop(context), child: const Text("Close")) ], )); return; } setState(() { data[subGame][i] = turn; nextPlay = subGameEnded(i) ? -1 : i; if (!gameEnded()) { _swapTurn(); } }); Navigator.pop(context); }; } Widget _subGameDialog(int subGame) { return Dialog( child: Padding( padding: const EdgeInsets.all(10), child: Column( mainAxisSize: MainAxisSize.min, children: [ Padding( padding: const EdgeInsets.only(bottom: 5), child: Text( "${Util.stateText(turn)} select cell", style: const TextStyle(fontWeight: FontWeight.bold), ), ), TTCGame( turn: turn, cellOnTapCallback: subGameCellOnTapCallback(subGame), data: data[subGame], ), Padding( padding: const EdgeInsets.only(top: 5), child: Row( mainAxisAlignment: MainAxisAlignment.end, children: [ ElevatedButton( onPressed: () { Navigator.pop(context); }, child: const Text("Close")) ], ), ), ], ), ), ); } void endedSubGameNotification(int index) { ScaffoldMessenger.of(context) ..clearSnackBars() ..showSnackBar( SnackBar( content: Text("${Util.stateText(subGameWinner(index))}" " already won the game at " "[${Util.cellAddress(index)}]"), ), ); } void _showSubGameDialog(int i) { if (nextPlay == i || nextPlay == -1) { showDialog( context: context, builder: (context) => _subGameDialog(i), ); } else { ScaffoldMessenger.of(context) ..clearSnackBars() ..showSnackBar( SnackBar( content: Text( "You can only play at [${(nextPlay % 3) + 1}," "${(nextPlay / 3).floor() + 1}]", ), ), ); } } void _gameEndedReminder() { ScaffoldMessenger.of(context) ..clearSnackBars() ..showSnackBar( SnackBar( content: Text("${Util.stateText(winner)} already won the game"), ), ); } void _cellOnTapCallback(int index) { if (subGameEnded(index)) { endedSubGameNotification(index); return; } else if (gameEnded()) { _gameEndedReminder(); return; } _showSubGameDialog(index); } Widget _turnText() => Text( gameEnded() ? "${Util.stateText(winner)} Wins" : "${Util.stateText(turn)}'s Turn", style: const TextStyle(fontSize: 25), ); Widget _subGmaeWidget(int i) { if (subGameEnded(i)) { return Text( subGameWinner(i).name.toUpperCase(), style: const TextStyle(fontSize: 40), ); } return TTCGame(turn: turn, data: data[i]); } List _generateCells() => Iterable.generate(data.length) .map( (i) => DecoratedBox( decoration: BoxDecoration( color: nextPlay == i ? Colors.lightGreenAccent : null, ), child: Padding( padding: const EdgeInsets.all(15), child: _subGmaeWidget(i), ), ), ) .toList(); @override Widget build(BuildContext context) { return Column( children: [ const Spacer(flex: 5), Center( child: _turnText(), ), const Spacer(flex: 1), GameHash( cellOnTapCallback: _cellOnTapCallback, children: _generateCells(), ), const Spacer(flex: 5), ], ); } }