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
  • 23-add-timer
  • 65-update-icons
  • 82-fix-colors
  • 84-improve-app-metadata
  • master
  • Release_0.0.16_16
  • Release_0.0.17_17
  • Release_0.0.18_18
  • Release_0.0.19_19
  • Release_0.0.20_20
  • Release_0.0.21_21
  • Release_0.0.22_22
  • Release_0.0.23_23
  • Release_0.0.24_24
  • Release_0.0.25_25
  • Release_0.0.26_26
  • Release_0.0.27_27
  • Release_0.0.28_28
  • Release_0.0.29_29
  • Release_0.0.30_30
  • Release_0.0.31_31
  • Release_0.0.32_32
  • Release_0.0.33_33
  • Release_0.0.34_34
  • Release_0.0.35_35
  • Release_0.0.36_36
  • Release_0.0.37_37
  • Release_0.0.38_38
  • Release_0.0.39_39
  • Release_0.0.40_40
  • Release_0.0.41_41
  • Release_0.0.42_42
  • Release_0.0.43_43
  • Release_0.0.44_44
  • Release_0.0.45_45
  • Release_0.0.46_46
  • Release_0.0.47_47
  • Release_0.0.48_48
  • Release_0.1.0_49
  • Release_0.1.10_59
  • Release_0.1.11_60
  • Release_0.1.12_61
  • Release_0.1.13_62
  • Release_0.1.14_63
  • Release_0.1.15_64
  • Release_0.1.16_65
  • Release_0.1.17_66
  • Release_0.1.18_67
  • Release_0.1.19_68
  • Release_0.1.1_50
  • Release_0.1.20_69
  • Release_0.1.21_70
  • Release_0.1.22_71
  • Release_0.1.2_51
  • Release_0.1.3_52
  • Release_0.1.4_53
  • Release_0.1.5_54
  • Release_0.1.6_55
  • Release_0.1.7_56
  • Release_0.1.8_57
  • Release_0.1.9_58
  • Release_0.10.0_87
  • Release_0.2.0_72
  • Release_0.2.1_73
  • Release_0.3.0_74
  • Release_0.3.1_75
  • Release_0.4.0_76
  • Release_0.4.1_77
  • Release_0.5.0_78
  • Release_0.5.1_79
  • Release_0.5.2_80
  • Release_0.6.0_81
  • Release_0.7.0_82
  • Release_0.8.0_83
  • Release_0.9.0_84
  • Release_0.9.1_85
  • Release_0.9.2_86
77 results

Target

Select target project
  • android/org.benoitharrault.sudoku
1 result
Select Git revision
  • 23-add-timer
  • 65-update-icons
  • 82-fix-colors
  • 84-improve-app-metadata
  • master
  • Release_0.0.16_16
  • Release_0.0.17_17
  • Release_0.0.18_18
  • Release_0.0.19_19
  • Release_0.0.20_20
  • Release_0.0.21_21
  • Release_0.0.22_22
  • Release_0.0.23_23
  • Release_0.0.24_24
  • Release_0.0.25_25
  • Release_0.0.26_26
  • Release_0.0.27_27
  • Release_0.0.28_28
  • Release_0.0.29_29
  • Release_0.0.30_30
  • Release_0.0.31_31
  • Release_0.0.32_32
  • Release_0.0.33_33
  • Release_0.0.34_34
  • Release_0.0.35_35
  • Release_0.0.36_36
  • Release_0.0.37_37
  • Release_0.0.38_38
  • Release_0.0.39_39
  • Release_0.0.40_40
  • Release_0.0.41_41
  • Release_0.0.42_42
  • Release_0.0.43_43
  • Release_0.0.44_44
  • Release_0.0.45_45
  • Release_0.0.46_46
  • Release_0.0.47_47
  • Release_0.0.48_48
  • Release_0.1.0_49
  • Release_0.1.10_59
  • Release_0.1.11_60
  • Release_0.1.12_61
  • Release_0.1.13_62
  • Release_0.1.14_63
  • Release_0.1.15_64
  • Release_0.1.16_65
  • Release_0.1.17_66
  • Release_0.1.18_67
  • Release_0.1.19_68
  • Release_0.1.1_50
  • Release_0.1.20_69
  • Release_0.1.21_70
  • Release_0.1.22_71
  • Release_0.1.2_51
  • Release_0.1.3_52
  • Release_0.1.4_53
  • Release_0.1.5_54
  • Release_0.1.6_55
  • Release_0.1.7_56
  • Release_0.1.8_57
  • Release_0.1.9_58
  • Release_0.10.0_87
  • Release_0.2.0_72
  • Release_0.2.1_73
  • Release_0.3.0_74
  • Release_0.3.1_75
  • Release_0.4.0_76
  • Release_0.4.1_77
  • Release_0.5.0_78
  • Release_0.5.1_79
  • Release_0.5.2_80
  • Release_0.6.0_81
  • Release_0.7.0_82
  • Release_0.8.0_83
  • Release_0.9.0_84
  • Release_0.9.1_85
  • Release_0.9.2_86
77 results
Show changes
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import '../provider/data.dart'; import '../provider/data.dart';
class Cell { class Cell {
int value; int value;
final int col;
final int row;
bool isFixed; bool isFixed;
int conflictsCount = 0; int conflictsCount = 0;
Cell( Cell(
@required this.value, @required this.value,
@required this.col,
@required this.row,
@required this.isFixed, @required this.isFixed,
); );
Container widget(Data myProvider) { static double cellBorderWidth = 3;
static Color cellBorderDarkColor = Colors.black;
static Color cellBorderLightColor = Colors.grey;
static Color cellBorderSelectedColor = Colors.red;
Container widget(Data myProvider, Border borders, int row, int col) {
String imageAsset = 'assets/skins/empty.png'; String imageAsset = 'assets/skins/empty.png';
if (this.value > 0) { if (this.value > 0) {
imageAsset = 'assets/skins/' + myProvider.skin + '_' + this.value.toString() + '.png'; imageAsset = 'assets/skins/' + myProvider.skin + '_' + this.value.toString() + '.png';
} }
int size = myProvider.size;
double borderWidth = 3;
Color borderDarkColor = Colors.black;
Color borderLightColor = Colors.grey;
Color borderSelectedColor = Colors.red;
Color backgroundColor = this.getBackgroundColor(myProvider);
Border borders = Border(
top: BorderSide(width: borderWidth, color: ((this.row % size) == 0) ? borderDarkColor : borderLightColor),
left: BorderSide(width: borderWidth, color: ((this.col % size) == 0) ? borderDarkColor : borderLightColor),
right: BorderSide(width: borderWidth, color: (((this.col + 1) % size) == 0) ? borderDarkColor : borderLightColor),
bottom: BorderSide(width: borderWidth, color: (((this.row + 1) % size) == 0) ? borderDarkColor : borderLightColor),
);
if (this.col == myProvider.currentCellCol && this.row == myProvider.currentCellRow) {
borders = Border.all(
color: borderSelectedColor,
width: borderWidth,
);
}
return Container( return Container(
decoration: BoxDecoration( decoration: BoxDecoration(
color: backgroundColor, color: this.getBackgroundColor(myProvider),
border: borders, border: borders,
), ),
child: GestureDetector( child: GestureDetector(
...@@ -56,9 +34,9 @@ class Cell { ...@@ -56,9 +34,9 @@ class Cell {
fit: BoxFit.fill fit: BoxFit.fill
), ),
onTap: () { onTap: () {
if (this.col != null && this.row != null) { if (col != null && row != null) {
if (!this.isFixed && (this.col != myProvider.currentCellCol || this.row != myProvider.currentCellRow)) { if (col != myProvider.currentCellCol || row != myProvider.currentCellRow) {
myProvider.selectCell(this.col, this.row); myProvider.selectCell(col, row);
} else { } else {
myProvider.selectCell(null, null); myProvider.selectCell(null, null);
} }
...@@ -73,6 +51,8 @@ class Cell { ...@@ -73,6 +51,8 @@ class Cell {
Color editableCellColorConflict = Colors.pink[100]; Color editableCellColorConflict = Colors.pink[100];
Color fixedCellColor = Colors.grey[300]; Color fixedCellColor = Colors.grey[300];
Color fixedCellColorConflict = Colors.pink[200]; Color fixedCellColorConflict = Colors.pink[200];
Color editableSelectedValueColor = Colors.green[100];
Color fixedSelectedValueColor = Colors.green[300];
Color backgroundColor = editableCellColor; Color backgroundColor = editableCellColor;
...@@ -88,6 +68,14 @@ class Cell { ...@@ -88,6 +68,14 @@ class Cell {
} }
} }
if (myProvider.showConflicts && (this.value == myProvider.currentCellValue)) {
if (this.isFixed) {
backgroundColor = fixedSelectedValueColor;
} else {
backgroundColor = editableSelectedValueColor;
}
}
return backgroundColor; return backgroundColor;
} }
...@@ -111,12 +99,34 @@ class Cell { ...@@ -111,12 +99,34 @@ class Cell {
fit: BoxFit.fill fit: BoxFit.fill
), ),
onTap: () { onTap: () {
if (this.col != null && this.row != null) { if (myProvider.currentCellCol != null && myProvider.currentCellRow != null) {
myProvider.updateCellValue(this.col, this.row, this.value); myProvider.updateCellValue(myProvider.currentCellCol, myProvider.currentCellRow, this.value);
} }
myProvider.selectCell(null, null); myProvider.selectCell(null, null);
}, },
) )
); );
} }
static Border getCellBorders(Data myProvider, int row, int col) {
int blockSizeHorizontal = myProvider.blockSizeHorizontal;
int blockSizeVertical = myProvider.blockSizeVertical;
Border borders = Border.all(
color: cellBorderSelectedColor,
width: cellBorderWidth,
);
if (col != myProvider.currentCellCol || row != myProvider.currentCellRow) {
borders = Border(
top: BorderSide(width: cellBorderWidth, color: ((row % blockSizeVertical) == 0) ? cellBorderDarkColor : cellBorderLightColor),
left: BorderSide(width: cellBorderWidth, color: ((col % blockSizeHorizontal) == 0) ? cellBorderDarkColor : cellBorderLightColor),
right: BorderSide(width: cellBorderWidth, color: (((col + 1) % blockSizeHorizontal) == 0) ? cellBorderDarkColor : cellBorderLightColor),
bottom: BorderSide(width: cellBorderWidth, color: (((row + 1) % blockSizeVertical) == 0) ? cellBorderDarkColor : cellBorderLightColor),
);
}
return borders;
}
} }
import 'dart:math';
import 'package:flutter/material.dart';
import '../entities/cell.dart';
import '../provider/data.dart';
import '../utils/board_utils.dart';
class Board {
static Container buildGameBoard(Data myProvider) {
Color borderColor = BoardUtils.checkBoardIsSolved(myProvider) ? Colors.green : Colors.orange;
return Container(
margin: EdgeInsets.all(2),
padding: EdgeInsets.all(2),
decoration: BoxDecoration(
color: borderColor,
borderRadius: BorderRadius.circular(2),
border: Border.all(
color: borderColor,
width: 2,
),
),
child: buildGameTileset(myProvider),
);
}
static Table buildGameTileset(Data myProvider) {
int boardSize = myProvider.blockSizeHorizontal * myProvider.blockSizeVertical;
List cells = myProvider.cells;
return Table(
defaultColumnWidth: IntrinsicColumnWidth(),
children: [
for (var row = 0; row < boardSize; row++)
TableRow(children: [
for (var col = 0; col < boardSize; col++)
Column(children: [
cells[row][col].widget(
myProvider,
Cell.getCellBorders(myProvider, row, col),
row,
col
)
]),
]),
]
);
}
}
import 'dart:math';
import 'package:flutter/material.dart';
import '../entities/cell.dart';
import '../layout/board.dart';
import '../provider/data.dart';
import '../utils/board_utils.dart';
class Game {
static Container buildGameWidget(Data myProvider) {
return Container(
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Board.buildGameBoard(myProvider),
SizedBox(height: 2),
Game.buildSelectCellValueBar(myProvider)
],
),
);
}
static Container buildSelectCellValueBar(Data myProvider) {
List cells = myProvider.cells;
Color borderColor = Colors.blue;
bool isCellSelected = (myProvider.currentCellCol != null && myProvider.currentCellRow != null);
bool isUpdatableCellSelected = isCellSelected ? !myProvider.cells[myProvider.currentCellRow][myProvider.currentCellCol].isFixed : false;
int maxValue = myProvider.blockSizeHorizontal * myProvider.blockSizeVertical;
return Container(
margin: EdgeInsets.all(2),
padding: EdgeInsets.all(2),
child: Table(
defaultColumnWidth: IntrinsicColumnWidth(),
children: [
TableRow(
children: [
for (var value = 0; value <= maxValue; value++)
Column(
children: [
Cell(
isUpdatableCellSelected ? value : 0,
false
).widgetUpdateValue(myProvider)
]
),
]
),
]
),
);
}
}
import 'package:flutter/material.dart';
import '../provider/data.dart';
import '../utils/game_utils.dart';
class Parameters {
static const double _parameterButtonSize = 70;
static const double _startButtonSize = 150;
static Container buildParametersSelector(Data myProvider) {
return Container(
child: Column(
mainAxisSize: MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.center,
children: [
Parameters.buildParameterSelector(myProvider, 'difficulty'),
Parameters.buildParameterSelector(myProvider, 'size'),
Parameters.buildParameterSelector(myProvider, 'skin'),
Parameters.buildStartGameButton(myProvider),
],
),
);
}
static Column buildStartGameButton(Data myProvider) {
return Column(
mainAxisSize: MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.center,
children: [
FlatButton(
child: Image(
image: AssetImage('assets/icons/button_start.png'),
width: _startButtonSize,
height: _startButtonSize,
fit: BoxFit.fill
),
onPressed: () => GameUtils.startGame(myProvider),
)
],
);
}
static Column buildParameterSelector(Data myProvider, String parameterCode) {
List availableValues = myProvider.getParameterAvailableValues(parameterCode);
return Column(
children: [
Table(
defaultColumnWidth: IntrinsicColumnWidth(),
children: [
TableRow(
children: [
for (var index = 0; index < availableValues.length; index++)
Column(
children: [
_buildParameterButton(myProvider, parameterCode, availableValues[index])
]
),
],
),
],
),
SizedBox(height: 20),
]
);
}
static FlatButton _buildParameterButton(Data myProvider, String parameterCode, String parameterValue) {
String currentValue = myProvider.getParameterValue(parameterCode).toString();
bool isActive = (parameterValue == currentValue);
String imageAsset = 'assets/icons/' + parameterCode + '_' + parameterValue + '.png';
return FlatButton(
child: Container(
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(10),
border: Border.all(
color: isActive ? Colors.blue : Colors.white,
width: 10,
),
),
child: Image(
image: AssetImage(imageAsset),
width: _parameterButtonSize,
height: _parameterButtonSize,
fit: BoxFit.fill
),
),
onPressed: () => myProvider.setParameterValue(parameterCode, parameterValue),
);
}
}
...@@ -4,7 +4,7 @@ class Data extends ChangeNotifier { ...@@ -4,7 +4,7 @@ class Data extends ChangeNotifier {
// Configuration available values // Configuration available values
List _availableDifficultyLevels = ['easy', 'medium', 'hard']; List _availableDifficultyLevels = ['easy', 'medium', 'hard'];
List _availableSizes = [2, 3]; List _availableSizes = ['2x2', '3x2', '3x3'];
List _availableSkins = ['default', 'food', 'nature']; List _availableSkins = ['default', 'food', 'nature'];
List get availableDifficultyLevels => _availableDifficultyLevels; List get availableDifficultyLevels => _availableDifficultyLevels;
...@@ -13,15 +13,18 @@ class Data extends ChangeNotifier { ...@@ -13,15 +13,18 @@ class Data extends ChangeNotifier {
// Application default configuration // Application default configuration
String _level = 'medium'; String _level = 'medium';
int _size = 3; String _size = '3x3';
String _skin = 'default'; String _skin = 'default';
bool _showConflicts = false; bool _showConflicts = false;
// Game data // Game data
bool _stateRunning = false; bool _stateRunning = false;
int _blockSizeVertical = null;
int _blockSizeHorizontal = null;
List _cells = []; List _cells = [];
int _currentCellCol = null; int _currentCellCol = null;
int _currentCellRow = null; int _currentCellRow = null;
int _currentCellValue = null;
String get level => _level; String get level => _level;
set updateLevel(String level) { set updateLevel(String level) {
...@@ -29,9 +32,13 @@ class Data extends ChangeNotifier { ...@@ -29,9 +32,13 @@ class Data extends ChangeNotifier {
notifyListeners(); notifyListeners();
} }
int get size => _size; String get size => _size;
set updateSize(int size) { int get blockSizeVertical => _blockSizeVertical;
int get blockSizeHorizontal => _blockSizeHorizontal;
set updateSize(String size) {
_size = size; _size = size;
_blockSizeHorizontal = int.parse(_size.split('x')[0]);
_blockSizeVertical = int.parse(_size.split('x')[1]);
notifyListeners(); notifyListeners();
} }
...@@ -69,7 +76,7 @@ class Data extends ChangeNotifier { ...@@ -69,7 +76,7 @@ class Data extends ChangeNotifier {
} }
} }
setParameterValue(String parameterCode, var parameterValue) { setParameterValue(String parameterCode, String parameterValue) {
switch(parameterCode) { switch(parameterCode) {
case 'difficulty': { updateLevel = parameterValue; } case 'difficulty': { updateLevel = parameterValue; }
break; break;
...@@ -98,9 +105,21 @@ class Data extends ChangeNotifier { ...@@ -98,9 +105,21 @@ class Data extends ChangeNotifier {
notifyListeners(); notifyListeners();
} }
int get currentCellValue => _currentCellValue;
set updateCurrentCellValue(int currentCellValue) {
_currentCellValue = currentCellValue;
notifyListeners();
}
selectCell(int col, int row) { selectCell(int col, int row) {
_currentCellCol = col; _currentCellCol = col;
_currentCellRow = row; _currentCellRow = row;
_currentCellValue = null;
if (row != null && col != null) {
if (_cells[row][col].value != 0) {
_currentCellValue = _cells[row][col].value;
}
}
notifyListeners(); notifyListeners();
} }
......
import 'dart:math';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
import '../entities/cell.dart'; import '../layout/game.dart';
import '../layout/parameters.dart';
import '../provider/data.dart'; import '../provider/data.dart';
import '../utils/random_pick_grid.dart'; import '../utils/game_utils.dart';
class Home extends StatelessWidget { class Home extends StatelessWidget {
static const String id = 'home'; static const String id = 'home';
static const double _parameterButtonSize = 70;
static const double _startButtonSize = 150;
Future<void> resetGame(Data myProvider) async {
myProvider.updateStateRunning = false;
}
Future<void> startGame(Data myProvider) async {
myProvider.updateStateRunning = true;
myProvider.updateCells = createEmptyBoard(myProvider.size);
pickGrid(myProvider);
}
printGrid(List cells) {
print('');
print('-------');
for (var rowIndex = 0; rowIndex < cells.length; rowIndex++) {
String row = '';
for (var colIndex = 0; colIndex < cells[rowIndex].length; colIndex++) {
row += cells[rowIndex][colIndex].value.toString();
}
print(row);
}
print('-------');
print('');
}
Future<void> pickGrid(Data myProvider) async {
int size = myProvider.size;
String grid;
RandomPickGrid randomPickGrid;
randomPickGrid = RandomPickGrid();
await randomPickGrid.init(myProvider.level, size);
if (randomPickGrid.grid != null) {
grid = randomPickGrid.grid;
}
if (grid.length == pow(size, 4)) {
myProvider.updateCells = createBoardFromTemplate(grid);
}
}
List createBoardFromTemplate(String grid) {
List cells = [];
int size = int.parse(pow(grid.length, 1/4).toStringAsFixed(0));
int sideLength = pow(size, 2);
int index = 0;
for (var rowIndex = 0; rowIndex < sideLength; rowIndex++) {
List row = [];
for (var colIndex = 0; colIndex < sideLength; colIndex++) {
int value = int.parse(grid[index++]);
row.add(Cell(value, colIndex, rowIndex, (value != 0)));
}
cells.add(row);
}
List<String> allowedFlip = ['', 'horizontal', 'vertical'];
List<String> allowedRotate = ['', 'left', 'right'];
var rand = new Random();
String flip = allowedFlip[rand.nextInt(allowedFlip.length)];
String rotate = allowedRotate[rand.nextInt(allowedRotate.length)];
switch(flip) {
case 'horizontal': {
List transformedBoard = createEmptyBoard(size);
for (var rowIndex = 0; rowIndex < sideLength; rowIndex++) {
for (var colIndex = 0; colIndex < sideLength; colIndex++) {
transformedBoard[rowIndex][colIndex].value = cells[sideLength - rowIndex - 1][colIndex].value;
}
}
cells = transformedBoard;
}
break;
case 'vertical': {
List transformedBoard = createEmptyBoard(size);
for (var rowIndex = 0; rowIndex < sideLength; rowIndex++) {
for (var colIndex = 0; colIndex < sideLength; colIndex++) {
transformedBoard[rowIndex][colIndex].value = cells[rowIndex][sideLength - colIndex - 1].value;
}
}
cells = transformedBoard;
}
break;
}
switch(rotate) {
case 'left': {
List transformedBoard = createEmptyBoard(size);
for (var rowIndex = 0; rowIndex < sideLength; rowIndex++) {
for (var colIndex = 0; colIndex < sideLength; colIndex++) {
transformedBoard[rowIndex][colIndex].value = cells[colIndex][sideLength - rowIndex - 1].value;
}
}
cells = transformedBoard;
}
break;
case 'right': {
List transformedBoard = createEmptyBoard(size);
for (var rowIndex = 0; rowIndex < sideLength; rowIndex++) {
for (var colIndex = 0; colIndex < sideLength; colIndex++) {
transformedBoard[rowIndex][colIndex].value = cells[sideLength - colIndex - 1][rowIndex].value;
}
}
cells = transformedBoard;
}
break;
}
// Fix cells fixed states
for (var rowIndex = 0; rowIndex < sideLength; rowIndex++) {
for (var colIndex = 0; colIndex < sideLength; colIndex++) {
cells[rowIndex][colIndex].isFixed = (cells[rowIndex][colIndex].value != 0) ? true : false;
}
}
return cells;
}
List createEmptyBoard(int size) {
int index = 0;
List cells = [];
for (var rowIndex = 0; rowIndex < pow(size, 2); rowIndex++) {
List row = [];
for (var colIndex = 0; colIndex < pow(size, 2); colIndex++) {
row.add(Cell(0, colIndex, rowIndex, false));
}
cells.add(row);
}
return cells;
}
Container _buildParametersSelector(Data myProvider) {
return Container(
child: Column(
mainAxisSize: MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.center,
children: [
_buildParameterSelector(myProvider, 'difficulty'),
_buildParameterSelector(myProvider, 'size'),
_buildParameterSelector(myProvider, 'skin'),
_buildStartGameButton(myProvider),
],
),
);
}
Column _buildStartGameButton(Data myProvider) {
return Column(
mainAxisSize: MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.center,
children: [
FlatButton(
child: Image(
image: AssetImage('assets/icons/button_start.png'),
width: _startButtonSize,
height: _startButtonSize,
fit: BoxFit.fill
),
onPressed: () => startGame(myProvider),
)
],
);
}
Column _buildParameterSelector(Data myProvider, String parameterCode) {
List availableValues = myProvider.getParameterAvailableValues(parameterCode);
return Column(
children: [
Table(
defaultColumnWidth: IntrinsicColumnWidth(),
children: [
TableRow(
children: [
for (var index = 0; index < availableValues.length; index++)
Column(
children: [
_buildParameterButton(myProvider, parameterCode, availableValues[index])
]
),
],
),
],
),
SizedBox(height: 20),
]
);
}
FlatButton _buildParameterButton(Data myProvider, String parameterCode, var parameterValue) {
String currentValue = myProvider.getParameterValue(parameterCode).toString();
bool isActive = (parameterValue.toString() == currentValue);
String imageAsset = 'assets/icons/' + parameterCode + '_' + parameterValue.toString() + '.png';
return FlatButton(
child: Container(
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(10),
border: Border.all(
color: isActive ? Colors.blue : Colors.white,
width: 10,
),
),
child: Image(
image: AssetImage(imageAsset),
width: _parameterButtonSize,
height: _parameterButtonSize,
fit: BoxFit.fill
),
),
onPressed: () => myProvider.setParameterValue(parameterCode, parameterValue),
);
}
Container _buildGameWidget(Data myProvider) {
return Container(
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
_buildGameBoard(myProvider),
SizedBox(height: 2),
_buildSelectCellValueBar(myProvider)
],
),
);
}
Container _buildGameBoard(Data myProvider) {
List cells = myProvider.cells;
int size = myProvider.size;
Color borderColor = _checkBoardIsSolved(myProvider) ? Colors.green : Colors.orange;
return Container(
margin: EdgeInsets.all(2),
padding: EdgeInsets.all(2),
decoration: BoxDecoration(
color: borderColor,
borderRadius: BorderRadius.circular(2),
border: Border.all(
color: borderColor,
width: 2,
),
),
child: Table(
defaultColumnWidth: IntrinsicColumnWidth(),
children: [
for (var row = 0; row < pow(size, 2); row++)
TableRow(children: [
for (var col = 0; col < pow(size, 2); col++)
Column(children: [
cells[row][col].widget(myProvider)
]),
]),
]
),
);
}
Container _buildSelectCellValueBar(Data myProvider) {
List cells = myProvider.cells;
int size = myProvider.size;
Color borderColor = Colors.blue;
bool isCellSelected = (myProvider.currentCellCol != null && myProvider.currentCellRow != null);
return Container(
margin: EdgeInsets.all(2),
padding: EdgeInsets.all(2),
child: Table(
defaultColumnWidth: IntrinsicColumnWidth(),
children: [
TableRow(
children: [
for (var value = 0; value < (pow(size, 2) + 1); value++)
Column(
children: [
Cell(
isCellSelected ? value : 0,
isCellSelected ? myProvider.currentCellCol : null,
isCellSelected ? myProvider.currentCellRow : null,
false
).widgetUpdateValue(myProvider)
]
),
]
),
]
),
);
}
bool _checkBoardIsSolved(Data myProvider) {
List cells = myProvider.cells;
int size = myProvider.size;
int sideLength = pow(size, 2);
bool isSolved = true;
// reset conflict states
for (var row = 0; row < sideLength; row++) {
for (var col = 0; col < sideLength; col++) {
cells[row][col].conflictsCount = 0;
}
}
// check grid is fully completed
for (var row = 0; row < sideLength; row++) {
for (var col = 0; col < sideLength; col++) {
if (cells[row][col].value == 0) {
isSolved = false;
}
}
}
// check lines does not contains a value twice
for (var row = 0; row < sideLength; row++) {
List values = [];
for (var col = 0; col < sideLength; col++) {
int value = cells[row][col].value;
if (value != 0) {
values.add(value);
}
}
List distinctValues = values.toSet().toList();
if (values.length != distinctValues.length) {
print('line ' + row.toString() + ' contains duplicates');
// Add line to cells in conflict
for (var col = 0; col < sideLength; col++) {
cells[row][col].conflictsCount++;
}
isSolved = false;
}
}
// check columns does not contains a value twice
for (var col = 0; col < sideLength; col++) {
List values = [];
for (var row = 0; row < sideLength; row++) {
int value = cells[row][col].value;
if (value != 0) {
values.add(value);
}
}
List distinctValues = values.toSet().toList();
if (values.length != distinctValues.length) {
print('column ' + col.toString() + ' contains duplicates');
// Add column to cells in conflict
for (var row = 0; row < sideLength; row++) {
cells[row][col].conflictsCount++;
}
isSolved = false;
}
}
// check blocks does not contains a value twice
for (var blockRow = 0; blockRow < size; blockRow++) {
for (var blockCol = 0; blockCol < size; blockCol++) {
List values = [];
for (var rowInBlock = 0; rowInBlock < size; rowInBlock++) {
for (var colInBlock = 0; colInBlock < size; colInBlock++) {
int row = (blockRow * size) + rowInBlock;
int col = (blockCol * size) + colInBlock;
int value = cells[row][col].value;
if (value != 0) {
values.add(value);
}
}
}
List distinctValues = values.toSet().toList();
if (values.length != distinctValues.length) {
print('block [' + blockCol.toString() + ',' + blockRow.toString() + '] contains duplicates');
// Add blocks to cells in conflict
for (var rowInBlock = 0; rowInBlock < size; rowInBlock++) {
for (var colInBlock = 0; colInBlock < size; colInBlock++) {
int row = (blockRow * size) + rowInBlock;
int col = (blockCol * size) + colInBlock;
cells[row][col].conflictsCount++;
}
}
isSolved = false;
}
}
}
if (isSolved) {
print('-> ok sudoku solved!');
}
return isSolved;
}
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
Data myProvider = Provider.of<Data>(context); Data myProvider = Provider.of<Data>(context);
...@@ -424,7 +16,7 @@ class Home extends StatelessWidget { ...@@ -424,7 +16,7 @@ class Home extends StatelessWidget {
List<Widget> menuActions = []; List<Widget> menuActions = [];
if (myProvider.stateRunning) { if (myProvider.stateRunning) {
menuActions.add( menuActions = [
FlatButton( FlatButton(
child: Container( child: Container(
decoration: BoxDecoration( decoration: BoxDecoration(
...@@ -440,29 +32,39 @@ class Home extends StatelessWidget { ...@@ -440,29 +32,39 @@ class Home extends StatelessWidget {
fit: BoxFit.fill fit: BoxFit.fill
), ),
), ),
onPressed: () { myProvider.updateShowConflicts = !myProvider.showConflicts; }, onPressed: () {
) myProvider.updateShowConflicts = !myProvider.showConflicts;
); },
),
menuActions.add(
FlatButton( FlatButton(
child: Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(4),
border: Border.all(
color: Colors.blue,
width: 4,
),
),
margin: EdgeInsets.all(8),
child: Image( child: Image(
image: AssetImage('assets/icons/button_back.png'), image: AssetImage('assets/icons/button_back.png'),
fit: BoxFit.fill fit: BoxFit.fill
), ),
onPressed: () => resetGame(myProvider),
), ),
); onPressed: () => GameUtils.resetGame(myProvider),
),
];
} }
return Scaffold( return Scaffold(
appBar: AppBar( appBar: AppBar(
title: Text('🔢'),
actions: menuActions, actions: menuActions,
), ),
body: SafeArea( body: SafeArea(
child: Center( child: Center(
child: myProvider.stateRunning ? _buildGameWidget(myProvider) : _buildParametersSelector(myProvider) child: myProvider.stateRunning
? Game.buildGameWidget(myProvider)
: Parameters.buildParametersSelector(myProvider)
), ),
) )
); );
......
import 'dart:math';
import '../entities/cell.dart';
import '../utils/random_pick_grid.dart';
import '../provider/data.dart';
class BoardUtils {
static printGrid(List cells) {
print('');
print('-------');
for (var rowIndex = 0; rowIndex < cells.length; rowIndex++) {
String row = '';
for (var colIndex = 0; colIndex < cells[rowIndex].length; colIndex++) {
row += cells[rowIndex][colIndex].value.toString();
}
print(row);
}
print('-------');
print('');
}
static Future<void> pickGrid(Data myProvider) async {
String grid;
RandomPickGrid randomPickGrid;
randomPickGrid = RandomPickGrid();
await randomPickGrid.init(myProvider.level, myProvider.size);
if (randomPickGrid.grid != null) {
grid = randomPickGrid.grid;
}
int blockSizeHorizontal = myProvider.blockSizeHorizontal;
int blockSizeVertical = myProvider.blockSizeVertical;
if (grid.length == pow(blockSizeHorizontal * blockSizeVertical, 2)) {
print('Picked grid from template: ' + grid);
bool isSymetric = (blockSizeHorizontal == blockSizeVertical);
myProvider.updateCells = BoardUtils.createBoardFromTemplate(grid, isSymetric);
}
}
static List createEmptyBoard(int boardSize) {
int index = 0;
List cells = [];
for (var rowIndex = 0; rowIndex < boardSize; rowIndex++) {
List row = [];
for (var colIndex = 0; colIndex < boardSize; colIndex++) {
row.add(Cell(0, false));
}
cells.add(row);
}
return cells;
}
static List createBoardFromTemplate(String grid, bool isSymetric) {
List cells = [];
int boardSize = int.parse(pow(grid.length, 1/2).toStringAsFixed(0));
int index = 0;
for (var rowIndex = 0; rowIndex < boardSize; rowIndex++) {
List row = [];
for (var colIndex = 0; colIndex < boardSize; colIndex++) {
int value = int.parse(grid[index++]);
row.add(Cell(value, (value != 0)));
}
cells.add(row);
}
List<String> allowedFlip = ['none', 'horizontal', 'vertical'];
List<String> allowedRotate = ['none', 'left', 'right'];
// Forbid rotation if blocks are not symetric
if (!isSymetric) {
allowedRotate = ['none'];
}
var rand = new Random();
String flip = allowedFlip[rand.nextInt(allowedFlip.length)];
String rotate = allowedRotate[rand.nextInt(allowedRotate.length)];
print('flip board: ' + flip);
print('rotate board: ' + rotate);
switch(flip) {
case 'horizontal': {
List transformedBoard = createEmptyBoard(boardSize);
for (var rowIndex = 0; rowIndex < boardSize; rowIndex++) {
for (var colIndex = 0; colIndex < boardSize; colIndex++) {
transformedBoard[rowIndex][colIndex].value = cells[boardSize - rowIndex - 1][colIndex].value;
}
}
cells = transformedBoard;
}
break;
case 'vertical': {
List transformedBoard = createEmptyBoard(boardSize);
for (var rowIndex = 0; rowIndex < boardSize; rowIndex++) {
for (var colIndex = 0; colIndex < boardSize; colIndex++) {
transformedBoard[rowIndex][colIndex].value = cells[rowIndex][boardSize - colIndex - 1].value;
}
}
cells = transformedBoard;
}
break;
}
switch(rotate) {
case 'left': {
List transformedBoard = createEmptyBoard(boardSize);
for (var rowIndex = 0; rowIndex < boardSize; rowIndex++) {
for (var colIndex = 0; colIndex < boardSize; colIndex++) {
transformedBoard[rowIndex][colIndex].value = cells[colIndex][boardSize - rowIndex - 1].value;
}
}
cells = transformedBoard;
}
break;
case 'right': {
List transformedBoard = createEmptyBoard(boardSize);
for (var rowIndex = 0; rowIndex < boardSize; rowIndex++) {
for (var colIndex = 0; colIndex < boardSize; colIndex++) {
transformedBoard[rowIndex][colIndex].value = cells[boardSize - colIndex - 1][rowIndex].value;
}
}
cells = transformedBoard;
}
break;
}
// Fix cells fixed states
for (var rowIndex = 0; rowIndex < boardSize; rowIndex++) {
for (var colIndex = 0; colIndex < boardSize; colIndex++) {
cells[rowIndex][colIndex].isFixed = (cells[rowIndex][colIndex].value != 0) ? true : false;
}
}
printGrid(cells);
return cells;
}
static bool checkBoardIsSolved(Data myProvider) {
List cells = myProvider.cells;
int blockSizeHorizontal = myProvider.blockSizeHorizontal;
int blockSizeVertical = myProvider.blockSizeVertical;
int boardSize = blockSizeHorizontal * blockSizeVertical;
bool isSolved = true;
// reset conflict states
for (var row = 0; row < boardSize; row++) {
for (var col = 0; col < boardSize; col++) {
cells[row][col].conflictsCount = 0;
}
}
// check grid is fully completed
for (var row = 0; row < boardSize; row++) {
for (var col = 0; col < boardSize; col++) {
if (cells[row][col].value == 0) {
isSolved = false;
}
}
}
// check lines does not contains a value twice
for (var row = 0; row < boardSize; row++) {
List values = [];
for (var col = 0; col < boardSize; col++) {
int value = cells[row][col].value;
if (value != 0) {
values.add(value);
}
}
List distinctValues = values.toSet().toList();
if (values.length != distinctValues.length) {
print('line ' + row.toString() + ' contains duplicates');
// Add line to cells in conflict
for (var col = 0; col < boardSize; col++) {
cells[row][col].conflictsCount++;
}
isSolved = false;
}
}
// check columns does not contains a value twice
for (var col = 0; col < boardSize; col++) {
List values = [];
for (var row = 0; row < boardSize; row++) {
int value = cells[row][col].value;
if (value != 0) {
values.add(value);
}
}
List distinctValues = values.toSet().toList();
if (values.length != distinctValues.length) {
print('column ' + col.toString() + ' contains duplicates');
// Add column to cells in conflict
for (var row = 0; row < boardSize; row++) {
cells[row][col].conflictsCount++;
}
isSolved = false;
}
}
// check blocks does not contains a value twice
int horizontalBlocksCount = blockSizeVertical;
int verticalBlocksCount = blockSizeHorizontal;
for (var blockRow = 0; blockRow < verticalBlocksCount; blockRow++) {
for (var blockCol = 0; blockCol < horizontalBlocksCount; blockCol++) {
List values = [];
for (var rowInBlock = 0; rowInBlock < blockSizeVertical; rowInBlock++) {
for (var colInBlock = 0; colInBlock < blockSizeHorizontal; colInBlock++) {
int row = (blockRow * blockSizeVertical) + rowInBlock;
int col = (blockCol * blockSizeHorizontal) + colInBlock;
int value = cells[row][col].value;
if (value != 0) {
values.add(value);
}
}
}
List distinctValues = values.toSet().toList();
if (values.length != distinctValues.length) {
print('block [' + blockCol.toString() + ',' + blockRow.toString() + '] contains duplicates');
// Add blocks to cells in conflict
for (var rowInBlock = 0; rowInBlock < blockSizeVertical; rowInBlock++) {
for (var colInBlock = 0; colInBlock < blockSizeHorizontal; colInBlock++) {
int row = (blockRow * blockSizeVertical) + rowInBlock;
int col = (blockCol * blockSizeHorizontal) + colInBlock;
cells[row][col].conflictsCount++;
}
}
isSolved = false;
}
}
}
if (isSolved) {
print('-> ok sudoku solved!');
}
return isSolved;
}
}
import '../provider/data.dart';
import '../utils/board_utils.dart';
class GameUtils {
static Future<void> resetGame(Data myProvider) async {
myProvider.updateStateRunning = false;
}
static Future<void> startGame(Data myProvider) async {
print('Start new game: ' + myProvider.size);
myProvider.updateSize = myProvider.size;
myProvider.updateStateRunning = true;
myProvider.updateCells = BoardUtils.createEmptyBoard(myProvider.blockSizeHorizontal * myProvider.blockSizeVertical);
BoardUtils.pickGrid(myProvider);
}
}
import 'dart:async';
import 'dart:convert'; import 'dart:convert';
import 'package:flutter/services.dart'; import 'package:flutter/services.dart';
...@@ -7,27 +6,25 @@ class RandomPickGrid { ...@@ -7,27 +6,25 @@ class RandomPickGrid {
String _grid; String _grid;
init(String difficulty, int size) async { init(String difficulty, String size) async {
_grid = ''; _grid = '';
await gridFromLocalFile(difficulty, size); await gridFromLocalFile(difficulty, size);
} }
Future<void> gridFromLocalFile(String difficulty, int size) async { Future<void> gridFromLocalFile(String difficulty, String size) async {
String sizeAsString = size.toString() + 'x' + size.toString();
// Get global grids list // Get global grids list
List grids; List grids;
try { try {
String jsonString = await rootBundle.loadString('assets/files/templates.json'); String jsonString = await rootBundle.loadString('assets/files/templates.json');
final jsonResponse = await json.decode(jsonString); final jsonResponse = await json.decode(jsonString);
grids = jsonResponse['templates'][sizeAsString][difficulty]; grids = jsonResponse['templates'][size][difficulty];
} catch (e) { } catch (e) {
print("$e"); print("$e");
} }
// Check we have enough grids // Check we have enough grids
if (grids.length < 1) { if (grids.length < 1) {
print('Not enough grids [' + sizeAsString + ', ' + difficulty + '] in templates.'); print('Not enough grids [' + size + ', ' + difficulty + '] in templates.');
} }
// Randomize grids list // Randomize grids list
......
...@@ -7,7 +7,7 @@ packages: ...@@ -7,7 +7,7 @@ packages:
name: async name: async
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "2.6.1" version: "2.7.0"
boolean_selector: boolean_selector:
dependency: transitive dependency: transitive
description: description:
...@@ -73,7 +73,7 @@ packages: ...@@ -73,7 +73,7 @@ packages:
name: meta name: meta
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "1.3.0" version: "1.4.0"
nested: nested:
dependency: transitive dependency: transitive
description: description:
...@@ -141,7 +141,7 @@ packages: ...@@ -141,7 +141,7 @@ packages:
name: test_api name: test_api
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "0.3.0" version: "0.4.0"
typed_data: typed_data:
dependency: transitive dependency: transitive
description: description:
......