I am creating a local multiplayer text based game that could involve up to an unlimited number of players. I have created an array to hold all the players names that are inputed by the user on the launch of the app. However I am having problems trying to work out how to display the array index by index and then repeat on its self such as
player 1 turn
player 2 turn
player 1 turn
player 2 turn
player 1 turn
And so forth until all questions have been asked (think of a quiz game)
So far I have come up with this but its not doing the job
int i;
int count;
for (i = 0, count = [_players count]; i < count; i = i + 1)
{
NSString *element = [_players objectAtIndex:i];
self.turnlabel.text =( i, element);
NSLog(#"The element at index %d in the array is: %#", i, element);
}
Previously when I was working without and array I used a simple if statement that checked the value of a string and counted how many times its been shown and then added to this and and if the value was less than the previous string the app determined it was the other players turn. However now I am working with an array I cant seem to work out how to do this.
Basically how would I go about showing each index in array in turn and then repeating until the game ends?
EDIT
The game ends when it runs out of questions that I am generating from a plist.
Each player will take it in turns so player 1 then player 2 then player 3 and then back to player 1 and player 2 and so forth. They will be asked one question at a time.
Sorry in advance if this is a very basic question I'm very very new to Xcode my first week now.
What you probably want to do is hold a reference to the current player. Then loop through the questions. If player gets them correct, continue to next question, if player gets it wrong, then increment the player reference. Do a check when you increment the player to see if it's necessary to go back to player #1.
So, for example:
NSArray *playerArray = #[#"Player 1", #"Player 2", #"Player 3"];
NSUInteger currentPlayerIndex = 1;
Player then has his turn, if he gets it incorrect,
currentPlayerIndex++;
Then check:
if (curentPlayerIndex >= playerArray.count) {
currentPlayerIndex = 0;
}
Hope this helps.
Related
I am having trouble getting objects added to my NSMutableArray to log properly (which definitely means they won't process any of the appropriate functions correctly) with Spritebuilder [version 1.4.9, from the Apple App Store]. I am creating several objects using the same class, but each new one is overriding the older objects which exist. I thought an array would help keep things in order (and then on collision, I could call the array to check for which object was collided with), but it simply is not working that way - at all. Here is the relevant code.
Main.h
#property Coven *coven;
#property Nellie *nellie;
#property NSMutableArray *array;
//Physics, other things
Main.m
/Adding other things...
-(void) addCovenMember{
//This function is called on a RANDOM time interval
_array = [[NSMutableArray] alloc]init];
for (i = 0, i < 15, i++){
_coven = (Coven*) [CCBReader load:#"CovenMember"];
[_array addChild:_coven];
}
[_physicNode addChild:_coven];
}
-(BOOL)ccPhysicsCollisionBegin:(CCPhysicsCollisionPair *)pair nellie:(Nellie*)nellie coven:(Coven*)coven{
for (_coven in _array){
NSLog(#"%#",_coven.name)
if (CGRectIntersectsRect(_nellie.boundingBox, _coven.boundingBox){
NSLog(#"We're intersecting!");
}
}
Coven. h
//Nothing Important Here
Coven.m
-(void)didLoadFromCCB{
self.physicsBody.CollisionType = #"coven";
}
Nellie.h
//Nothing Here
Nellie.m
-(void) didLoadFromCCB{
self.physicsBody.CollisionType = #"nellie";
}
The collision is logging with every collision - but only as the name of the LATEST _coven member to be generated, no matter what I am colliding with. This also means that the _coven.boundingBox is solely on the latest _coven member and interaction only occurs when I hit the new member as soon as it generates on to the screen.
Any ideas? Any help?
Note: This is also posted on the Spritebuilder website - I decided to post it here as well because answers can be a little slow on those forums.
The -(void) addCovenMember overwrites (creates a new instance) of _array every time it's called. Thus, when you try to iterate in -ccPhysicsCollisionBegin: you'll only ever see 1 coven.
Add a nil check around your array creation:
if(_array == nil) {
_array = [[NSMutableArray] alloc]init];
}
The for loop in the -addCovenMember method looks broken (at least not a c loop). Reaplace the , with ;:
for (i = 0; i < 15 i++){
Also, using for(_coven in _array) seems wrong, you already have a property self.coven (presumably) with a backing _coven ivar. Try changing it to for(Coven * c in self.array) and use the local c in the loop:
for (Coven * c in _array){
NSLog(#"%#",c.name)
if (CGRectIntersectsRect(_nellie.boundingBox, c.boundingBox){
NSLog(#"We're intersecting!");
}
}
To everyone out in the world struggling with their ccPhysicsCollisions, arrays may not be the answer - this was a simple fix that left me incapacitated for days.
Using the basic ccPhysicsCollisionsBegan that ships with spritebuilder, try this without arrays first:
Scene.m
-(BOOL)ccPhysicsCollisionBegin:(CCPhysicsCollisionPair *)pair nellie:(Nellie*)nellie coven:(Coven*)coven{
[_coven stopAction:coven.path];
}
I initially created the method with:
[_coven stopAction:_coven.path];
Yes, that (underscore) set me back three weeks. Be sure you refer to the object interacting through the physics delegate, and not the object itself, which in my case, was constantly being overwritten by the new ones being generated.
Check your underscores.
Solved! :D
Thanks to #thelaws for your help! I'll get better at Obj C... eventually.
I am newly to iphone. I am working on an application where we need to calculate the value from an array of objects.
I have created a NSObject class "Catalogue", which includes catalogue_Value and catalogue_quantity. Now, suppose if we have two catalogue object in my array, then i need to calculate the total value.
here is my code :
int initialTotalPoints = 9999;
int totalUsedPoints = 0;
for (int i = 0; i<[arrayCheckout count];i++)
{
Catalogue *catalog = [[Catalogue alloc] init];
catalog = [arrayCheckout objectAtIndex:i];
NSLog(#"checkout voucher %d is = %d*%d", i, catalog.catalogue_Value,catalog.catalogue_quantity);
totalUsedPoints = catalog.catalogue_Value * catalog.catalogue_quantity;
}
initialTotalPoints = initialTotalPoints-totalUsedPoints;
The problem is due to the for loop, always it is taking "totalUsedPoints" of my last array object. But in actually, i need to add "catalog.catalogue_Value,catalog.catalogue_quantity" in my "totalUsedPoints" as per my total array objects. Please help me to solve this problem. Thanks!
If you just want to sum up quantity*value per catalog
int totalPoints = 0;
for (int i = 0; i<[arrayCheckout count];i++) {
Catalogue *catalog = [arrayCheckout objectAtIndex:i];
totalPoints += catalog.catalogue_Value * catalog.catalogue_quantity;
}
// totalPoints is now the sum of each arrays catalogue_Value*catalogue_quantity
You could check out Blockskit, a nice package to make array iterations easier
There is nothing specific to objective c here. Every loop you are overwriting totalUsedPoints with a new value. You then do nothing with it, and it gets overwritten again. At the end of the loop it will only contain the last value assigned to it.
I think what you are looking for is:
totalUsedPoints += catalog.catalogue_Value * catalog.catalogue_quantity;
+= is equal to:
totalUsedPoints = totalUsedPoints + catalog.catalogue_Value * catalog.catalogue_quantity;
meaning it will be assigned with the previous value, plus the new value
This is computer science 101 stuff, not unique to Objective-C. Others have already posted info on what you were doing wrong and how to fix it. I wanted to point out another flaw in your code. Take a look at these 2 lines:
Catalogue *catalog = [[Catalogue alloc] init];
catalog = [arrayCheckout objectAtIndex:i];
In the first line you create a new, empty Catalogue object and save a pointer to it in the variable catalog. In the very next line you fetch an object from your arrayCheckout object and save a pointer to it in your catalog variable. You end up discarding the object you created one line before.
This is like building a brand new car, putting it in front of your house, then junking it and fetching an existing car from a numbered parking space in a parking lot.
In ARC the empty Catalogue object you create in the first object will get deallocated on the very next line, so you aren't leaking memory, but it's pointless and wasteful to create an object that you immediately discard. (Memory allocation is one of the slowest tasks in an OS like iOS. It has to make a kernel call)
If your program was using manual reference counting then you would have leaked the Catalogue object. It would never get deallocated. Those two lines should read like this:
Catalogue *catalog;
catalog = [arrayCheckout objectAtIndex:i];
Or even as 1 line:
Catalogue *catalog = [arrayCheckout objectAtIndex:i];
I am developing a game for iPhone in which I have 2 arrays.
One with the objects "living" in the game, and when these objects "die" they are placed in another array to be removed from the first one in the end of the first loop.
This is necessary because if the object dies in the loop and it is removed immediately from the first array, the index is lost and sometimes gives an invalid address access.
Then I have an NSMutableArray that contains objects to be removed from the living objects array.
In the array with objects to remove, I am constantly adding and removing items. Sometimes when I use objectAtIndex with the array with items to remove, it is retuning me other object.
For example in the first moment _enemiesToRemove has 2 objects:
([0]-> 0x0a8b5120, [1]->0x18f3a090)
for(int i = [_enemiesToRemove count] - 1; i >= 0 ; i--){
fish = [_enemiesToRemove objectAtIndex:i];
[self removeEnemy:fish];
}
and then
int i = [_enemiesToRemove count] - 1
gives i=1 but when it is doing
[_enemiesToRemove objectAtIndex:i]
it is returning me other object with address 0xbfffcd58 and it should be [1]->0x18f3a090
What is happening here, somebody knows? It is not happening always. It happens randomly.
I have an NSArray of songs and would like to put them in a playlist. When I play the playlist I use indexOfObject to figure out the current songs index in the queue. I already overided isEqual, so to show that two media items were the same and would prefer not to hack at this method. I tried out NSOrderedSet instead of NSArray and it displayed each song once as opposed to how many instances of the same song are in it. Is their a class that mixes NSArray and NSOrderedSet so that each index is a unique object but there can be duplicate objects at different indexes?
Code:
- (PlayerItem *)nextSong{
if(queue.count > 0){
NSInteger songIndex = [queue indexOfObject:currentSong];
NSLog(#"%ld in %lu", (long)songIndex, (unsigned long)queue.count);
songIndex = songIndex + 1;
if (songIndex < [queue count]){
return queue[songIndex];
}else{
return queue[0];
}
}
}
return nil;
}
Comment from Below:
I mean if I cycle threw songs than it can play Song 1 then 1 again
then 2 then 3 then 3 again. This isn't possible though because the
indexOfObject always returns the first duplicate object.
The problem is in the way you are finding out which song from the playlist is currently playing: You seem to store the currentSong in an ivar or so.
As it is possible that this song appears twice in the playlist it is just not enough information to know what's playing. Example:
"My playlist is A, A, B, C, C. Right now A is playing."
As you can see, from this information you can't know what's the next song.
A solution would be to store the index in the playlist or some other information to know the progress in the playlist.
In my app I'm using two NSMutableDictionaries. Lets call them basicDictionary and refreshDictionary.
In basicDictionary I have values, lets say
key:"1" value:"2000" photo:someUIImage //Lets say I want to track score of player
key:"2" value:"1500" photo:someUIImage2
key:"3" value:"1500" photo:someUIImage3
key:"4" value:"1500" photo:someUIImage4
key stands for player id and rest is pretty clear.
I do server api call every 20 sec to refresh score of players. Because I don't want to load photo as well im using refresh call to bring me only player id and his actual score.
So every 20 secs I get data that I save in refreshDictionary. There are only ids and current score of that id.
refreshDictionary example:
key:"1" value:"2500"
key:"2" value:"2800"
key:"3" value:"2700"
I update my tableView with new values. As you can see, I got data only for 3 players, because player 4 has deleted his profile. Now my question is, how do I update basicDictionary to remove player 4?
I know that I'm supposed tu use if (!([basicDictionary isEqualToDictionary:refreshDictionary))
however, it won't tell me at which key they aren't equal.
So what would you guys do? Should I iterate through both of them in nested loop? That seems to consume alot of time when dictionaries are bigger. Oh by the way, my dictionaries are always sorted same way (by players id)
My idea is, that I compare these two dictionaries in
- (void)connectionDidFinishLoading:(NSURLConnection *)connection {
if (refresh)
{ //compare dictionaries and modify basicDictionary that is data source for my tableview by deleting where key doesn't match
}
this code will give you keys that changed:
NOTE: as the lookup of keys is basically jumping into a hashmap (an o1 op), you dont have to worry about the 2nd array walk you talk about
#import <Foundation/Foundation.h>
#interface NSDictionary (changedKeys)
- (NSArray*)changedKeysIn:(NSDictionary*)d;
#end
#implementation NSDictionary (changedKeys)
- (NSArray*)changedKeysIn:(NSDictionary*)d {
NSMutableArray *changedKs = [NSMutableArray array];
for(id k in self) {
if(![[self objectForKey:k] isEqual:[d objectForKey:k]])
[changedKs addObject:k];
}
return changedKs;
}
#end
int main(int argc, char *argv[]) {
#autoreleasepool {
NSDictionary *d1 = #{#"1":#"value",#"2":#"value",#"3":#"value",#"4":#"value"};
NSDictionary *d2 = #{#"1":#"value",#"2":#"newvalue",#"3":#"value"};
NSArray *ks = [d1 changedKeysIn:d2];
NSLog(#"%#", ks);
}
return 0;
}
Edit: self.allKeys changed to just self -- a dictionary can be enumerated already