sosochka

MineSweeper

Dec 7th, 2022 (edited)
57
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 8.59 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.         local nextReveal = {x = clickWithOffset.x, y = clickWithOffset.y}
  92.         while hasItem(PlayGrid.revealedGrid, "t") do
  93.             for i = 0, PlayGrid.playFieldSize.y - 1 do
  94.                 for j = 0, PlayGrid.playFieldSize.x - 1 do
  95.                     if PlayGrid.revealedGrid[i][j] == "t" then
  96.                         nextReveal.x, nextReveal.y = j, i
  97.                         revealCell(j, i, PlayGrid)
  98.                     end
  99.                 end
  100.             end
  101.         end
  102.     end
  103. end
  104.  
  105. function handleEvent(PlayGrid, eventID, ...)
  106.     if (eventID) then
  107.         eventHandler[eventID](PlayGrid, ...)
  108.     end
  109. end
  110.  
  111. gpu.setForeground(0xFFFFFF)
  112.  
  113. --Init
  114. local PlayGrid = {values = {}, revealedGrid = {}, playFieldSize = {x = 0, y = 0}, offset = {x = 0, y = 0},  mineAmount = 0,  unrevealedAmount = 0,
  115.                   flagedAmount = 0, gameOver = false, gameWon = false, cheater = false }
  116.  
  117. local arguments_as_a_table = {...}
  118. if arguments_as_a_table[1] == "cheater" then
  119.     PlayGrid.cheater = true
  120. end
  121.  
  122. --Player input on difficulty
  123. term.clear()
  124. term.setCursor(1, 1)
  125. print("MINESWEEPER")
  126. print("Enter difficulty [1][2][3]: ")
  127. local input = tostring(term.read())
  128. term.clear()
  129.  
  130.  
  131. if input == "1\n" then
  132.     PlayGrid.playFieldSize.x, PlayGrid.playFieldSize.y = 9, 9
  133.     PlayGrid.mineAmount = 10
  134. elseif input == "2\n" then
  135.     PlayGrid.playFieldSize.x, PlayGrid.playFieldSize.y = 16, 16
  136.     PlayGrid.mineAmount = 40
  137. elseif input == "3\n" then
  138.     PlayGrid.playFieldSize.x, PlayGrid.playFieldSize.y = 30, 16
  139.     PlayGrid.mineAmount = 99
  140. else
  141.     term.clear()
  142.     term.write("Wrong difficulty!")
  143.     return
  144. end
  145.  
  146. PlayGrid.unrevealedAmount = PlayGrid.playFieldSize.x * PlayGrid.playFieldSize.y
  147.  
  148. --Global variables
  149. local termSize = {}
  150. termSize.width, termSize.height = component.gpu.getViewport()
  151. PlayGrid.offset.x, PlayGrid.offset.y = math.ceil(termSize.width / 2 - PlayGrid.playFieldSize.x / 2), math.ceil(termSize.height / 2 - PlayGrid.playFieldSize.y / 2)
  152.  
  153. --Initializing play playGrid
  154. for y = 0, PlayGrid.playFieldSize.y - 1 do
  155.     PlayGrid.values[y] = {}
  156.     for x = 0, PlayGrid.playFieldSize.x - 1 do
  157.         PlayGrid.values[y][x] = "0"
  158.     end
  159. end
  160.  
  161. --Population the grid with mines
  162. math.randomseed(os.time())
  163. local tempMineAmount = PlayGrid.mineAmount
  164. while tempMineAmount > 0 do
  165.     local xMine = math.floor(math.random() * PlayGrid.playFieldSize.x)
  166.     local yMine = math.floor(math.random() * PlayGrid.playFieldSize.y)
  167.     if PlayGrid.values[yMine][xMine] ~= "M" then
  168.         PlayGrid.values[yMine][xMine] = "M"
  169.         tempMineAmount = tempMineAmount - 1
  170.     end
  171. end
  172.  
  173.  
  174. --Populating the playgrid with mine counts
  175.  
  176. for y = 0, PlayGrid.playFieldSize.y - 1 do
  177.     for x = 0, PlayGrid.playFieldSize.x - 1 do
  178.         if PlayGrid.values[y][x] ~= "M" then
  179.             local combinations = {
  180.                 [0] = {y = y - 1, x = x, condition = (y - 1 > -1)},
  181.                 [1] = {y = y - 1, x = x +  1, condition = (y - 1  > -1) and (x + 1 < PlayGrid.playFieldSize.x)},
  182.                 [2] = {y = y, x = x + 1, condition = (x + 1 < PlayGrid.playFieldSize.x)},
  183.                 [3] = {y = y + 1, x = x + 1, condition = (y + 1 < PlayGrid.playFieldSize.y) and (x + 1 < PlayGrid.playFieldSize.x)},
  184.                 [4] = {y = y + 1, x = x, condition = (y + 1 < PlayGrid.playFieldSize.y)},
  185.                 [5] = {y = y + 1, x = x - 1, condition = (y + 1 < PlayGrid.playFieldSize.y) and (x - 1 > -1)},
  186.                 [6] = {y = y, x = x - 1, condition = (x - 1 > -1)},
  187.                 [7] = {y = y - 1, x = x - 1, condition = (y - 1 > -1) and (x - 1 > -1)},
  188.             }
  189.             local tempMineAmount = 0
  190.             for i=0,#combinations do
  191.                 if combinations[i].condition then
  192.                     if PlayGrid.values[combinations[i].y][combinations[i].x] == "M" then
  193.                         tempMineAmount = tempMineAmount + 1
  194.                     end
  195.                 end
  196.             end
  197.             PlayGrid.values[y][x] = tostring(tempMineAmount)
  198.         end
  199.     end
  200. end
  201.  
  202. --Creating the reavealed-unrevealed playgrid
  203. for y = 0, PlayGrid.playFieldSize.y - 1 do
  204.     PlayGrid.revealedGrid[y] = {}
  205.     for x = 0, PlayGrid.playFieldSize.x - 1 do
  206.         PlayGrid.revealedGrid[y][x] = "u"
  207.     end
  208. end
  209.  
  210. while not PlayGrid.gameOver do
  211.     drawing.drawPlayField(PlayGrid)
  212.     handleEvent(PlayGrid, event.pull())
  213.     term.setCursor(1, 1)
  214.     -- term.write(PlayGrid.unrevealedAmount .. "\n") Debug
  215.     -- term.write(PlayGrid.flagedAmount .. "\n")
  216.     if PlayGrid.unrevealedAmount == PlayGrid.mineAmount and PlayGrid.flagedAmount == PlayGrid.mineAmount then
  217.         PlayGrid.gameWon = true
  218.         break
  219.     end
  220. end
  221.  
  222. gpu.setForeground(0xFFFFFF)
  223.  
  224. term.clear()
  225. term.setCursor(1, 1)
  226. if PlayGrid.gameWon then
  227.     term.write("Game Won!\n")
  228. elseif PlayGrid.gameOver then
  229.     term.write("Game Over!\n")
  230. end
  231. term.write("Restart? [y/n]\n")
  232.  
  233. input = term.read()
  234. if input == "y\n" then
  235.     shell.execute("/home/MineSweeper/MineSweeper.lua")
  236. elseif input == "cheater\n" then
  237.     shell.execute("/home/MineSweeper/MineSweeper.lua cheater")
  238. else
  239.     term.clear()
  240. end
Advertisement
Add Comment
Please, Sign In to add comment