Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found
Select Git revision

Target

Select target project
  • android/org.benoitharrault.sudoku
1 result
Select Git revision
Show changes
Commits on Source (4)
org.gradle.jvmargs=-Xmx1536M
android.useAndroidX=true
android.enableJetifier=true
app.versionName=0.0.38
app.versionCode=38
app.versionName=0.0.40
app.versionCode=40
Improve tip on grid if cell with wrong value, compute solved grid on new game
Save/retrieve game settings
Amélioration du coup de pouce en cas de cellule avec une valeur fausse, calcul de la grille résolue au début de la partie
Sauvegarde et recharge des paramètres de jeu
......@@ -91,12 +91,16 @@ class Cell {
Color backgroundColor = Colors.grey[200];
List cells = myProvider.cells;
int blockSizeHorizontal = myProvider.blockSizeHorizontal;
int blockSizeVertical = myProvider.blockSizeVertical;
if (
myProvider.showConflicts
&& myProvider.currentCellCol != null
&& myProvider.currentCellRow != null
) {
if (!BoardUtils.isValueAllowed(myProvider, myProvider.currentCellCol, myProvider.currentCellRow, this.value)) {
if (!BoardUtils.isValueAllowed(cells, blockSizeHorizontal, blockSizeVertical, myProvider.currentCellCol, myProvider.currentCellRow, this.value)) {
backgroundColor = Colors.pink[100];
}
}
......
import 'package:flutter/foundation.dart';
import 'package:shared_preferences/shared_preferences.dart';
class Data extends ChangeNotifier {
......@@ -12,9 +13,12 @@ class Data extends ChangeNotifier {
List get availableSkins => _availableSkins;
// Application default configuration
String _level = 'medium';
String _size = '3x3';
String _skin = 'default';
String _level = null;
String _levelDefault = 'medium';
String _size = null;
String _sizeDefault = '3x3';
String _skin = null;
String _skinDefault = 'default';
bool _showConflicts = false;
// Game data
......@@ -22,6 +26,7 @@ class Data extends ChangeNotifier {
int _blockSizeVertical = null;
int _blockSizeHorizontal = null;
List _cells = [];
List _cellsSolved = [];
int _currentCellCol = null;
int _currentCellRow = null;
int _currentCellValue = null;
......@@ -77,7 +82,7 @@ class Data extends ChangeNotifier {
}
}
setParameterValue(String parameterCode, String parameterValue) {
setParameterValue(String parameterCode, String parameterValue) async {
switch(parameterCode) {
case 'difficulty': { updateLevel = parameterValue; }
break;
......@@ -86,6 +91,15 @@ class Data extends ChangeNotifier {
case 'skin': { updateSkin = parameterValue; }
break;
}
final prefs = await SharedPreferences.getInstance();
prefs.setString(parameterCode, parameterValue);
}
void initParametersValues() async {
final prefs = await SharedPreferences.getInstance();
setParameterValue('difficulty', prefs.getString('difficulty') ?? _levelDefault);
setParameterValue('size', prefs.getString('size') ?? _sizeDefault);
setParameterValue('skin', prefs.getString('skin') ?? _skinDefault);
}
List get cells => _cells;
......@@ -94,6 +108,11 @@ class Data extends ChangeNotifier {
notifyListeners();
}
List get cellsSolved => _cellsSolved;
set updateCellsSolved(List cells) {
_cellsSolved = cells;
}
int get currentCellCol => _currentCellCol;
set updateCurrentCellCol(int currentCellCol) {
_currentCellCol = currentCellCol;
......
......@@ -7,9 +7,22 @@ import '../layout/parameters.dart';
import '../provider/data.dart';
import '../utils/game_utils.dart';
class Home extends StatelessWidget {
class Home extends StatefulWidget {
static const String id = 'home';
@override
_HomeState createState() => _HomeState();
}
class _HomeState extends State<Home> {
@override
void initState() {
super.initState();
Data myProvider = Provider.of<Data>(context, listen: false);
myProvider.initParametersValues();
}
@override
Widget build(BuildContext context) {
Data myProvider = Provider.of<Data>(context);
......
......@@ -6,16 +6,18 @@ import '../provider/data.dart';
class BoardUtils {
static printGrid(List cells) {
static printGrid(List cells, List solvedCells) {
String stringValues = '0123456789ABCDEFG';
print('');
print('-------');
for (var rowIndex = 0; rowIndex < cells.length; rowIndex++) {
String row = '';
String rowSolved = '';
for (var colIndex = 0; colIndex < cells[rowIndex].length; colIndex++) {
row += stringValues[cells[rowIndex][colIndex].value];
rowSolved += stringValues[solvedCells[rowIndex][colIndex].value];
}
print(row);
print(row + ' | ' + rowSolved);
}
print('-------');
print('');
......@@ -40,13 +42,14 @@ class BoardUtils {
print('Picked grid from template: ' + grid);
bool isSymetric = (blockSizeHorizontal == blockSizeVertical);
myProvider.updateCells = BoardUtils.createBoardFromTemplate(grid, isSymetric);
myProvider.updateCellsSolved = BoardUtils.getSolvedGrid(myProvider);
myProvider.selectCell(null, null);
printGrid(myProvider.cells, myProvider.cellsSolved);
}
}
static List createEmptyBoard(int boardSize) {
int index = 0;
List cells = [];
for (var rowIndex = 0; rowIndex < boardSize; rowIndex++) {
List row = [];
......@@ -59,6 +62,18 @@ class BoardUtils {
return cells;
}
static List copyBoard(List cells) {
List copiedGrid = [];
for (var rowIndex = 0; rowIndex < cells.length; rowIndex++) {
List row = [];
for (var colIndex = 0; colIndex < cells[rowIndex].length; colIndex++) {
row.add(Cell(cells[rowIndex][colIndex].value, false));
}
copiedGrid.add(row);
}
return copiedGrid;
}
static List createBoardFromTemplate(String grid, bool isSymetric) {
List cells = [];
......@@ -145,12 +160,9 @@ class BoardUtils {
}
}
printGrid(cells);
return cells;
}
static bool checkBoardIsSolved(Data myProvider) {
List cells = myProvider.cells;
......@@ -178,16 +190,11 @@ class BoardUtils {
return true;
}
static bool isValueAllowed(Data myProvider, int candidateCol, int candidateRow, int candidateValue) {
static bool isValueAllowed(List cells, int blockSizeHorizontal, int blockSizeVertical, int candidateCol, int candidateRow, int candidateValue) {
if (candidateValue == 0) {
return true;
}
List cells = myProvider.cells;
int blockSizeHorizontal = myProvider.blockSizeHorizontal;
int blockSizeVertical = myProvider.blockSizeVertical;
int boardSize = blockSizeHorizontal * blockSizeVertical;
// check lines does not contains a value twice
......@@ -257,7 +264,6 @@ class BoardUtils {
return true;
}
static void computeConflictsInBoard(Data myProvider) {
List cells = myProvider.cells;
......@@ -345,4 +351,82 @@ class BoardUtils {
}
}
static List getCellsWithWrongValue(List cells, List cellsSolved, int blockSizeHorizontal, int blockSizeVertical) {
List cellsWithWrongValue = [];
int boardSize = blockSizeHorizontal * blockSizeVertical;
for (var row = 0; row < boardSize; row++) {
for (var col = 0; col < boardSize; col++) {
if (cells[row][col].value != 0 && cells[row][col].value != cellsSolved[row][col].value) {
cellsWithWrongValue.add([col, row]);
}
}
}
return cellsWithWrongValue;
}
static List getConflictingCells(List cells, int blockSizeHorizontal, int blockSizeVertical) {
List conflictingCells = [];
int boardSize = blockSizeHorizontal * blockSizeVertical;
for (var row = 0; row < boardSize; row++) {
for (var 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 getCellsWithUniqueAvailableValue(List cells, int blockSizeHorizontal, int blockSizeVertical) {
List candidateCells = [];
int boardSize = blockSizeHorizontal * blockSizeVertical;
for (var row = 0; row < boardSize; row++) {
for (var col = 0; col < boardSize; col++) {
if (cells[row][col].value == 0) {
int allowedValuesCount = 0;
int candidateValue = 0;
for (var value = 1; value <= boardSize; value++) {
if (BoardUtils.isValueAllowed(cells, blockSizeHorizontal, blockSizeVertical, col, row, value)) {
candidateValue = value;
allowedValuesCount++;
}
}
if (allowedValuesCount == 1) {
candidateCells.add([col, row, candidateValue]);
}
}
}
}
return candidateCells;
}
static List getSolvedGrid(Data myProvider) {
List cells = copyBoard(myProvider.cells);
int blockSizeHorizontal = myProvider.blockSizeHorizontal;
int blockSizeVertical = myProvider.blockSizeVertical;
do {
List cellsWithUniqueAvailableValue = BoardUtils.getCellsWithUniqueAvailableValue(cells, blockSizeHorizontal, blockSizeVertical);
if (cellsWithUniqueAvailableValue.length == 0) {
break;
}
for (var i = 0; i < cellsWithUniqueAvailableValue.length; i++) {
int col = cellsWithUniqueAvailableValue[i][0];
int row = cellsWithUniqueAvailableValue[i][1];
int value = cellsWithUniqueAvailableValue[i][2];
cells[row][col].value = value;
}
} while (true);
return cells;
}
}
......@@ -29,42 +29,25 @@ class GameUtils {
static void helpSelectCell(Data myProvider) {
List cells = myProvider.cells;
int boardSize = myProvider.blockSizeHorizontal * myProvider.blockSizeVertical;
int blockSizeHorizontal = myProvider.blockSizeHorizontal;
int blockSizeVertical = myProvider.blockSizeVertical;
// pick one of conflicting cells, if found
List conflictingCells = [];
for (var row = 0; row < boardSize; row++) {
for (var col = 0; col < boardSize; col++) {
if (!cells[row][col].isFixed && cells[row][col].value != 0) {
if (cells[row][col].conflictsCount != 0 && !BoardUtils.isValueAllowed(myProvider, col, row, cells[row][col].value)) {
conflictingCells.add([col, row]);
}
}
}
// pick one of wrong value cells, if found
List wrongValueCells = BoardUtils.getCellsWithWrongValue(cells, myProvider.cellsSolved, blockSizeHorizontal, blockSizeVertical);
if (wrongValueCells.length != 0) {
GameUtils.pickRandomFromList(myProvider, wrongValueCells);
return;
}
// pick one of conflicting cells, if found
List conflictingCells = BoardUtils.getCellsWithUniqueAvailableValue(cells, blockSizeHorizontal, blockSizeVertical);
if (conflictingCells.length != 0) {
GameUtils.pickRandomFromList(myProvider, conflictingCells);
return;
}
// pick one form cells with unique non-conflicting candidate value
List candidateCells = [];
for (var row = 0; row < boardSize; row++) {
for (var col = 0; col < boardSize; col++) {
if (cells[row][col].value == 0) {
int allowedValuesCount = 0;
for (var value = 1; value <= boardSize; value++) {
if (BoardUtils.isValueAllowed(myProvider, col, row, value)) {
allowedValuesCount++;
}
}
if (allowedValuesCount == 1) {
candidateCells.add([col, row]);
}
}
}
}
List candidateCells = BoardUtils.getCellsWithUniqueAvailableValue(cells, blockSizeHorizontal, blockSizeVertical);
if (candidateCells.length != 0) {
GameUtils.pickRandomFromList(myProvider, candidateCells);
return;
......@@ -80,14 +63,19 @@ class GameUtils {
}
static void helpFillCell(Data myProvider) {
int boardSize = myProvider.blockSizeHorizontal * myProvider.blockSizeVertical;
List cells = myProvider.cells;
int blockSizeHorizontal = myProvider.blockSizeHorizontal;
int blockSizeVertical = myProvider.blockSizeVertical;
int boardSize = blockSizeHorizontal * blockSizeVertical;
// Will clean cell if no eligible value found
int eligibleValue = 0;
// ensure there is only one eligible value for this cell
int allowedValuesCount = 0;
for (var value = 1; value <= boardSize; value++) {
if (BoardUtils.isValueAllowed(myProvider, myProvider.currentCellCol, myProvider.currentCellRow, value)) {
if (BoardUtils.isValueAllowed(cells, blockSizeHorizontal, blockSizeVertical, myProvider.currentCellCol, myProvider.currentCellRow, value)) {
allowedValuesCount++;
eligibleValue = value;
}
......@@ -97,4 +85,5 @@ class GameUtils {
myProvider.selectCell(null, null);
BoardUtils.computeConflictsInBoard(myProvider);
}
}
......@@ -35,7 +35,7 @@ packages:
name: charcode
url: "https://pub.dartlang.org"
source: hosted
version: "1.2.0"
version: "1.3.1"
clock:
dependency: transitive
description:
......@@ -57,6 +57,20 @@ packages:
url: "https://pub.dartlang.org"
source: hosted
version: "1.2.0"
ffi:
dependency: transitive
description:
name: ffi
url: "https://pub.dartlang.org"
source: hosted
version: "1.1.2"
file:
dependency: transitive
description:
name: file
url: "https://pub.dartlang.org"
source: hosted
version: "6.1.2"
flutter:
dependency: "direct main"
description: flutter
......@@ -67,6 +81,18 @@ packages:
description: flutter
source: sdk
version: "0.0.0"
flutter_web_plugins:
dependency: transitive
description: flutter
source: sdk
version: "0.0.0"
js:
dependency: transitive
description:
name: js
url: "https://pub.dartlang.org"
source: hosted
version: "0.6.3"
matcher:
dependency: transitive
description:
......@@ -80,7 +106,7 @@ packages:
name: meta
url: "https://pub.dartlang.org"
source: hosted
version: "1.4.0"
version: "1.7.0"
nested:
dependency: transitive
description:
......@@ -95,6 +121,48 @@ packages:
url: "https://pub.dartlang.org"
source: hosted
version: "1.8.0"
path_provider_linux:
dependency: transitive
description:
name: path_provider_linux
url: "https://pub.dartlang.org"
source: hosted
version: "2.0.2"
path_provider_platform_interface:
dependency: transitive
description:
name: path_provider_platform_interface
url: "https://pub.dartlang.org"
source: hosted
version: "2.0.1"
path_provider_windows:
dependency: transitive
description:
name: path_provider_windows
url: "https://pub.dartlang.org"
source: hosted
version: "2.0.3"
platform:
dependency: transitive
description:
name: platform
url: "https://pub.dartlang.org"
source: hosted
version: "3.0.0"
plugin_platform_interface:
dependency: transitive
description:
name: plugin_platform_interface
url: "https://pub.dartlang.org"
source: hosted
version: "2.0.1"
process:
dependency: transitive
description:
name: process
url: "https://pub.dartlang.org"
source: hosted
version: "4.2.3"
provider:
dependency: "direct main"
description:
......@@ -102,6 +170,48 @@ packages:
url: "https://pub.dartlang.org"
source: hosted
version: "5.0.0"
shared_preferences:
dependency: "direct main"
description:
name: shared_preferences
url: "https://pub.dartlang.org"
source: hosted
version: "2.0.6"
shared_preferences_linux:
dependency: transitive
description:
name: shared_preferences_linux
url: "https://pub.dartlang.org"
source: hosted
version: "2.0.2"
shared_preferences_macos:
dependency: transitive
description:
name: shared_preferences_macos
url: "https://pub.dartlang.org"
source: hosted
version: "2.0.2"
shared_preferences_platform_interface:
dependency: transitive
description:
name: shared_preferences_platform_interface
url: "https://pub.dartlang.org"
source: hosted
version: "2.0.0"
shared_preferences_web:
dependency: transitive
description:
name: shared_preferences_web
url: "https://pub.dartlang.org"
source: hosted
version: "2.0.1"
shared_preferences_windows:
dependency: transitive
description:
name: shared_preferences_windows
url: "https://pub.dartlang.org"
source: hosted
version: "2.0.2"
sky_engine:
dependency: transitive
description: flutter
......@@ -148,7 +258,7 @@ packages:
name: test_api
url: "https://pub.dartlang.org"
source: hosted
version: "0.4.0"
version: "0.4.1"
typed_data:
dependency: transitive
description:
......@@ -163,6 +273,20 @@ packages:
url: "https://pub.dartlang.org"
source: hosted
version: "2.1.0"
win32:
dependency: transitive
description:
name: win32
url: "https://pub.dartlang.org"
source: hosted
version: "2.2.5"
xdg_directories:
dependency: transitive
description:
name: xdg_directories
url: "https://pub.dartlang.org"
source: hosted
version: "0.2.0"
sdks:
dart: ">=2.12.0 <3.0.0"
flutter: ">=1.16.0"
dart: ">=2.13.0 <3.0.0"
flutter: ">=2.0.0"
......@@ -11,6 +11,7 @@ dependencies:
sdk: flutter
provider: ^5.0.0
badges: ^2.0.1
shared_preferences: ^2.0.6
dev_dependencies:
flutter_test:
......