views:

268

answers:

4

Ok, I'm going to try to make this more clear because my last question was extremely confusing. I've included a picture this time. Each one of these circles is a UIImageView and they are each assigned a random image which is one of 7 colors. So each circle could be one of 7 colors. I want to make it so that the user has to hit the circles in order of a pre-determined order according to color. For example, blue, green, yellow, pink, purple, orange, red. My HUGE problem is that I can't seem to figure out how to determine whether or not a color that isn't supposed to be hit got hit. Is there a way to assign multiple image views the same value and then somehow have an if statement that says....

if(a blue circle is hit && ANY ORANGE CIRCLE IS STILL IN VIEW){
do something
}

The only way I know how to code this would be an insane amount of code, because of all the random images being assigned.

    bluebubble = [UIImage imageNamed:@"bluebubble.png"];
    greenbubble = [UIImage imageNamed:@"greenbubble.png"];
    redbubble = [UIImage imageNamed:@"redbubble.png"];
    yellowbubble = [UIImage imageNamed:@"yellowbubble.png"];
    orangebubble = [UIImage imageNamed:@"orangebubble.png"];
    pinkbubble = [UIImage imageNamed:@"pinkbubble.png"];
    purplebubble = [UIImage imageNamed:@"purplebubble.png"];


    image1 = arc4random()%7;

    if(image1 == 0){
        [test setImage:bluebubble];
    }
    else if(image1 == 1){
        [test setImage:greenbubble];
    }
    else if(image1 == 2){
        [test setImage:redbubble];
    }
    else if(image1 == 3){
        [test setImage:yellowbubble];
    }
    else if(image1 == 4){
        [test setImage:orangebubble];
    }
    else if(image1 == 5){
        [test setImage:pinkbubble];
    }
    else if(image1 == 6){
        [test setImage:purplebubble];
    }

    image2 = arc4random()%7;

    if(image2 == 0){
        [test2 setImage:bluebubble];
    }
    else if(image2 == 1){
        [test2 setImage:greenbubble];
    }
    else if(image2 == 2){
        [test2 setImage:redbubble];
    }
    else if(image2 == 3){
        [test2 setImage:yellowbubble];
    }
    else if(image2 == 4){
        [test2 setImage:orangebubble];
    }
    else if(image2 == 5){
        [test2 setImage:pinkbubble];
    }
    else if(image2 == 6){
        [test2 setImage:purplebubble];
    }

alt text

A: 

Yes, you can set the image property of UIImageView to the same UIImage. In fact, you are already doing this!

The imageNamed: class method will return a reference to the same object when called again with the same image file name.

However, you should get the four UIImage references once and then use those. You should also use an array and loop or at least a function to make this code shorter and simpler.

Actually, it sounds like you will want your four UIImage references to be instance variables so that you can compare the image property of tapped UIImageView objects against them later.

gerry3
i updated my code with a picture and some more code. i get the references once now, but i still don't know how to check if an image still exists within an image view?
NextRev
You should probably have a data model that keeps track of the game state so that you can apply any logic as needed.
gerry3
A: 

If your purpose is simply the if clause, then what I would do is to define two dictionaries with the key as the color and the values as the arrays of burbles with the value be the location of the burble.

NSDictionary *hitDictionaryOfBurbles;
NSDictionary *notCurrentlyBeingHitDictionaryOfBurbles;

With this dictionary defined, you have with you all the items of all colors currently not being hit. You can then easily check this dictionary the value of the array of Orange color to see how many items there are.

Offcourse, once the burble is being hit, you should change the value of these two dictionaries to reflect the change.

Es.

hitDictioanryOfBurbles: 
        "blue", [0,7,13]
        "green", [2,6,16]
         etc...
notCurrentlyBeingHitDictioanryOfBurbles: 
        "blue", [25,33,37]
        "green", [19,27,29]
         etc...

If you have other logic to support, then you should define more data structures.

sfa
A: 

Are you always going to be hitting these in a certain order, one after the other, where only one color is valid at a time? If so, you can create a stack of UIImages (I don't think there's a built-in stack data type, but you can simulate it easily with NSMutableArray) consisting of the colors in order.

You also keep track of all the color-circle subviews on the screen in a separate NSMutableArray. Then, whenever a user hits a circle, execute the following code:

if(hitImageView.image == [imageStack peek]) {
    //"hit the right one" logic

    //you hit it, so remove it from the screen
    [allImageViews removeObject:hitImageView];
    [hitImageView removeFromSuperView];

    //if it was the last imageview of the "correct" color...
    BOOL wasLast = YES;

    for(UIImageView *imageView in allImageViews) {
        if(imageView.image == [imageStack peek]) {
            wasLast = NO;
            break;
        }
    }

    //...then set the correct color to whatever is next
    if(wasLast)
        [imageStack pop];

    if(![imageStack hasItems])
       ;//"won the game" logic

}
else {
    //"hit the wrong one" logic
}

(This is O(N) for determining remaining circles, but if you're dealing with such a small set then it really doesn't matter. If you needed to optimize it, you could of course keep track of the remaining counts of each color.)

On another note, you'll be a much happier person if, instead of using that gigantic if-else block to identify the correct color, you just name the files color1.png, color2.png, etc. and say [UIImage imageNamed:[NSString stringWithFormat:@"color%i.png", randNum]];

Ian Henry
A: 

I think it's also wise to create a more reasonable way to assign the different color images to your image views, so this solution does both.

These Should be declared in the header of the class

NSArray *allCircleImagesViews; // These are suppose to be the onscreen UIImagesViews 

NSArray *circlesByColor;
NSMutableArray *correctCircles; // The current circles the user is allowed to click
NSArray *colorOrder; // The order of the colors to click
int currentColorIndex; // The current index in the order of colors

Now for the functions: The first one creates assign the different color images, sets the correct order of the colors, and sets the mechanism to determine if the correct color was clicked

- (void) populateImages
{
    NSArray *images = [NSArray arrayWithObjects:
                       [UIImage imageNamed:@"bluebubble.png"],
                       [UIImage imageNamed:@"redbubble.png"],
                       [UIImage imageNamed:@"yellowbubble.png"],
                       [UIImage imageNamed:@"greenbubble.png"],
                       [UIImage imageNamed:@"orangebubble.png"],
                       [UIImage imageNamed:@"pinkbubble.png"],
                       [UIImage imageNamed:@"purplebubble.png"],
                       nil];

    NSArray *circlesByColor=[NSArray arrayWithObjects:
                             [NSMutableArray array],
                             [NSMutableArray array],
                             [NSMutableArray array],
                             [NSMutableArray array],
                             [NSMutableArray array],
                             [NSMutableArray array],
                             [NSMutableArray array],
                             nil];
    [circlesByColor retain];

    // Assign images to circles and set the 
    for (UIImageView *currCircle in allCircleImagesViews)
    {
        int nextIndex = arc4random()%7; 
        currCircle.image = [images objectAtIndex:0];
        [(NSMutableArray *)[circlesByColor objectAtIndex:nextIndex] addObject:currCircle];
    }

    // Set the correct order
    NSArray *colorOrder = [NSArray arrayWithObjects:
                  [NSNumber numberWithInt:5], // Pink
                  [NSNumber numberWithInt:0], // Blue 
                  [NSNumber numberWithInt:1], // etc.
                  [NSNumber numberWithInt:4],
                  [NSNumber numberWithInt:2],
                  [NSNumber numberWithInt:3],
                  [NSNumber numberWithInt:6],nil];
    [colorOrder retain];

    currentColorIndex = 0;            
    correctCircles = [circlesByColor objectAtIndex:[[colorOrder objectAtIndex:currentColorIndex] intValue]];
}

The following function takes care of checking if the correct circle was clicked

- (void) checkCircle:(UIImageView *)clickedImageView
{
    BOOL result;

    if ([correctCircles containsObject:clickedImageView])
    {
        [correctCircles removeObject:clickedImageView];
        result = YES;
    }
    else {
        result =  NO;
    }


    if ([correctCircles count] == 0)
    {
        currentColorIndex++;
        if (currentColorIndex < 7)
            correctCircles = [circlesByColor objectAtIndex:[[colorOrder objectAtIndex:currentColorIndex] intValue]];
        else
            correctCircles = nil;
    }

    if (!result)
    {
        // Wrong circle clicked logic
    }
    else {
        if (!correctCircles)
        {
            // Game won logic
        }
        else {
            // Correct circle clicked logic
        }

    }

}
Ron Srebro
`circlesByColor` contains a bunch of arrays that will leak. They are do `init` (retain count 1), then are retained by the `circlesByColor` array (retain count 2). When `circlesByColor` is released, the arrays are released too (retain count 1), and you no longer have a reference to them and it leaks. Those arays should be created like this: `[NSMutableArray array]`
Squeegy
Nice catch. Thanks. Will edit.
Ron Srebro