wwwRong

minesweeper_jl_2_lua

Oct 28th, 2021 (edited)
1,066
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 8.98 KB | None | 0 0
  1. --[[
  2. โค้ดต้นฉบับภาษา Julia จาก https://rosettacode.org/wiki/Minesweeper_game#Julia
  3. โค้ด Lua เริ่มที่บรรทัด 125
  4.  
  5. mutable struct Field
  6.     size::Tuple{Int, Int}
  7.     numbers::Array{Int, 2}
  8.     possible_mines::Array{Bool, 2}
  9.     actual_mines::Array{Bool, 2}
  10.     visible::Array{Bool, 2}
  11. end
  12.  
  13. function Field(x, y)
  14.     size = (x, y)
  15.     actual_mines = convert(Array{Bool, 2}, rand(x, y) .< 0.15)
  16.     possible_mines = zeros(Bool, x, y)
  17.     numbers = zeros(Int, x, y)
  18.     visible = zeros(Bool, x, y)
  19.     for i = 1:x
  20.         for j = 1:y
  21.             n = 0
  22.             for di = -1:1
  23.                 for dj = -1:1
  24.                     n += (0 < di+i <= x && 0 < dj+j <= y) ?
  25.                          (actual_mines[di+i, dj+j] ? 1 : 0) : 0
  26.                 end
  27.             end
  28.             numbers[i, j] = n
  29.         end
  30.     end
  31.     return Field(size, numbers, possible_mines, actual_mines, visible)
  32. end
  33.  
  34. function printfield(f::Field; showall = false)
  35.     spaces = Int(floor(log(10, f.size[2])))
  36.  
  37.     str = " "^(4+spaces)
  38.     for i in 1:f.size[1]
  39.         str *= string(" ", i, " ")
  40.     end
  41.     str *= "\n" * " "^(4+spaces) * "___"^f.size[1] * "\n"
  42.     for j = 1:f.size[2]
  43.         str *= " " * string(j) * " "^(floor(log(10, j)) > 0 ? 1 : spaces+1) * "|"
  44.         for i = 1:f.size[1]
  45.             if showall
  46.                 str *= f.actual_mines[i, j] ? " * " : "   "
  47.             else
  48.                 if f.visible[i, j]
  49.                     str *= " " * string(f.numbers[i, j] > 0 ? f.numbers[i, j] : " ") * " "
  50.                 elseif f.possible_mines[i, j]
  51.                     str *= " ? "
  52.                 else
  53.                     str *= " . "
  54.                 end
  55.             end
  56.         end
  57.         str *= "\r\n"
  58.     end
  59.     println("Found " * string(length(f.possible_mines[f.possible_mines.==true])) *
  60.             " of " * string(length(f.actual_mines[f.actual_mines.==true])) * " mines.\n")
  61.     print(str)
  62. end
  63.  
  64. function parse_input(str::String)
  65.     input = split(chomp(str), " ")
  66.     mode = input[1]
  67.     println(str)
  68.     coords =  length(input) > 1 ? (parse(Int,input[2]), parse(Int,input[3])) : (0, 0)
  69.     return mode, coords
  70. end
  71.  
  72. function eval_input(f::Field, str::String)
  73.     mode, coords = parse_input(str)
  74.     (coords[1] > f.size[1] || coords[2] > f.size[2]) && return true
  75.     if mode == "o"
  76.         reveal(f, coords...) || return false
  77.     elseif mode == "m" && f.visible[coords...] == false
  78.         f.possible_mines[coords...] = !f.possible_mines[coords...]
  79.     elseif mode == "close"
  80.         error("You closed the game.")
  81.     end
  82.     return true
  83. end
  84.  
  85. function reveal(f::Field, x::Int, y::Int)
  86.     (x > f.size[1] || y > f.size[2]) && return true # check for index out of bounds
  87.     f.actual_mines[x, y] && return false # check for mines
  88.     f.visible[x, y] = true
  89.     if f.numbers[x, y] == 0
  90.         for di = -1:1
  91.             for dj = -1:1
  92.                 if (0 < di+x <= f.size[1] && 0 < dj+y <= f.size[2]) &&
  93.                         f.actual_mines[x+di, y+dj] == false &&
  94.                         f.visible[x+di, y+dj] == false
  95.                     reveal(f, x+di, y+dj)
  96.                 end
  97.             end
  98.         end
  99.     end
  100.     return true
  101. end
  102.  
  103. function play()
  104.     print("\nWelcome to Minesweeper\n\nEnter the gridsize x  y:\n")
  105.     s = split(readline(), " ")
  106.     f = Field(parse.(Int,s)...)
  107.     won = false
  108.     while true
  109.         printfield(f)
  110.         print("\nWhat do you do? (\"o x y\" to reveal a field; \"m x y\" to toggle a mine; close)\n")
  111.         eval_input(f, readline()) || break
  112.         print("_"^80 * "\n")
  113.         (f.actual_mines == f.possible_mines ||
  114.               f.visible == .!f.actual_mines) && (won = true; break)
  115.     end
  116.     println(won ? "You won the game!" : "You lost the game:\n")
  117.     printfield(f, showall = true)
  118. end
  119.  
  120. play()
  121. ]]
  122.  
  123. -- แปลงเป็น Lua
  124.  
  125. math.randomseed(os.time())
  126. function Field(x, y)
  127.   size = {x, y}
  128.   actual_mines = {}
  129.   possible_mines = {}
  130.   numbers = {}
  131.   visible = {}
  132.   for r = 1, y do
  133.     actual_mines[r] = {}
  134.     possible_mines[r] = {}
  135.     numbers[r] = {}
  136.     visible[r] = {}
  137.     for c = 1, x do
  138.       --actual_mines[r][c] = math.random(x*y)<=(x*y/3) and true or false
  139.       actual_mines[r][c] = false
  140.       possible_mines[r][c] = false
  141.       numbers[r][c] = 0
  142.       visible[r][c] = false
  143.     end
  144.   end
  145.   local mines = ("%.f"):format(x * y * 0.15)
  146.   for i = 1, mines do
  147.     local x = math.random(1, x)
  148.     local y = math.random(1, y)
  149.     while actual_mines[y][x] do
  150.       x = math.random(1, x)
  151.       y = math.random(1, y)
  152.     end
  153.     actual_mines[y][x] = true
  154.   end
  155.   for i = 1, x do
  156.     for j = 1, y do
  157.       local n = 0
  158.       for di = -1, 1 do
  159.         for dj = -1,1 do
  160.           dii, djj = i + di, j + dj
  161.           n = n + ((0 < dii and dii <= x and 0 < djj and djj <= y) and (actual_mines[djj][dii] and 1 or 0) or 0)
  162.         end
  163.       end
  164.       numbers[j][i] = n
  165.     end
  166.   end
  167.   print(is(numbers))
  168.   print(is(actual_mines))
  169.   return {
  170.     size = size,
  171.     numbers = numbers,
  172.     possible_mines = possible_mines,
  173.     actual_mines = actual_mines,
  174.     visible = visible
  175.   }
  176. end
  177.  
  178. function printfield(field, showall)
  179.   showall = showall or false
  180.   local spaces = math.floor(math.log(field.size[2], 10))
  181.  
  182.   local str = {(" "):rep(4+spaces)}
  183.   for i = 1, f.size[1] do
  184.     str[#str+1] = " " .. i .. " "
  185.   end
  186.   str[#str+1] = "\n" .. (" "):rep(4+spaces) .. ("___"):rep(field.size[1]) .. "\n"
  187.   for j = 1, f.size[2] do
  188.     str[#str+1] = " " .. j .. (" "):rep((math.floor(math.log(j, 10)) > 0) and 1 or (spaces+1)) .. "|"
  189.     for i = 1, f.size[1] do
  190.       if showall then
  191.         str[#str+1] = field.actual_mines[j][i] and " * " or "   "
  192.       else
  193.         if field.visible[j][i] then
  194.           str[#str+1] = " " .. (field.numbers[j][i] > 0 and field.numbers[j][i] or " ") .. " "
  195.         elseif field.possible_mines[j][i] then
  196.           str[#str+1] = " ? "
  197.         else
  198.           str[#str+1] = " . "
  199.         end
  200.       end
  201.     end
  202.     str[#str+1] = "\r\n"
  203.     end
  204.     local possible, actual = 0, 0
  205.     for j = 1, field.size[2] do
  206.       for i = 1, field.size[1] do
  207.         possible = possible + (field.possible_mines[j][i] and 1 or 0)
  208.         actual = actual + (field.actual_mines[j][i] and 1 or 0)
  209.       end
  210.     end
  211.     print("Found " .. possible ..
  212.             " of " .. actual .. " mines.\n")
  213.     print(table.concat(str))
  214. end
  215.  
  216. function parse_input(str)
  217.   local input = {}
  218.   if str:sub(-2)=="\n\r" then
  219.     str = str:sub(1, -2)
  220.   elseif ({["\n"]=true, ["\r"]=true})[str:sub(-1)] then
  221.     str = str:sub(1, -1)
  222.   end
  223.   for s in str:gmatch("[^%s]+") do
  224.     input[#input+1] = s
  225.   end
  226.   mode = input[1]
  227.   print(str)
  228.   coords =  #input == 3 and {tonumber(input[2]) or 0, tonumber(input[3]) or 0} or {0, 0}
  229.   return mode, coords
  230. end
  231.  
  232. function eval_input(field, str)
  233.   local mode, coords = parse_input(str)
  234.   if coords[1] > field.size[1] or coords[2] > field.size[2] then
  235.     return true
  236.   end
  237.   if mode == "o" then
  238.     return reveal(field, coords[1], coords[2]) or false
  239.   elseif mode == "m" and field.visible[coords[2]][coords[1]] == false then
  240.     field.possible_mines[coords[2]][coords[1]] = not field.possible_mines[coords[2]][coords[1]]
  241.   elseif mode == "c" then
  242.     print("You closed the game.")
  243.     os.exit()
  244.   end
  245.   return true
  246. end
  247.  
  248. function reveal(field, x, y)
  249.   if (x > field.size[1] or y > field.size[2]) then
  250.     return true -- check for index out of bounds
  251.   end
  252.   if (x < 1 or y < 1) then
  253.     return true -- check for index out of bounds
  254.   end
  255.   if field.actual_mines[y][x] then
  256.     return false -- check for mines
  257.   end
  258.   field.visible[y][x] = true
  259.   if field.numbers[y][x] == 0 then
  260.     for di = -1, 1 do
  261.       for dj = -1, 1 do
  262.         local dix, djy = di+x, dj+y
  263.         if (0 < dix and dix <= field.size[1] and 0 < djy and djy <= field.size[2]) and field.actual_mines[djy][dix] == false and f.visible[djy][dix] == false then
  264.           reveal(f, dix, djy)
  265.         end
  266.       end
  267.     end
  268.   end
  269.   return true
  270. end
  271.  
  272. function play()
  273.   print("\nWelcome to Minesweeper\n\nEnter the gridsize x  y:")
  274.   local x, y = io.read("n", "n")
  275.   f = Field(x or 1, y or 1)
  276.   local won = false
  277.   while true do
  278.     printfield(f)
  279.     print("\nWhat do you do? (\"o x y\" to reveal a field; \"m x y\" to toggle a mine; \"c\" to close)")
  280.     if not eval_input(f, io.read()) then
  281.       break
  282.     end
  283.     print(("_"):rep(80))
  284.     local comp = {true, true}
  285.     for j = 1, y do
  286.       for i = 1, x do
  287.         if comp[1] and (f.actual_mines[j][i]~=f.possible_mines[j][i]) then
  288.           comp[1] = false
  289.         end
  290.         if comp[2] and (f.visible[j][i]==f.actual_mines[j][i]) then
  291.           comp[2] = false
  292.         end
  293.         if not (comp[1] or comp[2]) then
  294.           break
  295.         end
  296.       end
  297.     end
  298.     if comp[1] or comp[2] then
  299.       won = true
  300.       break
  301.     end
  302.   end
  303.   print(won and "You won the game!" or "You lost the game:\n")
  304.   printfield(f, true)
  305. end
  306.  
  307. play()
Add Comment
Please, Sign In to add comment