Skip to content

Commit

Permalink
Add minesweeper (exercism#353)
Browse files Browse the repository at this point in the history
  • Loading branch information
blakelewis authored Feb 25, 2024
1 parent c73ec32 commit 5c8fa4f
Show file tree
Hide file tree
Showing 7 changed files with 264 additions and 0 deletions.
8 changes: 8 additions & 0 deletions config.json
Original file line number Diff line number Diff line change
Expand Up @@ -638,6 +638,14 @@
"practices": [],
"prerequisites": [],
"difficulty": 4
},
{
"slug": "minesweeper",
"name": "Minesweeper",
"uuid": "a7bd6275-b624-4c09-9040-4b57afe1c4b6",
"practices": [],
"prerequisites": [],
"difficulty": 3
}
]
},
Expand Down
32 changes: 32 additions & 0 deletions exercises/practice/minesweeper/.docs/instructions.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
# 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·
```
15 changes: 15 additions & 0 deletions exercises/practice/minesweeper/.meta/config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
{
"authors": ["blakelewis"],
"files": {
"solution": [
"minesweeper.rkt"
],
"test": [
"minesweeper-test.rkt"
],
"example": [
".meta/example.rkt"
]
},
"blurb": "Add the numbers to a minesweeper board."
}
38 changes: 38 additions & 0 deletions exercises/practice/minesweeper/.meta/example.rkt
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
#lang racket

(provide annotate)

(define (bomb-at loc row)
(cond [(null? row) 0]
[(negative? loc) 0]
[(>= loc (string-length row)) 0]
[else (let ([c (string-ref row loc)])
(if (char=? c #\*) 1 0))]))


(define (bombs-around loc row)
(+ (bomb-at (sub1 loc) row) (bomb-at loc row) (bomb-at (add1 loc) row)))

(define (make-annotated-row top middle bottom)
(list->string
(for/list ([c (in-string middle)]
[i (in-range (string-length middle))])
(if (char=? c #\space)
(let ([b (+ (bombs-around i top)
(bombs-around i middle)
(bombs-around i bottom))])
(if (zero? b) #\space (integer->char (+ b (char->integer #\0)))))
c))))

(define (following-row i field)
(if (>= (add1 i) (length field)) '() (list-ref field (add1 i))))

(define (annotate minefield)
(for/fold ([out '()]
[top '()]
[middle (following-row -1 minefield)]
[bottom (following-row 0 minefield)]
#:result (reverse out))
([i (in-inclusive-range 1 (length minefield))])
(values (cons (make-annotated-row top middle bottom) out)
middle bottom (following-row i minefield))))
46 changes: 46 additions & 0 deletions exercises/practice/minesweeper/.meta/tests.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
# This is an auto-generated file.
#
# Regenerating this file via `configlet sync` will:
# - Recreate every `description` key/value pair
# - Recreate every `reimplements` key/value pair, where they exist in problem-specifications
# - Remove any `include = true` key/value pair (an omitted `include` key implies inclusion)
# - Preserve any other key/value pair
#
# As user-added comments (using the # character) will be removed when this file
# is regenerated, comments can be added via a `comment` key.

[0c5ec4bd-dea7-4138-8651-1203e1cb9f44]
description = "no rows"

[650ac4c0-ad6b-4b41-acde-e4ea5852c3b8]
description = "no columns"

[6fbf8f6d-a03b-42c9-9a58-b489e9235478]
description = "no mines"

[61aff1c4-fb31-4078-acad-cd5f1e635655]
description = "minefield with only mines"

[84167147-c504-4896-85d7-246b01dea7c5]
description = "mine surrounded by spaces"

[cb878f35-43e3-4c9d-93d9-139012cccc4a]
description = "space surrounded by mines"

[7037f483-ddb4-4b35-b005-0d0f4ef4606f]
description = "horizontal line"

[e359820f-bb8b-4eda-8762-47b64dba30a6]
description = "horizontal line, mines at edges"

[c5198b50-804f-47e9-ae02-c3b42f7ce3ab]
description = "vertical line"

[0c79a64d-703d-4660-9e90-5adfa5408939]
description = "vertical line, mines at edges"

[4b098563-b7f3-401c-97c6-79dd1b708f34]
description = "cross"

[04a260f1-b40a-4e89-839e-8dd8525abe0e]
description = "large minefield"
119 changes: 119 additions & 0 deletions exercises/practice/minesweeper/minesweeper-test.rkt
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
#lang racket/base

(require "minesweeper.rkt")

(module+ test
(require rackunit rackunit/text-ui))

(module+ test
(define suite
(test-suite
"minesweeper tests"
(test-equal? "no rows"
(annotate '())
'())

(test-equal? "no columns"
(annotate '(""))
'(""))

(test-equal? "no mines"
(annotate
'(" "
" "
" "))
'(" "
" "
" "))

(test-equal? "minefield with only mines"
(annotate
'("***"
"***"
"***"))
'("***"
"***"
"***"))

(test-equal? "mine surrounded by spaces"
(annotate
'(" "
" * "
" "))
'("111"
"1*1"
"111"))

(test-equal? "space surrounded by mines"
(annotate
'("***"
"* *"
"***"))
'("***"
"*8*"
"***"))

(test-equal? "horizontal line"
(annotate '(" * * "))
'("1*2*1"))

(test-equal? "horizontal line, mines at edges"
(annotate '("* *"))
'("*1 1*"))

(test-equal? "vertical line"
(annotate
'(" "
"*"
" "
"*"
" "))
'("1"
"*"
"2"
"*"
"1"))

(test-equal? "vertical line, mines at edges"
(annotate
'("*"
" "
" "
" "
"*"))
'("*"
"1"
" "
"1"
"*"))

(test-equal? "cross"
(annotate
'(" * "
" * "
"*****"
" * "
" * "))
'(" 2*2 "
"25*52"
"*****"
"25*52"
" 2*2 "))

(test-equal? "large minefield"
(annotate
'(" * * "
" * "
" * "
" * *"
" * * "
" "))
'("1*22*1"
"12*322"
" 123*2"
"112*4*"
"1*22*2"
"111111"))))

(run-tests suite))

6 changes: 6 additions & 0 deletions exercises/practice/minesweeper/minesweeper.rkt
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
#lang racket

(provide annotate)

(define (annotate minefield)
(error "Not implemented yet"))

0 comments on commit 5c8fa4f

Please sign in to comment.