How do I stop a Math.Random from repeating numbers?

In This script I am trying to give the player 3 random weapons from a folder, the issue I have right now is that since its random weapons, that means you can double up, or even triple up on the same weapon, and that is not what was intended. I’ve combed through the wiki but none of it seems to apply to this.

This script here, at the click of a part, puts 3 different tools into your inventory.

The variable count is just to find how many weapons there are to consider.

local debounce = false
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local EligibleItems = ReplicatedStorage.PossibleItems:GetChildren()

local count = 0
for _,v in pairs(EligibleItems) do -- finds the max amount of numbers allowed
	count = count + 1
end

script.Parent.ClickDetector.MouseClick:Connect(function(hit)
	if debounce == false then
		debounce = true
		hit.Team = game.Teams.Blue
		
		for i = 1,3 do -- sends back 3 random numbers from the amount of weapons there are
			local Index = math.random(1, count)
			local RandomChild = ReplicatedStorage.PossibleItems:GetChildren()[Index]
			local ClonedForInv = RandomChild:Clone()
			ClonedForInv.Parent = hit.Backpack
			
		end
		wait(5)
		debounce = false
		
	end
end)

Thanks for your help, I have been suffering tryna do this for so long,

Snipperdiaper

You could use a variable and a loop to re-roll a different Index.

script.Parent.ClickDetector.MouseClick:Connect(function(hit)
   -- . . .
   local lastIndex = 0 -- Zero is never used as an index.
   for i = 1,3 do
      local Index
      repeat
         Index = math.random(1,count)
      until Index ~= lastIndex -- repeat the loop if Index ends up repeating the last index.
      -- . . .
   end
   -- . . .
end
3 Likes

Workspace.Redteam.RedTeam:22: attempt to index nil with ‘Clone’

it also shows that, On line 20,
local RandomChild = ReplicatedStorage.PossibleItems:GetChildren()[Index]

Index is underlined with undefined global variable, I’ve already tried to add a Local Index = 0, Like your lastIndex, but I couldnt fix it.

Current Setup:

local debounce = false
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local EligibleItems = ReplicatedStorage.PossibleItems:GetChildren()

local count = 0
for _,v in pairs(EligibleItems) do -- finds the max amount of numbers allowed
	count = count + 1
end

script.Parent.ClickDetector.MouseClick:Connect(function(hit)
	if debounce == false then
		debounce = true
		hit.Team = game.Teams.Blue
		local lastIndex = 0
		for i = 1,3 do -- sends back 3 random numbers from the amount of weapons there are
			repeat
				local Index = math.random(1,count)
			until Index ~= lastIndex
			
			local RandomChild = ReplicatedStorage.PossibleItems:GetChildren()[Index]
			local ClonedForInv = RandomChild:Clone()
			ClonedForInv.Parent = hit.Backpack

		end
		wait(5)
		debounce = false

	end
end)

That’s because you are creating Index in the repeat loop.
Also, there is another problem. Lua checks the condition of the repeat loop first, so if it is true, it just doesn’t execute the loop. when we do local Index the value will be set to nil by default, meaning that the condition will be infact true, so the loop won’t execute.
Do this:

local Index = math.random(1,count)
repeat
	Index = math.random(1,count)
until Index ~= lastIndex

You’re defining local Index inside of the repeat loop, which doesn’t exist outside of it.
Which is why i normally defined it before the repeat loop.

The loop you’re mentioning is the while (condition) do loop, repeat will check the condition after the loop has been iterated.
Although technically this works too.

1 Like

had to make it = nil, new error appeared.

Workspace.Redteam.RedTeam:23: attempt to index nil with 'Clone'

Tried this but it still isnt truly random (I got 3 of the same item)

The method is not perfect, of course. Since we can let’s say get the same number from math.random 15 times in a row (the chances are low, but still). It’s better to use tables with numbers that you need and them removing number lastIndex from it, then doing numbers[math.random(1, #numbers)].
About the index with nil issue, can you print ReplicatedStorage.PossibleItems:GetChildren()?

Forgot to add the line where lastIndex should be set after the loop ends, my bad.

local lastIndex = 0 -- Zero is never used as an index.
   for i = 1,3 do
      local Index
      repeat
         Index = math.random(1,count)
      until Index ~= lastIndex
      lastIndex = Index
      -- . . .
   end
1 Like

Also, why do you need to use ReplicatedStorage.PossibleItems:GetChildren() when variable EligibleItems has the same value?
Why use

local count = 0
for _,v in pairs(EligibleItems) do -- finds the max amount of numbers allowed
	count = count + 1
end

when it can be easily simplified?

local count = #EligibleItems:GetChildren()
1 Like

Same error as last time since you have to initialize or assign the Index ( = nil )

( Workspace.Redteam.RedTeam:23: attempt to index nil with 'Clone')

Fixed The problem (I hope)

By also doing Local Index = 0 with lastIndex, it assigns index and seems to work.

1 Like

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