import 'package:solitaire_game/entities/tile.dart'; import 'package:solitaire_game/layout/game.dart'; import 'package:solitaire_game/provider/data.dart'; import 'package:solitaire_game/utils/board_utils.dart'; class GameUtils { static Future<void> quitGame(Data myProvider) async { myProvider.updateGameIsRunning(false); } static Future<void> startNewGame(Data myProvider) async { print('Starting game'); BoardUtils.createNewBoard(myProvider); myProvider.updateGameIsRunning(true); } static void deleteSavedGame(Data myProvider) { myProvider.resetCurrentSavedState(); } static void resumeSavedGame(Data myProvider) { Map<String, dynamic> savedState = myProvider.getCurrentSavedState(); if (savedState.isNotEmpty) { try { myProvider.setParameterValue('skin', savedState['skin']); myProvider.updateMovesCount(int.parse(savedState['movesCount'])); myProvider.updateBoard( BoardUtils.createBoardFromSavedState(myProvider, savedState['boardValues'])); myProvider.updateGameIsRunning(true); } catch (e) { print('Failed to resume game. Will start new one instead.'); myProvider.resetCurrentSavedState(); myProvider.initParametersValues(); startNewGame(myProvider); } } else { myProvider.resetCurrentSavedState(); myProvider.initParametersValues(); startNewGame(myProvider); } } static bool isMoveAllowed(Data myProvider, List<int> source, List<int> target) { List<List<Tile?>> board = myProvider.board; int sourceCol = source[0]; int sourceRow = source[1]; int targetCol = target[0]; int targetRow = target[1]; // ensure source exists and has a peg if (board[sourceRow][sourceCol] == null || board[sourceRow][sourceCol]?.hasPeg == false) { print('move forbidden: source peg does not exist'); return false; } // ensure target exists and is empty if (board[targetRow][targetCol] == null || board[targetRow][targetCol]?.hasPeg == true) { print('move forbidden: target does not exist or already with a peg'); return false; } // ensure source and target are in the same line/column if ((targetCol != sourceCol) && (targetRow != sourceRow)) { print('move forbidden: source and target are not in the same line or column'); return false; } // ensure source and target are separated by exactly one tile if (((targetCol == sourceCol) && ((targetRow - sourceRow).abs() != 2)) || ((targetRow == sourceRow) && ((targetCol - sourceCol).abs() != 2))) { print('move forbidden: source and target must be separated by exactly one tile'); return false; } // ensure middle tile exists and has a peg int middleRow = (sourceRow + ((targetRow - sourceRow) / 2)).round(); int middleCol = (sourceCol + ((targetCol - sourceCol) / 2)).round(); if (board[middleRow][middleCol] == null || board[middleRow][middleCol]?.hasPeg == false) { print('move forbidden: tile between source and target does not contain a peg'); return false; } // ok, move is allowed return true; } static void move(Data myProvider, List<int> source, List<int> target) { print('Move from ' + source.toString() + ' to ' + target.toString()); int sourceCol = source[0]; int sourceRow = source[1]; int targetCol = target[0]; int targetRow = target[1]; int middleRow = (sourceRow + ((targetRow - sourceRow) / 2)).round(); int middleCol = (sourceCol + ((targetCol - sourceCol) / 2)).round(); // remove peg from source myProvider.updatePegValue(sourceRow, sourceCol, false); // put peg in target myProvider.updatePegValue(targetRow, targetCol, true); // remove peg from middle tile myProvider.updatePegValue(middleRow, middleCol, false); // increment moves count myProvider.incrementMovesCount(); // update remaining pegs count myProvider.updateRemainingPegsCount(GameUtils.countRemainingPegs(myProvider)); } static int countRemainingPegs(Data myProvider) { int count = 0; List<List<Tile?>> board = myProvider.board; for (var rowIndex = 0; rowIndex < board.length; rowIndex++) { for (var colIndex = 0; colIndex < board[rowIndex].length; colIndex++) { Tile? tile = board[rowIndex][colIndex]; if (tile != null && tile.hasPeg == true) { count++; } } } return count; } }