Checking if the BrickColor of 64 bricks are the same at once

A while ago I sought help with this same problem but the solution was still broken in practice, so here I am again, tired of manually awarding this badge to my players so hoping I get automation fixed.

We have an area of 64 bricks that players can touch to change color. Making all 64 the same color awards a badge to everyone in the server. However, I cannot find a way to get this badge to automatically award.

When I initially came to the Devforum to fix this problem, this was the script I was given:

local BadgeService = game:GetService("BadgeService")
local BadgeID = BADGEID -- yes, this is actually filled out properly in the real script
local Bricks = game.Workspace.randomcolorbricks:GetChildren()
-- // Filter out the sneaky little Script (and anything else)
for Index,Brick in ipairs(Bricks) do 
	if not Brick:IsA("BasePart") then 
		table.remove(Bricks, Index) 
	end 
end

local MasterBrick = game.Workspace.randomcolorbricks.RandomColorBrick52
local MasterColor = MasterBrick.BrickColor

local Matches = 0

while true do
	for _, Brick in pairs(Bricks) do
	-- // I really like the new ternary syntax. It just reads really nice.
		Matches += if Brick.BrickColor == MasterColor then 1 else 0
		wait(0.01)
	end
end

-- // You can add as many bricks as you would like, and not need to worry about changing the value here.
if Matches == #Bricks then
	print("dedication badge awarded")
	local Players = game:GetService("Players"):GetPlayers()
	for Index, Player in pairs(Players) do
		BadgeService:AwardBadge(Player.UserId, BadgeID)
	end
end

It doesn’t work when players are actually in the game and won’t do what we need it to. Yes, it is not a LocalScript.

How do I get this script to realize when all the BrickColors are the same?

Please provide script samples if you can! I learn best when I have visuals.

1 Like

Loop through the bricks and check the color.

Maybe something like:

for _, brick in pairs(YourBricks:GetChildren()) do
	if brick then
		if brick.BrickColor ~= YourColor then
			-- There is a brick that does not match
		else
			-- Award Badge
		end
	end
end

Theres 3 mistakes in your code,

  1. You cant use if statements when adding a number to a variable, you should do something like this:
    Matches += (Brick.BrickColor == MasterColor and 1 or 0)
  2. The while true loop stops the code after it from running, you need to put it inside a seperate thread using task.spawn() or coroutines,
  3. You only check if the Matches variable is equal to the number of bricks there are, you should also put that inside a loop.

The (hopefully) working code:

local BadgeService = game:GetService("BadgeService")
local BadgeID = BADGEID -- yes, this is actually filled out properly in the real script
local Bricks = game.Workspace.randomcolorbricks:GetChildren()
-- // Filter out the sneaky little Script (and anything else)
for Index,Brick in ipairs(Bricks) do 
	if not Brick:IsA("BasePart") then 
		table.remove(Bricks, Index) 
	end 
end

local MasterBrick = game.Workspace.randomcolorbricks.RandomColorBrick52
local MasterColor = MasterBrick.BrickColor

local Matches = 0

task.spawn(function() --// Create a new thread.
	while true do
		Matches = 0 --// Reset the matches count because it would just keep on adding to it.
		
		for _, Brick in pairs(Bricks) do
			-- // I really like the new ternary syntax. It just reads really nice.
			Matches += (Brick.BrickColor == MasterColor and 1 or 0)
			--wait(0.01) // The wait here was useless because theres not that many parts that will cause lagging and will just slow down your code.
		end
		
		-- // You can add as many bricks as you would like, and not need to worry about changing the value here.
		if Matches == #Bricks then
			print("dedication badge awarded")
			local Players = game:GetService("Players"):GetPlayers()
			for Index, Player in pairs(Players) do
				BadgeService:AwardBadge(Player.UserId, BadgeID)
			end
		end
		
	end
end)




It seems that the current script you have provided is not detecting when all the brick colors are the same, which is the main issue. One possible solution to this problem is to modify the script to use a dictionary to keep track of the number of bricks with each color, and then check if there is only one color with the same number of bricks as the total number of bricks. Here is an example of how this can be implemented:

local BadgeService = game:GetService("BadgeService")
local BadgeID = BADGEID -- replace with your badge ID
local Bricks = game.Workspace.randomcolorbricks:GetChildren()

-- filter out non-BaseParts
for Index,Brick in ipairs(Bricks) do 
	if not Brick:IsA("BasePart") then 
		table.remove(Bricks, Index) 
	end 
end

-- create a dictionary to keep track of the number of bricks with each color
local Colors = {}
for _, Brick in pairs(Bricks) do
	local ColorName = Brick.BrickColor.Name
	if Colors[ColorName] then
		Colors[ColorName] += 1
	else
		Colors[ColorName] = 1
	end
end

-- find the color with the most bricks and the number of bricks with that color
local MaxCount = 0
local MaxColor = nil
for Color, Count in pairs(Colors) do
	if Count > MaxCount then
		MaxCount = Count
		MaxColor = Color
	end
end

-- if the color with the most bricks has the same number of bricks as the total number of bricks, award the badge to all players in the server
if MaxCount == #Bricks then
	print("dedication badge awarded")
	local Players = game:GetService("Players"):GetPlayers()
	for _, Player in pairs(Players) do
		BadgeService:AwardBadge(Player.UserId, BadgeID)
	end
end

Make sure to replace BADGEID with your badge ID.

In this modified script, we first create a dictionary called Colors which keeps track of the number of bricks with each color. We then loop through all the bricks and add the color of each brick to the Colors dictionary. After that, we find the color with the most bricks (MaxColor) and the number of bricks with that color (MaxCount).

Finally, we check if MaxCount is equal to the total number of bricks. If it is, then we award the badge to all players in the server.

Note: This script should be placed in a Script object, not a LocalScript object.

Here’s a simple function that checks if an array of parts have the same color:

--receives an array of parts, returns if their color is the same or no
function HaveSameBrickColor(parts: {BasePart}): boolean
	if #parts < 2 then return true end
	--for reference pick the color of the first element
	local color = parts[1].BrickColor
	for i = 2, #parts do
		--if an element's color is different than the first, then the parts aren't of same color
		if parts[i].BrickColor ~= color then return false end
	end
	--no element was found with a different color than the first, so they all have the same color
	return true
end

local areSameColor = HaveSameBrickColor(workspace.randomcolorbricks:GetChildren())
print(areSameColor) --true or false

you will need to pass the parts through the function every time a part color changes, this can get expensive if the parts count increases(let’s say to 5k) but for 64 parts you honestly shouldn’t care(if you’re checking larger amounts you should use caching to avoid looping through all the parts every time)

Correction: You absolutely can! They’re ternary statements.

1 Like

I tried all three, here’s the results:

@CZXPEK - The script times out immediately and doesn’t detect when all the tiles are the same. Returns no errors other than two timeouts.

Screen Shot 2023-04-11 at 2.15.29 PM

@VariantBD - Your script just doesn’t do anything. Nothing prints, nothing errors, simply doesn’t work. Let me know where I can drop a print statement to debug.

EDIT: It works fine if I manually set all the tiles to the same color BEFORE I test the game. If I am actually playing and get all the tiles to the correct color in game, nothing happens.

@NyrionDev - You have an unknown global here: local color = t[1].BrickColor. You never call t. I assume this is the table we get from workspace.randomcolorbricks:GetChildren(), but you already break it up in the function parameters and I’m too much of a functions noob to even begin to figure out how to put that back together.

1 Like

I think the problem with @NyrionDev’s Function is that as it is it never gets called, you could have a button to “submit” and check if it gets activated to run the Function, or when the colour of a part changes run the code as @realmhopping said, even though I’m not sure of how you would do that…

1 Like

When do you run this whole script? You’d need to run it everytime a block changes color in order to keep track of them. If you only run it at the start of the game it won’t do anything more.

2 Likes

Try something like this:

local BadgeService = game:GetService("BadgeService")
local BadgeID = BADGEID -- yes, this is actually filled out properly in the real script
local Bricks = game.Workspace.randomcolorbricks:GetChildren()
-- // Filter out the sneaky little Script (and anything else)
for Index,Brick in ipairs(Bricks) do 
	if not Brick:IsA("BasePart") then 
		table.remove(Bricks, Index) 
	end 
end

local MasterBrick = game.Workspace.randomcolorbricks.RandomColorBrick52
local MasterColor = MasterBrick.BrickColor

local Matches = 0


for _, v in pairs(Bricks) do

	v.Touched:Connect(function()

		checkMatches()

	end)

end

function checkMatches()
	
	while true do
		for _, Brick in pairs(Bricks) do
			-- // I really like the new ternary syntax. It just reads really nice.
			Matches += if Brick.BrickColor == MasterColor then 1 else 0
			wait(0.01)
		end
	end
	
	if Matches == #Bricks then
		print("dedication badge awarded")
		local Players = game:GetService("Players"):GetPlayers()
		for Index, Player in pairs(Players) do
			BadgeService:AwardBadge(Player.UserId, BadgeID)
		end
	end
	
end
1 Like

My bad! The global should be the parameter parts, I forgot to rename it when writing the function.

1 Like

No dice, @NyrionDev and @realmhopping .
Thanks for the help though.

2 Likes