Advertisement
Mangus875

Minesweeper

Sep 8th, 2023 (edited)
1,136
0
Never
1
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 4.39 KB | None | 0 0
  1. --[[  BOARD SETTINGS  ]]--
  2. local size = 9          -- side length of the board (e.g. 5 = 5x5 board)
  3. local mines = 10        -- how many mines are on the board
  4.  
  5. -- Classic difficulty settings: (SIZE x MINES)
  6. --   beginner     = 09x10  (12.35%)
  7. --   intermediate = 16x40  (15.63%)
  8. --   expert       = 22x99  (20.63%)
  9.  
  10. --[[  CELL TABLES  ]]--
  11. local realBoard = {}    -- stores which cells have mines
  12. local gameBoard = {}    -- stores how many mines are near each cell
  13. local liveBoard = {}    -- stores current state of each cell (unknown, known, or flagged)
  14. local showBoard = {}    -- stores what is currently being shown to the player
  15.  
  16. local rng = Random.new()
  17.  
  18.  
  19. local function toXY(i)
  20.     local x = (i-1)%size+1
  21.     local y = math.floor((i-1)/size)+1
  22.     return x,y
  23. end
  24.  
  25. local function toIndex(x,y)
  26.     return x+(y-1)*size
  27. end
  28.  
  29. local function isValid(x,y)
  30.     return x > 0 and x <= size and y > 0 and y <= size
  31. end
  32.  
  33. local function getNeighbors(x,y)
  34.     local neighbors = {}
  35.     for ix = x-1, x+1 do
  36.         for iy = y-1, y+1 do
  37.             if isValid(ix,iy) then
  38.                 table.insert(neighbors,toIndex(ix,iy))
  39.             end
  40.         end
  41.     end
  42.     return neighbors
  43. end
  44.  
  45. local function countNearbyMines(x,y)
  46.     local count = 0
  47.     for _, i in ipairs(getNeighbors(x,y)) do
  48.         count = count + if realBoard[i] then 1 else 0
  49.     end
  50. end
  51.  
  52. local function display()
  53.     local board = '\n\n   '
  54.     for i = 1, size do
  55.         board = board..i..' '
  56.     end
  57.     board = board..'\n   '
  58.     for i = 1, size-1 do
  59.         board = board..'‾‾'
  60.     end
  61.     board = board..'‾\n'
  62.    
  63.     for y = 1, size do
  64.         local line = ""
  65.         for x = 1, size do
  66.             local v = showBoard[toIndex(x,y)]
  67.             if v ~= 0 then
  68.                 line = line..v
  69.             else
  70.                 line = line..'·'
  71.             end
  72.             line = line..' '
  73.         end
  74.         line = y.."| "..line..'\n'
  75.         board = board..line
  76.     end
  77.     print(board..'\n')
  78. end
  79.  
  80. local function update()
  81.     for i, v in ipairs(liveBoard) do
  82.         showBoard[i] = ''
  83.         if v == 0 then
  84.             showBoard[i] = '■'
  85.         elseif v == 1 then
  86.             if realBoard[i] then
  87.                 warn("game ova")
  88.             end
  89.             showBoard[i] = gameBoard[i]
  90.         else
  91.             showBoard[i] = '▲'
  92.         end
  93.     end
  94.     display()
  95. end
  96.  
  97. local function expand(x,y)
  98.     local nextLayer = {}
  99.     for _, i in ipairs(getNeighbors(x,y)) do
  100.         if liveBoard[i] ~= 0 then continue end
  101.         liveBoard[i] = 1
  102.         if gameBoard[i] == 0 then
  103.             table.insert(nextLayer,i)
  104.         end
  105.     end
  106.     for _, v in ipairs(nextLayer) do
  107.         expand(toXY(v))
  108.     end
  109. end
  110.  
  111. local firstMove
  112. local isFirst = true
  113. local function open(x,y)
  114.     if isFirst then
  115.         isFirst = false
  116.         firstMove(x,y)
  117.     end
  118.     liveBoard[toIndex(x,y)] = 1
  119.     if gameBoard[toIndex(x,y)] == 0 then
  120.         expand(x,y)
  121.     end
  122.     update()
  123. end
  124.  
  125. local function chord(x,y)
  126.     local flagCount = 0
  127.     for _, i in ipairs(getNeighbors(x,y)) do
  128.         if liveBoard[i] == 2 then
  129.             flagCount += 1
  130.         end
  131.     end
  132.     if flagCount == gameBoard[toIndex(x,y)] then
  133.         for _, i in ipairs(getNeighbors(x,y)) do
  134.             if liveBoard[i] ~= 0 then continue end
  135.             open(toXY(i))
  136.         end
  137.     end
  138. end
  139.  
  140. local function getAvailableSpots(myTable,exclude)
  141.     local available = {}
  142.     for i, v in ipairs(myTable) do
  143.         if v ~= exclude then
  144.             table.insert(available,i)
  145.         end
  146.     end
  147.     return available
  148. end
  149.  
  150. local function labelCells()
  151.     for _, m in ipairs(getAvailableSpots(realBoard,false)) do
  152.         for _, c in ipairs(getNeighbors(toXY(m))) do
  153.             gameBoard[c] += 1
  154.         end
  155.     end
  156. end
  157.  
  158. function firstMove(x,y)
  159.     local c = toIndex(x,y)
  160.     local available = getAvailableSpots(realBoard,true)
  161.     for _, i in ipairs(getNeighbors(x,y)) do
  162.         table.remove(available,table.find(available,i))
  163.         if realBoard[i] then
  164.             local newPos = rng:NextInteger(1,#available)
  165.             table.remove(available,newPos)
  166.             realBoard[i] = false
  167.             realBoard[newPos] = true
  168.         end
  169.     end
  170.  
  171.     labelCells()
  172.     open(x,y)
  173. end
  174.  
  175. local function flag(x,y)
  176.     local c = toIndex(x,y)
  177.     if liveBoard[c] == 1 then return end
  178.     liveBoard[c] = (liveBoard[c]+2)%4
  179.     update()
  180. end
  181.  
  182. local function shuffle(myTable)
  183.     local buffer
  184.     for i = #myTable, 1, -1 do
  185.         local r = rng:NextInteger(1,i)
  186.         buffer = myTable[i]
  187.         myTable[i] = myTable[r]
  188.         myTable[r] = buffer
  189.     end
  190.     return myTable
  191. end
  192.  
  193. local function setup()
  194.     realBoard = {}
  195.     gameBoard = {}
  196.     liveBoard = {}
  197.     showBoard = {}
  198.     isFirst = true
  199.  
  200.     if mines > size^2+9 then
  201.         error("Too many mines. (Max mine count: "..(size^2+9)..")")
  202.     end
  203.  
  204.     for i = 1, size^2 do
  205.         realBoard[i] = false
  206.         gameBoard[i] = 0
  207.         liveBoard[i] = 0
  208.  
  209.         if i <= mines then
  210.             realBoard[i] = true
  211.         end
  212.     end
  213.     shuffle(realBoard)
  214. end
  215.  
  216. setup()
Advertisement
Comments
Add Comment
Please, Sign In to add comment
Advertisement