Advertisement
sosochka

MineSweeper

Dec 7th, 2022 (edited)
44
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 8.45 KB | None | 0 0
  1. local term = require("term")
  2. local drawing = require("drawing")
  3. local component = require("component")
  4. local event = require("event")
  5. local keyboard = require("keyboard")
  6. local shell = require("shell")
  7. local gpu = component.gpu
  8.  
  9. function clamp(num, min, max)
  10.     if (num > max) then
  11.         return max
  12.     elseif (num < min) then
  13.         return min
  14.     else
  15.         return num
  16.     end
  17. end
  18.  
  19. --Complementary function
  20. function hasItem(table, item)
  21.     for i = 0, #table-1 do
  22.         for j = 0, #table[0]-1 do
  23.             if table[i][j] == item then
  24.                 return true
  25.             end
  26.         end
  27.     end
  28. end
  29.  
  30.  
  31. function revealCell(x, y, PlayGrid)
  32.     local combinations = {
  33.         [0] = {y = y - 1, x = x, condition = (y - 1 > -1)},
  34.         [1] = {y = y - 1, x = x +  1, condition = (y - 1  > -1) and (x + 1 < PlayGrid.playFieldSize.x)},
  35.         [2] = {y = y, x = x + 1, condition = (x + 1 < PlayGrid.playFieldSize.x)},
  36.         [3] = {y = y + 1, x = x + 1, condition = (y + 1 < PlayGrid.playFieldSize.y) and (x + 1 < PlayGrid.playFieldSize.x)},
  37.         [4] = {y = y + 1, x = x, condition = (y + 1 < PlayGrid.playFieldSize.y)},
  38.         [5] = {y = y + 1, x = x - 1, condition = (y + 1 < PlayGrid.playFieldSize.y) and (x - 1 > -1)},
  39.         [6] = {y = y, x = x - 1, condition = (x - 1 > -1)},
  40.         [7] = {y = y - 1, x = x - 1, condition = (y - 1 > -1) and (x - 1 > -1)},
  41.     }
  42.     if PlayGrid.revealedGrid[y][x] == "r" then
  43.         return
  44.     end
  45.     if PlayGrid.values[y][x] == "M" then
  46.         PlayGrid.revealedGrid[y][x] = "r"
  47.         PlayGrid.gameOver = true
  48.         return
  49.     elseif PlayGrid.values[y][x] == "0" then
  50.         PlayGrid.revealedGrid[y][x] = "r"
  51.         PlayGrid.unrevealedAmount = PlayGrid.unrevealedAmount - 1
  52.         for i=0,#combinations do
  53.             if combinations[i].condition then
  54.                 if PlayGrid.values[combinations[i].y][combinations[i].x]  ~= "M" and PlayGrid.revealedGrid[combinations[i].y][combinations[i].x] ~= "r" then
  55.                     PlayGrid.revealedGrid[combinations[i].y][combinations[i].x] = "t"
  56.                     drawing.drawPlayField(PlayGrid)
  57.                 end
  58.             end
  59.         end
  60.     else
  61.         PlayGrid.revealedGrid[y][x] = "r"
  62.         PlayGrid.unrevealedAmount = PlayGrid.unrevealedAmount - 1
  63.     end
  64. end
  65.  
  66. --Event handlers
  67. function nullEvent()
  68.     --Do nothing
  69. end
  70.  
  71. local eventHandler = setmetatable({}, {__index = function() return nullEvent end})
  72.  
  73. function eventHandler.touch(PlayGrid, screenAddress, x, y, button, playerName)
  74.     local clickWithOffset = {x = x - PlayGrid.offset.x, y = y - PlayGrid.offset.y}
  75.     local isClickInPlayFieldBounds = (clickWithOffset.x >= 0 and clickWithOffset.x < PlayGrid.playFieldSize.x) and (clickWithOffset.y >= 0 and clickWithOffset.y < PlayGrid.playFieldSize.y)
  76.     if isClickInPlayFieldBounds then
  77.         if keyboard.isAltDown() then
  78.             if PlayGrid.revealedGrid[clickWithOffset.y][clickWithOffset.x] == "r" then
  79.                 return
  80.             end
  81.             if PlayGrid.revealedGrid[clickWithOffset.y][clickWithOffset.x] == "f" then
  82.                 PlayGrid.revealedGrid[clickWithOffset.y][clickWithOffset.x] = "u"
  83.                 PlayGrid.flagedAmount = PlayGrid.flagedAmount - 1
  84.             else
  85.                 PlayGrid.revealedGrid[clickWithOffset.y][clickWithOffset.x] = "f"
  86.                 PlayGrid.flagedAmount =  PlayGrid.flagedAmount + 1
  87.             end
  88.             return
  89.         end
  90.         revealCell(clickWithOffset.x, clickWithOffset.y, PlayGrid)
  91.         while hasItem(PlayGrid.revealedGrid, "t") do
  92.             for i = 0, #PlayGrid.revealedGrid-1 do
  93.                 for j = 0, #PlayGrid.revealedGrid[0]-1 do
  94.                     if PlayGrid.revealedGrid[i][j] == "t" then
  95.                         revealCell(j, i, PlayGrid)
  96.                     end
  97.                 end
  98.             end
  99.         end
  100.     end
  101. end
  102.  
  103. function handleEvent(PlayGrid, eventID, ...)
  104.     if (eventID) then
  105.         eventHandler[eventID](PlayGrid, ...)
  106.     end
  107. end
  108.  
  109. gpu.setForeground(0xFFFFFF)
  110.  
  111. --Init
  112. local PlayGrid = {values = {}, revealedGrid = {}, playFieldSize = {x = 0, y = 0}, offset = {x = 0, y = 0},  mineAmount = 0,  unrevealedAmount = 0,
  113.                   flagedAmount = 0, gameOver = false, gameWon = false, cheater = false }
  114.  
  115. local arguments_as_a_table = {...}
  116. if arguments_as_a_table[1] == "cheater" then
  117.     PlayGrid.cheater = true
  118. end
  119.  
  120. --Player input on difficulty
  121. term.clear()
  122. term.setCursor(1, 1)
  123. print("MINESWEEPER")
  124. print("Enter difficulty [1][2][3]: ")
  125. local input = tostring(term.read())
  126. term.clear()
  127.  
  128.  
  129. if input == "1\n" then
  130.     PlayGrid.playFieldSize.x, PlayGrid.playFieldSize.y = 9, 9
  131.     PlayGrid.mineAmount = 10
  132. elseif input == "2\n" then
  133.     PlayGrid.playFieldSize.x, PlayGrid.playFieldSize.y = 16, 16
  134.     PlayGrid.mineAmount = 40
  135. elseif input == "3\n" then
  136.     PlayGrid.playFieldSize.x, PlayGrid.playFieldSize.y = 30, 16
  137.     PlayGrid.mineAmount = 99
  138. else
  139.     term.clear()
  140.     term.write("Wrong difficulty!")
  141.     return
  142. end
  143.  
  144. PlayGrid.unrevealedAmount = PlayGrid.playFieldSize.x * PlayGrid.playFieldSize.y
  145.  
  146. --Global variables
  147. local termSize = {}
  148. termSize.width, termSize.height = component.gpu.getViewport()
  149. PlayGrid.offset.x, PlayGrid.offset.y = math.ceil(termSize.width / 2 - PlayGrid.playFieldSize.x / 2), math.ceil(termSize.height / 2 - PlayGrid.playFieldSize.y / 2)
  150.  
  151. --Initializing play playGrid
  152. for y = 0, PlayGrid.playFieldSize.y - 1 do
  153.     PlayGrid.values[y] = {}
  154.     for x = 0, PlayGrid.playFieldSize.x - 1 do
  155.         PlayGrid.values[y][x] = "0"
  156.     end
  157. end
  158.  
  159. --Population the grid with mines
  160. math.randomseed(os.time())
  161. local tempMineAmount = PlayGrid.mineAmount
  162. while tempMineAmount > 0 do
  163.     local xMine = math.floor(math.random() * PlayGrid.playFieldSize.x)
  164.     local yMine = math.floor(math.random() * PlayGrid.playFieldSize.y)
  165.     if PlayGrid.values[yMine][xMine] ~= "M" then
  166.         PlayGrid.values[yMine][xMine] = "M"
  167.         tempMineAmount = tempMineAmount - 1
  168.     end
  169. end
  170.  
  171.  
  172. --Populating the playgrid with mine counts
  173.  
  174. for y = 0, PlayGrid.playFieldSize.y - 1 do
  175.     for x = 0, PlayGrid.playFieldSize.x - 1 do
  176.         if PlayGrid.values[y][x] ~= "M" then
  177.             local combinations = {
  178.                 [0] = {y = y - 1, x = x, condition = (y - 1 > -1)},
  179.                 [1] = {y = y - 1, x = x +  1, condition = (y - 1  > -1) and (x + 1 < PlayGrid.playFieldSize.x)},
  180.                 [2] = {y = y, x = x + 1, condition = (x + 1 < PlayGrid.playFieldSize.x)},
  181.                 [3] = {y = y + 1, x = x + 1, condition = (y + 1 < PlayGrid.playFieldSize.y) and (x + 1 < PlayGrid.playFieldSize.x)},
  182.                 [4] = {y = y + 1, x = x, condition = (y + 1 < PlayGrid.playFieldSize.y)},
  183.                 [5] = {y = y + 1, x = x - 1, condition = (y + 1 < PlayGrid.playFieldSize.y) and (x - 1 > -1)},
  184.                 [6] = {y = y, x = x - 1, condition = (x - 1 > -1)},
  185.                 [7] = {y = y - 1, x = x - 1, condition = (y - 1 > -1) and (x - 1 > -1)},
  186.             }
  187.             local tempMineAmount = 0
  188.             for i=0,#combinations do
  189.                 if combinations[i].condition then
  190.                     if PlayGrid.values[combinations[i].y][combinations[i].x] == "M" then
  191.                         tempMineAmount = tempMineAmount + 1
  192.                     end
  193.                 end
  194.             end
  195.             PlayGrid.values[y][x] = tostring(tempMineAmount)
  196.         end
  197.     end
  198. end
  199.  
  200. --Creating the reavealed-unrevealed playgrid
  201. for y = 0, PlayGrid.playFieldSize.y - 1 do
  202.     PlayGrid.revealedGrid[y] = {}
  203.     for x = 0, PlayGrid.playFieldSize.x - 1 do
  204.         PlayGrid.revealedGrid[y][x] = "u"
  205.     end
  206. end
  207.  
  208. while not PlayGrid.gameOver do
  209.     drawing.drawPlayField(PlayGrid)
  210.     handleEvent(PlayGrid, event.pull())
  211.     term.setCursor(1, 1)
  212.     -- term.write(PlayGrid.unrevealedAmount .. "\n") Debug
  213.     -- term.write(PlayGrid.flagedAmount .. "\n")
  214.     if PlayGrid.unrevealedAmount == PlayGrid.mineAmount and PlayGrid.flagedAmount == PlayGrid.mineAmount then
  215.         PlayGrid.gameWon = true
  216.         break
  217.     end
  218. end
  219.  
  220. gpu.setForeground(0xFFFFFF)
  221.  
  222. term.clear()
  223. term.setCursor(1, 1)
  224. if PlayGrid.gameWon then
  225.     term.write("Game Won!\n")
  226. elseif PlayGrid.gameOver then
  227.     term.write("Game Over!\n")
  228. end
  229. term.write("Restart? [y/n]\n")
  230.  
  231. input = term.read()
  232. if input == "y\n" then
  233.     shell.execute("/home/MineSweeper/MineSweeper.lua")
  234. elseif input == "cheater\n" then
  235.     shell.execute("/home/MineSweeper/MineSweeper.lua cheater")
  236. else
  237.     term.clear()
  238. end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement