2017-09-23 2 views
1

Mon code génère déjà une chaîne aléatoire d'un tableau lorsque j'appuie sur un bouton, mais parfois une chaîne est répétée. Que dois-je faire pour que la chaîne "Mango" ne soit appelée à nouveau que lorsque toutes les autres chaînes ont déjà été appelées sans utiliser de shuffle, je veux appeler une chaîne à la fois?Générer des chaînes aléatoires sans mélanger et répéter les précédents?

Exemple: "Mango", "Kiwi", "banane", "ananas", "melon", "Mango", "Kiwi", .....

Voici mon code:

var array = ["Mango", "Banana", "Apple","Kiwi", "Melon", "Pineapple"] 

let fruits = Int(arc4random_uniform(UInt32(array.count))) 

print(array[fruits]) 
+1

double possible de [sélectionner aléatoirement 5 éléments à partir d'une liste de réseau sans répéter un élément] (https://stackoverflow.com/questions/45132047/randomly-select-5-elements-from-an-array- list-without-repeating-an-element) – Lukas

+0

non, j'ai déjà vu ça. Je ne veux pas imprimer toute la liste avec un shuffle.Je ne veux appeler qu'un seul @lukvol –

+1

Pourquoi ne voulez-vous pas utiliser un shuffle? – rmaddy

Répondre

0

Afin d'éviter les répétitions, vous devez savoir quels fruits ont déjà été observés. Il y a plusieurs façons de faire que toutes les solutions proposées le font d'une manière ou d'une autre.

Pour votre cas d'utilisation spécifique, vous aurez besoin que ce suivi soit conservé en dehors du code exécuté par le bouton (dans votre contrôleur de vue par exemple).

Voici une structure générale qui pourrait aider à ceci: (vous pouvez définir à l'intérieur du contrôleur de vue si cela est une chose unique ou à l'extérieur de celui-ci si vous avez l'intention de réutiliser le mécanisme ailleurs)

struct RandomItems 
{ 
    var items : [String] 
    var seen = 0 

    init(_ items:[String]) 
    { self.items = items } 

    mutating func next() -> String 
    { 
    let index = Int(arc4random_uniform(UInt32(items.count - seen))) 
    let item = items.remove(at:index) 
    items.append(item) 
    seen = (seen + 1) % items.count 
    return item 
    } 
} 

pour l'utiliser, vous déclarez une variable (dans votre CV) qui gardera la trace de vos fruits:

var fruits = RandomItems(["Mango", "Banana", "Apple","Kiwi", "Melon", "Pineapple"]) 

Et dans l'utilisation du code du bouton variable (fruits) pour imprimer un fruit non-répétition nom à chaque exécution

func buttonPressed() // <- use your function here 
{ 
    print(fruits.next()) 
} 
+0

Merci @AlainT. ça a finalement marché –

0

Vous devez implémenter une certaine logique. C'est assez facile si vous pensez plus fort. Exécutez ceci dans votre Playground, ou si vous comprenez parfaitement ce bloc de code, vous pouvez déjà le faire dans votre projet.

var array = ["Mango", "Banana", "Apple","Kiwi", "Melon", "Pineapple"] 
var selectedIndices = [Int]() 

for _ in 1...20 { 

    let randomFruitIndex = Int(arc4random_uniform(UInt32(array.count))) 

    // Print only if not yet printed once 

    if !selectedIndices.contains(randomFruitIndex) { 
     print(array[randomFruitIndex]) 
     selectedIndices.append(randomFruitIndex) 
    } 

    // Reset 

    if selectedIndices.count == array.count { 
     print("----- CLEARING SELECTED INDICES----") 
     selectedIndices.removeAll() 
    } 
} 

Comme vous pouvez le voir, nous ajoutons chaque produit de nombres aléatoires (dans votre cas, il est la variable fruits.) Dans un tableau de Int. Ensuite, si le nombre de selectedIndices est égal au nombre de fruits array, effacez tous les selectedIndices stockés.

SORTIE:

Pineapple 
Melon 
Mango 
Kiwi 
Banana 
Apple 
----- CLEARING SELECTED INDICES---- 
Mango 
Melon 
+0

La sortie devrait ressembler à: Mango // Et si l'utilisateur clique sur le bouton le prochain fruit s'appelle @Glenn –

0

Ceci est une adaptation de la réponse acceptée du sujet lié à mon commentaire:

var source = ["Mango", "Banana", "Apple","Kiwi", "Melon", "Pineapple"] 
var usedElements = [String]() 

func choosePseudoRandomElement() -> String { 
    if source.count == 0 { 
     source = usedElements 
     usedElements = [] 
    } 

    let randomIndex = Int(arc4random_uniform(UInt32(source.count))) 
    let randomItem = source[randomIndex] 
    usedElements.append(randomItem) 
    source.remove(at: randomIndex) 

    return randomItem 
} 

for _ in 1...18 { 
    print("Item: \(choosePseudoRandomElement())") 
} 

Un problème potentiel avec cette solution est qu'il peut arriver que le le dernier élément d'une itération complète se produit également en tant que premier élément de la deuxième itération. Vous pouvez gérer ce cas en comparant l'élément choisi au hasard avec l'élément qui a été choisi auparavant (utilisez une boucle while jusqu'à ce que les éléments ne correspondent plus). En outre, cela supprime des éléments du tableau source. Si vous ne le souhaitez pas, créez une copie du tableau source.

+0

Maintenant, je reçois 18 fruits imprimés I, il devrait être juste un @lukvol –

+0

Vous pouvez ignorer la boucle for à la fin. Il suffit d'appeler choosePseudoRandomElement et d'imprimer le résultat chaque fois que vous avez besoin d'un autre élément. – Lukas

+0

comment puis-je appeler le résultat @lukvol –