# Minesweeper At Work

Everyone knows the old minesweeper game that shipped with Windows XP. It's a simple grid with a 9x9 matrix of cells containing either a number (indicating how many mines are adjacent to it) or a mine. The challenge is to generate a random 9x9 grid with 10 bombs given any integer seed (up to whatever your machine/language's largest int is) with brownie points if you implement the PRNG yourself

example output: cells contain either numerals 0-8 or * for mines

*101*1000
110111000
123210000
1***10000
123210011
00000002*
00000114*
000112*3*
0001*2121


Shortest code in bytes wins.. standard rules etc, etc..

• You should indicate what the numbers mean :) Sep 2, 2016 at 20:11
• Microsoft Minesweeper is a heck of a lot older than XP and minesweeper-like games date back to at least the 60s. Sep 2, 2016 at 20:19
• Also, I don't have time to play Minesweeper while at work -- I'm too busy on PPCG. ;-) Sep 2, 2016 at 20:41
• What counts as a PRNG, exactly? How many different configurations must it be able to produce? Can we not use the seed and just generate a different configuration each time, if our language has a PRNG which is automatically initallized to a "random" seed? Sep 2, 2016 at 21:07
• @TimmyD But XP's version is the first version that had a 9x9 grid. Anything older uses an 8x8 grid for Beginner. #outnerded ;) Sep 2, 2016 at 21:37

# MATLAB, 94 93 bytes

rng(input(''));x(9,9)=~1;x(randperm(81,10))=1;y=[conv2(+x,ones(3),'s')+48 ''];y(x)=42;disp(y)


Example run (the first line after the code is the input typed by the user):

>> rng(input(''));x(9,9)=~1;x(randperm(81,10))=1;y=[conv2(+x,ones(3),'s')+48 ''];y(x)=42;disp(y)
99
*10001*2*
220001232
*201111*1
*312*1111
12*211000
011211000
0001*1000
000112110
000001*10


### Explanation

rng(input(''));


takes an integer and uses it as seed. (This works in modern MATLAB versions. Old versions may need a different syntax.)

x(9,9)=~1;


assigns logical 0, or false (obtained by logically negating 1) to the entry (9,9) of a matrix x. The rest of the entries are automatically initiallized to logical 0 too.

x(randperm(81,10))=1;


assigns 1 (autoomatically cast to logical 1, or true) to 10 of the 81 entries of x, chosen randomly without replacement. These entries are the ones that contain bombs.

conv2(+x,ones(3),'s')


is an abbreviation of conv2(+x,ones(3),'same'). It convolves the matrix x (which needs to be cast to double, using +) with a 3×3 neighbourhood containing 1. This counts how many bombs are adjacent to each entry. For entries that contain a bomb it includes that bomb, but the value there will be overwritten later.

y=[...+48 ''];


adds 48 to the value, to convert from number to ASCII code. Concatenating with the empty matrix casts these ASCII codes to chars.

y(x)=42;


assigns 42 (ASCII code for '*') to the positions of the bombs. These positions are given by x, which is here used as a logical index.

disp(y)


displays the result.

## Javascript (ES6), 204 or 198 bytes

### Custom PRNG (204 bytes)

s=>(p=-1,S=n=>(x=p%9-(n+=p)%9)*x-64&&b[n]=='*',T=n=>S(n)+S(-n),b=[...'*00000000'.repeat(9)]).sort(_=>(s=(22695477*s+1)>>>0)&1||-1).map(c=>(p++,c=='0'?T(1)+T(8)+T(9)+T(10):c)).join.match(/.{9}/g).join



This code is using a linear congruential generator with multiplier 22695477 and increment 1 (this is the Borland C/C++ implementation).

Due to the poor efficiency of the PRNG during its warmup phase, I had to place one bomb per row (instead of 10 at the beginning or 10 at the end of the unshuffled array). So, there are only 9 bombs. I may try to fix that later.

Also, there must be a simpler/shorter way of processing the 'out of board' check (x=p%9-(n+=p)%9)*x-64 but I just can't figure it out right now.

### Using Math.random() (198 bytes)

s=>(p=-1,S=n=>(x=p%9-(n+=p)%9)*x-64&&b[n]=='*',T=n=>S(n)+S(-n),b=[...'**********'+'0'.repeat(71)]).sort(_=>Math.random()-.5).map(c=>(p++,c=='0'?T(1)+T(8)+T(9)+T(10):c)).join.match(/.{9}/g).join



This one includes 10 mines as requested.

### Demo

let f =
_=>(p=-1,S=n=>(x=p%9-(n+=p)%9)*x-64&&b[n]=='*',T=n=>S(n)+S(-n),b=[...'**********'+'0'.repeat(71)]).sort(_=>Math.random()-.5).map(c=>(p++,c=='0'?T(1)+T(8)+T(9)+T(10):c)).join.match(/.{9}/g).join

console.log(f())

• '**********'+'0' is equal to '**********'+0; that saves two bytes on the 198-byte-version. Sep 3, 2016 at 12:42
• @PaulSchmitz - Unfortunately this '0' is supposed to be repeated and 0.repeat() wouldn't work. Sep 3, 2016 at 13:58
• Oops, I though it would get executed like ...('**********'+0).repeat(71). Sorry. Sep 3, 2016 at 14:40

# Dyalog APL, 40 bytes

⎕rl←1⋄(1,¨a)⍕¨{⍉3+/0,⍵,0}⍣2⊢a←9 9⍴9≥?⍨81

(assumes ⎕io←0)

the 1 in ⎕rl←1 is the seed

from right to left:

?⍨81 is the same as 81?81 - a random permutation

9≥ results in a bitmask containing ten 1s at random positions, the rest are 0s

a←9 9⍴ reshape to a 9-by-9 square and call it "a"

{ }⍣2 do the following twice:

⍉3+/0,⍵,0 sliding window sum of 3 columns (assume 0s outside), then transpose

(1,¨a)⍕¨ is format (convert to string) each. The left argument to ⍕ specifies the total number of characters and fractional characters in the result. If ⍕ can't format according to that spec it outputs a * - a lucky coincidence for this problem. a will be 1 where the mines are - trying to fit a whole and fractional part into a single char is impossible, so those will appear as *s.

• Can you explain the ⎕io←0 assumption? I'm not familiar with Dyalog APL... Apr 10, 2017 at 13:44
• Array indices in Dyalog are 1-based by default. Setting ⎕io (the "Index Origin") to 0 makes them 0-based and changes some primitives accordingly, e.g. ⍳3 will be 0 1 2, not 1 2 3. That can be done either programmatically (⎕io←0) or from the preferences in the GUI. Having this choice is a 50-year-old mistake that still splits the tiny APL community of today.
– ngn
Apr 10, 2017 at 14:30

# Python 2, 269266 264 bytes

from random import*
seed(input())
z=1,0,-1
n=range(9)
m=[*9 for _ in n]
for x,y in sample([[x,y]for x in n for y in n],10):
m[x][y]=-9
for a in z:
for b in z:
if 0<=x+a<9>0<=y+b<9:m[x+a][y+b]+=1 # it gets displayed as 4 spaces, but the beginning of this line is a single tab
print("\n".join("".join([c,'*'][c<0]for c in l)for l in m))


Try it on ideone.com

Saved 2 bytes thanks to Aaron.

Most likely still golfable.

### Explanation

random is imported for using seed to seed the PRNG and sample to select ten bomb locations randomly. m is a 9 x 9 matrix saving the board. For each of the bomb locations, the corresponding entry in m gets set to -9 and all neighbouring entries get incremented. This way m ends up containing the count of adjacent bombs for non-bomb cells and a negative number for bomb cells. The final print prints the whole board by iterating through all lines l in m and all cells c in l.

• What exactly is 'random' used for, exactly? Sep 2, 2016 at 22:13
• @Qwerp-Derp probably to seed the random number generator indirectly used by sample() Sep 2, 2016 at 23:10
• save 2 bytes by mixing tab indents inside for a in z: block (only python 2.x) Apr 7, 2017 at 14:57

# R, 187 Bytes

set.seed();x=1:121;y=x[!(x%%11 %in% 0:1|(x-1)%/%11 %in% c(0,10))];z=sample(y,10);x=x*0;for(t in z){p=t+c(-10:-12,-1,1,10:12);x[p]=x[p]+1};x[z]=9;m=data.frame(matrix(x[y],9));m[m==9]='*';m


Try it on Ideone

Explanation:

set.seed() take a cst seed.

x is the index for a 11*11 matrix

y is the index of the 9*9 matrix in the 11*11 matrix

z is the index of the bomb

x=x*0 initialise the matrix value

• I think you have to take the argument to set.seed() as input.
– BLT
Apr 8, 2017 at 3:51

## JavaScript ES6, 244 bytes

f=(a=[...Array(11)].map(_=>Array(11).fill(0)),n=10,r=_=>Math.random()*9|0,x=r(),y=r())=>a[x+1][y+1]>8||[0,1,2].map(i=>[0,1,2].map(j=>a[x+i][y+j]++),a[x+1][y+1]=9)&&--n?f(a,n):a.slice(1,-1).map(a=>a.slice(1,-1).map(n=>n<9?n:*).join).join

;o.textContent=f()
<pre id=o>

• You may want to elaborate on which part is your code. Sep 2, 2016 at 23:49
• @NoOneIsHere The first 244 bytes, hopefully ;-) The first line should be 242 bytes long, then there's the newline and the  character.
– Neil
Sep 3, 2016 at 0:10

# Ruby, 181194 183+1 = 184 bytes

Forgot to actually set the seed, whoops. Uses the -n flag.

Try it online!

srand\$_.to_i
a=*81
[*0..80].sample(10).map{|i|w=i%9;h=i/9;a[i]=-99
(r=-1..1).map{|x|x+=w
x<0||x>8?0:r.map{|y|y+=h
y<0||y>8?0:a[9*y+x]+=1}}}
puts a.map{|c|c<0??*:c}.join.scan /.{9}/


# Python 2, 172 bytes

from random import*
seed(input())
r=range
b=set(sample(r(81),10))
for j in r(9):print''.join([[len({x-10,x-9,x-8,x-1,x+1,x+8,x+9,x+10}&b),'*'][x in b]for x in r(j,81,9)])
`

Try it online!