Search code examples
randomlualua-tablegarrys-mod

Getting one value from a table and assigning it to another with no repeats


Specifically, this is for Garry's Mod, however I don't think that matters too much in this problem. What I want to do is get one player, and set their value to another random player (so every player has a random 'target'). I want to do this with no repeats, and so that a player is not assigned to their self. To better illustrate:

Player assigning illustation.

The only difference to that picture is that I want each player to be assigned to another random player, so more like player1 => player 5, player 3 => player 2, etc.

Here is my code at the moment, however this always leaves one person unpicked:

validTargets = {}
TargetList = {}

local Swap = function(array, index1, index2)
    array[index1], array[index2] = array[index2], array[index1]
end

GetShuffle = function(numelems)
    local shuffle = {}
    for i = 1, numelems do
        shuffle[#shuffle + 1] = i
    end
    for ii = 1, numelems do
        Swap(shuffle, ii, math.random(ii, numelems))        
    end
    return shuffle
end

function assignTargets()
    local shuffle = GetShuffle(#playing)
    for k,v in ipairs(shuffle) do
        TargetList[k] = v
    end

    SyncTargets()
end

function SyncTargets()
    for k,v in pairs(TargetList) do
        net.Start("sendTarget")
            net.WriteEntity(v)
        net.Send(k)
    end
end

Solution

  • I have a lua function that generates a Random shuffle of numbers from 1 to n, given n. The method is based on a popular algorithm to generate a random permutation of an array of elements .

    You can try using that like so:

    local Swap = function(array, index1, index2)
        array[index1], array[index2] = array[index2], array[index1]
    end
    
    
    GetShuffle = function(numelems)
        local shuffle = {}
        for i = 1, numelems do
            shuffle[#shuffle + 1] = i
        end
        for ii = 1, numelems do
            Swap(shuffle, ii, math.random(ii, numelems))        
        end
        return shuffle
    end
    
    function assignTargets()
        local shuffle = GetShuffle(#playing) --assuming `playing` is a known global
        for k,v in ipairs(shuffle) do
            TargetList[k] = v
        end
    end