RosettaCodeData/Task/Minesweeper-game/Phix/minesweeper-game.phix

173 lines
4.3 KiB
Plaintext

constant help = """
Minesweeper
===========
Enter eg A1 to open a cell, FA1 to flag a cell, Q to quit.
The board is initially displayed with 10-20% of cells mined, as follows:
. - an unknown cell (unopened and not flagged)
_ - an empty cell, with no surrounding mines
1..8 - an empty cell, with some nearby mines
? - a cell you have flagged as a mine
(a flag can only be cleared by opening)
On completion:
X - the mine you detonated (if any)
* - a mine which was not flagged
+ - a mine which was correctly flagged
"""
string board = """
123456
A......
B......
C......
D......
"""
sequence data = repeat(repeat(0,6),4)
-- 0: empty, no nearby mines
-- 1-8: empty, with surrounding mines
-- 9: a mine
-- data[row][col] maps to board[row*8+4+col], lets quickly verify that:
if find('.',board)!=13 then ?9/0 end if
if rfind('.',board)!=42 then ?9/0 end if
-- (above may trigger if copy/paste/dowload etc messed up whitespace)
constant prompt = "\nEnter eg A1 to open a cell, FA1 to flag a cell, Q to quit, or ? for help:"
integer mines = round((6*4)*0.10+rand(6*4)*0.10), -- 10-20%
cleared = 0,
flagged = 0,
flag = false,
row = 0,
col
procedure plant_mines()
for i=1 to mines do
while 1 do
row = rand(4)
col = rand(6)
if data[row][col]!=9 then
data[row][col] = 9
for rx=row-1 to row+1 do
if rx>=1 and rx<=4 then
for cx=col-1 to col+1 do
if cx>=1 and cx<=6 then
if data[rx][cx]!=9 then
data[rx][cx] += 1
end if
end if
end for
end if
end for
exit
end if
end while
end for
printf(1,"%d mines planted\n",mines)
row = 0
end procedure
procedure clear_cell(integer row, col, drc)
board[row*8+4+col] = iff(drc?drc+'0':' ')
cleared += 1
if drc=0 then
for rx=row-1 to row+1 do
if rx>=1 and rx<=4 then
for cx=col-1 to col+1 do
if cx>=1 and cx<=6 then
drc = data[rx][cx]
if drc!=9
and board[rx*8+4+cx]='.' then
clear_cell(rx,cx,drc)
end if
end if
end for
end if
end for
end if
end procedure
function make_move()
integer brc = row*8+4+col
if flag then
if board[brc]='.' then
board[brc] = '?'
flagged += 1
end if
else
integer drc = data[row][col]
if drc=9 then
board[brc] = 'X'
puts(1,"\n\n***BOOM!***")
return true
end if
if find(board[brc],".?") then
clear_cell(row,col,drc)
end if
end if
row = 0
flag = false
-- nb: flagged and cleared may be wrong following incorrect input.
if flagged=mines
or cleared=6*4-mines then
puts(1,"\n\n***You Win!***")
return true
end if
return false -- no "BOOM" yet!
end function
procedure disclose()
for row=1 to 4 do
for col=1 to 6 do
if data[row][col]=9 then
integer bdx = row*8+4+col,
bch = board[bdx]
if bch='.' then
bch = '*'
elsif bch='?' then
bch = '+'
elsif bch!='X' then
?9/0
end if
board[bdx] = bch
end if
end for
end for
end procedure
plant_mines()
while 1 do
if not flag and row=0 then
puts(1,board)
puts(1,prompt)
end if
integer ch = upper(getc(0))
puts(1,ch)
if ch='Q' then exit end if
if ch='?' then
puts(1,help)
elsif ch='F' then
flag = true
elsif ch>='A'
and ch<='D' then
row = ch-'@'
elsif ch>='1'
and ch<='6' then
col = ch-'0'
if make_move() then exit end if
else
printf(1,"\n\nunrecognised:%c\n\n",ch)
flag = false
row = 0
end if
end while
disclose()
puts(1,board&"game over\n\n")
{} = wait_key()