Minesweeper is a puzzle game where mines are hidden around a board of nondescript tiles with the goal of identifying the location of all mines. Clicking on a mine loses the game, but clicking on any other tile will reveal a number from 0-8 which signifies how many mines directly surround it.
Given a number, you must display a random* possible combination of empty tiles and mines surrounding it. This should be in the form of a 3x3 array. The center tile should be the number of mines taken as input.
*Must have a non-zero chance for all combinations to occur.
Examples
_ = blank square
X = mine
0
___
_0_
___
1
_X_
_1_
___
1
___
_1_
X__
___
_1_
__X
4
_X_
X4X
_X_
4
X_X
_4_
X_X
4
___
X4X
X_X
8
XXX
X8X
XXX
Input
- The number of mines surrounding the center tile (0-8)
Output
- Any reasonable form of output that displays the 3x3 array of tiles
Other rules
- Each combination does not have to have an equal chance of happening. There just must be a non-zero chance of each combination to occur when executing your program.
- Any 2 characters can be chosen for the mine and empty tile.
- This is code golf, the program with fewest bytes wins.
22 Answers 22
APL (Dyalog Unicode), (削除) 28 (削除ここまで) 15 bytes
-13 bytes thanks to ngn!
{3 3⍴5⌽⍵,⍵≥8?8}
Explanation:
{...} A direct function (D-Fn), ⍵ is its right argument.
8?8 deal 8 random numbers from the list 1..8:
8?8
7 2 1 8 4 6 5 3
⍵≥ is the argument greater or equal to each of them?:
5 ≥ 7 2 1 8 4 6 5 3
0 1 1 0 1 0 1 1
⍵, prepend the argument to the boolean list:
5 , 0 1 1 0 1 0 1 1
5 0 1 1 0 1 0 1 1
5⌽ rotate the list 5 positions to the left, so that the argument is in the center:
5 ⌽ 5 0 1 1 0 1 0 1 1
1 0 1 1 5 0 1 1 0
3 3⍴ reshape the list to a 3x3 matrix:
3 3 ⍴ 1 0 1 1 5 0 1 1 0
1 0 1
1 5 0
1 1 0
J, 15 bytes
Also many bytes thanks to ngn!
3 35ドル|.],]>8?8:
-
1\$\begingroup\$
(8↑1⍴⍨⍵)[8?8]->⍵>8?8(assuming⎕io←0) \$\endgroup\$ngn– ngn2018年06月03日 17:49:24 +00:00Commented Jun 3, 2018 at 17:49 -
1\$\begingroup\$
3 3⍴1↓,⍵,2 4⍴->3 3⍴5⌽⍵,\$\endgroup\$ngn– ngn2018年06月03日 17:51:57 +00:00Commented Jun 3, 2018 at 17:51 -
\$\begingroup\$ @ngn Thanks! I feel ashamed by my verbose attempt... \$\endgroup\$Galen Ivanov– Galen Ivanov2018年06月03日 18:23:27 +00:00Commented Jun 3, 2018 at 18:23
-
1\$\begingroup\$ no need for shame :) thank you - this answer gave me an opportunity to learn some J \$\endgroup\$ngn– ngn2018年06月03日 18:36:38 +00:00Commented Jun 3, 2018 at 18:36
-
1\$\begingroup\$ that J answer is really lovely. \$\endgroup\$Jonah– Jonah2018年06月04日 05:07:38 +00:00Commented Jun 4, 2018 at 5:07
JavaScript (ES6), 67 bytes
Shorter version suggested by @tsh
Empty slots are 0, mines are 1.
n=>`___
_${t=9,n}_
___`.replace(/_/g,_=>n-(n-=Math.random()<n/--t))
Original trial-and-error version, 78 bytes
Empty slots are _, mines are 7.
f=(n,o=`___
_${k=n}_
___`.replace(/_/g,c=>Math.random()<.5?--k|7:c))=>k?f(n):o
Commented
f = ( // f = recursive function
n, // n = input
o = `___\n_${k = n}_\n___` // o = minesweeper field / k = backup of n
.replace(/_/g, c => // for each underscore character c in o:
Math.random() < .5 ? // random action:
--k | 7 // either decrement k and yield 7
: // or:
c // let the underscore unchanged
) // end of replace()
) => //
k ? // if k is not equal to 0:
f(n) // try again
: // else:
o // stop recursion and return o
-
1
Jelly, (削除) 13 (削除ここまで) 10 bytes
8Ẉ>RẊs4js3
The returned list of lists has the displayed integer in the centre surrounded by 0s and 1s representing mines and blanks respectively.
Try it online! (footer pretty prints the array)
How?
8Ẉ>RẊs4js3 - Link: integer, n e.g. 3
8 - eight 8
Ẉ - length of each (implicit range of eight) [1,1,1,1,1,1,1,1]
R - range of n [1,2,3]
> - greater than? (vectorises) [0,0,0,1,1,1,1,1]
Ẋ - shuffle [1,1,1,0,0,1,1,0]
s4 - split into chunks of 4 [[1,1,1,0],[0,1,1,0]]
j - join (with n) [1,1,1,0,3,0,1,1,0]
s3 - split into chunks of 3 [[1,1,1],[0,3,0],[1,1,0]]
-
1\$\begingroup\$ As a small note,
ŒHalso works in place ofs4. \$\endgroup\$Mr. Xcoder– Mr. Xcoder2018年06月03日 06:24:57 +00:00Commented Jun 3, 2018 at 6:24 -
\$\begingroup\$ ;ṙ4s3 also works \$\endgroup\$dylnan– dylnan2018年06月03日 17:53:05 +00:00Commented Jun 3, 2018 at 17:53
-
\$\begingroup\$ @dylnan I actually posted with a TIO having that same code at one point during my golfing (but quickly put it back so I didn't have to rewrite the explanation). \$\endgroup\$Jonathan Allan– Jonathan Allan2018年06月03日 19:06:20 +00:00Commented Jun 3, 2018 at 19:06
Pyth, (削除) 16 (削除ここまで) 14 bytes
c3jQc2.S.[d8*N
Saved 2 bytes thanks to isaacg.
Uses spaces for safe spots and quotes for mines.
Try it here
Explanation
c3jQc2.S.[d8*N
*NQ Get (implicit) input number of quotes...
.[d8 ... and pad to length 8 with spaces.
.S Shuffle.
jQc2 Stick the input in the middle.
c3 Split into three.
-
\$\begingroup\$
.[d8instead of>8+*8d\$\endgroup\$izzyg– izzyg2018年06月03日 03:25:34 +00:00Commented Jun 3, 2018 at 3:25
Jelly, 9 bytes
<Ɱ8Ẋs4js3
empty = 1
mine = 0
Note that 1 and 0 are integers.
Another note: this is somewhat similar to Jonathan Allan's 10-byte answer, but it's not really influenced by it in any way, and the mechanism, if you pay close attention, is actually more different than at first glance.
-
\$\begingroup\$ Ugh I missed a trick :) \$\endgroup\$Jonathan Allan– Jonathan Allan2018年06月03日 19:07:23 +00:00Commented Jun 3, 2018 at 19:07
-
\$\begingroup\$ @JonathanAllan Do you believe this is close enough to yours? The suffix is the same anyway... \$\endgroup\$Erik the Outgolfer– Erik the Outgolfer2018年06月03日 19:08:41 +00:00Commented Jun 3, 2018 at 19:08
-
1\$\begingroup\$ It's slightly different. If I read a post and find a quick golf I comment; if I'm just trying to solve the challenge I post. I've posted identical code before independently. \$\endgroup\$Jonathan Allan– Jonathan Allan2018年06月03日 19:15:33 +00:00Commented Jun 3, 2018 at 19:15
-
\$\begingroup\$ @JonathanAllan My approach to that is a bit different, if I find out that my independent solution is actually almost the same as somebody else's but with a slightly different element which saves a byte or two (subjective opinion ensues), I comment, otherwise I outgolf. That's why I had asked, but you seem to prefer me posting it here, so... \$\endgroup\$Erik the Outgolfer– Erik the Outgolfer2018年06月03日 19:20:02 +00:00Commented Jun 3, 2018 at 19:20
Oracle 18 SQL, 230 bytes
Not a golfing language but...
WITH v(v)AS(SELECT*FROM SYS.ODCINUMBERLIST(0,1))SELECT v.v||b.v||c.v||'
'||d.v||n||e.v||'
'||f.v||g.v||h.v
FROM n,v,v b,v c,v d,v e,v f,v g,v h
WHERE v.v+b.v+c.v+d.v+e.v+f.v+g.v+h.v=n
ORDER BY DBMS_RANDOM.VALUE
FETCH NEXT ROW ONLY
The input value is in a table n with column n:
CREATE TABLE n(n) AS
SELECT 7 FROM DUAL;
Try it online - log onto https://livesql.oracle.com and paste it into a worksheet.
Output:
V.V||B.V||C.V||''||D.V||N||E.V||''||F.V||G.V||H.V
-------------------------------------------------
101
171
111
To get all possible combinations (183 Bytes):
WITH v(v)AS(SELECT*FROM SYS.ODCINUMBERLIST(0,1))SELECT v.v||b.v||c.v||'
'||d.v||n||e.v||'
'||f.v||g.v||h.v
FROM n,v,v b,v c,v d,v e,v f,v g,v h
WHERE v.v+b.v+c.v+d.v+e.v+f.v+g.v+h.v=n
Output:
V.V||B.V||C.V||''||D.V||N||E.V||''||F.V||G.V||H.V
-------------------------------------------------
111
171
110
111
171
101
111
171
011
111
170
111
111
071
111
110
171
111
101
171
111
011
171
111
Japt, 13 bytes
çÊú8 öÊi4U ò3
Explanation
:Implicit input of integer U
Ê :"l"
ç :Repeat U times
ú8 :Pad right to length 8
öÊ :Random permutation
i4U :Insert U at index 4
ò3 :Split at every 3rd character
QBasic 1.1, (削除) 206 (削除ここまで) 186 bytes
RANDOMIZE TIMER
INPUT N
O=N
Z=8-N
FOR I=0TO 7
IF O*Z THEN
R=RND<.5
O=O+R
Z=Z-1-R
A(I)=-R
ELSEIF O THEN
O=O-1
A(I)=1
ELSE
Z=Z-1
A(I)=0
ENDIF
NEXT I
?A(0)A(1)A(2)
?A(3)N;A(4)
?A(5)A(6)A(7)
-20 thanks to DLosc (newly-posted golfing trick).
Empty = 0
Mine = 1
Note that 0 and 1 are integers, but I'm using STDOUT anyway, so...
Output appears like this:
A B C
D x E
F G H
Where A-H are 0/1 and x is the input.
-
\$\begingroup\$ Nice trick, working with QBasic's wonky number output by using numbers for the mine & empty tile! \$\endgroup\$DLosc– DLosc2018年06月04日 15:26:33 +00:00Commented Jun 4, 2018 at 15:26
Charcoal, 19 bytes
W¬=ΣIKA8«E3⭆3‽2↑↗↖θ
Try it online! Link is to verbose version of code. Uses 0 for a mine, 1 for an empty space. Explanation:
KA Peek the entire canvas
I Cast to integer
Σ Take the sum
8 Literal 8
= Equals
¬ Logical Not
W « While
3 3 Literal 3
E Map over implicit range
⭆ Map over implicit range and join
2 Literal 2
‽ Random element of implicit range
Implicitly print on separate lines
↑↗↖θ Print the original input in the middle
Peekreturns an array of strings, whichSumsimply concatenates, which is why we have to cast to integer first. (Sum(Sum(PeekAll()))also works.)SumreturnsNonefor an empty array (first loop), so the only safe comparison isNot(Equals(...)).- Nilary
Randomalways returns0, although its documentation says otherwise.
Alternative solution, was 19 bytes, now 17 bytes after a Charcoal bugfix:
θ←9W−ΣIKA8UMKMI‽2
Try it online! Link is to verbose version of code. Uses 0 for a mine, 1 for an empty space. Explanation:
θ
Print the original input.
←9
Print a 9 leftwards. This moves the cursor back over the original input, and also forces at least one iteration of the while loop (otherwise an input of 8 would do nothing).
W−ΣIKA8
Repeat while the difference between the sum of all the digits on the canvas and 8 is nonzero:
UMKMI‽2
Replace each of the surrounding characters randomly with 0 or 1.
R, (削除) 67 63 62 (削除ここまで) 59 bytes
matrix(c(sample(rep(1:0,c(n<-scan(),8-n))),n),6,5)[2:4,1:3]
Uses 1 and 0. Build a n* 1 +(8-n)* 0 vector, shuffles it, appends n, builds the bigger matrix shown below(where a...i stand for the elements of the original vector) and extracts the proper sub-matrix shown in uppercase:
[,1] [,2] [,3] [,4] [,5]
[1,] "a" "g" "d" "a" "g"
[2,] "B" "H" "E" "b" "h"
[3,] "C" "I" "F" "c" "i"
[4,] "D" "A" "G" "d" "a"
[5,] "e" "b" "h" "e" "b"
[6,] "f" "c" "i" "f" "c"
-
\$\begingroup\$ One byte shorter:
matrix((c(sample(rep(1:0,c(n<-scan(),8-n))),n))[c(1:4,9:5)],3)\$\endgroup\$Gregor Thomas– Gregor Thomas2018年06月04日 19:47:38 +00:00Commented Jun 4, 2018 at 19:47 -
1\$\begingroup\$ @Gregor you're right an array is probably a reasonable form of output to display an array :) \$\endgroup\$JayCe– JayCe2018年06月04日 19:55:45 +00:00Commented Jun 4, 2018 at 19:55
Python 2, 93 bytes
from random import*
def f(n):a=[1]*n+[0]*(8-n);shuffle(a);a[4:4]=[n];return zip(*[iter(a)]*3)
0 for empty; 1 for a mine; and n for one's self.
-
\$\begingroup\$ The use of
iteris smart! \$\endgroup\$Jonathan Allan– Jonathan Allan2018年06月03日 13:54:33 +00:00Commented Jun 3, 2018 at 13:54 -
\$\begingroup\$ @Jonathan Allan: xnor showed me that just the other day. \$\endgroup\$Chas Brown– Chas Brown2018年06月03日 18:40:32 +00:00Commented Jun 3, 2018 at 18:40
Attache, 51 bytes
{[3,3]&Rotate[Sample[{Sum@_=_2}&_\BinBelow@8]'_,4]}
Explanation
Similar to Galen's J/APL answer, the basic technique is to generate an array of 1s and 0s with the correct number of mines, inserting the input by appending it to the end, rotating the array such that the input lies in the center, then reshaping into a 3x3 matrix.
Part 1: generating the binary array
There are many ways to go about doing this, but I mainly happened across two types: brute force and selection.
The primary brute force method looks like this:
NestWhile[{Random[8&2]},0,{Sum@_/=_2}&_]
This generates random arrays of 8 binary digits (Random[8&2]) while their sums do not equal the input {Sum@_/=_2}&_. This is a bit verbose, as the following emphasized portions of the code are there "just to make it work":
NestWhile[{Random[8&2]},0,{Sum@_/=_2}&_]
^ ^^^^^ ^^^^
And I discarded the idea.
Selection is more interesting. The main concept is to use the BaseBelow[b, n] builtin, which generates a list of all base-b integers of width n (as digit arrays), from 0 to b^n-1. For example, BaseBelow[3, 2] generates all ternary integers of width 2:
A> BaseBelow[3, 2]
0 0
0 1
0 2
1 0
1 1
1 2
2 0
2 1
2 2
We specifically use BaseBelow[2, 8] for all binary integers of width 8. These represent all possible minefields of all lengths. This is the first step.
The second step is selecting all such arrays with only N 1s, where N is the input. My first idea was to translate this English statement directly into Attache:
Chunk[SortBy[Sum,BaseBelow[2,8]],Sum]@N@1
However, not only did this come out to be 1 byte longer than the aforementioned approach, it's also highly repetitive—and it isn't even randomized yet!. Sure, I could probably save 1 byte by reorganizing how BaseBelow is called, but it simply isn't worth using the approach.
So I decided to kill two birds with one stone and use a Shuffle based approach. The following gives all valid minefields of length N in random order:
{Sum@_=_2}&N\Shuffle[BaseBelow&8!2]
Then, all that needs to be done is to select the first. But I can do better—surely it'd be better to simply Sample the filtered array? This approach comes out to be something like this:
Sample[{Sum@_=_2}&_\BaseBelow[2,8]]
I had to revert the BaseBelow&8!2 golf because \s precedence is too high. Otherwise satisfied, I proceeded to chop a byte off of that:
Sample[{Sum@_=_2}&_2円&BaseBelow@8]
(I discovered another way to succinctly call a dyadic function here: x&f@y is a high-precedence expression which evaluates to f[x, y].)
However, despite this, I remembered that, all along, an alias for 2&BaseBelow existed: BinBelow. So I used that:
Sample[{Sum@_=_2}&_\BinBelow@8]
This generates the desired minefield. I'm convinced this is near optimal.
Part 2: Forming the array
As said earlier, the forming technique I used is similar to the J/APL answer, so I won't go into too much detail. Suppose MINEFIELD is the result from the last section. The function then becomes:
{[3,3]&Rotate[MINEFIELD'_,4]}
MINEFIELD'_ concatenates the minefield with the original input _, giving us something like this:
[1, 0, 0, 0, 1, 0, 0, 1, 3]
Then, Rotate[MINEFIELD'_,4] rotates this list 4 times to the left, placing the center:
[1, 0, 0, 1, 3, 1, 0, 0, 0]
The last step is using [3,3]& to reshape the list into a 3x3 matrix:
1 0 0
1 3 1
0 0 0
Java 10, (削除) 165 (削除ここまで) (削除) 157 (削除ここまで) 141 bytes
n->{var r="___\n_"+n+"_\n___";for(int i;n>0;r=r.charAt(i*=Math.random())>58?r.substring(0*n--,i)+(i>9?0:0+r.substring(i+1)):r)i=11;return r;}
Empty tiles are _ (any character with a unicode value above 58 is fine) and mines are 0.
Explanation:
n->{ // Method with integer parameter and String return-type
var r="___\n_"+n+"_\n___"; // Result-String, starting at:
// "___
// _n_
// ___"
for(int i;n>0 // Loop as long as `n` isn't 0 yet:
; // After every iteration:
r=r.charAt(i*=Math.random())
// Select a random integer in the range [0,11)
>58? // And if the character at this random index is a '_':
r.substring(0*n--,i) // Set `r` to the first part excluding character `i`,
// (and decrease `n` by 1 in the process)
+(i>9?0:0+ // appended with a '0',
r.substring(i+1)) // appended with the second part
: // Else:
r) // Leave `r` unchanged
i=11; // Set `i` to 11 so a new random integer can be chosen
return r;} // Return the result
PowerShell, 77 bytes
param($n)-join(0..7|random -c 8|%{'X_'[$_-ge$n]
$n[++$i-ne4]
'
'*($i-in3,5)})
PHP, (削除) 135 (削除ここまで) (削除) 134 (削除ここまで) (削除) 123 (削除ここまで) (削除) 117 (削除ここまで) (削除) 122 (削除ここまで) 121 bytes
Looping over str to print instead saves 1 byte
str_split and implode to insert the centre number saves 11 bytes
(削除) Don't need to assign the string to $s anymore saving 6 bytes (削除ここまで)
Yes you do. Otherwise the string is shuffled after every echo...
Removing whitespace after echo saves 1 byte
Replacing "\n" with an ctual line break saves 1 byte
$n=$argv[1];$s=implode($n,str_split(str_shuffle(str_pad(str_repeat(m,$n),8,n)),4));for(;$i<9;)echo$s[$i].(++$i%3?"":"
");
PowerShell, (削除) 91 (削除ここまで) 86 bytes
-5 bytes thanks to mazzy
param($n)$x=,'X'*$n+,'_'*(8-$n)|random -c 8
-join$x[0..2]
$x[3,4]-join$n
-join$x[5..7]
Shuffles a generated string ranging from ________ to XXXXXXXX (replacing from the left). It then slices through it multiple times, inserting $n in the middle, to build the output string. This last part can probably be greatly optimized because each index costs a minimum of 5 bytes.
-
1
05AB1E, 12 bytes
×ばつ8j.r2äIý3ô
Uses 0 for mines, spaces for blank squares. Outputs a list of lines, which is pretty printed in the TIOs below by joining with newline delimiter (»).
Try it online or verify a few more test cases at once.
Explanation:
$ # Push 0 and the input-digit
×ばつ # Repeat the 0 the input-digit amount of times as string
# i.e. 4 → "0000"
8j # Prepend spaces to make the size 8
# → " 0000"
.r # Randomly shuffle the characters in this string
# i.e. " 0000" → " 00 0 0"
2ä # Split it into two equal halves (of 4 characters)
# → [" 00 ","0 0"]
Iý # Join it with the input-digit
# → " 00 40 0"
3ô # And then split it into (three) parts of 3 characters
# → [" 00"," 40"," 0"]
# (which is output implicitly as result)
12 bytes alternative:
[email protected]š5._3ô
Uses 1 for mines, 0 for blank squares. Outputs a matrix of digits, which is pretty printed in the TIOs below by joining each row, and then these rows with newline delimiter (J»).
Try it online or verify a few more test cases at once.
Explanation:
8L # Push the list [1,2,3,4,5,6,7,8]
@ # Check for each if the (implicit) input-integer is >= it
# (1 if truthy; 0 if falsey)
# i.e. 4 → [1,1,1,1,0,0,0,0]
.r # Randomly shuffle this list
# i.e. [1,1,1,1,0,0,0,0] → [0,1,1,0,1,0,0,1]
Iš # Prepend the input-digit to the list
# → [4,0,1,1,0,1,0,0,1]
5._ # Rotate the list five times towards the left
# → [1,0,0,1,4,0,1,1,0]
3ô # And then split it into (three) parts of 3 digits each
# → [[1,0,0],[1,4,0],[1,1,0]]
# (which is output implicitly as result)
Vyxal j, 53 bitsv2 , 6.625 bytes
IṅÞc/o1⁄2j2
Bitstring:
01011100001000000101111111001100101100100000000011001
Spaces for mines, 0 for empty spaces
IṅÞc/o1⁄2j2
I # Push n spaces
ṅ # pad with zeros to the nearest multiple of 8
Þc/o # shuffle
1⁄2j # split in half and join by the input
2 # shape as a square
# j flag joins on newlines
💎
Created with the help of Luminespire.
1and0? \$\endgroup\$