Создать генератор случайных чисел без повторного повторения последнего, сгенерированного On swift (xcode)

Привет всем, я пытался создать игру в течение нескольких недель, однако я не могу создать функцию, которая все время случайным образом воспроизводит новую функцию, не повторяя ту же функцию, в которую она только что играла раньше.

Я использовал следующий скрипт для создания случайной функции для воспроизведения.

func playgame(){   
var randomgen = arc4random % 6                   
switch(randomgen){             
case 0:          
 game1()        
break      
case 1:   
 game2()   
break  
case 2:    
 game3()  
 break  
case 3:  
 game4()  
break  
case 4:   
 game5()  
 break  
case 5:   
 game6()   
 break   
default:    
 break     
  }    

Когда игрок нажимает кнопку, функция снова запускается, генерируя случайную функцию игры.
Как я могу сгенерировать случайную игру, не создавая ту же игру, которая была сгенерирована до этого.
Например: если game1() была сгенерирована и Я нажимаю кнопку следующей игры. Я хочу сгенерировать случайную игру из других 5 доступных игр. Идея состоит в том, чтобы иметь возможность играть в шесть игр бесконечно.


person Cristian Siles    schedule 11.08.2015    source источник
comment
Сохраните текущую игру в переменной. Когда будет выбрана следующая игра, и randomgen совпадет с последней игрой, снова вызовите arc4random, поместите это в цикл while, чтобы, если совпадений больше, он продолжал вызывать.   -  person zaph    schedule 11.08.2015


Ответы (2)


Я бы рекомендовал создать NSArray из всех игр, затем случайным образом выбрать одну из игр из индекса NSArray, удалить рандомизированную игру, чтобы в следующий раз она случайным образом выбрала любую из оставшихся игр в NSArray.

Это единственный способ убедиться, что это не повторится. Вы можете управлять рандомайзером, используя засеянную версию, но это дает вам возможность сделать ее повторяемой.

Этого легко добиться, создав категорию NSArray:

- (id) randomARC4Element
{
    if(self.count > 0)
    {
        return [self objectAtIndex:[self randomIntBetweenMin:0 andMax:self.count-1]];
    }

    return nil;
}

- (int)randomIntBetweenMin:(int)minValue andMax:(int)maxValue
{
    return (int)(minValue + [self randomFloat] * (maxValue - minValue));
}

- (float)randomFloat
{
    return (float) arc4random() / UINT_MAX;
}

После того, как все игры сыграны, вы можете просто воссоздать массив.

Если вы хотите рандомизировать игру, просто убедившись, что только последняя не будет повторяться, я бы рекомендовал сохранить последние рандомизированные элементы, создать NSArray всех элементов, удалить последний рандомизированный элемент и рандомизировать любой из элементов из такого массива - то есть гарантировать результат только после одной итерации рандомизации.

person Grzegorz Krukowski    schedule 11.08.2015
comment
Если вам нужно, я поделился некоторыми утилитами случайных чисел, которые упрощают iOS API. Также позволяет использовать генераторы заполнения: github.com/grzegorzkrukowski/random-utils - person Grzegorz Krukowski; 12.08.2015

Сделайте цикл while для проверки последней игры.

var lastGame = -1

func playGame() {

    var randomgen = 0

    repeat {
        randomgen = arc4random % 6
    } while (randomgen == lastGame)

    lastGame = randomgen

    switch randomgen {
        case 1: game1()
        case 2: game2()    
        /* ... */
        default:
    }
}  

Избегание сценария бесконечного цикла в некоторых случаях. Но также нуждается в доработке в случае, если lastGame превышает количество ваших игр

var lastGame = -1

func playGame() {

    var randomgen = 0
    var counter = 0
    let limit = 10

    repeat {
        randomgen = arc4random % 6
        counter++
    } while (randomgen == lastGame && counter < limit)

    if counter == limit {
        randomgen = lastGame + 1
    }

    lastGame = randomgen

    switch randomgen {
        case 1: game1()
        case 2: game2()    
        /* ... */
        default:
    }
}
person Andrew Luca    schedule 11.08.2015
comment
Я бы не рекомендовал повторять при случайном достижении заданного значения - в худшем случае это может стать бесконечным циклом. - person Grzegorz Krukowski; 11.08.2015
comment
Добавление счетчика должно избавиться от бесконечного цикла. Я добавлю этот сценарий к этому ответу - person Andrew Luca; 11.08.2015
comment
Да, это просто теоретически возможно, но в целом зацикливание до тех пор, пока рандомизатор не получит желаемое значение, на мой взгляд, не лучший подход. Особенно, если, например, позже вы захотите рандомизировать элемент только один раз и сохранить результаты в массиве - тогда рандомизация последнего элемента может занять некоторое время, в зависимости от количества данных. - person Grzegorz Krukowski; 11.08.2015
comment
Я бы по-прежнему рекомендовал хранить все игры в NSArray, сохраняя последнюю рандомизированную игру. Затем создайте копию NSArray, удалите последнюю рандомизированную игру и рандомизируйте любые другие элементы из массива. Это просто гарантия результатов после одной итерации рандомизатора. - person Grzegorz Krukowski; 11.08.2015
comment
Теперь я понял идею. Буду иметь в виду на будущее, пригодится. Спасибо - person Andrew Luca; 11.08.2015