Skip to content
Snippets Groups Projects
Commit 20562ae0 authored by Benoît Harrault's avatar Benoît Harrault
Browse files

Clean code, refactor classes, improve conception

parent 5f6335e9
No related branches found
No related tags found
1 merge request!17Resolve "Clean "cell" entity, add "Board" class"
Pipeline #1423 passed
org.gradle.jvmargs=-Xmx1536M org.gradle.jvmargs=-Xmx1536M
android.useAndroidX=true android.useAndroidX=true
android.enableJetifier=true android.enableJetifier=true
app.versionName=0.0.13 app.versionName=0.0.14
app.versionCode=13 app.versionCode=14
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';
...@@ -25,29 +25,9 @@ class Cell { ...@@ -25,29 +25,9 @@ class Cell {
int size = myProvider.size; 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 +36,9 @@ class Cell { ...@@ -56,9 +36,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 (!this.isFixed && (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);
} }
...@@ -111,12 +91,33 @@ class Cell { ...@@ -111,12 +91,33 @@ 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 size = myProvider.size;
Border borders = Border.all(
color: cellBorderSelectedColor,
width: cellBorderWidth,
);
if (col != myProvider.currentCellCol || row != myProvider.currentCellRow) {
borders = Border(
top: BorderSide(width: cellBorderWidth, color: ((row % size) == 0) ? cellBorderDarkColor : cellBorderLightColor),
left: BorderSide(width: cellBorderWidth, color: ((col % size) == 0) ? cellBorderDarkColor : cellBorderLightColor),
right: BorderSide(width: cellBorderWidth, color: (((col + 1) % size) == 0) ? cellBorderDarkColor : cellBorderLightColor),
bottom: BorderSide(width: cellBorderWidth, color: (((row + 1) % size) == 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 size = myProvider.size;
List cells = myProvider.cells;
return 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,
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;
int size = myProvider.size;
Color borderColor = Colors.blue;
bool isCellSelected = (myProvider.currentCellCol != null && myProvider.currentCellRow != null);
int maxValue = pow(size, 2) + 1;
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(
isCellSelected ? 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, 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),
);
}
}
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,19 +32,18 @@ class Home extends StatelessWidget { ...@@ -440,19 +32,18 @@ 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: 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(
...@@ -462,7 +53,9 @@ class Home extends StatelessWidget { ...@@ -462,7 +53,9 @@ class Home extends StatelessWidget {
), ),
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 {
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 = BoardUtils.createBoardFromTemplate(grid);
}
}
static 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, false));
}
cells.add(row);
}
return cells;
}
static 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, (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;
}
}
printGrid(cells);
return cells;
}
static 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;
}
}
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 {
myProvider.updateStateRunning = true;
myProvider.updateCells = BoardUtils.createEmptyBoard(myProvider.size);
BoardUtils.pickGrid(myProvider);
}
}
import 'dart:async';
import 'dart:convert'; import 'dart:convert';
import 'package:flutter/services.dart'; import 'package:flutter/services.dart';
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment