0

I am trying to create a simple app that allows you to pick a card from a deck. What I need it to do is to not repeat the same card. I've looked all over the internet and it isn't very clear to me how to do this.

Here is the code I have right now:

-(IBAction) randomize: (id)sender {

    int randomcards = rand() % 53 + 1;
    switch (randomcards) {
        case 0:
            imageview.image = [UIImage imageNamed:@"1.png"];
            break;
        case 1:
            imageview.image = [UIImage imageNamed:@"2.png"];
            break;
        case 2:
            imageview.image = [UIImage imageNamed:@"3.png"];
            break;
        case 3:
            imageview.image = [UIImage imageNamed:@"4.png"];
            break;
        case 4:
            imageview.image = [UIImage imageNamed:@"5.png"];
            break;
        case 5:
            imageview.image = [UIImage imageNamed:@"6.png"];
            break;
        case 6:
            imageview.image = [UIImage imageNamed:@"7.png"];
            break;
        case 7:
            imageview.image = [UIImage imageNamed:@"8.png"];
            break;
        case 8:
            imageview.image = [UIImage imageNamed:@"9.png"];
            break;
        case 9:
            imageview.image = [UIImage imageNamed:@"10.png"];
            break;
        case 10:
            imageview.image = [UIImage imageNamed:@"11.png"];
            break;
        case 11:
            imageview.image = [UIImage imageNamed:@"12.png"];
            break;
        case 12:
            imageview.image = [UIImage imageNamed:@"13.png"];
            break;
        case 13:
            imageview.image = [UIImage imageNamed:@"14.png"];
            break;
        case 14:
            imageview.image = [UIImage imageNamed:@"15.png"];
            break;
        case 15:
            imageview.image = [UIImage imageNamed:@"16.png"];
            break;
        case 16:
            imageview.image = [UIImage imageNamed:@"17.png"];
            break;
        case 17:
            imageview.image = [UIImage imageNamed:@"18.png"];
            break;
        case 18:
            imageview.image = [UIImage imageNamed:@"19.png"];
            break;
        case 19:
            imageview.image = [UIImage imageNamed:@"20.png"];
            break;
        case 20:
            imageview.image = [UIImage imageNamed:@"21.png"];
            break;
        case 21:
            imageview.image = [UIImage imageNamed:@"22.png"];
            break;
        case 22:
            imageview.image = [UIImage imageNamed:@"23.png"];
            break;
        case 23:
            imageview.image = [UIImage imageNamed:@"24.png"];
            break;
        case 24:
            imageview.image = [UIImage imageNamed:@"25.png"];
            break;
        case 25:
            imageview.image = [UIImage imageNamed:@"26.png"];
            break;
        case 26:
            imageview.image = [UIImage imageNamed:@"27.png"];
            break;
        case 27:
            imageview.image = [UIImage imageNamed:@"28.png"];
            break;
        case 28:
            imageview.image = [UIImage imageNamed:@"29.png"];
            break;
        case 29:
            imageview.image = [UIImage imageNamed:@"30.png"];
            break;
        case 30:
            imageview.image = [UIImage imageNamed:@"31.png"];
            break;
        case 31:
            imageview.image = [UIImage imageNamed:@"32.png"];
            break;
        case 32:
            imageview.image = [UIImage imageNamed:@"33.png"];
            break;
        case 33:
            imageview.image = [UIImage imageNamed:@"34.png"];
            break;
        case 34:
            imageview.image = [UIImage imageNamed:@"35.png"];
            break;
        case 35:
            imageview.image = [UIImage imageNamed:@"36.png"];
            break;
        case 36:
            imageview.image = [UIImage imageNamed:@"37.png"];
            break;
        case 37:
            imageview.image = [UIImage imageNamed:@"38.png"];
            break;
        case 38:
            imageview.image = [UIImage imageNamed:@"39.png"];
            break;
        case 39:
            imageview.image = [UIImage imageNamed:@"40.png"];
            break;
        case 40:
            imageview.image = [UIImage imageNamed:@"41.png"];
            break;
        case 41:
            imageview.image = [UIImage imageNamed:@"42.png"];
            break;
        case 42:
            imageview.image = [UIImage imageNamed:@"43.png"];
            break;
        case 43:
            imageview.image = [UIImage imageNamed:@"44.png"];
            break;
        case 44:
            imageview.image = [UIImage imageNamed:@"45.png"];
            break;
        case 45:
            imageview.image = [UIImage imageNamed:@"46.png"];
            break;
        case 46:
            imageview.image = [UIImage imageNamed:@"47.png"];
            break;
        case 47:
            imageview.image = [UIImage imageNamed:@"48.png"];
            break;
        case 48:
            imageview.image = [UIImage imageNamed:@"49.png"];
            break;
        case 49:
            imageview.image = [UIImage imageNamed:@"50.png"];
            break;
        case 50:
            imageview.image = [UIImage imageNamed:@"51.png"];
            break;
        case 51:
            imageview.image = [UIImage imageNamed:@"52.png"];
            break;
        case 52:
            imageview.image = [UIImage imageNamed:@"53.png"];
            break;
        case 53:
            imageview.image = [UIImage imageNamed:@"54.png"];
            break;
    }

Can anyone give me some clear instructions on how to stop the same card coming up twice before the deck has run out? I would be greatly appreciated.

mmmmmm
  • 32,227
  • 27
  • 88
  • 117
  • Nor directly related to the question but all the switches are imageview.image = [UIImage imageNamed:@":number.png"]; better to derive the file name from the id – mmmmmm Nov 18 '12 at 14:49

3 Answers3

4

Rather than picking random cards, allocate all of your cards into an array, then shuffle the array. After that you can iterate through the array resulting in a random selection of cards.

See this SO question whats-the-best-way-to-shuffle-an-nsmutablearray

Look at Gregory Goltsov's answer that uses arc4random_uniform()

Community
  • 1
  • 1
Peter M
  • 7,309
  • 3
  • 50
  • 91
1

Pre-load an array with the names of all your images (or whatever you use to indicate a unique card).

For each card: calculate the random number based on the number of cards remaining in the array, select the card, remove its reference from the array.

Phillip Mills
  • 30,888
  • 4
  • 42
  • 57
  • Hi, thanks for the help, I am not unsure how to create an array for the app. I'm pretty new to xCode and I assumed this would have a simple fix. Is there anywhere I can find tutorials to make arrays and random image selections without repeats? – user1833648 Nov 18 '12 at 14:43
  • If you need help with creating arrays, you need to read about the basics of Objective-C. Otherwise, you'll be endlessly frustrated by copying and pasting stuff you don't understand. (http://developer.apple.com/library/ios/#documentation/cocoa/conceptual/ProgrammingWithObjectiveC/FoundationTypesandCollections/FoundationTypesandCollections.html) – Phillip Mills Nov 18 '12 at 14:48
  • @user1833648 - XCode is a IDE you are writing Objective C which you can do in other ways. Your question is nothing to do with XCode – mmmmmm Nov 18 '12 at 14:51
0

The easiest way to do this, as others have pointed out, is to make an array of the names of your images and remove names you've already used. Here's an example. Declare a property like this in your header.

@property (strong, nonatomic) NSMutableArray *availableCards;

Synthesize it at the top of your implementation.

@synthesize availableCards = _availableCards;

Make a convenience method to let you initialize it/reset it.

- (void) resetAvailableCards {
    NSMutableArray *resetArray = [[NSMutableArray alloc] init];
    //the temporary array to store what we'll set our property to at the end

    for (int i = 1; i < 55; ++i){//for every card in the deck
        NSString* imageName = [NSString stringWithFormat:@"%d.png",i];//make the image name
        [resetArray addObject:imageName];//store it in the array
    }

    self.availableCards = resetArray;//set our property to the array
}

Call it in your controller's viewDidLoad to initialize state.

[self resetAvailableCards];

You can also call it whenever you need to make all the cards available again. Now, for your original method.

- (IBAction) randomize: (id) sender {
    int cardIndex = arc4random() % [self.availableCards count];//random number within the bounds of the array; no need to add 1 as count is 1 higher than highest available index
    NSString* cardImageName = [self.availableCards objectAtIndex: cardIndex];//get the name of the card we chose
    imageview.image = [UIImage imageNamed: cardImageName];//set the image
    [self.availableCards removeObjectAtIndex:cardIndex];//remove the card name so we can't get it again
    return;
}

Notice I used arc4random instead of rand. It has twice the effective range and it tends to give a better distribution as well as doesn't need to be seeded. If you want to use rand effectively, you'd need to seed it with the time or something using srand. I also recommend you remove the sender argument from the action as it's not used, although you'd have to change that in other places too, so you might want to leave it in.

Just wondering, but what IS imageview? Since you don't use self.imageview, is it an ivar? Is it a property and you forgot to use dot notation and are directly accessing the ivar backing it? Either way, you should declare that as a property/outlet of some sort and access it through accessors.

Metabble
  • 11,773
  • 1
  • 16
  • 29