tags:

views:

26

answers:

1

Hi,

I am building a simple game for 2-4 players in Cocoa. This is my first Cocoa app, so not being familiar with the libraries, I am probably doing a lot of weird things. If you see anything that could be done better, just say so.

The first step requires user to choose number of players from NSPopUp and that data is pulled into an int. I create an array and loop in a number of player objects.

- (IBAction)startGame:(id)sender {

// Get value of playersPopup into a string
NSString *playersReturn = [[NSString alloc] initWithString:[playersPopup titleOfSelectedItem]];

// Convert that string to an int
numberOfPlayers = [playersReturn intValue];

// Create an array
playerArray = [[NSMutableArray alloc] init];

// Create a counter
int i = 0;

// While counter is less than number of players, create player object and add to array
while (i < numberOfPlayers) {

    // Create a player object
    Player *player = [[Player alloc] init];

    // Add player to array
    [playerArray addObject:player];

    // Increment
    i++;

} 

}

It's a bit weird because all the objects have the same name. I'm not sure how to programmatically give the objects a title using the counter like player1, etc, but its easy enough to pull them by key from the array with objectAtIndex. That would be part 1 of my question: in Cocoa how do I use the counter in naming the objects? Because from what I gather if I did:

player *player[i] = 

it would create arrays of that object when all I want to do is call it player1 etc.

Second question is: I have another view where, after the player objects are created, user sees NSTextFields to input names for the players. Given that I should declare the IBOutlets in the AppDelegate, I'm not sure how to provide for a range 2-4 players. I can declare all 4 outlets and just use two, and then just programmatically hide unused textfields. But it seems like there ought to be a way to just create the outlets and view objects based on how many players has been selected. I mean I have that int for the whole AppDelegate so I should use it somehow.

If someone wouldn't mind pointing me a good direction, that would be awesome! I really enjoy programming in Cocoa, but it's kind of a different world at this point. I knew there would be a learning curve, but it's just really different from .net!

Thanks guys!

-Alec

A: 

It's a bit weird because all the objects have the same name. I'm not sure how to programmatically give the objects a title using the counter like player1, etc, but its easy enough to pull them by key from the array with objectAtIndex. That would be part 1 of my question: in Cocoa how do I use the counter in naming the objects?

You don't. Except for a few classes that provide API specifically for naming the object (e.g., NSThread), there is no way to name an object.

What you're talking about is declaring variables, which hold pointers to objects. These variables are separate from the objects themselves; you can even have multiple variables all pointing to the same object. Naming a variable does not affect anything about the object it may point to.

Because from what I gather if I did:

player *player[i] = 

it would create arrays of that object when all I want to do is call it player1 etc.

No, it would declare a variable named player as holding a C array of i pointers to player objects. It would also be hairy if not invalid, since you're using the name player for two different things (a class and a pointer variable).

Suppose you got your wish, and could create a bunch of variables named player0, player1, player2, etc. How would you work with all of them? More to the point, how would you work with each of them? How would you give each view a different player? How would you lay out each view into a different place? How would you send messages to a single specific view that needs updating?

The correct solution to your problem is a second NSMutableArray: This one, of views. Put the views into that array just as you put the model objects into the players array. You can maintain the arrays such that each index refers to a model object in one array and the corresponding view in the other array—so, for example, if you receive an action message, you'd look up the index for that view in the views array, then get the model object by that index in the players array to respond to the action.

A more robust variation of that solution, but also more work, would be to loop over the array of views searching for one that has a specific player. This solution wouldn't require them to have the same order, and would enable you to handle the (shouldn't-happen) case of a player view whose player has gone missing from the model array. But, as I said, it's more work—both for you and for the program (i.e., it's slower). I'd probably just do the parallel array.

I mean I have that int for the whole AppDelegate so I should use it somehow.

You don't need it.

For one thing, it's the wrong type. The correct type for indexes into and counts of NSArrays is NSUInteger.

More importantly, once you have added all the players, that number contains the number of players. You can obtain that information almost as easily by sending the players array a count message. If you maintain separate knowledge of how many players you have, it's one more thing that can go wrong, by your adding or removing a player and forgetting to update your own count variable.

Cut out that variable. When you need to know how many players you have, just ask the array.

As for limiting how many players you add: Copy the number of players to a local variable, and count it down. When it reaches zero, you've added all the players you need to. Alternatively, you could cut that out, too, add two players to start with, and enable the user to add as many other players as they want.

Peter Hosey
Thank you so much. Really, this is above and beyond anything I expected. First of all, thank you for clarifying about naming variables. I was in the dark but you're explanation clears that up. In fact, in trying to pull strings from the view and into the model, I stumbled upon the approach of using two corresponding arrays. In this particular case, it was just an array of strings that was released after being looped into the model. Having an array of views makes perfect sense, and obviously this negates a need for having unique variable names since they are meant have corresponding keys...
Alec Sloman
What I don't get is how I would eliminate the numberofPlayers variable pre creating the player objects. I have to pull something in from the view, otherwise the while loop that creates the player objects and sticks them into the array wouldn't know when to stop. I can see using [playerArray count] after I've created the objects, but how can I get rid of it before the array has been populated?Also, I like the last approach and just create two players straight off the bat, then let them add other players later. That seems good design and code-wise. Thanks again Peter.
Alec Sloman
Starting with 2 players cleans up the code tremendously btw. Thanks for that.
Alec Sloman
Just realized I didn't need the NSPopUp box anymore. So that's how I will get rid of the variable. Cool :)
Alec Sloman