Moving from AI to Multiplayer Game - ios

I currently have a single player board game with one human player and three AI players. I would like to change that to four human players. How can I achieve that from the code below? Can I simply use and OR statement for the 1st line "currentplayer ==3" and have that read "currentplayer == 3 | 1"
if (currentPlayer == 3 && ([currentTokens count])){
for (int count = 0; count < [currentTokens count]; count++) {
Token *token = (Token*)[currentTokens objectAtIndex:count];
[token setUserInteractionEnabled:YES];
}
}
else if ([currentTokens count])//For NonHuman Players
{
// NSLog(#"Break3.3");
int arrLength = [currentTokens count];
// NSLog(#"Break3.4 and %i",arrLength);
////////////////// AI for NON HUMAN AT OCCURENCE OF SIX OF DICE////////////
Token *nonHumanToken;
int tokenAtHomeCount = 0;
if (firstDiceValue == 6) {
for (int count = 0; count < [currentTokens count]; count++) {
Token *selectedToken = (Token*)[currentTokens objectAtIndex:count];
if (selectedToken.isAtHome) {
tokenAtHomeCount++;
nonHumanToken = (Token*)[currentTokens objectAtIndex:count];
break;
}
}
if (!tokenAtHomeCount) {
nonHumanToken = (Token*)[currentTokens objectAtIndex:(arc4random()%arrLength)];
}
}
else{
nonHumanToken = (Token*)[currentTokens objectAtIndex:(arc4random()%arrLength)];
}
////////////////////////////////
[self performSelector:#selector(courseOfActionWithDelay:) withObject:nonHumanToken afterDelay:1.5];
// [self moveToken:nonHumanToken Till:firstDiceValue];
if ([currentTokens count]) {
[self DisplayMessageForMovingTokens:currentPlayer];
}
}

Ideally if you are replacing your AI with human players, you would completely ditch the AI code. I would look into duplicating the human code for each player.
Say you have:
if(player==1) {
player 1's turn stuff here
}
you would expand off of that and move on to:
if(player==2) {
player 2's turn stuff here
}
If this is to be a turn based game, instead of tracking players, track turns. Turn one would be player one, turn two is player two, and then just reset once you get to the max number of players for the round.

Related

How to generate random numbers from 1-99 range in Objective-C? [duplicate]

This question already has answers here:
Generating random numbers in Objective-C
(13 answers)
Non repeating random numbers in Objective-C
(6 answers)
Closed 8 years ago.
This is my code for generating random numbers from 1-99, but it's only generating same set of numbers (15 numbers) every time. I'm storing those numbers in an NSArray and getting output in NSLog properly. It's ok, but I want different set of random numbers with no repeated number whenever I call this random method. Can any one help me please?
-(void) randoms
{
myset=[[NSArray alloc]init];
int D[20];
BOOL flag;
for (int i=0; i<15; i++)
{
int randum= random()%100;
flag= true;
int size= (sizeof D);
for (int x=0; x<size; x++)
{
if (randum == D[x])
{
i--;
flag= false;
break;
}
}
if (flag) D[i]=randum;
}
for (int j=0; j<15; j++)
{
myset=[myset arrayByAddingObject:[NSNumber numberWithInt:D[j]]];
}
NSLog(#"first set..%#",myset.description);
}
You have to seed the generator before using it. If you want to skip the seeding, you can use arc4random_uniform(). It's a different algorithm and takes care of the seeding process on its own. Other than that, you can use it in your code almost exactly like you used random(). You'll just have to specify the upper bound as a parameter, instead of using modulo:
-(void) randoms
{
myset=[[NSArray alloc]init];
int D[20];
BOOL flag;
for (int i=0; i<15; i++)
{
int randum= arc4random_uniform(100);
flag= true;
int size= (sizeof D);
for (int x=0; x<size; x++)
{
if (randum == D[x])
{
i--;
flag= false;
break;
}
}
if (flag) D[i]=randum;
}
for (int j=0; j<15; j++)
{
myset=[myset arrayByAddingObject:[NSNumber numberWithInt:D[j]]];
}
NSLog(#"first set..%#",myset.description);
}
Try this command before starting your arc4random
srand(time(NULL));
If I understand you correctly you want a set containing 15 random numbers between 1-99. You can use the following:
- (NSSet *)randomSetOfSize:(int)size lowerBound:(int)lowerBound upperBound:(int)upperBound {
NSMutableSet *randomSet=[NSMutableSet new];
while (randomSet.count <size) {
int randomInt=arc4random_uniform(upperBound-lowerBound)+lowerBound;
NSNumber *randomNumber=[NSNumber numberWithInt:randomInt];
[randomSet addObject:randomNumber];
}
return randomSet;
}
and call it with
NSSet *myRandomSet=[self randomSetOfSize:14 lowerBound:1 upperBound:99];

Change an integer value after a time interval ios

I am making a game with powerups. I have 3 powerups. When a powerup is active, I use an integer to identify which one it is, 1, 2, or 3, with 0 representing no active powerups. Once I activate a powerup, I want it to expire after a time interval, say 10 seconds. How do I reset the identifier integer back to 0?
For example, one powerup speeds up the ship. Here is my update method.
-(void) update:(ccTime)dt
{
if (powerupIdentifier == 0)
{
shipSpeed = 100;
}
if (powerupIdentifier == 1)
{
shipSpeed = 200;
}
CCArray* touches = [KKInput sharedInput].touches;
if ([touches count] == 1)
{
//MAKES SHIP MOVE TO TAP LOCATION
KKInput * input = [KKInput sharedInput];
CGPoint tap = [input locationOfAnyTouchInPhase:KKTouchPhaseBegan];
ship.position = ccp( ship.position.x, ship.position.y);
if (tap.x != 0 && tap.y != 0)
{
[ship stopAllActions]; // Nullifies previous actions
int addedx = tap.x - ship.position.x;
int addedy = tap.y - ship.position.y;
int squaredx = pow(addedx, 2);
int squaredy = pow(addedy, 2);
int addedSquares = squaredx + squaredy;
int distance = pow(addedSquares, 0.5);
[ship runAction: [CCMoveTo actionWithDuration:distance/shipSpeed position:tap]];//makes ship move at a constant speed
}
}
}
First, use an enum rather than an int.
typedef NS_ENUM(unsigned short, PowerUp) {
PowerUp_Level0,
PowerUp_Level1,
PowerUp_Level2,
PowerUp_Level3
};
Enum is far more readable, and is a lot more self-documenting then random integers.
Now, say we have a property:
#property (nonatomic, assign) PowerUp powerUp;
We can write a method to reset the power up:
- (void)resetPowerUp {
self.powerUp = PowerUp_Level0;
}
Now, when we've set it to some non-zero value and need to reset it (after 10 seconds), it's as simple as this:
self.powerUp = PowerUp_Level2;
[self performSelector:#selector(resetPowerUp) withObject:nil afterDelay:10.0f];

IOS have a report builder generate in PDF

I have data to generate report that have header footer and content.
In the content have many group when the data in each group over the page area it add new page and write header of group and continued content data
Where can I have lib. or something to do this Task ??
Thanks For Advance.
Add for request code
NSArray *headObject = [uniqueStates allObjects];////Store head of each group
NSArray *detail; //Store all of data to present in table
int allData = [detail count]; // Tel amount of all data to show
/*
int headGroupline = 1; //Tel amount of head group line
int footGroupline = 1; //Tel amount of foot group line
*/
int detailIndex = 0; ///Tel what line we are now
int detailHeadIndex = 0; ///Tel what group we are now
int subdetail = 0; // Tel what line on group now
int aviableLineInpage = 24; // Line avilable in page for data to show
int allPage = 0; //Sum of all page
for (; detailIndex < allData; ) {
allPage++;
for (int i=0; i < aviableLineInpage;) {
if (allData - detailIndex == 0) {
///ShowgrandTotal
........
detailIndex++;
i+=25;
}else{
if (i == 0) {
//Show Head Group
......
}else{
if (subdetail == [[detail filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:#"(buy_date == %#)", headObject[detailHeadIndex]]] count]+1) {
detailHeadIndex++;
//Show Head Group
..........
}else{
if (subdetail == [[detail filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:#"(buy_date == %#)", headObject[detailHeadIndex]]] count]) {
//Show sum of each group
..........
i++;
detailIndex++;
subdetail++;
detailHeadIndex++;
}else{
//Show data of detail
........................
detailIndex++;
subdetail++;
}
}
}
i++;
}
}//for all line in page
}//for allData
It format is:
date 27/01/2014
data1
data2
data3
sum date 27/01/2014
date 28/01/2014
data1
data2
<============if page brake add new page and
date 28/01/2014
data3
sum date 28/01/2014
grand total........
But it goes
date 27/01/2014
data1
data2
data3
sum date 27/01/2014
data1
data2
<============if page brake add new page and
date 28/01/2014
data3
grand total........
Thanks very much
Use CGPDFDocumentRef and the associated functions to create the PDF document and each page it contains. When you create a page (UIGraphicsBeginPDFPageWithInfo) you can get the associated drawing context (UIGraphicsGetCurrentContext). Once you have that you can draw in a number of ways:
You could create a view with your header and footer, add content and render it into the view (using its layer)
You could draw images and text direct into the context (using CoreText (CTFrameDraw))
You need to create the logic to set how much content can fit on any one page and when you need to create a new page.
Also, depending on how you choose to draw content into the context you may need to scale and transform (CGContextScaleCTM + CGContextTranslateCTM) the context so that your content isn't upside down.
See this Apple guide.
int allData = [detail count]; // Tel amount of all data to show
/*
int headGroupline = 1; //Tel amount of head group line
int footGroupline = 1; //Tel amount of foot group line
*/
int detailIndex = 0; ///Tel what line we are now
int detailHeadIndex = 0; ///Tel what group we are now
int subdetail = 0; // Tel what line on group now
int aviableLineInpage = 24; // Line avilable in page for data to show
int allPage = 0; //Sum of all page
for (; detailIndex < allData; ) {
allPage++;
for (int i=0; i < aviableLineInpage;) {
if (allData - detailIndex == 0) {
detailIndex++;
i+=25;
}else{
if (i == 0) {
if (subdetail == -1) {
subdetail = 0;
}
}else{
if (subdetail == -1) {
subdetail = 0;
}else{
if (subdetail == [[detail filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:#"(buy_date == %#)", headObject[detailHeadIndex]]] count]) {
i++;
subdetail = -1;
detailHeadIndex++;
if (detailHeadIndex == [headObject count] ) {
detailIndex++;
}
}else{
detailIndex++;
subdetail++;
}
}
}
i++;
}
}//for all line in page
}//for allData

Get an array of 3 ordered values whilst favouring a specified value

Sorry for the somewhat generic title, if anyone has a better suggestion please let me know.
Basically I am writing a custom leaderboard view whereby I want to show 3 scores only. If possible it will show the current user's score in the middle but, if the user is at the top or the bottom of the list, it should still show 3 scores but itll show another users above or below the list.
e.g.
Me (If I am top, then show 2 below)
User 1
User 2
or
User 1
Me (usual case where I am in the middle of two scores)
User 2
or
User 1
User 2
Me (If I am bottom show two scores above me)
I have a function written that does the first part of this but doesnt take into account edge cases which is what I am struggling with. Can anyone please advise?
-(void)getNearbyScores:(int)score{
GCLeaderboardScore *closestScoreAbove = nil; //Custom container for GC properties
GCLeaderboardScore *closestScoreBelow = nil; //Contains playerID, score, alias etc
if ([playerScores count] == 0){ //playerScores is an NSMutableDictionary
return;
}
for (NSString* key in playerScores) {
GCLeaderboardScore *playerScore = (GCLeaderboardScore *)[playerScores objectForKey:key];
if ((closestScoreAbove == nil || closestScoreAbove->score > playerScore->score) && playerScore->score > score){
closestScoreAbove = playerScore;
}
else if ((closestScoreBelow == nil || closestScoreAbove->score < playerScore->score) && playerScore->score < score){
closestScoreBelow = playerScore;
}
}
me->score = score;
me->rank = 1;
if (closestScoreAbove != nil) {
me->rank = closestScoreAbove->rank + 1;
nearbyScores = [NSMutableArray arrayWithObjects: closestScoreAbove, me, closestScoreBelow, nil];
}
else {
nearbyScores = [NSMutableArray arrayWithObjects: me, closestScoreBelow, nil];
}
}
Assuming there is a me GCLeaderboardScore object, the method below should return an array with the desired GCLeaderboardScore objects (untested):
-(NSArray *)getNearbyScores {
if(playerScores.count==0) return nil;
// Create an array sorted by score
NSArray *sortedByScore=[playerScores sortedArrayUsingComparator: ^(id object1, id object2) {
GCLeaderboardScore *score1=object1;
GCLeaderboardScore *score2=object2;
if(score1->score < score2->score) return NSOrderedAscending;
if(score1->score > score2->score) return NSOrderedDescending;
return NSOrderedSame;
}];
// Find index of me
NSUInteger idx=[sortedByScore indexOfObject:me];
// If me not found, return nil
if(idx==NSNotFound) return nil;
// Ideally we want to show the player before and behind
idx=MAX(0,(NSInteger)idx-1);
// maxIdx will be idx+2 or index of last object if lower
NSUInteger maxIdx=MIN(sortedByScore.count-1,idx+2);
// In case we are last, show two previous results (if array large enough)
if (maxIdx > 3)
idx=MAX(0,maxIdx-3);
// And return the objects, may be 1..3 objects
return [sortedByScore subarrayWithRange:NSMakeRange(idx,maxIdx-idx+1)];
}
I assume you have an array of scores. (Actual implementation can be adapted to your code)
Initialize:
firstScoreAbove = VERY_LARGE_SCORE; secondScoreAbove = VERY_LARGE_SCORE + 1;
firstScoreBelow = -1; secondScoreBelow = -2;
Scan the array elements.
if ( newScore > myScore ) {
if ( newScore < firstScoreAbove ) {
secondScoreAbove = firstScoreAbove;
firstScoreAbove = newScore;
} else if ( newScore < secondScoreAbove ) {
secondScoreAbove = newScore;
}
} else {
// similarly for below.
}
After scanning,
If firstScoreAbove has not changed, then myScore is top and output the two below scores.
If firstScoreBelow has not changed, then myScore is lowest and output the two above scores.
Else Output firstScoreAbove, myScore, firstScoreBelow.

iOS Fastest method to extract a substring

I have several thousand strings in the form "verb-noun" for which I want to extract the noun portion. I am looking for the FASTEST way to do this. The verb and noun portions can be any length.
I have tried
NSString *noun = [[verb componentsSeparatedByString:#"-"] lastObject];
Which is slow... For my list of over 3000 entries it takes about 3 seconds.
Also tried
NSString *noun = [verb substringFromIndex:[verb rangeOfString:#"-"].location + 1];
which is MUCH faster, about a half second.
Anyone have suggestions for making this even faster?
If your work with these strings is thread-safe then one option is to use GCD to iterate over multiple verb values simultaneously, bringing multiple cores into action. Use dispatch_apply instead of whatever loop you're using, something like:
dispatch_apply([myWordArray count], queue, ^(size_t i) {
NSString *verb = [myWordArray objectAtIndex:i];
NSString *noun = [verb substringFromIndex:[verb rangeOfString:#"-"].location + 1];
// do something with noun...
});
Just keep in mind that this will do more than one pass simultaneously, so be very sure about threading issues.
Fastest way would probably to sort the most likely cases for where the hyphen is, and then check for those first without using a loop. For example, if the most likely cases for index of hyphen are 5, 4, 6, 7, 3, 2 in that order, you could do this:
NSString * verb = #"verb-noun";
NSString * noun = nil;
//use do...while(0) to avoid nested if else
do
{
if([verb characterAtIndex:5] == '-')
{
noun = [verb substringFromIndex:6];
break;
}
if([verb characterAtIndex:4] == '-')
{
noun = [verb substringFromIndex:5];
break;
}
if([verb characterAtIndex:6] == '-')
{
noun = [verb substringFromIndex:7];
break;
}
if([verb characterAtIndex:7] == '-')
{
noun = [verb substringFromIndex:8];
break;
}
if([verb characterAtIndex:3] == '-')
{
noun = [verb substringFromIndex:4];
break;
}
if([verb characterAtIndex:2] == '-')
{
noun = [verb substringFromIndex:4];
break;
}
} while(0);
//if not one of most likely cases, loop
if(!noun)
{
for(int j = 8; j < verb.length; j++)
{
if([verb characterAtIndex:j] == '-')
{
noun = [verb substringFromIndex:j + 1];
break;
}
}
}
if(noun)
{
//noun should never be nil
NSLog(#"found the noun");
}

Resources