Skip to content

Instantly share code, notes, and snippets.

@radgeRayden
Last active May 13, 2022 00:36
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save radgeRayden/6f43edcf82b60b883905f4c3542324f1 to your computer and use it in GitHub Desktop.
Save radgeRayden/6f43edcf82b60b883905f4c3542324f1 to your computer and use it in GitHub Desktop.
minesweeper
local field = {}
local field_width = 10
local field_height = 10
local field_position_x = 100
local field_position_y = 100
local n_mines = 15
local size_square = 30
local start_time = 0
local play_time = 0
local is_game_over = false
local function getxy_from_index(index, width, height)
if index < 1 or index > width * height then
return false
end
return ((index - 1) % width), (math.floor((index - 1) / height))
end
local function get_index_fromxy(x, y, width, height)
if x < 0 or y < 0 or x >= width or y >= height then
return false
end
return ((y * width) + x) + 1
end
local function square_reveal(self)
if self.revealed then return end
self.revealed = true
if self.has_mine then
is_game_over = true
elseif self.n_neighbour_mines == 0 then
for i, neighbour in ipairs(self.neighbours) do
if not neighbour.has_mine and not neighbour.is_flagged then
neighbour:reveal()
end
end
end
end
local function square_flag_toggle(self)
self.is_flagged = not self.is_flagged
end
function love.load()
love.window.setTitle("Minefield Game")
start_time = love.timer.getTime()
is_game_over = false
for i=1, field_width * field_height do
field[i] =
{
has_mine = false,
revealed = false,
n_neighbour_mines = 0,
neighbours = {},
is_flagged = false,
toggle_flag = square_flag_toggle,
reveal = square_reveal,
neighbours = {}
}
end
for i, square in ipairs(field) do
local x, y = getxy_from_index(i, field_width, field_height)
local neighbour_indexes =
{
get_index_fromxy(x - 1, y - 1, field_width, field_height), -- top left
get_index_fromxy(x , y - 1, field_width, field_height), -- top center
get_index_fromxy(x + 1, y - 1, field_width, field_height), -- top right
get_index_fromxy(x - 1, y , field_width, field_height), -- center left
get_index_fromxy(x + 1, y , field_width, field_height), -- center right
get_index_fromxy(x - 1, y + 1, field_width, field_height), -- bottom left
get_index_fromxy(x , y + 1, field_width, field_height), -- bottom center
get_index_fromxy(x + 1, y + 1, field_width, field_height) -- bottom right
}
for _, index in ipairs(neighbour_indexes) do
if index then
table.insert(square.neighbours, field[index])
end
end
end
for i=1, n_mines do
:: retry ::
local index = (math.ceil(love.math.random(field_width * field_height)))
if not field[index].has_mine then
field[index].has_mine = true
else
goto retry
end
local x, y = getxy_from_index(i, field_width, field_height)
-- add 1 to each neighbour mine counter
for i,square in ipairs(field[index].neighbours) do
square.n_neighbour_mines = square.n_neighbour_mines + 1
end
end
love.graphics.setBackgroundColor(0.14, 0.14, 0.14)
end
function get_square_from_screenpos(x, y)
local rel_position_x, rel_position_y = x - field_position_x, y - field_position_y
local x, y = math.floor(rel_position_x / size_square), math.floor(rel_position_y / size_square)
local index = get_index_fromxy(x, y, field_width, field_height)
if not index then return false end
return field[index]
end
function love.draw()
if is_game_over then
love.graphics.print("Game over! Press 'r' to restart!")
end
love.graphics.print(tostring(play_time), 10, 10)
love.graphics.translate(field_position_x, field_position_y)
for i=1, field_width * field_height do
local square = field[i]
local x, y = getxy_from_index(i, field_width, field_height)
if square.revealed then
love.graphics.rectangle('fill', x * size_square, y * size_square, size_square, size_square)
if square.has_mine then
love.graphics.setColor(252/255, 186/255, 3/255)
love.graphics.circle('fill', (x * size_square) + (size_square / 2),(y * size_square) + (size_square / 2), size_square / 2)
love.graphics.setColor(1,1,1)
elseif square.n_neighbour_mines > 0 then
love.graphics.setColor(0.14, 0.14, 0.14)
love.graphics.print(square.n_neighbour_mines, (x * size_square) + (size_square / 2) - 5, (y * size_square) + (size_square / 2) - 7)
love.graphics.setColor(1,1,1)
end
else
love.graphics.rectangle('line', x * size_square, y * size_square, size_square, size_square)
if square.is_flagged then
love.graphics.push()
love.graphics.translate(x * size_square, y * size_square)
love.graphics.scale(size_square)
-- draw flag
love.graphics.setColor(1,0,0)
love.graphics.polygon('fill', 0.1, 0.4, 0.8, 0.1, 0.8, 0.4)
love.graphics.setColor(0,1,0)
love.graphics.setLineWidth(0.1)
love.graphics.line(0.8, 0.1, 0.8, 0.9)
love.graphics.setColor(1,1,1)
love.graphics.pop()
end
end
end
end
function love.keypressed(key)
if key == 'r' then
love.load()
end
end
function love.mousereleased(x, y, button)
if is_game_over then return end
local square = get_square_from_screenpos(x, y)
if not square then return end
if button == 1 then
square:reveal()
end
if button == 2 then
square:toggle_flag()
end
end
function love.update(dt)
-- time since start of play session
if not is_game_over then
play_time = math.floor(love.timer.getTime() - start_time)
end
local field_complete = true
for _,v in ipairs(field) do
local revealed = v.revealed or (v.is_flagged and v.has_mine)
field_complete = field_complete and revealed
end
is_game_over = is_game_over or field_complete
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment