Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- -- Minesweeper by JPiolho
- -- Version 1.0
- -- BUGS: Recursive sometimes dont explore every block
- -- Feel free to copy and edit as long you credit the original author
- -- More Info @ http://bit.ly/zoxn6V
- local function PlaySound(side)
- redstone.setOutput(side,true)
- sleep(0.01)
- redstone.setOutput(side,false)
- end
- local function RecursiveDiscover(fields,width,height,lx,ly)
- local toVisit = {{lx,ly}}
- local visited = {}
- local AddToVisit = function(visitedlist,tx,ty)
- for _,tv in pairs(visitedlist) do
- if tonumber(tv[1]) == tonumber(tx) and tonumber(tv[2]) == tonumber(ty) then
- return
- end
- end
- for _,tv in pairs(toVisit) do
- if tv[1] == tx and tv[2] == ty then
- return
- end
- end
- table.insert(toVisit,{tx,ty})
- end
- while #toVisit > 0 do
- local visiting = {}
- local id,v
- -- Copy array
- for id,v in pairs(toVisit) do
- table.insert(visiting,{id,v})
- end
- for id,v in pairs(visiting) do
- local x = v[2][1]
- local y = v[2][2]
- local curField = fields[y][x]
- table.remove(toVisit,v[1])
- table.insert(visited,{x,y})
- curField.discovered = true
- if curField.number <= 0 then
- if x > 1 then AddToVisit(visited,x-1,y) end
- if y > 1 then AddToVisit(visited,x,y-1) end
- if x < width then AddToVisit(visited,x+1,y) end
- if y < height then AddToVisit(visited,x,y+1) end
- if x > 1 and y > 1 then AddToVisit(visited,x-1,y-1) end
- if x > 1 and y < height then AddToVisit(visited,x-1,y+1) end
- if x < width and y > 1 then AddToVisit(visited,x+1,y-1) end
- if x < width and y < height then AddToVisit(visited,x+1,y+1) end
- end
- end
- end
- end
- local function PrintCenter(msg)
- local msgLen = string.len(msg)
- local screenWidth,_ = term.getSize()
- local xCoords = tonumber(math.ceil((screenWidth / 2) - (msgLen / 2)))
- local _,termY = term.getCursorPos()
- term.setCursorPos(xCoords,termY)
- print(msg)
- return xCoords
- end
- local function EndGame(msg)
- local _,h = term.getSize()
- term.setCursorPos(1,h-2)
- PrintCenter(msg)
- PrintCenter("Press any key to continue...")
- term.setCursorPos(1,h-1)
- while true do
- local e,v = os.pullEvent()
- if e == "key" then
- break
- end
- end
- end
- local function NewGame(difficulty)
- local sizeW, sizeH
- local minesTotal
- if difficulty == "easy" then sizeW = 10; sizeH = 10; minesTotal = 30; end
- if difficulty == "medium" then sizeW = 15; sizeH = 15; minesTotal = 50; end
- if difficulty == "hard" then sizeW = 30; sizeH = 15; minesTotal = 90; end
- local field = {}
- -- Initialize the field
- local x,y
- for y = 1,sizeH do
- field[y] = {}
- for x = 1,sizeW do
- field[y][x] = {discovered = false,
- mine = false,
- number = 0,
- flag = false
- }
- end
- end
- -- Randomly place the minefield
- local mines = 0
- while mines < minesTotal do
- x = math.random(1,sizeW)
- y = math.random(1,sizeH)
- if field[y][x].mine == false then
- field[y][x].mine = true
- mines = mines + 1
- end
- end
- -- Build the numbers
- for y = 1,sizeH do
- for x = 1,sizeW do
- mines = 0
- if x > 1 and field[y][x-1].mine == true then
- mines = mines + 1
- end
- if y > 1 and field[y-1][x].mine == true then
- mines = mines + 1
- end
- if x < sizeW and field[y][x+1].mine == true then
- mines = mines + 1
- end
- if y < sizeH and field[y+1][x].mine == true then
- mines = mines + 1
- end
- if x > 1 and y > 1 and field[y-1][x-1].mine == true then
- mines = mines + 1
- end
- if x > 1 and y < sizeH and field[y+1][x-1].mine == true then
- mines = mines + 1
- end
- if x < sizeW and y < sizeH and field[y+1][x+1].mine == true then
- mines = mines + 1
- end
- if x < sizeW and y > 1 and field[y-1][x+1].mine == true then
- mines = mines + 1
- end
- field[y][x].number = mines
- end
- end
- local flaggedMines = 0
- local flagCount = 0
- local end_flags = false
- local end_mines = false
- local cursorX, cursorY
- cursorX = 1
- cursorY = 1
- while true do
- term.clear()
- term.setCursorPos(1,1)
- local minX,maxX,minY,maxY
- minY = 1
- maxY = sizeH +1
- for y = 1,sizeH do
- local line = ""
- for x = 1,sizeW do
- local curField = field[y][x]
- if curField.discovered == true then
- if curField.mine == true then
- line = line .. "x"
- elseif curField.number > 0 then
- line = line .. curField.number
- else
- line = line .. " "
- end
- else
- if curField.flag == true then
- line = line .. "P"
- else
- line = line .. "#"
- end
- end
- end
- if y == 1 then
- minX = PrintCenter(line)
- maxX = minX + string.len(line)
- else
- PrintCenter(line)
- end
- end
- term.setCursorPos(minX + (cursorX-1),minY + (cursorY-1))
- term.setCursorBlink(true)
- if end_flags == true then
- EndGame("You have found all mines")
- break
- end
- if end_mines == true then
- EndGame("*Boom* You step on a mine")
- break
- end
- local e,v = os.pullEvent()
- local curField = field[cursorY][cursorX]
- if e == "key" then
- if v == 208 then -- Down Arrow
- if cursorY + 1 <= maxY - minY then
- cursorY = cursorY + 1
- end
- end
- if v == 200 then -- Up Arrow
- if cursorY - 1 >= 1 then
- cursorY = cursorY - 1
- end
- end
- if v == 203 then -- Left Arrow
- if cursorX - 1 >= 1 then
- cursorX = cursorX - 1
- end
- end
- if v == 205 then -- Right Arrow
- if cursorX + 1 <= maxX - minX then
- cursorX = cursorX + 1
- end
- end
- if v == 28 then -- Enter
- if curField.flag == false and curField.discovered == false then
- if curField.mine == true then
- end_mines = true
- end
- RecursiveDiscover(field,sizeW,sizeH,cursorX,cursorY)
- end
- end
- if v == 16 then -- Q
- break
- end
- if v == 57 then -- Space
- if curField.discovered == false then
- if curField.flag == false then
- flagCount = flagCount + 1
- curField.flag = true
- if curField.mine == true then
- flaggedMines = flaggedMines + 1
- end
- else
- flagCount = flagCount - 1
- curField.flag = false
- if curField.mine == true then
- flaggedMines = flaggedMines - 1
- end
- end
- if flaggedMines == minesTotal and flaggedMines == flagCount then
- end_flags = true
- end
- end
- end
- end
- end
- end
- local function Instructions()
- term.clear()
- term.setCursorPos(1,1)
- PrintCenter("Instructions")
- PrintCenter("------------")
- PrintCenter("Regular minesweeper game. If you don\'t know")
- PrintCenter("how to play, google it.")
- PrintCenter("Use arrow keys to move your cursor")
- PrintCenter("Use Space to flag a square")
- PrintCenter("Use Enter to explore a square")
- PrintCenter("Press Q to go back to main menu")
- PrintCenter(" ")
- PrintCenter("Written by JPiolho")
- PrintCenter(" ")
- PrintCenter("Press any key to continue...")
- while true do
- local e,v = os.pullEvent()
- if e == "key" then
- break
- end
- end
- end
- local _mainmenu_options = {"New Easy Game","New Medium Game","New Hard Game","Instructions","Exit"}
- local _mainmenu_selected = 1
- local function DrawMainMenu()
- term.clear()
- term.setCursorPos(1,1)
- PrintCenter("JPiolho\'s Minesweeper")
- PrintCenter("=====================")
- local id,v
- for id,v in pairs(_mainmenu_options) do
- if _mainmenu_selected == id then
- PrintCenter("[" .. v .. "]")
- else
- PrintCenter(v)
- end
- end
- end
- local function MainMenu()
- local canExit = false
- while canExit == false do
- DrawMainMenu()
- local r,s = os.pullEvent()
- if r == "key" then
- if s == 208 then -- Down Arrow
- if _mainmenu_selected + 1 <= #_mainmenu_options then
- _mainmenu_selected = _mainmenu_selected + 1
- PlaySound("right")
- end
- elseif s == 200 then -- Up Arrow
- if _mainmenu_selected - 1 >= 1 then
- _mainmenu_selected = _mainmenu_selected - 1
- PlaySound("right")
- end
- elseif s == 28 then -- Enter Key
- if _mainmenu_selected == 1 then NewGame("easy") end
- if _mainmenu_selected == 2 then NewGame("medium") end
- if _mainmenu_selected == 3 then NewGame("hard") end
- if _mainmenu_selected == 4 then Instructions() end
- if _mainmenu_selected == 5 then
- canExit = true
- term.clear()
- term.setCursorPos(1,1)
- end
- end
- end
- end
- end
- MainMenu()
Advertisement
Add Comment
Please, Sign In to add comment