How to check NSMutableArray for objects with identical flags? - objective-c

I have a Card object, that has a flag isFlipped. I store them in a NSMutableArray. I want to check if two objects in my array have the flag on, and if they do, I remove them.
As far as I understand I need to iterate over array, but how do I get another object with a flag?
- (void) checkCards
{
for (Card *card in cards) {
if (card.flipped)
{
if ( ??? )
{
}
}
}
}

Store the index of the cards that you want to remove in variables and if the value of both the variables are set then just remove the cards. See the following
- (void) checkCards {
int card1 = -1;
int card2 = -1;
for(int i = 0; i < [cards count]; i++) {
Card *card = [cards objectAtIndex: i];
if(card.flipped) {
if(card1 == -1) {
card1 = i;
} else {
card2 = i;
}
if(card1 != -1 && card2 != -1) {
// remove cards
break;
}
}
}
}

I would use the NSArray method, indexesOfObjectsPassingTest:. You can use it like this:
NSIndexSet *indexSet = [cards indexesOfObjectsPassingTest:^BOOL (Card *obj, NSUInteger idx, BOOL *stop) {
return obj.isFlipped = YES;
}];
[cards removeObjectsAtIndexes:indexSet];
This will remove all cards, whose isFlipped is YES, so if there could be more than 2, and you only want to remove 2, then you would have to iterate through the indexSet and stop after removing 2.

Related

Poker hand strength

I've programatically determined hand rankings as added below. However, the issue is - if per say, two players end up with a pair.. How do I determine the winner?
To each card object I've added a prime number value. Ace being 41 and deuce being 3 and the in betweens. I'm thinking of multiplying these values when the hand is determined and whoever has the highest is winning. I need help determining whether this is the correct approach.
+(BOOL)isFull:(NSArray*)cards {
Cards *card1 = [cards objectAtIndex:0];
Cards *card2 = [cards objectAtIndex:1];
Cards *card3 = [cards objectAtIndex:2];
Cards *card4 = [cards objectAtIndex:3];
Cards *card5 = [cards objectAtIndex:4];
if (([card1.face isEqualToString:card3.face] && [card4.face isEqualToString:card5.face]) || ([card1.face isEqualToString:card2.face] && [card3.face isEqualToString:card5.face])) {
return true;
}
return false;
}
+(BOOL)isFlush:(NSArray*)cards {
NSMutableArray *organizedBySuit = [self organizeCardsSuitOrder:cards];
Cards *card1 = [organizedBySuit objectAtIndex:0];
Cards *card2 = [organizedBySuit objectAtIndex:4];
if ([card1.suit isEqualToString:card2.suit]) { return true; } else { return false; } // cards are organized by suit, so if the first equals the last..
}
+(BOOL)isStraight:(NSArray*)cards {
Cards *card1 = [cards objectAtIndex:0];
Cards *card2 = [cards objectAtIndex:1];
Cards *card3 = [cards objectAtIndex:2];
Cards *card4 = [cards objectAtIndex:3];
Cards *card5 = [cards objectAtIndex:4];
if ((card1.rankByInt) == 0 && (card2.rankByInt) == 9 && (card3.rankByInt) == 10 && (card4.rankByInt) == 11 && (card5.rankByInt) == 12) {
return true;
}
else if ((card1.rankByInt) < 9) {
if ((card2.rankByInt) == (card1.rankByInt) + 1) {
if ((card3.rankByInt) == (card1.rankByInt) + 2) {
if ((card4.rankByInt) == (card1.rankByInt) + 3) {
if ((card5.rankByInt) == (card1.rankByInt) + 4) {
return true;
}
}
}
}
}
return false;
}
+(BOOL)isTrip:(NSArray*)cards {
NSArray *faces = [self returnArrayOfFaces];
__block int pairCounter = 0;
for (int i = 0; i < [faces count]; i++) {
for (int t = 0; t < [cards count]; t++) {
Cards *card = [cards objectAtIndex:t];
if ([card.face isEqualToString:faces[i]]) {
pairCounter++;
}
}
if (pairCounter > 2) {
return true;
}
pairCounter = 0;
}
return false;
}
+(BOOL)isTwoPair:(NSArray*)cards {
NSArray *faces = [self returnArrayOfFaces];
__block int pairCount = 0;
__block int doublePairCount = 0;
for (int i = 0; i < [faces count]; i++) {
for (int t = 0; t < [cards count]; t++) {
Cards *card = [cards objectAtIndex:t];
if ([card.face isEqualToString:faces[i]]) {
pairCount++;
}
}
if (pairCount > 1) {
doublePairCount++;
}
pairCount = 0;
}
if (doublePairCount > 1) {
return true;
}
return false;
}
+(BOOL)isPair:(NSArray*)cards {
NSArray *faces = [self returnArrayOfFaces];
__block int pairCounter = 0;
for (int i = 0; i < [faces count]; i++) {
for (int t = 0; t < [cards count]; t++) {
Cards *card = [cards objectAtIndex:t];
if ([card.face isEqualToString:faces[i]]) {
pairCounter++;
}
}
if (pairCounter > 1) {
return true;
}
pairCounter = 0;
}
return false;
}
And the cards are generated to include their primes here.
+(NSMutableArray*)createDeck:(id)sender {
[sender removeAllObjects];
NSArray *faces = [[NSArray alloc] initWithObjects:#"A",#"2",#"3",#"4",#"5",#"6",#"7",#"8",#"9",#"10",#"J",#"Q",#"K", nil];
NSArray *suits = [[NSArray alloc] initWithObjects:#"h",#"d",#"c",#"s", nil];
NSArray *primes = [[NSArray alloc] initWithObjects:[NSNumber numberWithInt:41],[NSNumber numberWithInt:2],[NSNumber numberWithInt:3],[NSNumber numberWithInt:5],[NSNumber numberWithInt:7],[NSNumber numberWithInt:11],[NSNumber numberWithInt:13],[NSNumber numberWithInt:17],[NSNumber numberWithInt:19],[NSNumber numberWithInt:23],[NSNumber numberWithInt:29],[NSNumber numberWithInt:31],[NSNumber numberWithInt:37], nil];
for (int i = 0; i < 52; i++) {
Cards *card = [[Cards alloc]init];
card.face = [NSString stringWithFormat:#"%#", faces[i % 13]];
card.suit = [NSString stringWithFormat:#"%#", suits[i / 13]];
card.rankByInt = i % 13;
card.symbol = [Cards symbolForSuit:card.suit];
card.prime = [[primes objectAtIndex:(i % 13)] intValue];
[sender addObject:card];
}
[sender shuffle];
return sender;
}
So if possible can you provide me with the way to go forward to essentially 'rank' each hand by the cards values after I have retrieved their rank such as flush, straight etc..
Also, if you see any ways to improve the efficiency of my checks for hand ranks, please share.
First evaluate the hand type. If those are equal, compare the highest card that makes up the hand (unless it's a full house, then compare the set). If all cards in the hand type are equal, and the hand type is less than 5 cards, compare the next highest card in the 5 card hand. Only if the best combination of 5 cards are equal between two hands do the hands tie.
I wrote a poker hand generator and strength comparer in python that may be of some interest to you: https://github.com/Alec-ala/poker-stud-showdown

checking whole boolean of NSMutableArray

I have an array that I am filling with boolean values in the following code.
for(int i = 0; i < 15; i++){
int checkVal = [(NSNumber *)[__diceValue objectAtIndex:i] intValue];
if(checkVal == matchVal){
[_diceMatch replaceObjectAtIndex:i withObject:[NSNumber numberWithBool:y]];
}
}
Whats the shortest way to write a conditional to check the array "_diceMatch" for all true values?
If your array can only contain the values "true" (#YES) or "false" (#NO)
then you can simply check for the absence of #NO:
if (![_diceMatch containsObject:#NO]) {
// all elements are "true"
}
NSUInteger numberOfTrueValues = 0;
for (NSNumber *value in _diceMatch) {
if ([value boolValue]) {
numberOfTrueValues++;
}
}
Shortest way? maybe not. Easiest way? Yes
- (BOOL)isDictMatchAllTrue {
for (NSNumber *n in _dictMatch) {
if (![n boolValue]) return NO;
}
return YES;
}
or you don't like writing loop
NSSet *set = [NSSet setWithArray:_diceMatch];
return set.count == 1 && [[set anyObject] boolValue];
Note: first version return YES when array is empty but second version return NO.
You can add
if (_dictMatch.count == 0) return YES; //or NO
to fix it.

Generating primes List in objective C?

I create this objective C class to Genrate prime numbers from n to limit. I have problem I could not get the item in NSMutableArray inside for loop. can some one show me how can I fix it?
#implementation Prime
-(NSMutableArray *)generatePrimes:(int)upperLimit{
NSMutableArray *primes = [[NSMutableArray alloc]init];
bool isPrime;
int j;
[primes addObject:[NSDecimalNumber numberWithInt:2]];
for (int i= 3; i <= upperLimit ; i+=2) {
j = 0;
isPrime = YES;
NSInteger index;
for(id obj in primes)
{
index = [primes indexOfObject:obj];
if((index * index) <= i )
{
if(i % index == 0)
{
isPrime = NO;
break;
}
}
}
if(isPrime)
{
[primes addObject:[NSDecimalNumber numberWithInt:i]];
}
}
return primes;
}
#end
This question is a little vague, but it seems to me what you're trying to do is convert the NSDecimalNumber back into an int. What your code is actually doing is getting the number's index inside the array (ie the first object is 0, the second is 1, etc.) If you are trying to get the original value of i, change these lines:
for(id obj in primes)
{
index = [primes indexOfObject:obj];
to this:
for(NSDecimalNumber num in primes)
{
index = [num integerValue];
I'd also recommend using a different name than index, as that's misleading as to what you're actually doing.
-(NSMutableArray *)generatePrimes:(int)upperLimit
{
NSMutableArray *primes = [[NSMutableArray alloc]init];
bool isPrime;
for (int i=2; i<upperLimit; i++)
{
bool prime = true;
for (int j=2; j*j<=i; j++)
{
if (i % j == 0)
{
prime = false;
break;
}
}
if(prime)
{
[primes addObject:[NSDecimalNumber numberWithInt:i]];
}
}
return primes;
}
or
-(NSMutableArray *)generatePrimes:(int)upperLimit
{
NSMutableArray *primes = [[NSMutableArray alloc]init];
[primes addObject:[NSDecimalNumber numberWithInt:2]];
for(int i=3; i < upperLimit; i++)
{
bool prime=true;
for(int j=0;j<primes.count && (((NSDecimalNumber *)primes[j]).integerValue*((NSDecimalNumber *)primes[j]).integerValue) <= i;j++)
{
if(i % (((NSDecimalNumber *)primes[j]).integerValue) == 0)
{
prime=false;
break;
}
}
if(prime)
{
[primes addObject:[NSDecimalNumber numberWithInt:i]];
}
}
return primes;
}
Hope this helps!

NSNumbers stored in NSMutableArray

I'm trying to store numbers in a NSMutableArray, but when I check it, all I get is garbage.
-(void)storeIntoArray:(int)indexInt
{
NSNumber *indexNum = [[NSNumber alloc] initWithInt:indexInt];
[last100 insertObject:indexNum atIndex:prevCount];
prevCount++;
if(prevCount > 100)
{
prevCount = 0;
cycledOnce = YES;
}
}
-(BOOL)checkArray:(int)indexInt
{
for(int i = 0;i < [last100 count];i++)
{
NSLog(#"Stored: %d",[last100 objectAtIndex:i]);
if (indexInt == (int)[last100 objectAtIndex:i]) {
NSLog(#"Same entry, trying again");
return YES;
}
}
return NO;
}
When I check, I'll get values back like Stored: 110577680 and just various garbage values.
You're printing the NSNumber object address, not its value. Try using intValue. Or, if you want to print the object directly, use %# rather than %d.
NSLog(#"Stored: %d",[last100 objectAtIndex:i]);
Should be:
NSLog(#"Stored: %#",[last100 objectAtIndex:i]);
NSNumber is an object not an integer.

How to sort NSMutableArray? Code review needed

Good evening.
This code works. It sorts an array of cards by both Suit and Card Value. It is also very much brute force. Can you recommend a better way? Does Objective-C help dealing with a situation where object being sorted itself has multiple fields, on which sorting depends?
-(void) sort: (NSMutableArray *) deck {
NSUInteger count = [deck count];
Card *thisCard;
Card *nextCard;
int this;
int next;
BOOL stillSwapping = true;
while (stillSwapping) {
stillSwapping = false;
for (NSUInteger i = 0; i < count; ++i) {
this = i;
next = i+1;
if (next < count) {
thisCard = [deck objectAtIndex:this];
nextCard = [deck objectAtIndex:next];
if ([thisCard suit] > [nextCard suit]) {
[deck exchangeObjectAtIndex:this withObjectAtIndex:next];
stillSwapping = true;
}
if ([thisCard suit] == [nextCard suit]) {
if ([thisCard value] > [nextCard value]) {
[deck exchangeObjectAtIndex:this withObjectAtIndex:next];
stillSwapping = true;
}
}
}
}
}
}
You have several options.
Perhaps the simplest is to define the method -compare: on Card, which returns an NSComparisonResult. This is preferable if sorting by suit and value is the "standard" way to sort a Card. If you've done this, then your entire sorting method can be turned into
[deck sortUsingSelector:#selector(compare:)];
If you don't want to do this, you can use an array of NSSortDescriptors, one for suit and one for value.
[deck sortUsingDescriptors:[NSArray arrayWithObjects:[NSSortDescriptor sortDescriptorWithKey:#"suit" ascending:YES], [NSSortDescriptor sortDescriptorWithKey:#"value"] ascending:YES], nil]];
If this doesn't work for whatever reason, you could try -sortUsingComparator:
[deck sortUsingComparator:^NSComparisonResult(Card *obj1, Card *obj2) {
int suit1 = [obj1 suit];
int suit2 = [obj2 suit];
if (suit1 > suit2) {
return NSOrderedDescending;
} else if (suit1 < suit2) {
return NSOrderedAscending;
} else {
id value1 = [obj1 value];
id value2 = [obj2 value];
if (value1 > value2) {
return NSOrderedDescending;
} else if (value1 < value2) {
return NSOrderedAscending;
} else {
return NSOrderedSame;
}
}
}