How To Make Sure math.random() Doesn't Duplicate

I will be showing you how to prevent duplicates when using math.random() in Roblox Studio.
It doesn’t take that much scripting and is pretty simple. Without further ado, let me get right into it!

The example I’m going to be using in this is so it could print every number 1-15 in a random order. Once all 15 numbers have been printed, it will print a message saying “All 15 Numbers Have Been Printed…Restarting Loop!” and start over again, this time in a different order. It will keep repeating forever. Obviously, you’re probably going to do something other than printing 15 numbers, so just make sure to apply your code into this system.


Step 1: Create A Table
This table will hold every number that has already been printed and make sure numbers don’t get printed again.

local printedNumbers = {}

Step 2: Create A For Loop
The for loop will individually print every number in a random order. Since we want to print 15 numbers, we will make this for loop repeat 15 times.

local printedNumbers = {}

for i = 1,15 do
	-- We will put our code here
end

Step 3: Generate A Random Number
This is where we will use math.random(). It’s simple to use. The first input is going to be the minimum number, while the second input is going to be the maximum.

local printedNumbers = {}

for i = 1,15 do
	local number = math.random(1,15)
end

Step 4: Check If The Number Is Already In The Table
This part is where we will prevent the duplicates. Using a conditional statement, we can check if the number is already in the table. If it is, we will give number a different value. Otherwise, we will continue to use its current value. We can do this very easily using table.find(). The first input for table.find() is the table, while the second one is the value we will check to see whether it’s in the table or not.

local printedNumbers = {}

for i = 1,15 do
	local number = math.random(1,15)

	if table.find(printedNumbers,number) ~= nil then
		-- Give New Value To "number"
	end
end

Step 5: Change Value Of Number
For this part, we can’t change the value only once, because that would create the risk of getting another number in the table. This is why we need to create a loop that will keep changing the value of number until its value changes into a number that isn’t in the table. We could do that using an until loop. This loop will repeat until something happens. We will make it repeat until number’s value isn’t found in the table.

local printedNumbers = {}

for i = 1,15 do
	local number = math.random(1,15)

	if table.find(printedNumbers,number) ~= nil then
		repeat
			number = math.random(1,15)
		until table.find(printedNumbers,number) == nil
	end
end

Step 6: Print The Number
Over here we will actually print the number. At this point in the code, number should be ready to print, so we could go ahead and print it. Obviously, we will use print() to do this. At the same time, I also want to add number to the table, using table.insert(). The first input is the table, and the second is whatever I want to add to the table. I also want to wait a second before printing each number. We can do this using task.wait().

local printedNumbers = {}

for i = 1,15 do
	local number = math.random(1,15)

	if table.find(printedNumbers,number) ~= nil then
		repeat
			number = math.random(1,15)
		until table.find(printedNumbers,number) == nil
	end

	print(number)
	table.insert(printedNumbers,number) 
	task.wait(1)
end

Step 7: Loop The Whole Thing Forever
Since we want this to repeat over and over again, we will use a while loop. A while loop is pretty simple, it is just a loop that never ends and runs forever. Or at least that’s the case for the way we will use it. We just want to put that while loop over the for loop. Then, in that same while loop, we also want to print "All 15 Numbers Have Been Printed..Restarting Loop!" and wait a second before looping the while loop.

local printedNumbers = {}

while true do
	for i = 1, 15 do
		local number = math.random(1,15)

		if table.find(printedNumbers,number) ~= nil then
			repeat
				number = math.random(1,15)
			until table.find(printedNumbers,number) == nil
		end

		print(number)
		table.insert(printedNumbers,number) 
		task.wait(1)
	end
	print("All 15 Numbers Have Been Printed...Restarting Loop!")
	task.wait(1)
end

Step 8: Clear The Table
Wait a second. The while loop won’t work a second time because the table is still filled with all the numbers. This is an easy fix. All we need to do is add one last line. At the very end of the while loop, we can add table.clear() to delete everything in the table. The input is the table. There we go! We finished!


The finished code:

local printedNumbers = {}

while true do
	for i = 1, 15 do
		local number = math.random(1,15)

		if table.find(printedNumbers,number) ~= nil then
			repeat
				number = math.random(1,15)
			until table.find(printedNumbers,number) == nil
		end
		
		print(number)
		table.insert(printedNumbers,number) 
		task.wait(1)
	end
	print("All 15 Numbers Have Been Printed...Restarting Loop!")
	task.wait(1)
	table.clear(printedNumbers)
end

Pseudocoded:

local printedNumbers = {} --table to hold all printed numbers

while true do --loops forever
	for i = 1, 15 do --loops 15 times
		local number = math.random(1,15) --generates random number between 1 and 15

		if table.find(printedNumbers,number) ~= nil then --checks if number is in the table already
			repeat --repeats until _ happens
				number = math.random(1,15) --changes the number's value
			until table.find(printedNumbers,number) == nil --loop stops once the number isn't found in the table
		end --ends conditional statement
		
		print(number) --prints the number
		table.insert(printedNumbers,number) --adds the number to the table
		task.wait(1) --waits one second
	end --ends for loop
	print("All 15 Numbers Have Been Printed...Restarting Loop!") --prints that message
	task.wait(1) --waits one second
	table.clear(printedNumbers) --deletes everything in the table
end --ends while loop

We can tell that this code works because the output is displaying exactly what’s expected:
Screenshot_20230429_101212


Great job! You just manipulated math.random() so that it doesn’t return the same number twice. Thanks for reading, I hope this helped!

11 Likes

I Love this so much! Thanks for sharing.

When I looked at this from my own approach, I was able to come up with this:

local start, finish = 1, 15
local numbers = {} 

while task.wait() do
	for i = start, finish do
        table.insert(numbers, i)
    end
    repeat
		local index = math.random(#numbers)
        local number = numbers[index]
        print(number)
        table.remove(numbers, index)
        task.wait()
	until #numbers == 0

	numbers = {}
end
1 Like

I really like this take on it since instead of adding numbers to an empty table, you remove numbers from a filled table! Good work!

A dictionary would be more efficient, like this.

local printedNumbers = {}

for i = 1, 15 do
	local number = math.random(1, 15)

	while printedNumbers[number] do
		number = math.random(1, 15)
	end
	printedNumbers[number] = true

	print(number)
end

table.find would loop through the array to find the value. A dictionary doesn’t need to.

3 Likes