I rewrote the Tiny Basic Minesweeper in n7.
Code:
' Minesweeper, by Marcus
' ----------------------
constant UNEXPLORED = 0, EXPLORING = 1, EXPLORED = 2, FLAGGED = 3
constant HIDDEN = 10, MINE = 11
constant PLAYING = 0, QUIT = -1, COMPLETED = 1, GAME_OVER = 2
visible gameField = fill([value: HIDDEN, status: UNEXPLORED], 10, 10)
visible gameState
' Init game stare and set mine count to 15.
gameState = PLAYING
mineCount = 15
' Display map, ask for first dig position and then generate a map where that position is safe and
' dig.
DisplayMap()
pos = InputPosition("Dig at")
InitMap(mineCount, pos)
DigAt(pos)
flags = mineCount
do
DisplayMap()
' Input action.
pln "Flags left: " + flags
write "Action (d = dig, f = add/remove flag, q = quit, c = cheat): "
select lower(left(rln(), 1))
case "d"
pos = InputPosition("Dig at")
if gameField[pos.x][pos.y].status <> UNEXPLORED
pln
pln "You can't dig there!"
elseif gameField[pos.x][pos.y].value = MINE
gameState = GAME_OVER
else
DigAt(pos)
endif
case "f"
pos = InputPosition("Add or remove flag at")
if gameField[pos.x][pos.y].status = FLAGGED
gameField[pos.x][pos.y].status = UNEXPLORED
flags = flags + 1
elseif flags = 0
pln
pln "You're out of flags!"
elseif gameField[pos.x][pos.y].status <> UNEXPLORED
pln
pln "You can't place a flag there!"
else
flags = flags - 1
gameField[pos.x][pos.y].status = FLAGGED
' Change game state to completed but restore if any mine is not flagged.
gameState = COMPLETED
for y = 0 to 9 for x = 0 to 9
if gameField[x][y].value = 11 and not gameField[x][y].status = FLAGGED
gameState = PLAYING
break
endif
next
endif
case "q"
gameState = QUIT
case "c"
DisplayActualMap()
endsel
until gameState <> PLAYING
' Display actual map and print a final message based on the game state.
DisplayActualMap()
if gameState = QUIT pln "Bye bye!"
elseif gameState = COMPLETED pln "ALL MINES MARKED, YOU SUCCEEDED!"
else pln "BOOM, YOU FAILED!"
pln
system "pause"
' InputPosition
' -------------
function InputPosition(msg)
pln msg
do
write " X (0-9): "
x = int(rln())
until x >= 0 and x <= 9
do
write " Y (0-9): "
y = int(rln())
until y >= 0 and y <= 9
return [x: x, y: y]
endfunc
' InitMap
' -------
function InitMap(mineCount, safePos)
freePositions = []
for y = 0 to 9 for x = 0 to 9
if x < safePos.x - 1 or x > safePos.x + 1 or y < safePos.y - 1 or y > safePos.y + 1
freePositions[sizeof(freePositions)] = [x: x, y: y]
endif
next
for i = 1 to mineCount
pos = freePositions[rnd(sizeof(freePositions))]
free val freePositions, pos
gameField[pos.x][pos.y].value = MINE
next
endfunc
' DisplayMap
' ----------
function DisplayMap()
pln
pln " | 0 1 2 3 4 5 6 7 8 9"
pln "-+--------------------"
for y = 0 to 9
write y + "| "
for x = 0 to 9
if gameField[x][y].status = FLAGGED write "F "
elseif gameField[x][y].value >= 10 write "? "
elseif gameField[x][y].value > 0 write gameField[x][y].value + " "
else write " "
next
pln
next
pln
endfunc
' DisplayActualMap
' ----------------
function DisplayActualMap()
pln
pln " | 0 1 2 3 4 5 6 7 8 9"
pln "-+--------------------"
for y = 0 to 9
write y + "| "
for x = 0 to 9
if gameField[x][y].value = MINE write "* "
else write " "
next
pln
next
pln
endfunc
' DigAt
' -----
function DigAt(pos)
if gameField[pos.x][pos.y].status <> UNEXPLORED return
gameField[pos.x][pos.y].status = EXPLORING
do
done = true
for y = 0 to 9 for x = 0 to 9
if gameField[x][y].status = EXPLORING
done = false
gameField[x][y].status = EXPLORED
gameField[x][y].value = CloseMines(x, y)
if gameField[x][y].value = 0 MarkNearUnexplored(x, y)
endif
next
until done
' CloseMines
' ----------
function CloseMines(cx, cy)
count = 0
for y = max(cy - 1, 0) to min(cy + 1, 9) for x = max(cx - 1, 0) to min(cx + 1, 9)
count = count + (gameField[x][y].value = MINE)
next
return count
endfunc
' MarkNearUnexplored
' ------------------
function MarkNearUnexplored(cx, cy)
for y = max(cy - 1, 0) to min(cy + 1, 9) for x = max(cx - 1, 0) to min(cx + 1, 9)
if gameField[x][y].status = UNEXPLORED gameField[x][y].status = EXPLORING
next
endfunc
endfunc