Working Minesweeper
Javascript, 978 bytes (824 without CSS)
http://jsbin.com/otayez/6/
Checklist:
Randomized mine generation - yes
8x8 field with 10 mines - yes
Mine flags - Yes
"unknown" flags - no
Reveal nearby blank spaces when a blank space has been revealed. - yes
Input and output code: It must be playable. - yes
JS:
(function(){
f=Math.floor;r=Math.random;b=8,s=[-1,0,1],o='',m='*',l=0;
for(g=[i=b];i;)g[--i]=[0,0,0,0,0,0,0,0];
for(i=10,a=f(r()*64);i--;g[f(a/b)][a%b]=m)while(g[f(a/b)][a%b])a=f(r()*64);
for(i=64;i--;z.id='b'+(63-i),c.appendChild(z))z=document.createElement('button');
for(d=b;d--;)
for(r=b;r--;)
s.map(function(y){
s.map(function(x){
if(g[d][r]!=m&&g[d+y]&&g[d+y][r+x]==m)g[d][r]++;
});
});
c.onclick=function(e){
var t=e.target,
i=t.id.slice(1),
x=i%b,
y=f(i/b),
n=t.className=='b';
if(t.innerHTML||(n&&!e.ctrlKey))return;
if(e.ctrlKey)return t.className=(n?'':'b')
if(q(x,y))alert('boom')
if(l==54)alert('win')
};
function q(x,y){
if(x<0||x>7||y<0||y>7)return;
var p=y*b+x,
v=g[y][x],
t=document.all['b'+p];
if(v!=m&&!t.innerHTML){
t.innerHTML=g[y][x];
t.className='f';
l++;
if(!v){t.className='z';s.map(function(d){s.map(function(r){q(x+r,y+d)})})}
}
return v==m
}
})();
MiniJS 812 bytes:
f=Math.floor;r=Math.random;b=8,s=[-1,0,1],o='',m='*',l=0,h='b';for(g=[i=b];i;)g[--i]=[0,0,0,0,0,0,0,0];for(i=10,a=f(r()*64);i--;g[f(a/b)][a%b]=m)while(g[f(a/b)][a%b])a=f(r()*64);for(i=64;i--;z.id=h+(63-i),c.appendChild(z))z=document.createElement('button');for(d=b;d--;)for(r=b;r--;)s.map(function(y){s.map(function(x){if(g[d][r]!=m&&g[d+y]&&g[d+y][r+x]==m)g[d][r]++})});c.onclick=function(e){var t=e.target,i=t.id.slice(1),n=t.className==h;if(t.innerHTML||(n&&!e.ctrlKey))return;if(e.ctrlKey)return t.className=(n?'':h);if(q(i%b,f(i/b)))alert('boom');if(l==54)alert('win')};function q(x,y){if(x<0||x>7||y<0||y>7)return;var p=y*b+x,v=g[y][x],t=document.all[h+p];if(v!=m&&!t.innerHTML){t.innerHTML=g[y][x];t.className='f';l++;if(!v){t.className='z';s.map(function(d){s.map(function(r){q(x+r,y+d)})})}}return v==m}
HTML 12 bytes
<div id="c">
The CSS isn't necessary from a functionality standpoint, but is from a usability standpoint:
#c{
width:300px;
height:300px;
}
button{
width:12.5%;
height:12.5%;
line-height:30px;
}
.f,.z{
background:#fff;
border:solid 1px #fff;
}
.z{
color:#fff;
}
.b{background:#f00}
Mini CSS 154 bytes:
#c{width:300px;height:300px}button{width:12.5%;height:12.5%;line-height:30px}.f,.z{background:#fff;border:solid 1px #fff}.z{color:#fff}.b{background:#f00}
C, 568, 557, 537
Checklist:
Randomized mine generation - yes
8x8 field with 10 mines - yes
Mine and "unknown" flags - yes
Reveal nearby blank spaces when a blank space has been revealed. - yes
Input and output code: It must be playable. - yes
Further to playable:
Win detection (found all mines, or revealed all empties)
Bang detection (hit a mine)
Game terminates.
Output format:
# - unrevealed
! - a flagged mine
* - a mine
(number) - number of neighbouring mines
? - unknown flag
Input format:
x y f
- where x is 0..7, y is 0..7 (origin upper-left)
- f is 0 to open up, 1 to flag a mine, and 2 to flag a unknown
example game:
./a.out
5 5 0
# 1 0 0 0 2 # #
# 1 0 0 0 2 # #
# 1 0 0 0 1 1 1
# 1 0 0 0 0 0 0
# # 1 0 0 0 1 1
# # 1 0 0 0 1 #
# # # 1 2 1 # #
# # # # # # # #
6 1 1
# 1 0 0 0 2 # #
# 1 0 0 0 2 ! #
# 1 0 0 0 1 1 1
# 1 0 0 0 0 0 0
# # 1 0 0 0 1 1
# # 1 0 0 0 1 #
# # # 1 2 1 # #
# # # # # # # #
7 5 0
# 1 0 0 0 2 # #
# 1 0 0 0 2 ! #
# 1 0 0 0 1 1 1
# 1 0 0 0 0 0 0
# # 1 0 0 0 1 1
# # 1 0 0 0 1 *
# # # 1 2 1 # 1
# # # # # # # #
bang!
code:
// 8x8 grid but with padding before first row, after last row, and after last column, i.e. its 9x10
m[99]; // 0=empty,1=mine
u[99]; // 0=revealed,1=unrevealed,2=flag,3=unknown
// count neighbouring mines (8way)
c(i){return m[i-8]+m[i-9]+m[i-10]+m[i+8]+m[i+9]+m[i+10]+m[i-1]+m[i+1];}
// reveal (4way)
r(i){
if(u[i]){
u[i]=0;
if(!c(i))r(i-9),r(i+9),r(i+1),r(i-1);
}
}
i,x,y,f,e;
main(){
// place 10 mines
for(srand(time(0));i<10;){
x=rand()%64;
x+=9+x/8;
if(!m[x]){
m[x]=1;
i++;
}
}
for(;y<64;y++)u[y+9+y/8]=1; // mark visible grid as being unrevealed
while(!e){
// read input 0..7 0..7 0..2
scanf("%d%d%d",&x,&y,&f);
i=x+9+y*9;
if(f)u[i]=f==1?2:u[i]==3?1:3;else r(i); // flag, toggle unknown/unrevealed, open
// show grid and calc score
for(y=f=x=0;x<64;x++){
i=x+9+x/8;
putchar(u[i]?" #!?"[u[i]]:m[i]?42:48+c(i)); // 42='*', 48='0'
putchar(x%8==7?10:32);
if(!u[i])y+=m[i]?-99:1; // y = number of correctly open
if(u[i]==2)f+=m[i]?1:-99; // f = number of correct mines
}
if(y<0||y==54||f==10)e=puts(y<0?"bang!":"win!"); // 54 = 64-10
}
}
Mathematica 566 548 1056
Edit: This is a complete rewrite. I gave up trying to obtain the shortest code and decided instead to build in the features that made most sense.
r
indicates the number of rows in the grid. c
indicates the number of columns in the grid.
m
: number of mines.
The game is played by mouse-clicking on the buttons. If the player clicks on a mine, the cell turns black and the program prints "You Lose!"
The checkbox "u" allows the player to peek at the complete solution at any time. The flags, "?" and "!" can be placed in any cell as desired.
DynamicModule[{s, x, f, l},
Manipulate[
Column[{
Grid[s],
If[u, Grid@f, Null]
}],
Grid[{{Control@{{r, 8}, 4, 16, 1, PopupMenu},
Control@{{c, 8}, 4, 16, 1, PopupMenu},
Control@{{m, 10}, 1, 50, 1, PopupMenu}},
{Button["New", i],
Control@{{e, 0}, {0 -> "play", 1 -> "?", 2 -> "!"}, SetterBar},
Control@{{u, False}, {True, False}}}}],
Deployed -> True,
Initialization :>
(p = ReplacePart;
q = ConstantArray;
z = Yellow;
w = White;
b := Array[Button[" ", v[{#, #2}], Background -> z] &, {r, c}];
a := RandomSample[l = Flatten[Array[List, {r, c}], 1], m];
d[m1_] :=
p[ListConvolve[BoxMatrix@1, p[q[0, {r, c}], (# -> 1) & /@ m1], 2,
0], (# -> "*") & /@ (x)];
n[y_] := Complement[Select[l, ChessboardDistance[y, #] == 1 &], x];
d[m1_] :=
p[ListConvolve[BoxMatrix@1, p[q[0, {r, c}], (# -> 1) & /@ m1], 2,
0], (# -> "*") & /@ (x)];
v[{r_, c_}] :=
Switch[e,
1, If[s[[r, c, 3, 2]] == z,
s = p[s, {{r, c, 1} -> If[s[[r, c, 1]] == "?", " ", "?"]}],
Null],
2, If[s[[r, c, 3, 2]] == z,
s = p[s, {{r, c, 1} -> If[s[[r, c, 1]] == "!", " ", "!"]}],
Null],
3, Null,
0, Switch[f[[r, c]],
"*", (Print["You lose!"]; (s = p[s, {r, c, 3, 2} -> Black])),
0, (s = p[s, {{r, c, 1} -> " ", {r, c, 3, 2} -> w}];
f = p[f, {{r, c} -> ""}]; v /@ n[{r, c}]),
" ", Null,
_, (s = p[s, {{r, c, 1} -> f[[r, c]], {r, c, 3, 2} -> w}])]];
i :=
(x = a;s = b;f = d[x]);i) ] ]
Initial State
At a later point...