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
Branches
Tags
1 merge request!17Resolve "Clean "cell" entity, add "Board" class"
Pipeline #1423 passed
This commit is part of merge request !17. Comments created here will be created in the context of that merge request.
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