Select Git revision
parameters.dart
-
Benoît Harrault authoredBenoît Harrault authored
board_utils.dart 6.76 KiB
import '../entities/cell.dart';
import '../provider/data.dart';
class BoardUtils {
static printGrid(List cells) {
final String IS_MINED = 'X';
final String IS_SAFE = '.';
final String MINE_FOUND = '#';
final String WRONG_MARKED_CELL = '0';
final String EXPLORED_SAFE_CELL = '.';
final String UNKNOWN_STATE = ' ';
print('');
String line = '--';
for (var i = 0; i < cells[0].length; i++) {
line += '-';
}
print(line + ' ' + line);
for (var rowIndex = 0; rowIndex < cells.length; rowIndex++) {
String currentLine = '';
String solvedLine = '';
for (var colIndex = 0; colIndex < cells[rowIndex].length; colIndex++) {
solvedLine += cells[rowIndex][colIndex].isMined ? IS_MINED : IS_SAFE;
String cellString = UNKNOWN_STATE;
if (cells[rowIndex][colIndex].isExplored) {
cellString = EXPLORED_SAFE_CELL;
}
if (cells[rowIndex][colIndex].isMarked) {
if (cells[rowIndex][colIndex].isMined) {
cellString = MINE_FOUND;
} else {
cellString = WRONG_MARKED_CELL;
}
}
currentLine += cellString;
}
print('|' + currentLine + '| |' + solvedLine + '|');
}
print(line + ' ' + line);
print('');
}
static List createEmptyBoard(int sizeHorizontal, int sizeVertical) {
int index = 0;
List cells = [];
for (var rowIndex = 0; rowIndex < sizeVertical; rowIndex++) {
List row = [];
for (var colIndex = 0; colIndex < sizeHorizontal; colIndex++) {
row.add(Cell(false));
}
cells.add(row);
}
return cells;
}
static int getMinesCount(int sizeHorizontal, int sizeVertical, String level) {
int minesCountRatio = 0;
switch(level) {
case 'easy': {
minesCountRatio = 5;
}
break;
case 'medium': {
minesCountRatio = 10;
}
break;
case 'hard': {
minesCountRatio = 15;
}
break;
case 'nightmare': {
minesCountRatio = 20;
}
break;
}
int minesCount = ((sizeHorizontal * sizeVertical) * minesCountRatio / 100).round();
print('Mines count: ' + minesCount.toString());
return minesCount;
}
static List createInitialEmptyBoard(Data myProvider) {
myProvider.updateIsBoardMined(false);
myProvider.updateCells(createEmptyBoard(myProvider.sizeHorizontal, myProvider.sizeVertical));
}
static List createBoard(Data myProvider, int forbiddenRow, int forbiddenCol) {
List cells = myProvider.cells;
int sizeHorizontal = myProvider.sizeHorizontal;
int sizeVertical = myProvider.sizeVertical;
String level = myProvider.level;
// Shuffle cells to put random mines, expect on currently selected one
List allowedCells = [];
for (var row = 0; row < sizeVertical; row++) {
for (var col = 0; col < sizeHorizontal; col++) {
if (!((forbiddenRow == row) && (forbiddenCol == col))) {
allowedCells.add([row, col]);
}
}
}
allowedCells.shuffle();
// Put random mines on board
int minesCount = getMinesCount(sizeHorizontal, sizeVertical, level);
for (var mineIndex = 0; mineIndex < minesCount; mineIndex++) {
cells[allowedCells[mineIndex][0]][allowedCells[mineIndex][1]].isMined = true;
}
// Compute all mines counts on cells
for (var row = 0; row < sizeVertical; row++) {
for (var col = 0; col < sizeHorizontal; col++) {
cells[row][col].minesCountAround = getMinesCountAround(cells, row, col);
}
}
printGrid(cells);
return cells;
}
static void reportCell(Data myProvider, int row, int col) {
if (!myProvider.cells[row][col].isExplored) {
myProvider.toggleCellMark(row, col);
}
}
static void walkOnCell(Data myProvider, int row, int col) {
myProvider.setCellAsExplored(row, col);
if (myProvider.cells[row][col].minesCountAround == 0) {
List safeCells = getAllSafeCellsAround(myProvider.cells, row, col);
for (var safeCellIndex = 0; safeCellIndex < safeCells.length; safeCellIndex++) {
int safeCellRow = safeCells[safeCellIndex][0];
int safeCellCol = safeCells[safeCellIndex][1];
if (!myProvider.cells[safeCellRow][safeCellCol].isExplored) {
walkOnCell(myProvider, safeCellRow, safeCellCol);
}
}
}
}
static List getAllSafeCellsAround(List cells, int row, int col) {
int sizeHorizontal = cells.length;
int sizeVertical = cells[0].length;
List safeCellsCoordinates = [];
if (cells[row][col].minesCountAround == 0) {
for (var deltaRow = -1; deltaRow <= 1; deltaRow++) {
for (var deltaCol = -1; deltaCol <= 1; deltaCol++) {
int candidateRow = row + deltaRow;
int candidateCol = col + deltaCol;
if (
(candidateRow >= 0 && candidateRow < sizeVertical)
&&
(candidateCol >= 0 && candidateCol < sizeHorizontal)
&&
!cells[candidateRow][candidateCol].isExplored
) {
safeCellsCoordinates.add([candidateRow, candidateCol]);
}
}
}
}
return safeCellsCoordinates;
}
static int getMinesCountAround(List cells, int row, int col) {
int sizeHorizontal = cells.length;
int sizeVertical = cells[0].length;
int minesCountAround = 0;
for (var deltaRow = -1; deltaRow <= 1; deltaRow++) {
for (var deltaCol = -1; deltaCol <= 1; deltaCol++) {
if (
(row + deltaRow >= 0 && row + deltaRow < sizeVertical)
&&
(col + deltaCol >= 0 && col + deltaCol < sizeHorizontal)
&&
(cells[row + deltaRow][col + deltaCol].isMined)
) {
minesCountAround++;
}
}
}
return minesCountAround;
}
static bool checkGameIsFinished(Data myProvider) {
List cells = myProvider.cells;
int sizeHorizontal = cells.length;
int sizeVertical = cells[0].length;
printGrid(cells);
myProvider.updateGameWin(false);
myProvider.updateGameFail(false);
for (var row = 0; row < sizeVertical; row++) {
for (var col = 0; col < sizeHorizontal; col++) {
// Walked on a mine
if (cells[row][col].isExploded == true) {
myProvider.updateGameFail(true);
return false;
}
}
}
for (var row = 0; row < sizeVertical; row++) {
for (var col = 0; col < sizeHorizontal; col++) {
if (
// Mine not already found
(cells[row][col].isMined == true && cells[row][col].isMarked == false)
||
// Safe cell marked as mined
(cells[row][col].isMined == false && cells[row][col].isMarked == true)
) {
return false;
}
}
}
print('-> ok all mines found!');
myProvider.updateGameWin(true);
return true;
}
}