diff --git a/android/gradle.properties b/android/gradle.properties index 53b891875db3301fbb76f2326d54e95a4e936155..c0b881d1dd585e55b5d7819caee1bafac587748e 100644 --- a/android/gradle.properties +++ b/android/gradle.properties @@ -1,5 +1,5 @@ org.gradle.jvmargs=-Xmx1536M android.useAndroidX=true android.enableJetifier=true -app.versionName=0.1.16 -app.versionCode=65 +app.versionName=0.1.17 +app.versionCode=66 diff --git a/fastlane/metadata/android/en-US/changelogs/66.txt b/fastlane/metadata/android/en-US/changelogs/66.txt new file mode 100644 index 0000000000000000000000000000000000000000..9dc5d6607e58b7f51562cda67edeb8054845a6ef --- /dev/null +++ b/fastlane/metadata/android/en-US/changelogs/66.txt @@ -0,0 +1 @@ +Improve game architecture. diff --git a/fastlane/metadata/android/fr-FR/changelogs/66.txt b/fastlane/metadata/android/fr-FR/changelogs/66.txt new file mode 100644 index 0000000000000000000000000000000000000000..4707814df041e7b418257e0ab5472ee7fd3a45b4 --- /dev/null +++ b/fastlane/metadata/android/fr-FR/changelogs/66.txt @@ -0,0 +1 @@ +Amélioration de la conception du jeu. diff --git a/lib/entities/cell.dart b/lib/entities/cell.dart index bec985d77c2f61c26dacfddf39b845004bd5f1a3..8767c741b7b3edf0380b48e12a9bbe2b1becf009 100644 --- a/lib/entities/cell.dart +++ b/lib/entities/cell.dart @@ -5,27 +5,30 @@ import 'package:sudoku/utils/board_animate.dart'; import 'package:sudoku/utils/board_utils.dart'; class Cell { - int value; - bool isFixed; - int conflictsCount = 0; + const Cell({ + required this.row, + required this.col, + required this.value, + required this.isFixed, + }); - bool isAnimated = false; + final int row; + final int col; + final int value; + final bool isFixed; - Cell( - this.value, - this.isFixed, - ); + static const Cell none = Cell(row: 0, col: 0, value: 0, isFixed: true); /* * Build widget for board cell, with interactions */ - Container widget(Data myProvider, int row, int col) { + Widget widget(Data myProvider) { final String imageAsset = getImageAssetName(myProvider); return Container( decoration: BoxDecoration( color: getBackgroundColor(myProvider), - border: getCellBorders(myProvider, row, col), + border: getCellBorders(myProvider), ), child: GestureDetector( child: AnimatedSwitcher( @@ -40,7 +43,7 @@ class Cell { ), ), onTap: () { - if (col != myProvider.currentCellCol || row != myProvider.currentCellRow) { + if (col != myProvider.selectedCellCol || row != myProvider.selectedCellRow) { myProvider.selectCell(col, row); } else { myProvider.selectCell(null, null); @@ -62,14 +65,14 @@ class Cell { Color backgroundColor = Colors.grey.shade200; if (myProvider.showConflicts && - myProvider.currentCellCol != null && - myProvider.currentCellRow != null) { - final List<List<Cell>> cells = myProvider.cells; + myProvider.selectedCellCol != null && + myProvider.selectedCellRow != null) { + final Board cells = myProvider.board; final int blockSizeHorizontal = myProvider.blockSizeHorizontal; final int blockSizeVertical = myProvider.blockSizeVertical; if (!BoardUtils.isValueAllowed(cells, blockSizeHorizontal, blockSizeVertical, - myProvider.currentCellCol, myProvider.currentCellRow, value)) { + myProvider.selectedCellCol, myProvider.selectedCellRow, value)) { backgroundColor = Colors.pink.shade100; } } @@ -85,9 +88,9 @@ class Cell { child: GestureDetector( child: Image(image: AssetImage(imageAsset), fit: BoxFit.fill), onTap: () { - if (myProvider.currentCellCol != null && myProvider.currentCellRow != null) { + if (myProvider.selectedCellCol != null && myProvider.selectedCellRow != null) { myProvider.updateCellValue( - myProvider.currentCellCol, myProvider.currentCellRow, value); + myProvider.selectedCellCol, myProvider.selectedCellRow, value); } myProvider.selectCell(null, null); if (BoardUtils.checkBoardIsSolved(myProvider)) { @@ -126,6 +129,8 @@ class Cell { backgroundColor = fixedCellColor; } + final int conflictsCount = myProvider.boardConflicts[row][col]; + if (myProvider.showConflicts && (conflictsCount != 0)) { if (isFixed) { backgroundColor = fixedCellColorConflict; @@ -134,7 +139,7 @@ class Cell { } } - if (myProvider.showConflicts && (value == myProvider.currentCellValue)) { + if (myProvider.showConflicts && (value == myProvider.selectedCellValue)) { if (isFixed) { backgroundColor = fixedSelectedValueColor; } else { @@ -142,6 +147,8 @@ class Cell { } } + final bool isAnimated = myProvider.boardAnimated[row][col]; + if (isAnimated) { if (isFixed) { backgroundColor = fixedAnimated; @@ -154,7 +161,9 @@ class Cell { } // Compute cell borders, from board size and cell state - Border getCellBorders(Data myProvider, int row, int col) { + Border getCellBorders(Data myProvider) { + // final int row = , int col; + final int blockSizeHorizontal = myProvider.blockSizeHorizontal; final int blockSizeVertical = myProvider.blockSizeVertical; @@ -184,7 +193,7 @@ class Cell { ); // Update cell borders if not currently selected cell - if (col != myProvider.currentCellCol || row != myProvider.currentCellRow) { + if (col != myProvider.selectedCellCol || row != myProvider.selectedCellRow) { borders = Border( top: BorderSide( width: cellBorderWidth, diff --git a/lib/layout/board.dart b/lib/layout/board.dart deleted file mode 100644 index 9ad79f26143580b2586409fb5b0c647f0120de51..0000000000000000000000000000000000000000 --- a/lib/layout/board.dart +++ /dev/null @@ -1,41 +0,0 @@ -import 'package:flutter/material.dart'; - -import 'package:sudoku/entities/cell.dart'; -import 'package:sudoku/provider/data.dart'; - -class Board { - static Container buildGameBoard(Data myProvider) { - const Color borderColor = Colors.black; - - return Container( - margin: const EdgeInsets.all(2), - padding: const EdgeInsets.all(2), - decoration: BoxDecoration( - color: borderColor, - borderRadius: BorderRadius.circular(2), - border: Border.all( - color: borderColor, - width: 2, - ), - ), - child: Column( - children: [ - buildGameTileset(myProvider), - ], - ), - ); - } - - static Widget buildGameTileset(Data myProvider) { - final int boardSize = myProvider.blockSizeHorizontal * myProvider.blockSizeVertical; - final List<List<Cell>> cells = myProvider.cells; - - return Table(defaultColumnWidth: const IntrinsicColumnWidth(), children: [ - for (int row = 0; row < boardSize; row++) - TableRow(children: [ - for (int col = 0; col < boardSize; col++) - Column(children: [cells[row][col].widget(myProvider, row, col)]), - ]), - ]); - } -} diff --git a/lib/layout/game.dart b/lib/layout/game.dart deleted file mode 100644 index a24deeafe90adc139ab86f0e1ee87d5d4586c418..0000000000000000000000000000000000000000 --- a/lib/layout/game.dart +++ /dev/null @@ -1,111 +0,0 @@ -import 'dart:math'; - -import 'package:flutter/material.dart'; - -import 'package:sudoku/entities/cell.dart'; -import 'package:sudoku/layout/board.dart'; -import 'package:sudoku/provider/data.dart'; -import 'package:sudoku/utils/board_utils.dart'; -import 'package:sudoku/utils/game_utils.dart'; - -class Game { - static Widget buildGameWidget(Data myProvider) { - final bool gameIsFinished = BoardUtils.checkBoardIsSolved(myProvider); - - return Column( - mainAxisAlignment: MainAxisAlignment.start, - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - Board.buildGameBoard(myProvider), - const SizedBox(height: 2), - gameIsFinished - ? Game.buildEndGameMessage(myProvider) - : Game.buildSelectCellValueBar(myProvider), - ], - ); - } - - static Container buildSelectCellValueBar(Data myProvider) { - final List<List<Cell>> cells = myProvider.cells; - - final bool isCellSelected = - (myProvider.currentCellCol != null && myProvider.currentCellRow != null); - final bool isUpdatableCellSelected = isCellSelected - ? !cells[myProvider.currentCellRow ?? 0][myProvider.currentCellCol ?? 0].isFixed - : false; - final int maxValue = myProvider.blockSizeHorizontal * myProvider.blockSizeVertical; - - const int maxItemsPerLine = 10; - final int linesCount = (maxValue / maxItemsPerLine).floor() + 1; - final int itemsCountPerLine = min(maxItemsPerLine, maxValue + 1); - - return Container( - margin: const EdgeInsets.all(2), - padding: const EdgeInsets.all(2), - child: Table( - defaultColumnWidth: const IntrinsicColumnWidth(), - children: [ - for (int lineIndex = 0; lineIndex < linesCount; lineIndex++) - TableRow( - children: [ - for (int value = lineIndex * itemsCountPerLine; - value < (lineIndex + 1) * itemsCountPerLine; - value++) - Column( - children: [ - Cell(isUpdatableCellSelected ? (value <= maxValue ? value : -1) : -1, - false) - .widgetUpdateValue(myProvider) - ], - ), - ], - ), - ], - ), - ); - } - - static Widget buildRestartGameButton(Data myProvider) { - return TextButton( - child: const Image( - image: AssetImage('assets/icons/button_back.png'), - fit: BoxFit.fill, - ), - onPressed: () => GameUtils.quitGame(myProvider), - ); - } - - static Container buildEndGameMessage(Data myProvider) { - const Image decorationImage = Image( - image: AssetImage('assets/icons/game_win.png'), - fit: BoxFit.fill, - ); - - return Container( - margin: const EdgeInsets.all(2), - padding: const EdgeInsets.all(2), - child: Table( - defaultColumnWidth: const IntrinsicColumnWidth(), - children: [ - TableRow( - children: [ - const Column( - children: [decorationImage], - ), - Column( - children: [ - myProvider.animationInProgress - ? decorationImage - : buildRestartGameButton(myProvider) - ], - ), - const Column( - children: [decorationImage], - ), - ], - ), - ], - ), - ); - } -} diff --git a/lib/main.dart b/lib/main.dart index 285517806e7383aed247fd7fa1b656f6a329ee36..a1fc31fe9c887e17017e8450e8740e2dd2b7c8b7 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -4,7 +4,7 @@ import 'package:provider/provider.dart'; import 'package:overlay_support/overlay_support.dart'; import 'package:sudoku/provider/data.dart'; -import 'package:sudoku/screens/home.dart'; +import 'package:sudoku/ui/screens/home.dart'; void main() { WidgetsFlutterBinding.ensureInitialized(); @@ -27,9 +27,6 @@ class MyApp extends StatelessWidget { visualDensity: VisualDensity.adaptivePlatformDensity, ), home: const Home(), - routes: { - Home.id: (context) => const Home(), - }, ), ); }), diff --git a/lib/provider/data.dart b/lib/provider/data.dart index b03d01be04307940e04998a3789a29f75d53138c..64585c0117478b18cee5e868cbf04042b5064a93 100644 --- a/lib/provider/data.dart +++ b/lib/provider/data.dart @@ -6,6 +6,11 @@ import 'package:shared_preferences/shared_preferences.dart'; import 'package:sudoku/entities/cell.dart'; import 'package:sudoku/utils/tools.dart'; +typedef Board = List<List<Cell>>; +typedef ConflictsCount = List<List<int>>; +typedef AnimatedBoard = List<List<bool>>; +typedef AnimatedBoardSequence = List<AnimatedBoard>; + class Data extends ChangeNotifier { // Configuration available values final List<String> _availableParameters = ['level', 'size', 'skin']; @@ -39,15 +44,17 @@ class Data extends ChangeNotifier { bool _animationInProgress = false; int _blockSizeVertical = 0; int _blockSizeHorizontal = 0; - List<List<Cell>> _cells = []; - List<List<Cell>> _cellsSolved = []; + Board _board = []; + Board _boardSolved = []; + ConflictsCount _boardConflicts = []; + AnimatedBoard _boardAnimated = []; List<int> _shuffledCellValues = []; - int? _currentCellCol; - int? _currentCellRow; - int? _currentCellValue; + int? _selectedCellCol; + int? _selectedCellRow; + int? _selectedCellValue; bool _showConflicts = false; int _givenTipsCount = 0; - String _currentState = ''; + String _currentSavedState = ''; void updateParameterLevel(String parameterLevel) { _parameterLevel = parameterLevel; @@ -115,15 +122,15 @@ class Data extends ChangeNotifier { setParameterValue('skin', prefs.getString('skin') ?? _parameterSkinDefault); } - String get currentState => _currentState; + String get currentSavedState => _currentSavedState; String computeCurrentGameState() { String cellsValues = ''; const String stringValues = '0123456789ABCDEFG'; - for (int rowIndex = 0; rowIndex < _cells.length; rowIndex++) { - for (int colIndex = 0; colIndex < _cells[rowIndex].length; colIndex++) { - cellsValues += stringValues[_cells[rowIndex][colIndex].value]; - cellsValues += _cells[rowIndex][colIndex].isFixed ? 'x' : ' '; + for (int rowIndex = 0; rowIndex < _board.length; rowIndex++) { + for (int colIndex = 0; colIndex < _board[rowIndex].length; colIndex++) { + cellsValues += stringValues[_board[rowIndex][colIndex].value]; + cellsValues += _board[rowIndex][colIndex].isFixed ? 'x' : ' '; } } @@ -140,35 +147,35 @@ class Data extends ChangeNotifier { void saveCurrentGameState() async { if (_gameIsRunning) { - _currentState = computeCurrentGameState(); + _currentSavedState = computeCurrentGameState(); final prefs = await SharedPreferences.getInstance(); - prefs.setString('savedState', _currentState); + prefs.setString('savedState', _currentSavedState); } else { resetCurrentSavedState(); } } void resetCurrentSavedState() async { - _currentState = ''; + _currentSavedState = ''; final prefs = await SharedPreferences.getInstance(); - prefs.setString('savedState', _currentState); + prefs.setString('savedState', _currentSavedState); notifyListeners(); } void loadCurrentSavedState() async { final prefs = await SharedPreferences.getInstance(); - _currentState = prefs.getString('savedState') ?? ''; + _currentSavedState = prefs.getString('savedState') ?? ''; } bool hasCurrentSavedState() { - return (_currentState != ''); + return (_currentSavedState != ''); } Map<String, dynamic> getCurrentSavedState() { - if (_currentState != '') { - Map<String, dynamic> savedState = json.decode(_currentState); + if (_currentSavedState != '') { + Map<String, dynamic> savedState = json.decode(_currentSavedState); if (savedState.isNotEmpty) { return savedState; } @@ -187,17 +194,20 @@ class Data extends ChangeNotifier { _assetsPreloaded = assetsPreloaded; } - List<List<Cell>> get cells => _cells; - void updateCells(List<List<Cell>> cells) { - _cells = cells; + Board get board => _board; + void updateCells(Board board) { + _board = board; notifyListeners(); } - List<List<Cell>> get cellsSolved => _cellsSolved; - void updateCellsSolved(List<List<Cell>> cells) { - _cellsSolved = cells; + Board get boardSolved => _boardSolved; + void updateCellsSolved(Board boardSolved) { + _boardSolved = boardSolved; } + AnimatedBoard get boardAnimated => _boardAnimated; + ConflictsCount get boardConflicts => _boardConflicts; + void shuffleCellValues() { const int maxCellValue = 16; final List<int> values = List<int>.generate(maxCellValue, (i) => i + 1); @@ -218,21 +228,21 @@ class Data extends ChangeNotifier { return _shuffledCellValues[originalValue - 1]; } - int? get currentCellCol => _currentCellCol; - set updateCurrentCellCol(int? currentCellCol) { - _currentCellCol = currentCellCol; + int? get selectedCellCol => _selectedCellCol; + set updateCelectedCellCol(int? selectedCellCol) { + _selectedCellCol = selectedCellCol; notifyListeners(); } - int? get currentCellRow => _currentCellRow; - set updateCurrentCellRow(int? currentCellRow) { - _currentCellRow = currentCellRow; + int? get selectedCellRow => _selectedCellRow; + set updateSelectedCellRow(int? selectedCellRow) { + _selectedCellRow = selectedCellRow; notifyListeners(); } - int? get currentCellValue => _currentCellValue; - set updateCurrentCellValue(int? currentCellValue) { - _currentCellValue = currentCellValue; + int? get selectedCellValue => _selectedCellValue; + set updateSelectedCellValue(int? selectedCellValue) { + _selectedCellValue = selectedCellValue; notifyListeners(); } @@ -253,21 +263,43 @@ class Data extends ChangeNotifier { } selectCell(int? col, int? row) { - _currentCellCol = col; - _currentCellRow = row; - _currentCellValue = null; + _selectedCellCol = col; + _selectedCellRow = row; + _selectedCellValue = null; if (row != null && col != null) { - if (_cells[row][col].value != 0) { - _currentCellValue = _cells[row][col].value; + if (_board[row][col].value != 0) { + _selectedCellValue = _board[row][col].value; } } notifyListeners(); } + void initConflictsBoard() { + ConflictsCount nonConflictedBoard = []; + final int boardSideLength = _blockSizeHorizontal * _blockSizeVertical; + for (int row = 0; row < boardSideLength; row++) { + List<int> line = []; + for (int col = 0; col < boardSideLength; col++) { + line.add(0); + } + nonConflictedBoard.add(line); + } + _boardConflicts = nonConflictedBoard; + } + + void updateConflicts(ConflictsCount conflictsCount) { + _boardConflicts = conflictsCount; + } + updateCellValue(int? col, int? row, int value) { if ((col != null) && (row != null)) { - if (!_cells[row][col].isFixed) { - _cells[row][col].value = value; + if (!_board[row][col].isFixed) { + _board[row][col] = Cell( + row: row, + col: col, + value: value, + isFixed: false, + ); saveCurrentGameState(); notifyListeners(); @@ -292,11 +324,24 @@ class Data extends ChangeNotifier { notifyListeners(); } + void initAnimatedBackground() { + AnimatedBoard staticBoard = []; + final int boardSideLength = _blockSizeHorizontal * _blockSizeVertical; + for (int row = 0; row < boardSideLength; row++) { + List<bool> line = []; + for (int col = 0; col < boardSideLength; col++) { + line.add(false); + } + staticBoard.add(line); + } + _boardAnimated = staticBoard; + } + void setAnimatedBackground(List animatedCellsPattern) { final int boardSideLength = _blockSizeHorizontal * _blockSizeVertical; for (int row = 0; row < boardSideLength; row++) { for (int col = 0; col < boardSideLength; col++) { - _cells[row][col].isAnimated = animatedCellsPattern[row][col]; + _boardAnimated[row][col] = animatedCellsPattern[row][col]; } } notifyListeners(); @@ -306,7 +351,7 @@ class Data extends ChangeNotifier { final int boardSideLength = _blockSizeHorizontal * _blockSizeVertical; for (int row = 0; row < boardSideLength; row++) { for (int col = 0; col < boardSideLength; col++) { - _cells[row][col].isAnimated = false; + _boardAnimated[row][col] = false; } } } diff --git a/lib/ui/layout/board.dart b/lib/ui/layout/board.dart new file mode 100644 index 0000000000000000000000000000000000000000..069557ef249bea8deb463c029133df17f038fd13 --- /dev/null +++ b/lib/ui/layout/board.dart @@ -0,0 +1,48 @@ +import 'package:flutter/material.dart'; + +import 'package:sudoku/provider/data.dart'; + +class BoardLayout extends StatelessWidget { + const BoardLayout({super.key, required this.myProvider}); + + final Data myProvider; + + @override + Container build(BuildContext context) { + const Color borderColor = Colors.black; + final int boardSize = myProvider.blockSizeHorizontal * myProvider.blockSizeVertical; + + final Widget gameTileset = Table( + defaultColumnWidth: const IntrinsicColumnWidth(), + children: [ + for (int row = 0; row < boardSize; row++) + TableRow( + children: [ + for (int col = 0; col < boardSize; col++) + Column( + children: [myProvider.board[row][col].widget(myProvider)], + ), + ], + ), + ], + ); + + return Container( + margin: const EdgeInsets.all(2), + padding: const EdgeInsets.all(2), + decoration: BoxDecoration( + color: borderColor, + borderRadius: BorderRadius.circular(2), + border: Border.all( + color: borderColor, + width: 2, + ), + ), + child: Column( + children: [ + gameTileset, + ], + ), + ); + } +} diff --git a/lib/ui/layout/game.dart b/lib/ui/layout/game.dart new file mode 100644 index 0000000000000000000000000000000000000000..e6cc4ee582875b63e60d5ed2b8951580277a9af0 --- /dev/null +++ b/lib/ui/layout/game.dart @@ -0,0 +1,30 @@ +import 'package:flutter/material.dart'; + +import 'package:sudoku/ui/layout/board.dart'; +import 'package:sudoku/ui/widgets/message_game_end.dart'; +import 'package:sudoku/ui/widgets/bar_select_cell_value.dart'; +import 'package:sudoku/provider/data.dart'; +import 'package:sudoku/utils/board_utils.dart'; + +class Game extends StatelessWidget { + const Game({super.key, required this.myProvider}); + + final Data myProvider; + + @override + Widget build(BuildContext context) { + final bool gameIsFinished = BoardUtils.checkBoardIsSolved(myProvider); + + return Column( + mainAxisAlignment: MainAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + BoardLayout(myProvider: myProvider), + const SizedBox(height: 2), + gameIsFinished + ? EndGameMessage(myProvider: myProvider) + : SelectCellValueBar(myProvider: myProvider), + ], + ); + } +} diff --git a/lib/layout/parameters.dart b/lib/ui/layout/parameters.dart similarity index 61% rename from lib/layout/parameters.dart rename to lib/ui/layout/parameters.dart index 7a3e5f1e515ba0dc81092bdc3758736e2a0ed138..abd8b9c25df646b7e7c4e75bb53aeacc7585d3de 100644 --- a/lib/layout/parameters.dart +++ b/lib/ui/layout/parameters.dart @@ -1,9 +1,14 @@ import 'package:flutter/material.dart'; import 'package:sudoku/provider/data.dart'; -import 'package:sudoku/utils/game_utils.dart'; +import 'package:sudoku/ui/widgets/button_game_resume.dart'; +import 'package:sudoku/ui/widgets/button_game_start_new.dart'; + +class Parameters extends StatelessWidget { + const Parameters({super.key, required this.myProvider}); + + final Data myProvider; -class Parameters { static const double separatorHeight = 2.0; static const double blockMargin = 3.0; static const double blockPadding = 2.0; @@ -15,7 +20,8 @@ class Parameters { static const double buttonPadding = 0.0; static const double buttonMargin = 0.0; - static Widget buildParametersSelector(Data myProvider) { + @override + Widget build(BuildContext context) { List<Widget> lines = []; List<String> parameters = myProvider.availableParameters; @@ -26,8 +32,8 @@ class Parameters { myProvider.loadCurrentSavedState(); Widget buttonsBlock = myProvider.hasCurrentSavedState() - ? buildResumeGameButton(myProvider) - : buildStartNewGameButton(myProvider); + ? ResumeGameButton(myProvider: myProvider) + : StartNewGameButton(myProvider: myProvider); return Column( mainAxisAlignment: MainAxisAlignment.start, @@ -73,66 +79,7 @@ class Parameters { ); } - static Container buildStartNewGameButton(Data myProvider) { - return Container( - margin: const EdgeInsets.all(blockMargin), - padding: const EdgeInsets.all(blockPadding), - child: Table( - defaultColumnWidth: const IntrinsicColumnWidth(), - children: [ - TableRow( - children: [ - buildDecorationImageWidget(), - Column( - children: [ - TextButton( - child: buildImageContainerWidget('button_start'), - onPressed: () => GameUtils.startNewGame(myProvider), - ), - ], - ), - buildDecorationImageWidget(), - ], - ), - ], - ), - ); - } - - static Container buildResumeGameButton(Data myProvider) { - return Container( - margin: const EdgeInsets.all(blockMargin), - padding: const EdgeInsets.all(blockPadding), - child: Table( - defaultColumnWidth: const IntrinsicColumnWidth(), - children: [ - TableRow( - children: [ - Column( - children: [ - TextButton( - child: buildImageContainerWidget('button_delete_saved_game'), - onPressed: () => GameUtils.deleteSavedGame(myProvider), - ), - ], - ), - Column( - children: [ - TextButton( - child: buildImageContainerWidget('button_resume_game'), - onPressed: () => GameUtils.resumeSavedGame(myProvider), - ), - ], - ), - buildDecorationImageWidget(), - ], - ), - ], - ), - ); - } - - static Widget buildParameterSelector(Data myProvider, String parameterCode) { + Widget buildParameterSelector(Data myProvider, String parameterCode) { List<String> availableValues = myProvider.getParameterAvailableValues(parameterCode); if (availableValues.length == 1) { @@ -156,8 +103,7 @@ class Parameters { ); } - static Widget _buildParameterButton( - Data myProvider, String parameterCode, String parameterValue) { + Widget _buildParameterButton(Data myProvider, String parameterCode, String parameterValue) { String currentValue = myProvider.getParameterValue(parameterCode).toString(); bool isActive = (parameterValue == currentValue); diff --git a/lib/screens/home.dart b/lib/ui/screens/home.dart similarity index 93% rename from lib/screens/home.dart rename to lib/ui/screens/home.dart index 90b6ffbfd9ad735c14dbb847ce3854c76c1f01db..af2cfa1f08d8c050725e7bf1425b56e9115d9f5d 100644 --- a/lib/screens/home.dart +++ b/lib/ui/screens/home.dart @@ -3,14 +3,12 @@ import 'package:provider/provider.dart'; import 'package:badges/badges.dart' as badges; import 'package:overlay_support/overlay_support.dart'; -import 'package:sudoku/layout/game.dart'; -import 'package:sudoku/layout/parameters.dart'; +import 'package:sudoku/ui/layout/game.dart'; +import 'package:sudoku/ui/layout/parameters.dart'; import 'package:sudoku/provider/data.dart'; import 'package:sudoku/utils/game_utils.dart'; class Home extends StatefulWidget { - static const String id = 'home'; - const Home({super.key}); @override @@ -69,7 +67,7 @@ class HomeState extends State<Home> { final Data myProvider = Provider.of<Data>(context); if (!myProvider.assetsPreloaded) { - List<String> assets = getImagesAssets(myProvider); + final List<String> assets = getImagesAssets(myProvider); for (String asset in assets) { precacheImage(AssetImage(asset), context); } @@ -155,8 +153,8 @@ class HomeState extends State<Home> { body: SafeArea( child: Center( child: myProvider.gameIsRunning - ? Game.buildGameWidget(myProvider) - : Parameters.buildParametersSelector(myProvider), + ? Game(myProvider: myProvider) + : Parameters(myProvider: myProvider), ), ), ); diff --git a/lib/ui/widgets/bar_select_cell_value.dart b/lib/ui/widgets/bar_select_cell_value.dart new file mode 100644 index 0000000000000000000000000000000000000000..581b36491edb1d2ce4d8f9be313ccdfd2df51e08 --- /dev/null +++ b/lib/ui/widgets/bar_select_cell_value.dart @@ -0,0 +1,56 @@ +import 'dart:math'; + +import 'package:flutter/material.dart'; + +import 'package:sudoku/entities/cell.dart'; +import 'package:sudoku/provider/data.dart'; + +class SelectCellValueBar extends StatelessWidget { + const SelectCellValueBar({super.key, required this.myProvider}); + + final Data myProvider; + + @override + Widget build(BuildContext context) { + final Board cells = myProvider.board; + + final bool isCellSelected = + (myProvider.selectedCellCol != null && myProvider.selectedCellRow != null); + final bool isUpdatableCellSelected = isCellSelected + ? !cells[myProvider.selectedCellRow ?? 0][myProvider.selectedCellCol ?? 0].isFixed + : false; + final int maxValue = myProvider.blockSizeHorizontal * myProvider.blockSizeVertical; + + const int maxItemsPerLine = 10; + final int linesCount = (maxValue / maxItemsPerLine).floor() + 1; + final int itemsCountPerLine = min(maxItemsPerLine, maxValue + 1); + + return Container( + margin: const EdgeInsets.all(2), + padding: const EdgeInsets.all(2), + child: Table( + defaultColumnWidth: const IntrinsicColumnWidth(), + children: [ + for (int lineIndex = 0; lineIndex < linesCount; lineIndex++) + TableRow( + children: [ + for (int value = lineIndex * itemsCountPerLine; + value < (lineIndex + 1) * itemsCountPerLine; + value++) + Column( + children: [ + Cell( + row: 1, + col: value, + value: isUpdatableCellSelected ? (value <= maxValue ? value : -1) : -1, + isFixed: false, + ).widgetUpdateValue(myProvider) + ], + ), + ], + ), + ], + ), + ); + } +} diff --git a/lib/ui/widgets/button_game_restart.dart b/lib/ui/widgets/button_game_restart.dart new file mode 100644 index 0000000000000000000000000000000000000000..a2e8b670a6cb3ebe8753baf5a7a331a53b3a5286 --- /dev/null +++ b/lib/ui/widgets/button_game_restart.dart @@ -0,0 +1,21 @@ +import 'package:flutter/material.dart'; + +import 'package:sudoku/provider/data.dart'; +import 'package:sudoku/utils/game_utils.dart'; + +class RestartGameButton extends StatelessWidget { + const RestartGameButton({super.key, required this.myProvider}); + + final Data myProvider; + + @override + Widget build(BuildContext context) { + return TextButton( + child: const Image( + image: AssetImage('assets/icons/button_back.png'), + fit: BoxFit.fill, + ), + onPressed: () => GameUtils.quitGame(myProvider), + ); + } +} diff --git a/lib/ui/widgets/button_game_resume.dart b/lib/ui/widgets/button_game_resume.dart new file mode 100644 index 0000000000000000000000000000000000000000..41cb5688656aecce2faa0238717b9bb5d653eb9d --- /dev/null +++ b/lib/ui/widgets/button_game_resume.dart @@ -0,0 +1,42 @@ +import 'package:flutter/material.dart'; + +import 'package:sudoku/ui/layout/parameters.dart'; +import 'package:sudoku/utils/game_utils.dart'; + +class ResumeGameButton extends Parameters { + const ResumeGameButton({super.key, required super.myProvider}); + + @override + Widget build(BuildContext context) { + return Container( + margin: const EdgeInsets.all(Parameters.blockMargin), + padding: const EdgeInsets.all(Parameters.blockPadding), + child: Table( + defaultColumnWidth: const IntrinsicColumnWidth(), + children: [ + TableRow( + children: [ + Column( + children: [ + TextButton( + child: Parameters.buildImageContainerWidget('button_delete_saved_game'), + onPressed: () => GameUtils.deleteSavedGame(myProvider), + ), + ], + ), + Column( + children: [ + TextButton( + child: Parameters.buildImageContainerWidget('button_resume_game'), + onPressed: () => GameUtils.resumeSavedGame(myProvider), + ), + ], + ), + Parameters.buildDecorationImageWidget(), + ], + ), + ], + ), + ); + } +} diff --git a/lib/ui/widgets/button_game_start_new.dart b/lib/ui/widgets/button_game_start_new.dart new file mode 100644 index 0000000000000000000000000000000000000000..88e004d9a4bd18f317c22f774762916b635ac568 --- /dev/null +++ b/lib/ui/widgets/button_game_start_new.dart @@ -0,0 +1,38 @@ +import 'package:flutter/material.dart'; + +import 'package:sudoku/provider/data.dart'; +import 'package:sudoku/ui/layout/parameters.dart'; +import 'package:sudoku/utils/game_utils.dart'; + +class StartNewGameButton extends StatelessWidget { + const StartNewGameButton({super.key, required this.myProvider}); + + final Data myProvider; + + @override + Widget build(BuildContext context) { + return Container( + margin: const EdgeInsets.all(Parameters.blockMargin), + padding: const EdgeInsets.all(Parameters.blockPadding), + child: Table( + defaultColumnWidth: const IntrinsicColumnWidth(), + children: [ + TableRow( + children: [ + Parameters.buildDecorationImageWidget(), + Column( + children: [ + TextButton( + child: Parameters.buildImageContainerWidget('button_start'), + onPressed: () => GameUtils.startNewGame(myProvider), + ), + ], + ), + Parameters.buildDecorationImageWidget(), + ], + ), + ], + ), + ); + } +} diff --git a/lib/ui/widgets/message_game_end.dart b/lib/ui/widgets/message_game_end.dart new file mode 100644 index 0000000000000000000000000000000000000000..168e055e50074f24ad953566e5c52d9df8633e5d --- /dev/null +++ b/lib/ui/widgets/message_game_end.dart @@ -0,0 +1,45 @@ +import 'package:flutter/material.dart'; + +import 'package:sudoku/ui/widgets/button_game_restart.dart'; +import 'package:sudoku/provider/data.dart'; + +class EndGameMessage extends StatelessWidget { + const EndGameMessage({super.key, required this.myProvider}); + + final Data myProvider; + + @override + Widget build(BuildContext context) { + const Image decorationImage = Image( + image: AssetImage('assets/icons/game_win.png'), + fit: BoxFit.fill, + ); + + return Container( + margin: const EdgeInsets.all(2), + padding: const EdgeInsets.all(2), + child: Table( + defaultColumnWidth: const IntrinsicColumnWidth(), + children: [ + TableRow( + children: [ + const Column( + children: [decorationImage], + ), + Column( + children: [ + myProvider.animationInProgress + ? decorationImage + : RestartGameButton(myProvider: myProvider) + ], + ), + const Column( + children: [decorationImage], + ), + ], + ), + ], + ), + ); + } +} diff --git a/lib/utils/board_animate.dart b/lib/utils/board_animate.dart index e3f7a93e1b9bde590e5ea10d58c71a1507217908..dd28298a282b09ec9ce4b7d1ce82903616b46dee 100644 --- a/lib/utils/board_animate.dart +++ b/lib/utils/board_animate.dart @@ -4,14 +4,14 @@ import 'package:sudoku/provider/data.dart'; class BoardAnimate { // Start game animation: blinking tiles - static List<List<List<bool>>> createStartGameAnimationPatterns(Data myProvider) { - List<List<List<bool>>> patterns = []; + static AnimatedBoardSequence createStartGameAnimationPatterns(Data myProvider) { + AnimatedBoardSequence patterns = []; int patternsCount = 3; int boardSideLength = myProvider.blockSizeHorizontal * myProvider.blockSizeVertical; for (int patternIndex = 0; patternIndex < patternsCount; patternIndex++) { - List<List<bool>> pattern = []; + AnimatedBoard pattern = []; for (int row = 0; row < boardSideLength; row++) { List<bool> patternRow = []; for (int col = 0; col < boardSideLength; col++) { @@ -26,14 +26,14 @@ class BoardAnimate { } // Win game animation: fill board with colored rows, from bottom to top - static List<List<List<bool>>> createWinGameAnimationPatterns(Data myProvider) { - List<List<List<bool>>> patterns = []; + static AnimatedBoardSequence createWinGameAnimationPatterns(Data myProvider) { + AnimatedBoardSequence patterns = []; int boardSideLength = myProvider.blockSizeHorizontal * myProvider.blockSizeVertical; int patternsCount = boardSideLength + 6; for (int patternIndex = 0; patternIndex < patternsCount; patternIndex++) { - List<List<bool>> pattern = []; + AnimatedBoard pattern = []; for (int row = 0; row < boardSideLength; row++) { List<bool> patternRow = []; for (int col = 0; col < boardSideLength; col++) { @@ -48,14 +48,14 @@ class BoardAnimate { } // Default multi-purpose animation: sliding stripes, from top left to right bottom - static List<List<List<bool>>> createDefaultAnimationPatterns(Data myProvider) { - List<List<List<bool>>> patterns = []; + static AnimatedBoardSequence createDefaultAnimationPatterns(Data myProvider) { + AnimatedBoardSequence patterns = []; int boardSideLength = myProvider.blockSizeHorizontal * myProvider.blockSizeVertical; int patternsCount = boardSideLength; for (int patternIndex = 0; patternIndex < patternsCount; patternIndex++) { - List<List<bool>> pattern = []; + AnimatedBoard pattern = []; for (int row = 0; row < boardSideLength; row++) { List<bool> patternRow = []; for (int col = 0; col < boardSideLength; col++) { @@ -70,7 +70,7 @@ class BoardAnimate { } static void startAnimation(Data myProvider, String animationType) { - List<List<List<bool>>> patterns = []; + AnimatedBoardSequence patterns = []; switch (animationType) { case 'start': diff --git a/lib/utils/board_utils.dart b/lib/utils/board_utils.dart index 624814daff232231479c0f4286c03e79bfd7a00b..8f0a835da2297b5fafebf68e5ba164ba718a8bee 100644 --- a/lib/utils/board_utils.dart +++ b/lib/utils/board_utils.dart @@ -6,7 +6,7 @@ import 'package:sudoku/utils/random_pick_grid.dart'; import 'package:sudoku/utils/tools.dart'; class BoardUtils { - static printGrid(List<List<Cell>> cells, List<List<Cell>> solvedCells) { + static printGrid(Board cells, Board solvedCells) { String stringValues = '0123456789ABCDEFG'; printlog(''); printlog('-------'); @@ -42,16 +42,21 @@ class BoardUtils { myProvider.updateCellsSolved(BoardUtils.getSolvedGrid(myProvider)); myProvider.selectCell(null, null); - printGrid(myProvider.cells, myProvider.cellsSolved); + printGrid(myProvider.board, myProvider.boardSolved); } } - static List<List<Cell>> createEmptyBoard(final int boardSize) { - final List<List<Cell>> cells = []; + static Board createEmptyBoard(final int boardSize) { + final Board cells = []; for (int rowIndex = 0; rowIndex < boardSize; rowIndex++) { final List<Cell> row = []; for (int colIndex = 0; colIndex < boardSize; colIndex++) { - row.add(Cell(0, false)); + row.add(Cell( + row: rowIndex, + col: colIndex, + value: 0, + isFixed: false, + )); } cells.add(row); } @@ -59,8 +64,8 @@ class BoardUtils { return cells; } - static List<List<Cell>> createBoardFromSavedState(Data myProvider, String savedBoard) { - final List<List<Cell>> cells = []; + static Board createBoardFromSavedState(Data myProvider, String savedBoard) { + final Board cells = []; final int boardSize = int.parse(pow((savedBoard.length / 2), 1 / 2).toStringAsFixed(0)); const String stringValues = '0123456789ABCDEFG'; @@ -75,7 +80,12 @@ class BoardUtils { final String isFixedString = savedBoard[index++]; final bool isFixed = (isFixedString != ' '); - row.add(Cell(value, isFixed)); + row.add(Cell( + row: rowIndex, + col: colIndex, + value: value, + isFixed: isFixed, + )); } cells.add(row); } @@ -83,12 +93,17 @@ class BoardUtils { return cells; } - static List<List<Cell>> copyBoard(List cells) { - final List<List<Cell>> copiedGrid = []; + static Board copyBoard(List cells) { + final Board copiedGrid = []; for (int rowIndex = 0; rowIndex < cells.length; rowIndex++) { final List<Cell> row = []; for (int colIndex = 0; colIndex < cells[rowIndex].length; colIndex++) { - row.add(Cell(cells[rowIndex][colIndex].value, false)); + row.add(Cell( + row: rowIndex, + col: colIndex, + value: cells[rowIndex][colIndex].value, + isFixed: false, + )); } copiedGrid.add(row); } @@ -96,8 +111,8 @@ class BoardUtils { return copiedGrid; } - static List<List<Cell>> createBoardFromTemplate(String grid, bool isSymetric) { - List<List<Cell>> cells = []; + static Board createBoardFromTemplate(String grid, bool isSymetric) { + Board cells = []; final int boardSize = int.parse(pow(grid.length, 1 / 2).toStringAsFixed(0)); const String stringValues = '0123456789ABCDEFG'; @@ -108,7 +123,12 @@ class BoardUtils { for (int colIndex = 0; colIndex < boardSize; colIndex++) { final String stringValue = grid[index++]; final int value = stringValues.indexOf(stringValue); - row.add(Cell(value, (value != 0))); + row.add(Cell( + row: rowIndex, + col: colIndex, + value: value, + isFixed: (value != 0), + )); } cells.add(row); } @@ -131,11 +151,15 @@ class BoardUtils { switch (flip) { case 'horizontal': { - final List<List<Cell>> transformedBoard = createEmptyBoard(boardSize); + final Board transformedBoard = createEmptyBoard(boardSize); for (int rowIndex = 0; rowIndex < boardSize; rowIndex++) { for (int colIndex = 0; colIndex < boardSize; colIndex++) { - transformedBoard[rowIndex][colIndex].value = - cells[boardSize - rowIndex - 1][colIndex].value; + transformedBoard[rowIndex][colIndex] = Cell( + row: rowIndex, + col: colIndex, + value: cells[boardSize - rowIndex - 1][colIndex].value, + isFixed: false, + ); } } cells = transformedBoard; @@ -143,11 +167,15 @@ class BoardUtils { break; case 'vertical': { - final List<List<Cell>> transformedBoard = createEmptyBoard(boardSize); + final Board transformedBoard = createEmptyBoard(boardSize); for (int rowIndex = 0; rowIndex < boardSize; rowIndex++) { for (int colIndex = 0; colIndex < boardSize; colIndex++) { - transformedBoard[rowIndex][colIndex].value = - cells[rowIndex][boardSize - colIndex - 1].value; + transformedBoard[rowIndex][colIndex] = Cell( + row: rowIndex, + col: colIndex, + value: cells[rowIndex][boardSize - colIndex - 1].value, + isFixed: false, + ); } } cells = transformedBoard; @@ -158,11 +186,15 @@ class BoardUtils { switch (rotate) { case 'left': { - final List<List<Cell>> transformedBoard = createEmptyBoard(boardSize); + final Board transformedBoard = createEmptyBoard(boardSize); for (int rowIndex = 0; rowIndex < boardSize; rowIndex++) { for (int colIndex = 0; colIndex < boardSize; colIndex++) { - transformedBoard[rowIndex][colIndex].value = - cells[colIndex][boardSize - rowIndex - 1].value; + transformedBoard[rowIndex][colIndex] = Cell( + row: rowIndex, + col: colIndex, + value: cells[colIndex][boardSize - rowIndex - 1].value, + isFixed: false, + ); } } cells = transformedBoard; @@ -170,11 +202,15 @@ class BoardUtils { break; case 'right': { - final List<List<Cell>> transformedBoard = createEmptyBoard(boardSize); + final Board transformedBoard = createEmptyBoard(boardSize); for (int rowIndex = 0; rowIndex < boardSize; rowIndex++) { for (int colIndex = 0; colIndex < boardSize; colIndex++) { - transformedBoard[rowIndex][colIndex].value = - cells[boardSize - colIndex - 1][rowIndex].value; + transformedBoard[rowIndex][colIndex] = Cell( + row: rowIndex, + col: colIndex, + value: cells[boardSize - colIndex - 1][rowIndex].value, + isFixed: false, + ); } } cells = transformedBoard; @@ -185,8 +221,12 @@ class BoardUtils { // Fix cells fixed states for (int rowIndex = 0; rowIndex < boardSize; rowIndex++) { for (int colIndex = 0; colIndex < boardSize; colIndex++) { - cells[rowIndex][colIndex].isFixed = - (cells[rowIndex][colIndex].value != 0) ? true : false; + cells[rowIndex][colIndex] = Cell( + row: rowIndex, + col: colIndex, + value: cells[rowIndex][colIndex].value, + isFixed: (cells[rowIndex][colIndex].value != 0) ? true : false, + ); } } @@ -194,7 +234,8 @@ class BoardUtils { } static bool checkBoardIsSolved(Data myProvider) { - final List<List<Cell>> cells = myProvider.cells; + final Board cells = myProvider.board; + final ConflictsCount conflicts = myProvider.boardConflicts; final int blockSizeHorizontal = myProvider.blockSizeHorizontal; final int blockSizeVertical = myProvider.blockSizeVertical; @@ -207,7 +248,7 @@ class BoardUtils { // check grid is fully completed and does not contain conflict for (int row = 0; row < boardSize; row++) { for (int col = 0; col < boardSize; col++) { - if (cells[row][col].value == 0 || cells[row][col].conflictsCount != 0) { + if (cells[row][col].value == 0 || conflicts[row][col] != 0) { return false; } } @@ -219,7 +260,7 @@ class BoardUtils { } static bool isValueAllowed( - List<List<Cell>> cells, + Board cells, int blockSizeHorizontal, int blockSizeVertical, int? candidateCol, @@ -300,7 +341,8 @@ class BoardUtils { } static void computeConflictsInBoard(Data myProvider) { - final List<List<Cell>> cells = myProvider.cells; + final Board cells = myProvider.board; + final ConflictsCount conflicts = myProvider.boardConflicts; final int blockSizeHorizontal = myProvider.blockSizeHorizontal; final int blockSizeVertical = myProvider.blockSizeVertical; @@ -310,7 +352,7 @@ class BoardUtils { // reset conflict states for (int row = 0; row < boardSize; row++) { for (int col = 0; col < boardSize; col++) { - cells[row][col].conflictsCount = 0; + conflicts[row][col] = 0; } } @@ -328,7 +370,7 @@ class BoardUtils { printlog('line $row contains duplicates'); // Add line to cells in conflict for (int col = 0; col < boardSize; col++) { - cells[row][col].conflictsCount++; + conflicts[row][col]++; } } } @@ -347,7 +389,7 @@ class BoardUtils { printlog('column $col contains duplicates'); // Add column to cells in conflict for (int row = 0; row < boardSize; row++) { - cells[row][col].conflictsCount++; + conflicts[row][col]++; } } } @@ -378,17 +420,19 @@ class BoardUtils { for (int colInBlock = 0; colInBlock < blockSizeHorizontal; colInBlock++) { int row = (blockRow * blockSizeVertical) + rowInBlock; int col = (blockCol * blockSizeHorizontal) + colInBlock; - cells[row][col].conflictsCount++; + conflicts[row][col]++; } } } } } + + myProvider.updateConflicts(conflicts); } static List<List<int>> getCellsWithWrongValue( - final List<List<Cell>> cells, - final List<List<Cell>> cellsSolved, + final Board cells, + final Board cellsSolved, final int blockSizeHorizontal, final int blockSizeVertical, ) { @@ -407,31 +451,8 @@ class BoardUtils { return cellsWithWrongValue; } - static List<List<int>> getConflictingCells( - final List<List<Cell>> cells, - final int blockSizeHorizontal, - final int blockSizeVertical, - ) { - final List<List<int>> conflictingCells = []; - final int boardSize = blockSizeHorizontal * blockSizeVertical; - - for (int row = 0; row < boardSize; row++) { - for (int col = 0; col < boardSize; col++) { - if (!cells[row][col].isFixed && cells[row][col].value != 0) { - if (cells[row][col].conflictsCount != 0 && - !BoardUtils.isValueAllowed(cells, blockSizeHorizontal, blockSizeVertical, col, - row, cells[row][col].value)) { - conflictingCells.add([col, row]); - } - } - } - } - - return conflictingCells; - } - static List<List<int>> getCellsWithUniqueAvailableValue( - List<List<Cell>> cells, + Board cells, final int blockSizeHorizontal, final int blockSizeVertical, ) { @@ -460,8 +481,8 @@ class BoardUtils { return candidateCells; } - static List<List<Cell>> getSolvedGrid(Data myProvider) { - final List<List<Cell>> cells = copyBoard(myProvider.cells); + static Board getSolvedGrid(Data myProvider) { + final Board cells = copyBoard(myProvider.board); final int blockSizeHorizontal = myProvider.blockSizeHorizontal; int blockSizeVertical = myProvider.blockSizeVertical; @@ -479,7 +500,12 @@ class BoardUtils { int col = cellsWithUniqueAvailableValue[i][0]; int row = cellsWithUniqueAvailableValue[i][1]; int value = cellsWithUniqueAvailableValue[i][2]; - cells[row][col].value = value; + cells[row][col] = Cell( + row: row, + col: col, + value: value, + isFixed: cells[row][col].isFixed, + ); } } while (true); diff --git a/lib/utils/game_utils.dart b/lib/utils/game_utils.dart index a9eca6faf37345f66753bbf7f8afb49ac982e9ae..4de2454cd2d382bc54cbe327f308ed9a7546a278 100644 --- a/lib/utils/game_utils.dart +++ b/lib/utils/game_utils.dart @@ -1,4 +1,3 @@ -import 'package:sudoku/entities/cell.dart'; import 'package:sudoku/provider/data.dart'; import 'package:sudoku/utils/board_animate.dart'; import 'package:sudoku/utils/board_utils.dart'; @@ -19,6 +18,8 @@ class GameUtils { myProvider.shuffleCellValues(); myProvider.updateCells(BoardUtils.createEmptyBoard( myProvider.blockSizeHorizontal * myProvider.blockSizeVertical)); + myProvider.initAnimatedBackground(); + myProvider.initConflictsBoard(); BoardUtils.pickGrid(myProvider); BoardAnimate.startAnimation(myProvider, 'start'); } @@ -57,7 +58,7 @@ class GameUtils { } static void showTip(Data myProvider) { - if (myProvider.currentCellCol == null || myProvider.currentCellRow == null) { + if (myProvider.selectedCellCol == null || myProvider.selectedCellRow == null) { // no selected cell -> pick one GameUtils.helpSelectCell(myProvider); } else { @@ -68,14 +69,14 @@ class GameUtils { } static void helpSelectCell(Data myProvider) { - final List<List<Cell>> cells = myProvider.cells; + final Board cells = myProvider.board; final int blockSizeHorizontal = myProvider.blockSizeHorizontal; final int blockSizeVertical = myProvider.blockSizeVertical; // pick one of wrong value cells, if found final List<List<int>> wrongValueCells = BoardUtils.getCellsWithWrongValue( cells, - myProvider.cellsSolved, + myProvider.boardSolved, blockSizeHorizontal, blockSizeVertical, ); @@ -116,7 +117,7 @@ class GameUtils { } static void helpFillCell(Data myProvider) { - final List<List<Cell>> cells = myProvider.cells; + final Board cells = myProvider.board; final int blockSizeHorizontal = myProvider.blockSizeHorizontal; final int blockSizeVertical = myProvider.blockSizeVertical; @@ -129,13 +130,13 @@ class GameUtils { int allowedValuesCount = 0; for (int value = 1; value <= boardSize; value++) { if (BoardUtils.isValueAllowed(cells, blockSizeHorizontal, blockSizeVertical, - myProvider.currentCellCol, myProvider.currentCellRow, value)) { + myProvider.selectedCellCol, myProvider.selectedCellRow, value)) { allowedValuesCount++; eligibleValue = value; } } - myProvider.updateCellValue(myProvider.currentCellCol, myProvider.currentCellRow, + myProvider.updateCellValue(myProvider.selectedCellCol, myProvider.selectedCellRow, allowedValuesCount == 1 ? eligibleValue : 0); myProvider.selectCell(null, null); if (BoardUtils.checkBoardIsSolved(myProvider)) { diff --git a/pubspec.yaml b/pubspec.yaml index 3194707d5756e45b34d8409013fe10fb0073a57d..e4e9a93338de0349d8a000d521a06c44834b5092 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,7 +1,7 @@ name: sudoku description: A sudoku game application. publish_to: 'none' -version: 0.1.16+65 +version: 0.1.17+66 environment: sdk: '^3.0.0'