Skip to content

Commit

Permalink
🎯 feat: minesweeper
Browse files Browse the repository at this point in the history
  • Loading branch information
LuCCoelho committed Oct 17, 2023
1 parent 4e269e5 commit 203c9b1
Show file tree
Hide file tree
Showing 8 changed files with 355 additions and 0 deletions.
21 changes: 21 additions & 0 deletions dart/minesweeper/.exercism/config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
{
"authors": [
"devkabiir"
],
"contributors": [
"sisminnmaw",
"kytrinyx"
],
"files": {
"solution": [
"lib/minesweeper.dart"
],
"test": [
"test/minesweeper_test.dart"
],
"example": [
".meta/lib/example.dart"
]
},
"blurb": "Add the numbers to a minesweeper board."
}
1 change: 1 addition & 0 deletions dart/minesweeper/.exercism/metadata.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"track":"dart","exercise":"minesweeper","id":"8561b6602a2e4305be4877a36687f970","url":"https://exercism.org/tracks/dart/exercises/minesweeper","handle":"LuCCoelho","is_requester":true,"auto_approve":false}
38 changes: 38 additions & 0 deletions dart/minesweeper/HELP.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
# Help

## Running the tests

To run the tests:

```sh
$ dart test
```

## Submitting your solution

You can submit your solution using the `exercism submit lib/minesweeper.dart` command.
This command will upload your solution to the Exercism website and print the solution page's URL.

It's possible to submit an incomplete solution which allows you to:

- See how others have completed the exercise
- Request help from a mentor

## Need to get help?

If you'd like help solving the exercise, check the following pages:

- The [Dart track's documentation](https://exercism.org/docs/tracks/dart)
- The [Dart track's programming category on the forum](https://forum.exercism.org/c/programming/dart)
- [Exercism's programming category on the forum](https://forum.exercism.org/c/programming/5)
- The [Frequently Asked Questions](https://exercism.org/docs/using/faqs)

Should those resources not suffice, you could submit your (incomplete) solution to request mentoring.

To get help if you're having trouble, you can use one of the following resources:

- [Dart API Documentation](https://api.dart.dev/)
- [Dart Gitter Chat](https://gitter.im/dart-lang/home)
- [Community Information](https://www.dart.dev/community)
- [/r/dartlang](https://www.reddit.com/r/dartlang) is the Dart subreddit.
- [StackOverflow](https://stackoverflow.com/questions/tagged/dart) can be used to search for your problem and see if it has been answered already. You can also ask and answer questions.
48 changes: 48 additions & 0 deletions dart/minesweeper/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
# Minesweeper

Welcome to Minesweeper on Exercism's Dart Track.
If you need help running the tests or submitting your code, check out `HELP.md`.

## Instructions

Add the mine counts to a completed Minesweeper board.

Minesweeper is a popular game where the user has to find the mines using numeric hints that indicate how many mines are directly adjacent (horizontally, vertically, diagonally) to a square.

In this exercise you have to create some code that counts the number of mines adjacent to a given empty square and replaces that square with the count.

The board is a rectangle composed of blank space (' ') characters.
A mine is represented by an asterisk (`*`) character.

If a given space has no adjacent mines at all, leave that square blank.

## Examples

For example you may receive a 5 x 4 board like this (empty spaces are represented here with the '·' character for display on screen):

```text
·*·*·
··*··
··*··
·····
```

And your code will transform it into this:

```text
1*3*1
13*31
·2*2·
·111·
```

## Source

### Created by

- @devkabiir

### Contributed to by

- @sisminnmaw
- @kytrinyx
15 changes: 15 additions & 0 deletions dart/minesweeper/analysis_options.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
analyzer:
errors:
unused_element: error
unused_import: error
unused_local_variable: error
dead_code: error

linter:
rules:
# Error Rules
- avoid_relative_lib_imports
- avoid_types_as_parameter_names
- literal_only_boolean_expressions
- no_adjacent_strings_in_list
- valid_regexps
159 changes: 159 additions & 0 deletions dart/minesweeper/lib/minesweeper.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,159 @@
class Minesweeper {
var minefield;
int rowCount = 0;
int columnCount = 0;

Minesweeper(List<String> minefield) {
if (minefield.length == 0) {
this.minefield = [];
} else {
this.minefield = minefield;
this.rowCount = minefield.length;
this.columnCount = minefield[0].length;
}
}

List<String> get annotated {
// Parse minefield - transform into a matrix of integers

var parsedField = this.parseMinefield();

// Add mine count - check the adjacent squares of each square
// that does not have a bomb and count how many of them have bombs

var calculatedField = this.addMineCount(parsedField);

// Format minefield - transforms back into a list o Strings

return this.formatCalculatedField(calculatedField);

}

/**
* This method is going to accept a list of integers in the format
* [[1,-1,2,-1,1]] and return ['1*2*1']
* or
* [[-1,-1,-1],[-1,8,-1],[-1,-1,-1]] and return ['***', '*8*', '***']
*/
List<String> formatCalculatedField(List<List<int>>calculatedField) {
List<String> formatedField = [];
for (int i = 0; i < rowCount; i++) {
formatedField.add('');
for (int j = 0; j < columnCount; j++) {
int square = calculatedField[i][j];
if (square == -1) {
formatedField[i] += '*';
}
if (square == 0) {
formatedField[i] += ' ';
}
if (square > 0) {
formatedField[i] += '$square';
}
}
}
return formatedField;
}

/**
* This method is going to parse this.minefield in the following way
* [' ', ' * ', ' '] will return [[0,0,0],[0,-1,0],[0,0,0]]
* or
* ['* *'] will return [[-1,0,0,0,-1]]
*/
List<List<int>> parseMinefield() {
List<List<int>> parsedField = [];
for (int i = 0; i < rowCount; i++) {
parsedField.add([]);
for (int j = 0; j < columnCount; j++) {
String square = this.minefield[i][j];
if (square == '*'){
parsedField[i].add(-1);
} else {
parsedField[i].add(0);
}
}
}
return parsedField;
}

/**
* This method is going to accept a list of integers in the format
* [[0,0,0],[0,-1,0],[0,0,0]] and return [[1,1,1],[1,-1,1],[1,0,0]]
* or
* [[-1,-1,-1],[-1,8,-1],[-1,-1,-1]] and return ['***', '*8*', '***']
*/
List<List<int>> addMineCount(List<List<int>> parsedField) {
for (int x = 0; x < rowCount; x++){
for (int y = 0; y < columnCount; y++) {
if (parsedField[x][y] != -1) {
List<List<int>> neighbors = getNeighbors(x, y);
int mineCount = 0;
for (List<int> neighbor in neighbors) {
int neighborX = neighbor[0];
int neighborY = neighbor[1];
if (parsedField[neighborX][neighborY] == -1) {
mineCount += 1;
}
}
parsedField[x][y] = mineCount;
}
}
}
return parsedField;
}


/**
* This method accepts two integers that represent coordinates in
* the format
* 1, 2 and return [[0,2],[0,1],[1,1],[2,1],[2,2]] if the matrix is 3x3
* or
* 1, 2 and return [[0,2],[0,1],[1,1]] if the matrix is 2x3
*/
List<List<int>> getNeighbors(int x, int y) {
List<List<int>> neighbors = [];

if (x-1 >= 0) {
List<int> neighborTop = [x-1, y];
neighbors.add(neighborTop);

if (y-1 >= 0) {
List<int> neighborLeftTop = [x-1, y-1];
neighbors.add(neighborLeftTop);
}

if (y+1 < columnCount) {
List<int> neighborRightTop = [x-1, y+1];
neighbors.add(neighborRightTop);
}
}

if (y-1 >= 0) {
List<int> neighborLeft = [x, y-1];
neighbors.add(neighborLeft);

if (x+1 < rowCount) {
List<int> neighborLeftBottom = [x+1, y-1];
neighbors.add(neighborLeftBottom);
}
}

if (y+1 < columnCount) {
List<int> neighborRight = [x, y+1];
neighbors.add(neighborRight);

if (x+1 < rowCount) {
List<int> neighborRightBottom = [x+1, y+1];
neighbors.add(neighborRightBottom);
}
}

if (x+1 < rowCount) {
List<int> neighborBottom = [x+1, y];
neighbors.add(neighborBottom);
}

return neighbors;
}
}
7 changes: 7 additions & 0 deletions dart/minesweeper/pubspec.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
name: 'minesweeper'
environment:
sdk: '>=2.18.0 <3.0.0'
dev_dependencies:
test: '<2.0.0'
dependencies:
matrices: ^1.2.7
66 changes: 66 additions & 0 deletions dart/minesweeper/test/minesweeper_test.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
import 'package:minesweeper/minesweeper.dart';
import 'package:test/test.dart';

void main() {
group('Minesweeper', () {
test('no rows', () {
final result = Minesweeper(<String>[]).annotated;
expect(result, equals(<String>[]));
});

test('no columns', () {
final result = Minesweeper(<String>['']).annotated;
expect(result, equals(<String>['']));
});

test('no mines', () {
final result = Minesweeper(<String>[' ', ' ', ' ']).annotated;
expect(result, equals(<String>[' ', ' ', ' ']));
});

test('minefield with only mines', () {
final result = Minesweeper(<String>['***', '***', '***']).annotated;
expect(result, equals(<String>['***', '***', '***']));
});

test('mine surrounded by spaces', () {
final result = Minesweeper(<String>[' ', ' * ', ' ']).annotated;
expect(result, equals(<String>['111', '1*1', '111']));
});

test('space surrounded by mines', () {
final result = Minesweeper(<String>['***', '* *', '***']).annotated;
expect(result, equals(<String>['***', '*8*', '***']));
});

test('horizontal line', () {
final result = Minesweeper(<String>[' * * ']).annotated;
expect(result, equals(<String>['1*2*1']));
});

test('horizontal line, mines at edges', () {
final result = Minesweeper(<String>['* *']).annotated;
expect(result, equals(<String>['*1 1*']));
});

test('vertical line', () {
final result = Minesweeper(<String>[' ', '*', ' ', '*', ' ']).annotated;
expect(result, equals(<String>['1', '*', '2', '*', '1']));
});

test('vertical line, mines at edges', () {
final result = Minesweeper(<String>['*', ' ', ' ', ' ', '*']).annotated;
expect(result, equals(<String>['*', '1', ' ', '1', '*']));
});

test('cross', () {
final result = Minesweeper(<String>[' * ', ' * ', '*****', ' * ', ' * ']).annotated;
expect(result, equals(<String>[' 2*2 ', '25*52', '*****', '25*52', ' 2*2 ']));
});

test('large minefield', () {
final result = Minesweeper(<String>[' * * ', ' * ', ' * ', ' * *', ' * * ', ' ']).annotated;
expect(result, equals(<String>['1*22*1', '12*322', ' 123*2', '112*4*', '1*22*2', '111111']));
});
});
}

0 comments on commit 203c9b1

Please sign in to comment.