Displaying Strings in iOS Randomly Without Repeating Them

Displaying strings in iOS randomly without repeating them

If I understand your requirements correctly:

  • You want to persist the randomly generated numbers between View Controller instances and application launches
  • you never want to repeat any question

A quick way to achieve this is to use NSUserDefaults to keep track of the order and value of (pseudo)random numbers from your PRNG. This way, you can instantiate the array of avaiable questions on instantaition by replaying previous dice rolls, removing those questions from the pool alongside in the right order.

This also lets you handle the PRNG as a black box, not caring about seeding and replay.

Also, make sure to remove any chosen questions from the current pool for any dice roll.

Side note: You are not following naming conventions - functions are to be starting lower case, for example.

For your own good and readability, please follow prevalent conventions, at least when sharing your code with others. Better yet, all the time.

Edit:

To be more verbose:

  • NSUserDefaults can save small amounts of data for you in an easy way. If you 'just want to remember an array of numbers', it's the go to place.
  • suppose your data is helt in an instance variable like so:

    var questions : [Question] = // load the questions - carefully, see below.

    you can easily remove the question your PSNG (pseudo-random number generator) selects like so:

    let randomNumber = Int(arc4random_uniform(UInt32(questions.count)))
    questions.removeAtIndex(randomNumber)

    Thus the next dice roll (e.g. invocation of your PSNG) is guaranteed not to select the question already asked because it is no longer in the pool of avaiable questions it selects from.

  • This approach does need you to save all your random numbers in the right order to 'replay' what has happened before when you are instantiating a new instance (for example, because the app has been reopened). That's where NSUserDefaults' setObject:forKey: and objectForKey: come into play when loading the questions initially and 'remembering' every new dice roll.

I hope, this covers what you might didn't understand before.

Randomly choosing an item from a Swift array without repeating

Create an array of indexes. Remove one of the indexes from the array and then use that to fetch a color.

Something like this:

var colorArray = [
(UIColor.redColor(), "red"),
(UIColor.greenColor(), "green"),
(UIColor.blueColor(), "blue"),
(UIColor.yellowColor(), "yellow"),
(UIColor.orangeColor(), "orange"),
(UIColor.lightGrayColor(), "grey")]

var indexes = [Int]();

func randomItem() -> UIColor
{
if indexes.count == 0
{
print("Filling indexes array")
indexes = Array(0..< colorArray.count)
}
let randomIndex = Int(arc4random_uniform(UInt32(indexes.count)))
let anIndex = indexes.removeAtIndex(randomIndex)
return colorArray[anIndex].0;
}

The code above creates an array indexes. The function randomItem looks to see if indexes is empty. if it is, it populates it with index values ranging from 0 to colorArray.count - 1.

It then picks a random index in the indexes array, removes the value at that index in the indexes array, and uses it to fetch and return an object from your colorArray. (It doesn't remove objects from the colorArray. It uses indirection, and removes objects from the indexesArray, which initially contains an index value for each entry in your colorArray.

The one flaw in the above is that after you fetch the last item from indexArray, you populate it with a full set of indexes, and it's possible that the next color you get from the newly repopulated array will be the same as the last one you got.

It's possible to add extra logic to prevent this.

Display String From Array Randomly, only once, and change each day

You could update your plist to either remove the quote or set a flag as used then exclude those from being selected.

As far as when to mark one as used. I'm not sure everyday at midnight works with your model If its truly random then marking them as used at midnight doesn't make much sense since they may not open the app every day and would miss random quotes. Where as if it were ordered there would be a quote a day.

EDIT FROM OP:

In the AppDelegate didFinishLaunch I added this code:

NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];

if (! [defaults boolForKey:@"notFirstRun"]) {

[defaults setBool:YES forKey:@"notFirstRun"];

[defaults setInteger:0 forKey:@"verseKey"];
[defaults synchronize];
}
NSTimeInterval date = [defaults doubleForKey:@"startTimeInterval"];

NSTimeInterval dateNow = [NSDate timeIntervalSinceReferenceDate];

NSTimeInterval difference = dateNow - date;

difference = difference / 84000;

if(difference >= 0 && difference <= 1) {

}

if(difference >= 1 ) {
NSLog(@"ITSMORE");
NSInteger savedIndex = [[NSUserDefaults standardUserDefaults] integerForKey:@"verseKey"];
savedIndex +=1;
if (savedIndex == 200) {
[defaults setInteger:0 forKey:@"verseKey"];
dateNow = [NSDate timeIntervalSinceReferenceDate];
[defaults setDouble:dateNow forKey:@"startTimeInterval"];
[defaults synchronize];
}
else {
[defaults setInteger:savedIndex forKey:@"verseKey"];
dateNow = [NSDate timeIntervalSinceReferenceDate];
[defaults setDouble:dateNow forKey:@"startTimeInterval"];
[defaults synchronize];
}
}

I believe that this code should set the value of 0 for verseKey on firstRun and synchronize it with NSUserDefaults. Then, each time it is launched, it will see if more than 24 hours have passed. If it has, then it will add 1 to the key of verseKey until it hits 200 (I have a total of 200 quotes). Once 200 has been hit, it will reset it to 0. Then I set the TextView to objectAtIndex:key for verses, so that it will change. Sound about right?

Random number without repeat in swiftUI

This approach uses an extra observable class. It copies the 6 numbers into a temporary array. On tap one random number is removed from the array (this number is being displayed) so each number is only used once. If the array is empty the cycle starts over.

class Random : ObservableObject {
var array = [Int]()

@Published var randomNumber = 0

func next() {
if array.isEmpty { array = [1,2,3,4,5,6] }
let index = Int.random(in: 0..<array.count)
randomNumber = array.remove(at: index)
}
}

struct RanNum: View {

@StateObject private var random = Random()

var body: some View {
VStack{

Text(random.randomNumber == 0 ? "" : "\(random.randomNumber)")
.padding()
.multilineTextAlignment(.center)
.background(Color.white.opacity(0.5))
.cornerRadius(10)
.frame(width: 390, alignment: .center)

Button(action: {
random.next()
}) {
Image(systemName: "arrow.counterclockwise.circle.fill")
.foregroundColor(.black)
.font(.system(size: 30))
.padding()
}
}
}
}

Unity C# Cycling some texts without repeating them

You can remove the switch statement and store each message in a list.

var tips = new List<string>();
tips.Add("The clouds are white");
...

Then you can randomize the elements in the list (more on that here) and show tips one by one. All you need is to keep track of the index. Example:

// This needs to be a field.
int index = 0;

void ShowTip()
{
// TODO: make sure index is not equal or greater than tips.Count

tip = tips[index];
index++;

// Display the tip
}

Non repeating random numbers in iOS?

    NSMutableArray *storeArray = [[NSMutableArray alloc] init];    
BOOL record = NO;
int x;

for (int i=0; [storeArray count] < 10; i++) //Loop for generate different random values
{
x = arc4random() % 10;//generating random number
if(i==0)//for first time
{
[storeArray addObject:[NSNumber numberWithInt:x]];
}
else
{
for (int j=0; j<= [storeArray count]-1; j++)
{
if (x ==[[storeArray objectAtIndex:j] intValue])
record = YES;
}

if (record == YES)
{
record = NO;
}
else
{
[storeArray addObject:[NSNumber numberWithInt:x]];
}
}
}
NSLog(@" Non Repeated Random Numbers : %@",storeArray);

can u try this code may be it's use full to you

Randomly select 5 elements from an array list without repeating an element

You can do it like this:

let array1 = ["salmon", "turkey", "salad", "curry", "sushi", "pizza", "curry", "sushi", "pizza"]
var resultSet = Set<String>()

while resultSet.count < 5 {
let randomIndex = Int(arc4random_uniform(UInt32(array1.count)))
resultSet.insert(array1[randomIndex])
}

let resultArray = Array(resultSet)

print(resultArray)

A set can contain unique elements only, so it can't have the same element more than once.

I created an empty set, then as long as the array contains less than 5 elements (the number you chose), I iterated and added a random element to the set.

In the last step, we need to convert the set to an array to get the array that you want.

How to generate non repeating random numbers in ios?

Use arc4random()
Example:

- (NSData *)randomBytes:(size_t)count
{
NSMutableData *data = [NSMutableData dataWithLength:count];

SecRandomCopyBytes( kSecRandomDefault,
data.length,
data.mutableBytes);
return data;
}

It turns out that getting a random number in a range is not as simple as using mod.

- (u_int32_t)randomInRangeLo:(u_int32_t)loBound toHi:(u_int32_t)hiBound
{
u_int32_t random;
int32_t range = hiBound - loBound + 1;
u_int32_t limit = UINT32_MAX - (UINT32_MAX % range);

do {
random = arc4random();
} while (random > limit);

return loBound + (random % range);
}


Related Topics



Leave a reply



Submit