How do you make a lights out puzzle game?

so i’m doing this post except that im using a GUI.

i’m trying to check what buttons surround the button that was clicked so i can turn the lights on or off depending on its light state. i appreciate any help ty!

yellow checkmark = button clicked
pink circles = the boxes im trying to access

progress so far:
image

code:

local p = game.Players.LocalPlayer
local plrgui = p.PlayerGui
local lightsoutTest : ScreenGui = plrgui:FindFirstChild("lightsoutTest")
local gameFrame = lightsoutTest:FindFirstChild("gameFrame")
local buttons = gameFrame:FindFirstChild("buttons")
local soundService = game:GetService("SoundService")
local clicks = soundService:FindFirstChild("clicks")

local lights = {
	LightsChance = {
		On = 0.44,
		Off = 0.56	
	},

	LightsColor = {
		On = Color3.new(1, 1, 1),
		Off = Color3.new(0.333333, 0.333333, 0.333333)
	},
	
	LightState = {}
}

local function chooseLightState()
	local newRandom = Random.new()
	local randomNo = newRandom:NextInteger(0, 1)

	if randomNo <= lights.LightsChance.On then
		return "On"
	else
		return "Off"
	end
end

local function PlayButtonSound(sound : Sound)
	sound:Play()
end

for i, button in pairs(buttons:GetChildren()) do
	if button:IsA("TextButton") then
		local LightState = chooseLightState()

		button.BackgroundColor3 = lights.LightsColor[LightState]
		lights.LightState[button.Name] = LightState

		button.MouseButton1Click:Connect(function()
			PlayButtonSound(clicks.click_3)
		end)

		button.MouseEnter:Connect(function()
			PlayButtonSound(clicks.click_idk)
		end)
	end
end

print(lights.LightState)

I would recommend storing all of your lights in a matrix, and using that to then create the visuals. Optimizes things a little further.

local matrix = {}
local rows = 4
local columns = 4

local plr = game.Players.LocalPlayer

local gui = Instance.new("ScreenGui")
local parent = Instance.new("Frame", gui)
parent.Position = UDim2.fromScale(0.5, 0.5)
parent.AnchorPoint = Vector2.new(0.5, 0.5)
parent.Size = UDim2.fromScale(0.5, 0.5)
parent.BackgroundColor3 = Color3.new(0.14902, 0.14902, 0.14902)
local layout = Instance.new("UIGridLayout", parent)
layout.CellPadding = UDim2.fromScale(0.1/(columns-1), 0.1/(rows-1))
layout.CellSize = UDim2.fromScale(0.9/columns, 0.9/rows)
layout.SortOrder = Enum.SortOrder.Name

local offColor = Color3.new(0.333333, 0.333333, 0.333333)
local onColor = Color3.new(1, 1, 1)

local function display()
	for r=1, rows, 1 do
		for c=1, columns, 1 do
			parent[r .. "x" .. c].BackgroundColor3 = matrix[r][c] and onColor or offColor
		end
	end
end


local function processClick(r, c)
	print(r, c)
	matrix[r][c] = not matrix[r][c]
	if r>1 then
		matrix[r-1][c] = not matrix[r-1][c]
	end
	if r<rows then
		matrix[r+1][c] = not matrix[r+1][c]
	end

	if c>1 then
		matrix[r][c-1] = not matrix[r][c-1]
	end
	if c<columns then
		matrix[r][c+1] = not matrix[r][c+1]
	end

	display()
end

for r=1, rows, 1 do
	matrix[r] = {}
	for c=1, columns, 1 do
		matrix[r][c] = false
		local button = Instance.new("TextButton", parent)
		button.Text = ""
		button.BackgroundColor3 = offColor
		button.Name = r .. "x" .. c
		button.MouseButton1Click:Connect(function()
			processClick(r, c)
		end)
	end
end
gui.Parent = plr:WaitForChild("PlayerGui")

Uncopylocked place for the lazier people: Lights Out - Roblox
Hope you enjoy, had some fun coding this. The script has everything, you could just put it in StarterPlayerScripts if you want to try it out. Btw you can customize the rows and columns, the code is setup to support different sizes. If you have any issues implementing something like this, let me know!

1 Like

hey rolo! thanks a million for your help. i did end up figuring it out in a different way myself but reading your script has defo opened up new possibilities for me. thanks so much for your help mate!

this was my script:

local p = game.Players.LocalPlayer
local plrgui = p.PlayerGui
local lightsoutTest : ScreenGui = plrgui:FindFirstChild("lightsoutTest")
local gameFrame = lightsoutTest:FindFirstChild("gameFrame")
local buttons = gameFrame:FindFirstChild("buttons")
local soundService = game:GetService("SoundService")
local clicks = soundService:FindFirstChild("clicks")

local lights = {
	LightsPerRow = 4,

	LightsChance = {
		On = 0.44,
		Off = 0.56	
	},

	LightsColor = {
		On = Color3.new(1, 1, 1),
		Off = Color3.new(0.333333, 0.333333, 0.333333)
	},

	LightState = {},

	BlockedLights = {
		LeftLight = {4, 8, 12},
		RightLight = {5, 9, 13},
		TopLight = {},
		BottomLight = {},
		ClickedLight = {}
	}
}

-- THIS FUNCTION IS NOT NEEDED --
local function chooseLightState()
	local newRandom = Random.new()
	local randomNo = newRandom:NextInteger(0, 1)

	if randomNo <= lights.LightsChance.On then
		return "On"
	else
		return "Off"
	end
end

local function PlayButtonSound(sound : Sound)
	sound:Play()
end

local function detectSurroundingButtons(buttonClicked : TextButton)
	local num = tonumber(buttonClicked.Name)
	local LeftLight = tostring(num - 1)
	local RightLight = tostring(num + 1)
	local TopLight = tostring(num - lights.LightsPerRow)
	local ClickedButton = buttonClicked.Name
	local BottomLight = tostring(num + lights.LightsPerRow)

	local surroundingLights = {LeftLight, RightLight}

	--print(typeof(lights.BlockedLights.LeftSide[1]))
	
	local function SwitchLights(LightName, button, tbl)
		if button.Name == LightName and not table.find(tbl, tonumber(button.Name)) then
			print("button found!")
			if button.BackgroundColor3 == lights.LightsColor.On then
				button.BackgroundColor3 = lights.LightsColor.Off
			elseif button.BackgroundColor3 == lights.LightsColor.Off then
				button.BackgroundColor3 = lights.LightsColor.On
			end
		end
	end

	for i, button in pairs(buttons:GetChildren()) do
		if button:IsA("TextButton") then
			SwitchLights(LeftLight, button, lights.BlockedLights.LeftLight)
			SwitchLights(RightLight, button, lights.BlockedLights.RightLight)
			SwitchLights(TopLight, button, lights.BlockedLights.TopLight)
			SwitchLights(ClickedButton, button, lights.BlockedLights.ClickedLight)
			SwitchLights(BottomLight, button, lights.BlockedLights.BottomLight)
		end
	end

end

local function initializeSolvableBoard()
	for _, button in pairs(buttons:GetChildren()) do
		if button:IsA("TextButton") then
			button.BackgroundColor3 = lights.LightsColor.Off
			lights.LightState[button.Name] = "Off"
		end
	end

	local random = Random.new()
	local numPresses = random:NextInteger(5, 15)

	for i = 1, numPresses do
		local randomButtonIndex = random:NextInteger(1, 16) --4x4 grid has 16 buttons
		local button = buttons:FindFirstChild(tostring(randomButtonIndex))
		if button then
			detectSurroundingButtons(button)
		end
	end
end

initializeSolvableBoard()

for i, button in pairs(buttons:GetChildren()) do
	if button:IsA("TextButton") then

		button.MouseButton1Click:Connect(function()
			PlayButtonSound(clicks.click_3)
			detectSurroundingButtons(button)
		end)

		button.MouseEnter:Connect(function()
			PlayButtonSound(clicks.click_idk)
		end)
	end
end

print(lights.LightState)

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.