classic game cleanup

This commit is contained in:
Andrei Stoica 2024-12-21 08:34:49 -05:00
parent 6caec73c0d
commit c9a43f505c
2 changed files with 81 additions and 33 deletions

View File

@ -1,6 +1,7 @@
import 'package:flutter/material.dart';
import 'state.dart';
import 'game.dart';
import "util.dart";
class ClassicGame extends StatefulWidget {
const ClassicGame({super.key});
@ -22,6 +23,8 @@ class _ClassicGameState extends State<ClassicGame> {
TTCState.empty,
TTCState.empty,
];
bool ended = false;
TTCState? winner;
String get turnText => switch (turn) {
TTCState.empty => "",
@ -40,7 +43,7 @@ class _ClassicGameState extends State<ClassicGame> {
Widget _invalidChoiceAlert(TTCState existingValue) {
return Dialog(
child: Padding(
padding: EdgeInsets.all(10),
padding: const EdgeInsets.all(10),
child: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.center,
@ -77,10 +80,40 @@ class _ClassicGameState extends State<ClassicGame> {
setState(() {
data[index] = turn;
winner = Util.checkWin(data);
if (winner != null && winner != TTCState.empty) {
ended = true;
}
_nextTurn();
});
}
void _endedCellOnTap(int index) {
showDialog(
context: context,
builder: (context) {
return Dialog(
child: Padding(
padding: const EdgeInsets.all(10),
child: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
const Text(
"GAME OVER",
style: TextStyle(fontWeight: FontWeight.bold),
),
Text("${winner?.name.toUpperCase()} has already won"),
ElevatedButton(
onPressed: () => Navigator.pop(context),
child: const Text("Ok")),
],
),
),
);
});
}
@override
Widget build(BuildContext context) {
return Column(
@ -89,13 +122,13 @@ class _ClassicGameState extends State<ClassicGame> {
const Spacer(flex: 5),
Center(
child: Text(
"$turnText's turn",
!ended ? "$turnText's turn" : "${winner?.name.toUpperCase()} wins",
style: const TextStyle(fontSize: 30, fontWeight: FontWeight.bold),
)),
const Spacer(flex: 1),
TTCGame(
turn: turn,
cellOnTapCallback: _cellOnTap,
cellOnTapCallback: !ended ? _cellOnTap : _endedCellOnTap,
data: data,
cellTextStyle: const TextStyle(fontSize: 40),
),

View File

@ -20,6 +20,27 @@ class TTCGame extends StatelessWidget {
/// hook into end of turn cycle;
final Function cellOnTapCallback;
@override
Widget build(BuildContext context) {
List<Widget> cells = data
.map((state) => Text(
state != TTCState.empty ? state.name.toUpperCase() : "",
style: cellTextStyle,
))
.toList();
return GameHash(
cellOnTapCallback: cellOnTapCallback,
children: cells,
);
}
}
class GameHash extends StatelessWidget {
const GameHash({super.key, required this.children, this.cellOnTapCallback});
final List<Widget> children;
final Function? cellOnTapCallback;
Border _genCellBorder(
int index, {
BorderSide borderSide = const BorderSide(),
@ -32,52 +53,46 @@ class TTCGame extends StatelessWidget {
);
}
Widget _genCell(int index, TTCState state) => Container(
MapEntry<int, Widget> _genCell(int index, Widget content) {
return MapEntry(
index,
Container(
decoration: BoxDecoration(border: _genCellBorder(index)),
child: TTCCell(
state: state,
textStyle: cellTextStyle,
child: HashCell(
stateSetCallback: () {
cellOnTapCallback(index);
if (cellOnTapCallback != null) {
cellOnTapCallback!(index);
}
},
));
child: content,
),
),
);
}
@override
Widget build(BuildContext context) {
List<Widget> cells = [];
for (final (index, state) in data.indexed) {
cells.add(_genCell(index, state));
}
return GridView.count(
crossAxisCount: 3,
shrinkWrap: true,
children: cells,
children: children.asMap().map(_genCell).values.toList(),
);
}
}
class TTCCell extends StatelessWidget {
const TTCCell({
class HashCell extends StatelessWidget {
const HashCell({
super.key,
required this.state,
required this.child,
this.stateSetCallback,
this.textStyle,
});
final TTCState state;
final Widget child;
final VoidCallback? stateSetCallback;
final TextStyle? textStyle;
String get text => switch (state) {
TTCState.empty => "",
TTCState.x => "X",
TTCState.o => "O",
};
@override
Widget build(BuildContext context) => InkWell(
onTap: stateSetCallback,
child: Center(
child: Text(text, style: textStyle),
));
child: Center(child: child),
);
}