Color changing part with table

Hi! So I attempted this challenge to make a color-changing part that stores it’s last colors in a table but looks like it doesn’t work.

Code:

local part = workspace.Part
local lastColors = {} --e.g: {[1] = "really blue", [2] = "really green", ...}

while true do
	wait(0.5)
	local newColor

	repeat
		newColor = BrickColor.Random()
	until not table.find(lastColors, newColor)

	part.BrickColor = newColor
	lastColors[#lastColors + 1] = newColor
	if #lastColors >= 5 then
		for i,v in ipairs(lastColors) do
			lastColors[i-1] = v 
		end
		lastColors[0] = nil --remove the oldest color
	end
end

I’m getting duplicates in the table. It’s something with the ipairs loop probably.
image
Thanks!

Try this:

local part = workspace.Part
local lastColors = {}

while true do
	wait(0.5)
        local newColor
	
        local function pick_color()
           -- function to pick a random color
           newColor = BrickColor.Random()

           if table.find(lastColors, newColor) then
               -- search the table to find if it already exists
               pick_color() -- call the function again
           end
       end

       pick_color()

	part.BrickColor = newColor
	table.insert(lastColors, newColor)
        -- use table.insert, it's easier

	if #lastColors >= 5 then
		for i,v in ipairs(lastColors) do
			lastColors[i-1] = v 
		end

        lastColors[#lastColors] = nil -- the last value in the table will be a duplicate
		lastColors[0] = nil --remove the oldest color
	end
end
1 Like

I would just use table.remove instead of writing your own remove code. I haven’t really analyzed it yet, but I think your issue is a mistake in the removing part.

1 Like

Oh, alright, thank you, so the problem was that I didn’t do
lastColors[#lastColors] = nil.
I added it to my code and now it works perfectly.

local part = workspace.Part
local lastColors = {} --e.g: {[1] = "really blue", [2] = "really green", ...}

while true do
	wait(0.5)
	local newColor

	repeat
		newColor = BrickColor.Random()
	until not table.find(lastColors, newColor)

	part.BrickColor = newColor
	lastColors[#lastColors + 1] = newColor
	if #lastColors >= 5 then
		for i,v in ipairs(lastColors) do
			lastColors[i-1] = v 
		end
		lastColors[0] = nil --remove the oldest color
		lastColors[#lastColors] = nil
	end
	print(lastColors)
end

Can you explain me why the last value in the table will be a duplicate? I kinda don’t understand it yet.

The loop only moves the current value to a lower index as long as there is a value above it. Since the last value in the array doesn’t have anything to replace it with, it keeps it’s value and stays in the array thus being a duplicate. My explanation might be a little confusing

1 Like

Why doesn’t it have anything to replace it with?
So if I have

{
[1] = "really green",
[2] = "really blue",
[3] = "sun yellow", 
[4] = "grass green", 
[5] = "very brown"
}

Wouldn’t it just become

{
[0] = "really green",
[1] = "really blue",
[2] = "sun yellow", 
[3] = "grass green", 
[4] = "very brown"
}

and then remove 0 meaning following will be left:

{
[1] = "really blue",
[2] = "sun yellow", 
[3] = "grass green", 
[4] = "very brown"
}

Then, next time it adds [5] again and [1] gets removed etc.?

The array would look this this:

{
[0] = "really green",
[1] = "really blue",
[2] = "sun yellow", 
[3] = "grass green", 
[4] = "very brown",
[5] = "very brown"
}

In the loop, moving the values downward doesn’t make the last value nil. I’ll try to visualize what’s happening in it:

{
[1] = "really green", --> [0] "really green"
[2] = "really blue", --> [1] "really blue"
[3] = "sun yellow", --> [2] "sun yellow"
[4] = "grass green", --> [3] "grass green"
[5] = "very brown" --> [4] "very brown"
                   --> [5] "very brown"
}

The reason why the last value is still very brown is because there isn’t another index to overwrite it, to examine your code:

for i,v in ipairs(lastColors) do
	lastColors[i-1] = v
    -- when the loop is on the last value
    -- nothing happens to it because the loop only affects the previous value, and since it's the last entry
    -- it can't be a 'previous value'
end

This either creates a new index or overwrites the previous one. When the loop is on the last entry, it only overwrites the value beneath it and the loop ends because it was the last entry, therefore, that entry itself, isn’t affected because there isn’t another value in front of it to make it become another value. I’m not the best at explanations lol

1 Like

Ohhhh, I understood it now, this makes a lot of sense.
Thank you!

1 Like