If one player left and others dead, then GUI says "..Won" and the players are teleported back to lobby and script loops

Hey so I am making a color block game and I already made the main frame but am struggling to make the game detect when players are dead (1 last left) and if so, gui appears that says “…Won” Thanks in advance :

local roundLength = 180
local intermissionLength = 30
local InRound = game.ReplicatedStorage.InRound
local Status = game.ReplicatedStorage.Status
local Players = game.Players

local LobbySpawn = game.Workspace.LobbySpawn
local GameAreaSpawn = game.Workspace.GameAreaSpawn

InRound.Changed:Connect(function()
	if InRound.Value == true then
		
		local playersInRound = {} -- track alive players
		local connections = {} -- store connections to disconnect later
		for _, Player in pairs(Players:GetChildren()) do
			if Player.Character and Player.Character:FindFirstChild('Humanoid') then

				table.insert(playersInRound, Player) -- add all players to table
				connections[Player.Name] = Player.Character.Humanoid.Died:Connect(function()
					table.remove(playersInRound, table.find(playersInRound, Player))
				end)
			end
		end

		connections["Removing"] = game.Players.PlayerRemoving:Connect(function(player) -- remove player from list if they leave
			
			local ind = table.find(playersInRound, player)
			if ind then
				table.remove(playersInRound, ind)
			end
		end)

		for _, player in pairs(game.Players:GetChildren()) do
			local char = player.Character
			char.HumanoidRootPart.CFrame = GameAreaSpawn.CFrame
			


		end
	else 
		for _, player in pairs(game.Players:GetChildren()) do
			local char = player.Character
			char.HumanoidRootPart.CFrame = LobbySpawn.CFrame
			
			local playersInRound = {}
			local connections = {}
			
			if #playersInRound == 1 then
				local success, message = pcall(function()
					local player = playersInRound[1]
					print("The Winner is: " .. player.Name)
					Status.Value = player.Name .. " won the game!"
					player.leaderstats.Wins.Value = player.leaderstats.Wins.Value + 1
					player.leaderstats.Coins.Value = player.leaderstats.Coins.Value + 100
				end)
				if not success then
					warn("An error occurred while rewarding winner: " .. message)
				end
			else
				print("There was no single winner.")
				Status.Value = "There was no single winner this round."
			end

			--Kill the players
			for _, connection in pairs(connections) do -- disconnect connections to prevent memory leaks
				connection:Disconnect()
			end

			for _, Player in pairs(playersInRound)do
				Player:LoadCharacter()
			end
		end
	end
end)


local function roundTimer()
	while wait() do
		for i = intermissionLength, 1, -1 do
			InRound.Value = false
			wait(1)
			Status.Value = "Game starting in "..i.." seconds."
			end
			
			for i = roundLength, 1, -1 do
				InRound.Value = true
				wait(1)
				Status.Value = "There are "..i.." seconds left for this round."

			
	
		end
	
		
			
		end
	end


spawn(roundTimer)

You are declaring playersInRound separately. It should instead be declared once per round.

local ReplicatedStorage = game:GetService("ReplicatedStorage");
local Players = game:GetService("Players");
local InRound = ReplicatedStorage:WaitForChild("InRound");
local Status = ReplicatedStorage:WaitForChild("Status");

local roundLength = 180;
local intermissionLength = 30;

local LobbySpawn = workspace.LobbySpawn;
local GameAreaSpawn = workspace.GameAreaSpawn;

local playersInRound = {} -- track alive players
local connections = {} -- store connections to disconnect later

local function removePlayer(player)
	playersInRound[player.UserId] = nil;
end

local playerRemovingConnection;

InRound.Changed:Connect(function()
	if (InRound.Value == true) then
		playersInRound = {};
		
		for _, Player in ipairs(Players:GetPlayers()) do
			playersInRound[Player.UserId] = Player;
			
			local Character = Player.Character or (Player.CharacterAdded:Wait());
			local Humanoid = Character:FindFirstChild("Humanoid");
			
			if (Humanoid) then
				connections[Player.UserId] = Humanoid.Died:Connect(function()
					removePlayer(Player);
				end)
			end
		end
		
		playerRemovingConnection = Players.PlayerRemoving:Connect(removePlayer);

		for _, Player in ipairs(game.Players:GetPlayers()) do
			local Character = Player.Character or (Player.CharacterAdded:Wait());
			local HRP = Character:FindFirstChild("HumanoidRootPart") or Character.PrimaryPart;
			
			if (HRP) then
				HRP.CFrame = GameAreaSpawn.CFrame;
			end
		end
	else 
		for _, Player in pairs(Players:GetPlayers()) do
			local Character = Player.Character or (Player.CharacterAdded:Wait());
			local HRP = Character:FindFirstChild("HumanoidRootPart") or Character.PrimaryPart;

			if (HRP) then
				HRP.CFrame = LobbySpawn.CFrame;
			end

			if (#playersInRound == 1) then
				local success, message = pcall(function()
					local player = playersInRound[1]
					print("The Winner is: " .. player.Name)
					Status.Value = player.Name .. " won the game!"
					player.leaderstats.Wins.Value = player.leaderstats.Wins.Value + 1
					player.leaderstats.Coins.Value = player.leaderstats.Coins.Value + 100
				end)
				if not success then
					warn("An error occurred while rewarding winner: " .. message)
				end
			else
				print("There was no single winner.")
				Status.Value = "There was no single winner this round."
			end

			--Kill the players
			playerRemovingConnection:Disconnect();
			
			for _, connection in ipairs(connections) do -- disconnect connections to prevent memory leaks
				connection:Disconnect()
			end

			for _, Player in ipairs(playersInRound)do
				Player:LoadCharacter();
			end
		end
	end
end)


local function roundTimer()
	while (true) do
		for i = intermissionLength, 1, -1 do
			InRound.Value = false
			wait(1)
			Status.Value = "Game starting in "..i.." seconds."
		end

		for i = roundLength, 1, -1 do
			InRound.Value = true
			wait(1)
			Status.Value = "There are "..i.." seconds left for this round."
		end
	end
end


coroutine.wrap(roundTimer);

And as good practice, use GetService instead of indexing a singleton. Use GetPlayers instead of GetChildren on the Players singleton.

I’d suggest you take a look at your code, trying to find issues or bad habits. This ultimately will help you more than anyone else could.

Hey thanks for the reply, should I keep this local script under game.StarterGui.Timer.Localscript?

local Status = game.ReplicatedStorage.Status

local TimerDisplay = script.Parent.TimerDisplay

Status.Changed:Connect(function()

TimerDisplay.Text = Status.Value

end)

I fixed the timer and realised I sent you the wrong script.

local Timer = 31 

for i = Timer, 0, -1 do
	task.wait(1)
	print(i)
end																	-- Intermission timer

local Round = 0

local StarterBlock = game.Workspace.StarterBlock


for i=1,3 do


local Circles = game.Workspace.Circles:GetChildren() 

Chosen_Colour = Circles[math.random(1,#Circles)]

	game.ReplicatedStorage.Colour.Value = Chosen_Colour.Name 
task.wait(6)
																					-- ROUND 1,2 and 3
StarterBlock.Transparency = 1
StarterBlock.CanCollide = false 
	
wait(2)

	for number,Circle_Colours in pairs(Circles) do
		for number,Circle_Part in pairs(Circle_Colours:GetChildren()) do

			Circle_Part.Transparency = 1 
			Circle_Part.CanCollide = false
		end
	end

	for number, Circle_Part in pairs(Chosen_Colour:GetChildren()) do
		Circle_Part.Transparency = 0 
		Circle_Part.CanCollide = true
	end

	wait(3) -- waits again

	for number,Circle_Colours in pairs(Circles) do 
		for number,Circle_Part in pairs(Circle_Colours:GetChildren()) do
			print("h")
			Circle_Part.Transparency = 0
			Circle_Part.CanCollide = true
			
		Round += 1	
		end
	end
end

print("Round 1, 2 and 3 completed")

So this is only part of the script, there are 7 other rounds but as you stated, i need to put the playersInround each round. Could you debug it?

If all players die, no winner

if one left standing, the winning player is teleported back to LobbySpawn without executing the rest of the rounds and the intermission timer goes again and the script loops.