JPiolho

[Minecraft][CC] Minesweeper

Feb 29th, 2012
556
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 8.35 KB | None | 0 0
  1. -- Minesweeper by JPiolho
  2. -- Version 1.0
  3. -- BUGS: Recursive sometimes dont explore every block
  4. -- Feel free to copy and edit as long you credit the original author
  5. -- More Info @ http://bit.ly/zoxn6V
  6.  
  7. local function PlaySound(side)
  8.  redstone.setOutput(side,true)
  9.  sleep(0.01)
  10.  redstone.setOutput(side,false)
  11. end
  12.  
  13. local function RecursiveDiscover(fields,width,height,lx,ly)
  14.  local toVisit = {{lx,ly}}
  15.  local visited = {}
  16.  
  17.  local AddToVisit = function(visitedlist,tx,ty)
  18.   for _,tv in pairs(visitedlist) do
  19.    if tonumber(tv[1]) == tonumber(tx) and tonumber(tv[2]) == tonumber(ty) then
  20.     return
  21.    end
  22.   end
  23.  
  24.   for _,tv in pairs(toVisit) do
  25.    if tv[1] == tx and tv[2] == ty then
  26.     return
  27.    end
  28.   end
  29.  
  30.   table.insert(toVisit,{tx,ty})
  31.  end
  32.  
  33.  while #toVisit > 0 do
  34.   local visiting = {}
  35.  
  36.   local id,v
  37.   -- Copy array
  38.   for id,v in pairs(toVisit) do
  39.    table.insert(visiting,{id,v})
  40.   end
  41.  
  42.  
  43.   for id,v in pairs(visiting) do
  44.    local x = v[2][1]
  45.    local y = v[2][2]
  46.    local curField = fields[y][x]
  47.  
  48.  
  49.  
  50.    table.remove(toVisit,v[1])
  51.    table.insert(visited,{x,y})
  52.    curField.discovered = true
  53.    if curField.number <= 0 then
  54.  
  55.     if x > 1 then AddToVisit(visited,x-1,y) end
  56.  
  57.     if y > 1 then AddToVisit(visited,x,y-1) end
  58.  
  59.     if x < width then AddToVisit(visited,x+1,y) end
  60.  
  61.     if y < height then AddToVisit(visited,x,y+1) end
  62.  
  63.     if x > 1 and y > 1 then AddToVisit(visited,x-1,y-1) end
  64.  
  65.     if x > 1 and y < height then AddToVisit(visited,x-1,y+1) end
  66.  
  67.     if x < width and y > 1 then AddToVisit(visited,x+1,y-1) end
  68.  
  69.     if x < width and y < height then AddToVisit(visited,x+1,y+1) end
  70.    end
  71.   end
  72.  
  73.  end
  74. end
  75.  
  76. local function PrintCenter(msg)
  77.  local msgLen = string.len(msg)
  78.  local screenWidth,_ = term.getSize()
  79.  
  80.  local xCoords = tonumber(math.ceil((screenWidth / 2) - (msgLen / 2)))
  81.  
  82.  local _,termY = term.getCursorPos()
  83.  
  84.  term.setCursorPos(xCoords,termY)
  85.  
  86.  print(msg)
  87.  
  88.  return xCoords
  89. end
  90.  
  91.  
  92. local function EndGame(msg)
  93.  local _,h = term.getSize()
  94.  
  95.  term.setCursorPos(1,h-2)
  96.  PrintCenter(msg)
  97.  PrintCenter("Press any key to continue...")
  98.  term.setCursorPos(1,h-1)
  99.  while true do
  100.   local e,v = os.pullEvent()
  101.   if e == "key" then
  102.    break
  103.   end
  104.  end
  105. end
  106.  
  107. local function NewGame(difficulty)
  108.  local sizeW, sizeH
  109.  local minesTotal
  110.  
  111.  if difficulty == "easy" then sizeW = 10; sizeH = 10; minesTotal = 30; end
  112.  if difficulty == "medium" then sizeW = 15; sizeH = 15; minesTotal = 50; end
  113.  if difficulty == "hard" then sizeW = 30; sizeH = 15; minesTotal = 90; end
  114.  
  115.  local field = {}
  116.  
  117.  -- Initialize the field
  118.  local x,y
  119.   for y = 1,sizeH do
  120.   field[y] = {}
  121.   for x = 1,sizeW do
  122.    field[y][x] = {discovered = false,
  123.                   mine = false,
  124.                   number = 0,
  125.                   flag = false
  126.                  }
  127.   end
  128.  end
  129.  
  130.  -- Randomly place the minefield
  131.  local mines = 0
  132.  while mines < minesTotal do
  133.   x = math.random(1,sizeW)
  134.   y = math.random(1,sizeH)
  135.  
  136.   if field[y][x].mine == false then
  137.    field[y][x].mine = true
  138.    mines = mines + 1
  139.   end
  140.  end
  141.  
  142.  -- Build the numbers
  143.  for y = 1,sizeH do
  144.   for x = 1,sizeW do
  145.    mines = 0
  146.  
  147.    if x > 1 and field[y][x-1].mine == true then
  148.     mines = mines + 1
  149.    end
  150.    if y > 1 and field[y-1][x].mine == true then
  151.     mines = mines + 1
  152.    end
  153.    if x < sizeW and field[y][x+1].mine == true then
  154.     mines = mines + 1
  155.    end
  156.    if y < sizeH and field[y+1][x].mine == true then
  157.     mines = mines + 1
  158.    end
  159.    if x > 1 and y > 1 and field[y-1][x-1].mine == true then
  160.     mines = mines + 1
  161.    end
  162.    if x > 1 and y < sizeH and field[y+1][x-1].mine == true then
  163.     mines = mines + 1
  164.    end
  165.    if x < sizeW and y < sizeH and field[y+1][x+1].mine == true then
  166.     mines = mines + 1
  167.    end
  168.    if x < sizeW and y > 1 and field[y-1][x+1].mine == true then
  169.     mines = mines + 1
  170.    end
  171.  
  172.    field[y][x].number = mines
  173.   end
  174.  end
  175.  local flaggedMines = 0
  176.  local flagCount = 0
  177.  
  178.  local end_flags = false
  179.  local end_mines = false
  180.  
  181.  
  182.  local cursorX, cursorY
  183.  cursorX = 1
  184.  cursorY = 1
  185.  while true do
  186.   term.clear()
  187.   term.setCursorPos(1,1)
  188.  
  189.   local minX,maxX,minY,maxY
  190.  
  191.   minY = 1
  192.   maxY = sizeH +1
  193.  
  194.   for y = 1,sizeH do
  195.    local line = ""
  196.    for x = 1,sizeW do
  197.     local curField = field[y][x]
  198.  
  199.     if curField.discovered == true then
  200.      if curField.mine == true then
  201.       line = line .. "x"
  202.      elseif curField.number > 0 then
  203.       line = line .. curField.number
  204.      else
  205.       line = line .. " "
  206.      end
  207.     else
  208.      if curField.flag == true then
  209.       line = line .. "P"
  210.      else
  211.       line = line .. "#"
  212.      end
  213.     end
  214.    end
  215.    if y == 1 then
  216.     minX = PrintCenter(line)
  217.     maxX = minX + string.len(line)
  218.    else
  219.     PrintCenter(line)
  220.    end
  221.   end
  222.  
  223.   term.setCursorPos(minX + (cursorX-1),minY + (cursorY-1))
  224.   term.setCursorBlink(true)
  225.  
  226.   if end_flags == true then
  227.    EndGame("You have found all mines")
  228.    break
  229.      end
  230.   if end_mines == true then
  231.    EndGame("*Boom* You step on a mine")
  232.    break
  233.   end
  234.  
  235.   local e,v = os.pullEvent()
  236.  
  237.   local curField = field[cursorY][cursorX]
  238.  
  239.   if e == "key" then
  240.    if v == 208 then -- Down Arrow
  241.     if cursorY + 1 <= maxY - minY then
  242.      cursorY = cursorY + 1
  243.     end
  244.    end
  245.    if v == 200 then -- Up Arrow
  246.     if cursorY - 1 >= 1 then
  247.      cursorY = cursorY - 1
  248.     end
  249.    end
  250.    if v == 203 then -- Left Arrow
  251.     if cursorX - 1 >= 1 then
  252.      cursorX = cursorX - 1
  253.     end
  254.    end
  255.    if v == 205 then -- Right Arrow
  256.     if cursorX + 1 <= maxX - minX then
  257.      cursorX = cursorX + 1
  258.     end
  259.    end
  260.    if v == 28 then -- Enter
  261.     if curField.flag == false and curField.discovered == false then
  262.      if curField.mine == true then
  263.       end_mines = true
  264.      end
  265.      RecursiveDiscover(field,sizeW,sizeH,cursorX,cursorY)
  266.     end
  267.    end
  268.    if v == 16 then -- Q
  269.     break
  270.    end
  271.    if v == 57 then -- Space
  272.     if curField.discovered == false then
  273.      if curField.flag == false then
  274.       flagCount = flagCount + 1
  275.       curField.flag = true
  276.  
  277.       if curField.mine == true then
  278.        flaggedMines = flaggedMines + 1
  279.       end
  280.      else
  281.       flagCount = flagCount - 1
  282.       curField.flag = false
  283.  
  284.       if curField.mine == true then
  285.        flaggedMines = flaggedMines - 1
  286.       end
  287.      end
  288.      if flaggedMines == minesTotal and flaggedMines == flagCount then
  289.       end_flags = true
  290.      end
  291.  
  292.     end
  293.    end
  294.   end
  295.  
  296.  end
  297. end
  298.  
  299.  
  300. local function Instructions()
  301.  term.clear()
  302.  term.setCursorPos(1,1)
  303.  
  304.  PrintCenter("Instructions")
  305.  PrintCenter("------------")
  306.  PrintCenter("Regular minesweeper game. If you don\'t know")
  307.  PrintCenter("how to play, google it.")
  308.  PrintCenter("Use arrow keys to move your cursor")
  309.  PrintCenter("Use Space to flag a square")
  310.  PrintCenter("Use Enter to explore a square")
  311.  PrintCenter("Press Q to go back to main menu")
  312.  PrintCenter(" ")
  313.  PrintCenter("Written by JPiolho")
  314.  PrintCenter(" ")
  315.  PrintCenter("Press any key to continue...")
  316.  while true do
  317.   local e,v = os.pullEvent()
  318.   if e == "key" then
  319.    break
  320.   end
  321.  end
  322. end
  323.  
  324.  
  325. local _mainmenu_options = {"New Easy Game","New Medium Game","New Hard Game","Instructions","Exit"}
  326. local _mainmenu_selected = 1
  327. local function DrawMainMenu()
  328.  
  329.  term.clear()
  330.  term.setCursorPos(1,1)
  331.  
  332.  PrintCenter("JPiolho\'s Minesweeper")
  333.  PrintCenter("=====================")
  334.  
  335.  
  336.  
  337.  local id,v
  338.  for id,v in pairs(_mainmenu_options) do
  339.   if _mainmenu_selected == id then
  340.    PrintCenter("[" .. v .. "]")
  341.      else
  342.    PrintCenter(v)
  343.   end
  344.  end
  345. end
  346.  
  347. local function MainMenu()
  348.  
  349.  local canExit = false
  350.  while canExit == false do
  351.   DrawMainMenu()
  352.   local r,s = os.pullEvent()
  353.   if r == "key" then
  354.    if s == 208 then -- Down Arrow
  355.     if _mainmenu_selected + 1 <= #_mainmenu_options then
  356.      _mainmenu_selected = _mainmenu_selected + 1
  357.      PlaySound("right")
  358.     end
  359.    elseif s == 200 then -- Up Arrow
  360.     if _mainmenu_selected - 1 >= 1 then
  361.      _mainmenu_selected = _mainmenu_selected - 1
  362.      PlaySound("right")
  363.     end
  364.    elseif s == 28 then -- Enter Key
  365.  
  366.     if _mainmenu_selected == 1 then NewGame("easy") end
  367.     if _mainmenu_selected == 2 then NewGame("medium") end
  368.     if _mainmenu_selected == 3 then NewGame("hard") end
  369.     if _mainmenu_selected == 4 then Instructions() end
  370.     if _mainmenu_selected == 5 then
  371.      canExit = true
  372.      term.clear()
  373.      term.setCursorPos(1,1)
  374.     end
  375.    end
  376.   end
  377.  end
  378. end
  379.  
  380. MainMenu()
Advertisement
Add Comment
Please, Sign In to add comment