How do I make Math.random NOT Select the same thing again?

I have a loading screen that randomly chooses an image and text from a table. It then makes a loop until the whole assets are loaded.

local Text1 = "Did you know this game started as a dare?"
local Text2 = "Did you know Elon Musk's Home is Mars?"
local Text3 = "Only big brain people know the hidden message."
local Text4 = "This game was inspired by SpaceX!"
local Text5 = "There's a Starman Waiting in the sky ♫"
local Text6 = "Subscribe to Foxyth_Dev you big CHAD."
local Text7 = "ur wifi might be bad that's why."
local Text8 = "Assets finished loaded:" .. AmountLoaded
local TextTable = {Text1, Text2, Text3, Text4, Text5, Text6, Text7, Text8}
--Text^

local Images = {"rbxgameasset://Images/Finsihed Nouvant", "rbxgameasset://Images/YAYYYY", "rbxgameasset://Images/AtlasRoverMarkOne!", "rbxgameasset://Images/Drone atmospheric- Theourus mark II- sceneryincluded"}
--My Image ids^
local ImageBackground = script.Parent.BackgroundImage1
--My Image Background^

The looped code:

local RandomTextLoop = coroutine.wrap(function()
	while LoadingAssetStatus == true do
		TextEnter1:Play()
		LoadingText2.Text = TextTable[math.random(1, 8)]
		wait(3)
		TextLeave1:Play()
		wait()
		TextEnter2:Play()
        LoadingText1.Text = TextTable[math.random(1, 8)]
		wait(3)
		TextLeave2:Play()
		wait()
	end
end)

Now I want to make sure it won’t select the same thing again. I’ve tried looking here, but I can’t find the correct word. I’ve thought also of making another table where it’s named last selected so I can move the one selected to my last selected table. I’m pretty confused. Help is greatly appreciated!

Edit: NOT SELECT

I would do almost what you’ve suggested, but you only need the last text, so just grab the index of it and keep generating numbers until it’s different to the last one.

Here’s an example of how I’d do that:

local lastText = 0
function selectNewText()
    local newIndex
    while not newIndex or newIndex == lastText do
        newIndex = math.random(1,#TextTable)
    end
    lastText = newIndex
    return TextTable[newIndex]
end


-- then, wherever you select a new bit of text,
LoadingText1.Text = selectNewText()
3 Likes

Hm, i see, let me try. you lnow 30chars

Seems like what you really want is to shuffle the list such as this:

https://devforum.roblox.com/t/table-scrambling/13784/14

Then you’d just cycle through that shuffled list?

1 Like

Ill check it out. Ill try to rely on @BanTech’s first. Thanks tho!

Hey there, cool900s !

What i’d recommend you do, is quite simple, there are a few ways to make this work:

  1. as @Sir_Highness stated, try table scrambling
  2. another alternative would be making a repeat loop like @BanTech mentioned to make sure it does not select the same text. What i mean by that is something along the lines of this!
local latest

local function select()
	local selected -- declaring the variable
	repeat -- repeat loop begins
		selected = TextTable[math.random(1, #TextTable)] -- selects random item from the table
	until selected ~= latest -- loop ends once selected text isn't the same as the 'latest' variable's text
	return selected -- returns the text selected
end

local RandomTextLoop = coroutine.wrap(function()
	while LoadingAssetStatus == true do
		TextEnter1:Play()
		latest = select() -- selects the random text and marks it as latest.
		LoadingText2.Text = last
		wait(3)
		TextLeave1:Play()
		wait()
		TextEnter2:Play()
		latest = select()
        LoadingText1.Text = selected
		wait(3)
		TextLeave2:Play()
		wait()
	end
end)

Whilst this is the simplest way I’m aware of, there are probably better ways to execute this properly.
Nonetheless, I hope my trash explaining abilities and social anxiety didn’t ruin the point of this reply and helped, as this is my first proper reply to any dev forum post after literally a year of making stuff on roblox, lol.

There’s a function for math.random() called math.randomseed() that sets the seed for math.random(). You could do something like this:

local function random(n, iterations)
    iterations = iterations or 3
    math.randomseed(os.time() ^ 5)

    local total = 0
    for x = 1, iterations do
        total =+ math.random(n)
    end

    return math.clamp(math.floor(total / iterations), 0, n)
end)

-- usage:
array[random(#array)]

math.random() with only one argument makes 1 the lower boundary automatically. An alternative to math.random() is Random.new():

local random = Random.new()

-- usage:
array[random:NextInteger(1, #array)]

If you want to sort the table, here’s an easy way to do it:

local array = {} -- anything inside here
table.sort(array, function(a, b)
    return math.random() > 0.5
end)

-- math.random() without any arguments returns a decimal from 0 to 1

That would randomly sort the table. Lua uses the Quicksort algorithm for table.sort(), so it’s pretty efficient (O(N*log(N)) average, O(N) worst case).

Here’s a solution with the things myself and @BanTech have mentioned:

local random = Random.new()
local lastChosenIndex = 0

local function sort(array)
    math.randomseed(os.time() ^ 5)
    table.sort(array, function(a, b)
        return math.random() > 0.5
    end)
end

local function randomObject(array)
    sort(array)
    local index = lastChosenIndex
    local length = #array

    while index == lastChosenIndex do
        index = random:NextInteger(1, length)
    end

    lastChosenIndex = index
    return array[index]
end

-- usage
local array = {1, 3, 2, 4}
print(randomObject(array)) --> a random thing from the array
--// that wasn't picked last time

Keep in mind that this will only work for arrays. Anything without numeric keys won’t get selected by this (it’ll work for what you need). You can also use Random.new() in the sort function, using :NextNumber(0, 1) (to match what math.random() returns)

2 Likes