Poker Game Results Between Two Players - c

I'm at the point where I'm trying to rank my players in the game, and determine the winner. You can read my code below, as I think I've documented the logic pretty well throughout.
What I need to do now is determine which player wins, given that there are two players. I've laid out functions for shuffling, dealing, and determining which type of hand it is.
//
// main.c
// Created by gixx88 on 7/22/15.
// Copyright (c) 2015 gixx88. All rights reserved.
//
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <string.h>
#define SUITS 4
#define FACES 13
#define CARDS 52
#define HAND 5
#define PLAYERS 2
//prototypes for shuffle and deal
void shuffle( size_t wDeck[][FACES] ); //shuffling modifies wDeck
void deal( size_t wDeck[][FACES], const char *wFace[],
const char *wSuit[] ); //dealing doesn't modify the arrays
void dealHand(size_t wHands[][HAND], size_t wDeck[][FACES]);
//prototypes for determing suit and face
size_t determineSuit(size_t wCard);
size_t determineFace(size_t wCard);
//prototypes for determing poker hand
unsigned int findAPair(size_t wHand[HAND]);
unsigned int findTwoPairs(size_t wHand[HAND]);
unsigned int findThreeOfAKind(size_t wHand[HAND]);
unsigned int findFourOfAKind(size_t wHand[HAND]);
unsigned int findFlush(size_t wHand[HAND]);
unsigned int findFullHouse(size_t wHand[HAND]);
unsigned int findStraightFlush(size_t wHand[HAND]);
unsigned int findStraight (size_t wHand[HAND]);
//prototypes for determing player outcomes
unsigned int determingPlayerHand(size_t wHand[HAND]);
void playerRank( size_t wHands[PLAYERS][HAND]);
int main(void) {
//initialize suit array
const char *suit[SUITS] = {"Hearts", "Diamonds", "Clubs", "Spades" };
//initilize face array
const char *face[ FACES ] = { "Ace", "Deuce", "Three", "Four", "Five", "Six", "Seven",
"Eight", "Nine", "Ten", "Jack", "Queen", "King" };
//initilize deck array
size_t deck[ SUITS ][FACES] = {{0}};
size_t hands[PLAYERS][HAND] = {{0}};
srand(time(NULL)); //random seed generator
shuffle(deck); //shuffle the deck
dealHand(hands, deck);
playerRank(hands);
} //end main
//determine suit
size_t determineSuit(size_t wCard){
return wCard / SUITS;
} // end determine suit
//determine face
size_t determineFace(size_t wCard){
return wCard % FACES;
}//end determine face
//if four of a kind
//shuffle cards in deck
void shuffle( size_t wDeck[][FACES] ){
size_t row; //row number
size_t column; //column number
size_t card; //counter
for (card = 0; card <= CARDS; ++card){
//choose a random location until unoccupied slot found
do {
row = rand() % SUITS;
column = rand() % FACES;
} //end do
while (wDeck[row][column] != 0); //end do while
//place card number in chosen slot of deck
wDeck[row][column] = card;
}// end for
} //end shuffle function
//deal cards in deck
void deal( size_t wDeck[][FACES], const char *wFace[],
const char *wSuit[] ){
size_t card; //card counter
size_t row; //row counter
size_t column; //column counter
//deal each of the cards
for (card = 0; card <= CARDS; ++card){
//loop through rows of wDeck
for (row = 0; row < SUITS; ++row){
//loop through columns in wDeck for current row
for(column = 0; column < FACES; ++column){
//if slot contians current card, display card
if (wDeck[row][column] == card){
printf("%5s of %-8s%c", wFace[column], wSuit[row],
card % 2 == 0 ? '\n' : '\t'); //two column format
} //end if
} //end column for
} //end row for
} //end card for
} //end function deal
void dealHand(size_t wHands[][HAND], size_t wDeck[][FACES]){
size_t cards;
size_t players;
unsigned int current;
unsigned int current_suit;
unsigned int current_face;
for (cards = 0; cards <= HAND; cards ++){
for (players = 0; players < PLAYERS; players++){
current = cards * PLAYERS + players;
current_suit = current / SUITS;
current_face = current % FACES;
wHands[players][cards] = wDeck[current_suit][current_face];
} // end players for
} // end cards for
} // end deal hand
//PRINT THE CARD
void printCard(unsigned int wCard, const char wFaces[FACES], const char wSuit[SUITS]){
//find suit and face
size_t suit;
size_t face;
suit = determineSuit(wCard);
face = determineFace(wCard);
printf("%s or %s", wFaces[face], wSuit[suit]);
} //end print card
//******************************
//BEGIN HAND TYPE DETERMINATION
//******************************
//find A PAIR
unsigned int findAPair(size_t wHand[HAND]){
size_t countOfFaces[FACES] = { 0 };
unsigned int foundAPair = 1;
size_t card;
for (card = 0; card < HAND; card++)
{
size_t face = determineFace(wHand[card]);
countOfFaces[face]++;
if (countOfFaces[face] == 3)
{
return 1;
}
else if (countOfFaces[face] == 2)
{
if (foundAPair)
{
return 1;
}
foundAPair = 0;
}
}
return foundAPair;
} // end find a pair
//find TWO PAIRS
unsigned int findTwoPairs(size_t wHand[HAND]){
size_t countOfFaces[FACES] = { 0 };
unsigned int numberOfPairs = 0;
size_t card;
for (card = 0; card < HAND; card++){
size_t face = determineFace(wHand[card]);
countOfFaces[face]++;
if (countOfFaces[face] == 3)
{
return 1;
}
else if (countOfFaces[face] == 2)
{
numberOfPairs++;
}
}
return numberOfPairs == 2;
} //end find two pairs
//find THREE OF A KIND
unsigned int findThreeOfAKind(size_t wHand[HAND]){
size_t countOfFaces[FACES] = {0};
size_t card;
unsigned int foundThree = 1;
for (card = 0; card < HAND; card++){
size_t face = determineFace(wHand[card]);
countOfFaces[face]++;
if (countOfFaces[face] == 3){
foundThree = 0;
} //end if
else if (countOfFaces[face] == 4){
return 1;
} //end else if
else if (countOfFaces[face] == 2 && foundThree){
return 1;
} //end else if
} //end card for loop
return 1;
} //end find three of a kind
//find FOUR OF A KIND
unsigned int findFourOfAKind(size_t wHand[HAND]){
size_t countOfFaces[FACES] = {0};
size_t card;
for (card = 0; card < HAND; card++){
size_t face = determineFace(wHand[card]);
countOfFaces[face]++;
if (countOfFaces[face] == 4){
return 0;
} //end if
} //end card for loop
return 1;
} //end for of a kind
unsigned int findStraight (size_t wHand[HAND]){
size_t card;
size_t lowFace;
size_t highFace;
size_t firstSuit;
unsigned int foundSecondSuit = 1;
for (card = 0; card < HAND; card++)
{
size_t suit = determineSuit(wHand[card]);
size_t face = determineFace(wHand[card]);
// first card
if (card == 0)
{
lowFace = face;
highFace = face;
firstSuit = suit;
}
// all other cards
// check for two equal faces first
else if (face == lowFace || face == highFace)
{
return 1;
}
// update low and high face, if necessary
else
{
if (suit != firstSuit)
{
foundSecondSuit = 0;
}
// an Ace can only go low if the low face is at most a Five
if (face == 0 && lowFace > HAND - 1)
{
face = 13;
}
if (face < lowFace)
{
lowFace = face;
}
if (face > highFace)
{
highFace = face;
}
if ((highFace - lowFace + 1) != HAND)
{
return 1;
}
}
}
return foundSecondSuit;
}
//find FLUSH
unsigned int findFlush(size_t wHand[HAND]){
size_t card;
size_t firstSuit = 5;
for (card = 0; card < HAND; card++){
size_t suit = determineSuit(wHand[card]);
//determing if all cards are the same suit
if (card == 0){
firstSuit = suit;
} //end if
else if (suit != firstSuit){
return 1;
} //end else if
} //end card for loop
return 0;
} //end find flush
//find FULL HOUSE
unsigned int findFullHouse(size_t wHand[HAND]){
if (findAPair(wHand) && findThreeOfAKind(wHand)){
return 0;
} //end if
return 1;
} //end full house
//find STRAIGHT FLUSH
unsigned int findStraightFlush(size_t wHand[HAND]){
size_t lowFace;
size_t highFace;
size_t card;
size_t firstSuit;
for (card = 0; card < HAND; card++){
size_t suit = determineSuit(wHand[card]);
size_t face = determineFace(wHand[card]);
//determing if all cards are the same suit
if (card == 0){
firstSuit = suit;
lowFace = face;
highFace = face;
} //end if
else if (suit != firstSuit || face == lowFace || face == highFace){
return 1;
} //end else if
//determination for ace being high or low, which depends on hand
else
{
// an Ace can only go low if the low face is at most a Five
if (face == 0 && lowFace > HAND - 1)
{
face = 13;
}
if (face < lowFace)
{
lowFace = face;
}
if (face > highFace)
{
highFace = face;
}
if ((highFace - lowFace + 1) != HAND)
{
return 1;
}
}
}
return 0;
} //end straight flush
//****************************
//DETERMINING PLAYER OUTCOMES
//****************************
//determing PLAYER HAND
unsigned int determingPlayerHand(size_t wHand[HAND]){
if (findStraightFlush(wHand) == 0){
return 8;
} //end if
else if (findFourOfAKind(wHand) == 0){
return 7;
} //end else if
else if (findFullHouse(wHand) == 0){
return 6;
} //end else if
else if (findFlush(wHand) == 0){
return 5;
} //end else if
else if (findStraight(wHand) == 0){
return 4;
} //end else if
else if (findThreeOfAKind(wHand) == 0){
return 3;
} //end else if
else if (findTwoPairs(wHand) == 0){
return 2;
} //end else if
else if (findAPair(wHand) == 0){
return 1;
}
return 0;
} //end determing player hand
//determing PLAYER RANK
void playerRank( size_t wHands[PLAYERS][HAND]){
unsigned int player1 = determingPlayerHand(wHands);
unsigned int player2 = determingPlayerHand(wHands);
if (player1 > player2){
printf("%s", "Player 1 Wins!");
}//end if
else if (player2 > player1){
printf("%s", "Player 2 Wins!");
}
} //end player rank
I'm loathe to post this, but sadly, I've got to finish this by tomorrow and I've already been working on it 12 hours straight. My concern is that I set up my poker hand type function to only take one dimension of the two dimensional array. Is there a way to effectively build a ranking system for players with what I have?
Here are some notes I made to myself elsewhere that may also be useful: determingPlayerHand only takes one subscript of the two dimensional array. I need playerRanking to take both subscripts. How can I make this happen so that my rankings will return properly to each player? The ranking returning values should be fine, I think. I initially had it as just true or false, 1 or 0, but then realized that wasn't specific enough
Please let me know what other information I can provide if I need to make this more clear or relevant.
After M Oehm's comment, I want to update this to reflect some other information that I realized would be useful.
Part of the parameters of the problem I'm solving require certain things to be the way they are. If I had my choice in changing them, I think there are better ways to do this as well. However, the deck being as it is, the shuffling algorithm, and the deal algorithm are built to specification of the problem. As for hands evaluating to what they should, so far they do, and I wrote it based on the idea that ace needs to go high at a certain point, which is part of why it's so complicated. The two dimensional array with [PLAYERS][HAND] is meant to make it so that cards are dealt in alternating order to each player from the top of the deck, as would be done in real life.

You have gotten off to a bad start when chosing how to represent your deck and the hands.
You represent the cards as integers from 0 to 51 in the deck's factory order from Ace of Hearts to King of Clubs. That's fine. You can determine the rank and suit from the card number:
rank = card % 13;
suit = card / 13;
That's not what you do in your determineFace/Suit functions. Next, the deck ist a one-dimensional array of cards:
int deck[52];
You can shuffle this array with one of the well-known shuffling algorithms, e.g. Fisher-Yates. You represent the deck as two-dimensional array, which doesn't make the shuffling any easier. It it also not clear what the two dimensions of the deck are. (Okay, they are suit and rank, but after shuffling, that doesn't make sense any longer.)
In a one-dimensional array, the first player's hand are the first five cards and the second player's hand are cards 5 to 9.
Your algorithms to determine the hands are too complicated and have some copy-and-paste errors. Evaluating poker hands boils down to three criteria:
Flush: Are all cards of a hand of the same suit?
Straight: Are all ranks consecutive? (With the special rule that the ace can be played high or lowas appropriate)
Multiples: Most hands have pairs, triplets or quadruplets of cards or combinations thereof, so you need a "histogram" of ranks, sorted by occurrence.
With that data, you can determine your hands. You also need secondary data to distinguish between two equal hands, e.g. a pair of Kings and a pair of Nines.
I suggest you start afresh, switch on compiler warnings and implement shuffling, dealing and the three hand criteria step by step with verification between the steps. (You can call these steps "Milestones", if you like.)

Related

how to see if there are 1 or 2 poker pairs in a hand in C

I am trying to develop a C program that checks if there are 1 or 2 pairs in a 5 card poker hand.
I am using a 5x3 array where every line is a card (the 3rd column being for the \0 character). Every time I execute the code it always shows the "two pairs" print.
I want to make sure that each letter (i, j, a, b) representing each line is different. Any help?
P.S.: This is for a university/college project, I have only started programming a few months ago from absolute scratch, so any detailed explanations on my mistakes would be very much appreciated :)
#include <stdio.h>
#include <stdlib.h>
char (cards[5][3])=
{
"5S", "6D", "4H", "KD", "5C"
};
int main ()
{
pair (cards[5][3]);
return 0;
}
void pair (char (arg[n][0]))
{
int i,j,a,b;
if (i!=j!=a!=b)
{
if ((arg[i][0]==arg[a][0])&&(arg[b][0]!=arg[j][0]))
{
printf("2 -> pair");
}
if ((arg[i][0]==arg[a][0])&&(arg[b][0]==arg[j][0]));
{
printf("3 -> two pairs");
}
if ((arg[i][0]!=arg[a][0])&&(arg[b][0]!=arg[j][0]))
{
printf("there is no pair");
}
}
else
{
printf("there is no pair");
}
}
The posted code has several issues, both logical and syntactical, some have been pointed out in the comments.
Just to pick one, consider this line
if ((arg[i][0]==arg[a][0])&&(arg[b][0]==arg[j][0]));
{
// This body will never be executed ^
}
I'd suggest to restart from scratch and to proceed in small steps. See, for instance, the following minimal implementation
// Include all the needed header files, not the unneeded ones.
#include <stdio.h>
// Declare the functions prototype before their use, they will be defined after.
int count_pairs(int n, char const cards[][3]);
// Always specify the inner size, ^ when passing a multidimensional array
void show_score(int n_pairs);
int have_the_same_value(char const *a, char const *b);
int main (void)
{
char hand[5][3] = {
// ^^^^^^ You could omit the 5, here
"5S", "6D", "4H", "KD", "5C"
};
int n_pairs = count_pairs(5, hand);
// Always pass the size ^ if there isn't a sentinel value in the array
show_score(n_pairs);
return 0;
}
// This is a simple O(n^2) algorithm. Surely not the best, but it's
// a testable starting point.
int count_pairs(int n, char const cards[][3])
{
// Always initialize the variables.
int count = 0;
// Pick every card...
for (int i = 0; i < n; ++i)
{
// Compare (only once) with all the remaining others.
for (int j = i + 1; j < n; ++j)
{ // ^^^^^
if ( have_the_same_value(cards[i], cards[j]) ) {
++count;
}
}
}
return count;
}
int have_the_same_value(char const *a, char const *b)
{
return a[0] == b[0];
}
// Interpret the result of count_pairs outputting the score
void show_score(int n_pairs)
{
switch (n_pairs)
{
case 1:
printf("one pair.\n");
break;
case 2:
printf("two pairs.\n");
break;
case 3:
printf("three of a kind.\n");
break;
case 4:
printf("full house.\n");
break;
case 6:
printf("four of a kind.\n");
break;
default:
printf("no pairs.\n");
}
}
Note that my count_pairs function counts every possible pair, so if you pass three cards of the same kind, it will return 3 (given AC, AS, AD, all the possible pairs are AC AS, AC AD, AS AD).
How to correctly calculate all the poker ranks is left to the reader.
Major improvements can be made to the pair function to make it slimmer. However, this answers your questions and solves several corner cases:
#include <stdio.h>
#include <stdlib.h>
void pairCheck(char hand[][2])
{
int pairCount = 0;
int tmpCount = 0;
char tmpCard = '0';
char foundPairs[2] = {0};
// Check Hand One
for(int i =0; i < 5; i++)
{
tmpCard = hand[i][0];
for(int j = 0; j < 5; j++)
{
if(tmpCard == hand[j][0] && i != j)
{
tmpCount++;
}
if(tmpCount == 1 && (tmpCard != foundPairs[0] && tmpCard != foundPairs[1]))
{
foundPairs[pairCount] = tmpCard;
pairCount++;
}
tmpCount = 0;
}
}
printf("Pair Count Hand One: %i\r\n",pairCount);
//Reset Variables
foundPairs[0] = 0;
foundPairs[1] = 0;
tmpCard = '0';
pairCount = 0;
// Check Hand One
for(int i =0; i < 5; i++)
{
tmpCard = hand[i][1];
for(int j = 0; j < 5; j++)
{
if(tmpCard == hand[j][1] && i != j)
{
tmpCount++;
}
if(tmpCount == 1 && (tmpCard != foundPairs[0] && tmpCard != foundPairs[1]))
{
foundPairs[pairCount] = tmpCard;
pairCount++;
}
tmpCount = 0;
}
}
printf("Pair Count Hand Two: %i",pairCount);
}
int main ()
{
char cards[5][2] = { {'5','H'},{'6','D'},{'4','H'},{'K','D'},{'5','C'}};
pairCheck(cards);
return 0;
}
This function will treat three, four, or five of a kind as a single pair. If you want a different behavior the change should be easy.

Suggestions/improvements on my simple Blackjack program

I am trying to get a head start on my class next semester so I made this basic version of Blackjack to start understanding the basics of C and I would love any thoughts you have that could help me gain a better understanding of C and its normal coding practices.
A lot of the things in C are new to me as I am coming from a background in JAVA so if I made a mistake in function declaration, in my use of pointers, or if I was thinking about how to approach the problem incorrectly and should have done things a completely different way please let me know.
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <string.h>
const int handSize = 2;
int randCard(int *isAce);
int sumCards(int cards[], int *hasAce[2]);
int main() {
srand(time(NULL));
int playGame = 0;
int dealerIsAce[handSize];
int *dealerAcePointers[handSize];
int playerIsAce[handSize];
int *playerAcePointers[handSize];
for (int i = 0; i < handSize; i++) {
dealerIsAce[i] = 0;
playerIsAce[i] = 0;
dealerAcePointers[i] = &dealerIsAce[0];
playerAcePointers[i] = &playerIsAce[0];
}
int dealerCards[] = {randCard(dealerAcePointers[0]), randCard(dealerAcePointers[1])};
int playerCards[] = {randCard(playerAcePointers[0]), randCard(playerAcePointers[1])};
int dealerSum;
int playerSum;
do {
printf("The dealer:\n? + %d\n\n", dealerCards[1]);
dealerSum = sumCards(dealerCards, dealerAcePointers);
if (dealerSum > 17) {
dealerCards[0] = dealerSum;
dealerCards[1] = randCard(dealerAcePointers[1]);
}
playerSum = sumCards(playerCards, playerAcePointers);
printf("You:\n%d + %d = %d", playerCards[0], playerCards[1], playerSum);
if (playerSum > 21) {
printf(" BUSTED");
playGame = 1;
} else {
printf("\nWould you like to \"hit\" or \"stand\"?\n");
}
if (playGame == 0) {
char stream[10];
if (strcmp(gets(stream), "hit") == 0) {
playerCards[0] = playerSum;
playerCards[1] = randCard(playerAcePointers[1]);
} else {
playGame = 1;
}
}
} while (playGame == 0);
if (playerSum > 21) {
if (dealerSum > 21) {
printf("\nTie!");
} else {
printf("\nDealer Wins!");
}
} else {
if (playerSum > dealerSum) {
printf("\nPlayer Wins!");
} else if (playerSum == dealerSum) {
printf("\nTie!");
} else if (playerSum < dealerSum) {
printf("\nDealer Wins!");
}
}
return 0;
}
int randCard(int *isAce) {
int card = rand() % 13 + 2;
if (card > 11) {
card = 10;
} else if (card == 11) {
*isAce = 1;
}
return card;
}
int sumCards(int cards[], int *hasAce[2]) {
int sum = cards[0] + cards[1];
if (sum > 21 && *hasAce[0] == 1) {
sum -= 10;
*hasAce[0] = *hasAce[1];
if (*hasAce[1] == 1) {
*hasAce = 0;
}
}
return sum;
}
As mentioned by a commenter, this could be better asked elsewhere, however I'm going to offer some opinions anyway. These are all opinions, and everyone will probably disagree with something I've said.
Incidentally, I'm entirely ignoring the rules of BlackJack and assuming that all your logic is correct.
First and foremost, there aren't any comments in the code. You mention this being for a class, therefore commenting is even more important as some poor person has to decipher a load of these to work out what they do. (Commenting code is important anyway incidentally, I always use the "Will I work out what this does in a months time" approach)
Having that much stuff in main() is unusual. I would personally break it out into a different function. You could then also consider putting it in a separate file, with a header file for the function declarations.
handSize is being used as a constant, you could probably make this a preprocessor macro instead: #define HAND_SIZE 2
The do-while loop could be replaced with a while(true) loop, then using the 'break' keyword to escape when you're done (Where you are currently setting playGame = 1. This also has the advantage of not having the if(playGame == 0) conditional. Also, in C, a boolean variable is 1 for true and 0 for false, so it would be more normal to have int playGame = 1; and then do { } while(playGame) and playGame = 0; when you're done with the loop. This case is a special in that you actually want to break out, rather than run to the end of the loop.
gets() was removed in C11 for security reasons (Implicit declaration of 'gets')
On a more whole-program points. These are even more subjective, and are mostly just how I would have solved the problem:
I personally would make dealerCards and playerCards large enough to hold the maximum possible number of cards (which I think is 5 in blackjack?) and initialise them to 0. Currently you are assigning the sum of the current cards to the first element of the dealerCards array, meaning that the values are not actual cards.
Rather than use separate arrays to track whether or not cards are aces, I would have made an enum for {EMPTY_SLOT, ACE, TWO, ..., JACK, QUEEN, KING} and then stored that in my Cards arrays. randCard can then just return a member of the enum, and take no arguments, and sumCards just iterates across the array and sums it. This also means that you can display the user's actual hand to them, rather than just the total.
For reference purposes, I've modified your code to how I would do it. The logic may not be perfect (or the exact same version of blackjack) but this is the sort of thing I would submit for a "program blackjack in C" homework. N.B. This could also do with a few more comments, particularly a block one at the top explaining what the general structure is.
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <string.h>
#define HAND_SIZE 5
typedef enum
{
// Technically I didn't need to set the values, as they are the defaults but
// it's good to be explicit when you're using the order for something.
EMPTY = 0,
ACE = 1,
TWO = 2,
THREE,
FOUR,
FIVE,
SIX,
SEVEN,
EIGHT,
NINE,
TEN,
JACK,
QUEEN,
KING
} card_t; // Types you typedef generally end _t as a convention.
// These should be in a separate header, but I'm keeping this in 1 file for StackOverflow
card_t randCard();
int sumCards(card_t cards[]);
void play();
int main()
{
srand(time(NULL));
play();
return 0;
}
card_t randCard()
{
int card = rand() % 13 + 1;
return (card_t)card;
}
int sumCards(card_t cards[])
{
int total = 0;
int num_aces = 0;
for (int i = 0; i < HAND_SIZE; i++) {
switch(cards[i]) {
case ACE:
num_aces++;
total += 11;
break;
case JACK:
case QUEEN:
case KING:
total += 10;
break;
default:
total += (int)cards[i]; // Relying here on the fact that the cards are in the correct order.
break;
}
}
while (num_aces > 0 && total > 10) {
total -= 10;
num_aces--;
}
return total;
}
void play()
{
card_t playerCards[HAND_SIZE];
card_t dealerCards[HAND_SIZE];
card_t dealerKnown[HAND_SIZE]; // Equivalent to dealer cards, but with first 2 elements blank
for (int i = 0; i < HAND_SIZE; i++) {
playerCards[i] = EMPTY;
dealerCards[i] = EMPTY;
dealerKnown[i] = EMPTY;
}
playerCards[0] = randCard();
playerCards[1] = randCard();
dealerCards[0] = randCard();
dealerCards[1] = randCard();
int num_cards = 2;
while(num_cards <= HAND_SIZE) {
printf("The dealer: ? + %d\n\n", sumCards(dealerKnown));
if (sumCards(dealerCards) > 17) {
dealerCards[num_cards] = randCard();
}
int playerSum = sumCards(playerCards);
printf("Your total: %d\n", playerSum);
if (playerSum > 21) {
printf("BUSTED\n");
break;
} else {
printf("Would you like to \"hit\" or \"stand\"?\n");
}
char stream[10];
if (strcmp(fgets(stream, sizeof(stream), stdin), "hit\n") != 0) {
break;
}
playerCards[num_cards] = randCard();
num_cards++;
}
printf("\n"); // Printing the new line separately rather than at the beginning of all the strings below
int playerSum = sumCards(playerCards);
int dealerSum = sumCards(dealerCards);
if (playerSum > 21) {
if (dealerSum > 21) {
printf("Tie!");
} else {
printf("Dealer Wins!");
}
} else {
if (playerSum > dealerSum) {
printf("Player Wins!");
} else if (playerSum == dealerSum) {
printf("Tie!");
} else if (playerSum < dealerSum) {
printf("Dealer Wins!");
}
}
printf("\n");
}

Algorithm in C - who is the winner team

I need to store data from a tournament. I need to know how many teams will play(n) and the number of games they will play (n!). Then, the team's names and their results. Something like this:
Input:
3 6
TeamX
TeamY
TeamZ
TeamX 0 - TeamY 3
TeamX 1 - TeamZ 0
TeamY 1 - TeamX 0
TeamY 0 - TeamZ 0
TeamZ 0 - TeamX 0
TeamZ 3 - TeamY 1
The output will be something like:
This winner is TeamY, with 7 point(s)
Won 2 game(s), tied 1 game(s) e lost 1 game(s)
Scored 5 goal(s) e suffered 3 goal(s)
EDIT2:
THIS is what I have until now. But it won't work at the scanf.... I can't type the team's names after the number of teams and games. Can you run it and try to understand?
Guide: I have game and team structs, first I add team names to theTeams array of structs, then I add the games to the games array of structs. Then, if/else blocks to do the maths of wins, losses, etc and finally see and printf the winner.
#include <stdio.h>
#include <string.h>
struct game {
const char *teamA;
int scoreA;
const char *teamB;
int scoreB;
};
struct team {
const char *teamA;
int score;
int wins;
int losses;
int ties;
int scored;
int suff;
};
struct team team_new(const char *teamA, int score, int wins, int losses, int ties, int scored, int suff)
{
struct team t;
t.teamA = strdup(teamA);
t.score = score;
t.wins = wins;
t.losses = losses;
t.ties = ties;
t.scored = scored;
t.suff = suff;
return t;
};
struct game game_new(const char *teamA, int scoreA, const char *teamB, int scoreB)
{
struct game g;
g.teamA = strdup(teamA);
g.scoreA = scoreA;
g.teamB = strdup(teamB);
g.scoreB = scoreB;
return g;
};
int main(void)
{
int i, j, teams, nrgames, biggestScore, whichTeam;
scanf("Teams and number of games %d %d", &teams, &nrgames);
//add team names to theTeamss struct
struct team theTeams[teams];
size_t num_teams = 0;
for (i = 0; i < teams; ++i)
{
char teamA[20];
if (scanf("%s", teamA) != 1)
exit(0);
theTeams[++num_teams] = team_new(teamA, 0, 0, 0, 0, 0, 0);
}
struct game games[nrgames]; //add games
size_t num_games = 0;
for (i = 0; i < sizeof games / sizeof *games; ++i)
{
char teamA[20], teamB[20];
int scoreA, scoreB;
if (scanf(" %s %d - %s %d", teamA, &scoreA, teamB, &scoreB) != 4)
exit(0);
games[++num_games] = game_new(teamA, scoreA, teamB, scoreB);
}
//run through games[] to change values of theTeams[] scores
//games - A against B
for (i = 0; i < sizeof games / sizeof *games; ++i)
{
for (j = 0; j < sizeof theTeams / sizeof *theTeams; ++j)
{
if ((games[i].teamA == theTeams[j].teamA)) //team(A)
{
//if A wins
if(games[i].scoreA > games[i].scoreB)
{
theTeams[j].score += 3;
theTeams[j].wins += 1;
theTeams[j].scored = games[i].scoreA;
}
//if A loses
else if (games[i].scoreA < games[i].scoreB)
{
theTeams[j].score += 0;
theTeams[j].losses += 1;
theTeams[j].suff = games[i].scoreB;
}
else //tied
{
theTeams[j].score += 1;
theTeams[j].ties += 1;
theTeams[j].suff = games[i].scoreA;
}
}
if ((games[i].teamB == theTeams[j].teamA))//team(B)
{
//if B wins
if(games[i].scoreB > games[i].scoreA)
{
theTeams[j].score += 3;
theTeams[j].wins += 1;
theTeams[j].scored = games[i].scoreB;
}
//if B loses
else if (games[i].scoreB < games[i].scoreA)
{
theTeams[j].score += 0;
theTeams[j].losses += 1;
theTeams[j].suff = games[i].scoreA;
}
else //tied
{
theTeams[j].score += 1;
theTeams[j].ties += 1;
theTeams[j].suff = games[i].scoreB;
}
}
}
}
//accessing to the winner team
biggestScore = theTeams[0].score;
whichTeam = 0;
for (i = 0; i < sizeof theTeams / sizeof *theTeams; ++i){
if (theTeams[i].score > biggestScore){
biggestScore = theTeams[i].score;
whichTeam = i;
}
}
//output
printf("\n This winner is %s, with %d point(s), Won %d game(s), tied %d game(s) and lost %d game(s), Scored %d goal(s) e suffered %d goal(s)\n", theTeams[whichTeam].teamA, theTeams[whichTeam].score, theTeams[whichTeam].wins, theTeams[whichTeam].losses, theTeams[whichTeam].ties, theTeams[whichTeam].scored, theTeams[whichTeam].suff);
return 0;
}
There are no "problems" with C language and strings; you can do whatever you want. It's just a bit more responsibility than in other languages.
You seem to need an array of structures, yes. I would recommend modelling it as just an array of games played, where each game records the teams that took part, and their scores. No need to first record a list of "available" teams, it's easier to just extract that from the game data afterwards.
struct game {
const char *teamA;
int scoreA;
const char *teamB;
int scoreB;
};
struct game game_new(const char *teamA, int scoreA, const char *teamB, int scoreB)
{
struct game g;
g.teamA = strdup(teamA);
g.scoreA = scoreA;
g.teamB = strdup(teamB);
g.scoreB = scoreB;
return g;
}
and then in the man program:
int main(void)
{
struct game games[100];
size_t num_games = 0;
for (size_t i = 0; i < sizeof games / sizeof *games; ++i)
{
char teamA[100], teamB[100];
int scoreA, scoreB;
if (scanf(" %s %d - %s %d", teamA, &scoreA, teamB, &scoreB) != 4)
break;
games[++num_games] = game_new(teamA, scoreA, teamB, scoreB);
}
}
C like all programming languages is only as good as the plan you have laid out to model the data
For this, an array of arrays that stores the data can work.
Might want to also consider a database for relationships based on teams. Then you can also add metadata and the like (for example, timestamps). Though its only good if you don't mind externalising application beyond C.

Poker Program in c Programming

I've put together a program that deals out a hand poker perfectly. Now I want the program to realize when the hand that is dealt is straight, flush, pair, 3 of a kind, and 4 of kind. The program runs but never prints the right condition when needed to, I believe I have some placement or logic error that I can't find. Here's what I have so far.
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define SUITS 4
#define FACES 13
#define CARDS 52
#define HAND 5//draw only 5
#define TRUE 1//positive print condition
#define FALSE 0//negative print condition
//prototypes
shuffle( unsigned int wDeck[][FACES]);//shuffling modifies wDeck
deal(unsigned int wDeck[][FACES], const char *wFace[],
const char *wSuit[] );//dealing doesn't modify the arrays
//true/false conditions
typedef int bool;
bool straight, flush, four, three;
int pairs; //0,1, or 2
int main()
{
//initialize suit array
const char *suit[ SUITS ] =
{
"Hearts", "Diamonds", "Clubs", "Spades"
};
//initialize face array
const char *face[ FACES ] =
{
"Ace", "Deuce", "Three", "Four",
"Five", "Six", "Seven", "Eight",
"Nine", "Ten", "Jack", "Queen", "King"
};
int suitInHand[SUITS], facesInHand[FACES];
analyzeHand(suitInHand, facesInHand);
//initialize deck array
unsigned int deck[SUITS][FACES] = { 0 };
srand( time( NULL ) );//seed random-number generator
shuffle( deck );//shuffle the deck
deal( deck, face, suit );//deal the deck
}//end main
//shuffle cards in deck
shuffle( unsigned int wDeck[][FACES])
{
size_t row;//row number
size_t column;//column number
size_t card;//counter
//for each of the cards, choose slot of deck randomly
for( card = 1; card <= CARDS; ++card) {
//choose new random location until unoccupied slot found
do {
row = rand() % SUITS;
column = rand() % FACES;
}
while( wDeck[ row ][ column ] !=0);
//end do-while
//pace card number in chosen slot of deck
wDeck[ row ][ column ] = card;
}//end for
}//end function shuffle
//deal cards in deck
deal(unsigned int wDeck[][FACES], const char *wFace[],
const char *wSuit[] )
{
size_t card;//card counter
size_t row;//row counter
size_t column;//column counter
//deal each of the cards
for( card = 1; card <= HAND; ++card) {
//loop through rows of wDeck
for( row = 0; row < SUITS; ++row) {
//loop through column of wDeck for current row
for( column = 0; column < FACES; ++column) {
//if slot contains current card, display card
if( wDeck[ row ][ column ] == card ) {
printf("%5s of %-8s%c", wFace[ column ], wSuit[ row ],
card % 2 == 0 ? '\n' : '\t' );//2 column format
}//end if
}//end for
}//end for
}//end for
}//end function deal
analyzeHand(int suitsInHand[], int facesInHand[])
{
int num_consec = 0;
int rank, suit;
straight = FALSE;
flush = FALSE;
four = FALSE;
three = FALSE;
pairs = 0;
for (suit = 0; suit < SUITS; suit++)
if ( suitsInHand[suit] == 5)
flush = TRUE;
rank = 0;
while ( facesInHand[rank] == 0)
rank++;
for (; rank < FACES && facesInHand[rank]; rank++)
num_consec++;
if(num_consec == 5){
straight = TRUE;
return;
}
for(rank = 0; rank < FACES; rank++) {
if(facesInHand[rank] == 4)
four = TRUE;
if(facesInHand[rank] == 3)
three = TRUE;
if(facesInHand[rank] == 2)
pairs++;
}
if(four)
printf("Four of a kind\n");
else if(straight)
printf("Straight\n");
else if(pairs == 2)
printf("Two Pairs\n");
else if(pairs == 1)
printf("Pair\n");
else
printf("Better Luck Next Time\n");
}
There seems to be a problem with the logic in your main() function :
int suitInHand[SUITS], facesInHand[FACES];
analyzeHand(suitInHand, facesInHand);
You are declaring two arrays of ints without initializing them, and them you use them in your analyzeHand() function while they are empty.
You must populate those 2 arrays first if you want to get any kind of valid result.
EDIT : Depending on what kind of infos will be stored in those 2 arrays, their may be some problems with the logic of your analyzeHand() function.

C, card game WAR

I am trying to create a War card game using C. Instead of making 2 decks for the "discarded" cards to be added to a players hand at a later time, I am instead just trying to add the dealers card[i] - which was previously compared with players card[i] to ensure that the player won the hand - to the players hand directly. index is used to make sure there are no empty elements playerhand ever points to by appending another card on to the end of the “hand,” which initially has 26 cards (half the deck). the deck is initially split in 2, the first 26 cards deck[0-25] going to the player's hand, and the last 26 deck[26-51] going to the dealers hand.
here is my code in question:
//adds new card to deck at given index
void addToPlayerHand(int i) {
int index=0;
playerHand[index+26] = deck[i+26];
index++;
}
here is my full game code:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
//Type Stucture for Card
typedef struct cards {
char suit;
int face;
struct cards *listp; // didn't use in this program
} card;
//Functions
//
int welcome();
//int checkWinWar();
int playGame();
int getComparison(card *firstCard,card *secndCard,int index);
void printingGame(int a,int b, int i);
void addToPlayerHand(int i);
void addToDealerHand(int i);
int addToDeck(card myCards, int index);
void hitPlayer(card theCard);
void hitDealer(card theCard);
void initilizeDeck();
int shuffleDeck();
int printFun(); // not used for game play
void freePlayers();
//Card Dynamics
//
card *playerHand; // contains contents of players cards
card *dealerHand; // contains contents of dealers cards
//Deck of 52 Cards with discard decks
card deck[52];
card playerDeck[52];
card dealerDeck[52];
int numPlayer = 0;
int numAllPlayer = 0;
int numDealer = 0; // needed for temp
int numAllDealer = 0;
//Main
int main(void) {
printf("Hello..Welcome to WAR\n");
//Game loop
while (welcome() == 1) { // welcome returns whether the player wants to play (1) or not (0)
// put first card face up
// display how many cards
// indicate (if/if no) war has occurred
// complete the war
// add cards to player discard pile
// check player for card count
// if end game conition met, end hame
if(playGame() == 1) { // playGame returns 1 if the function went through correctly
if(checkWinWar()==1){
}
else{
}
} else {
printf("Bust! Try Again\n\n");
freePlayers(); // refreshes the dynamics of the hands
}
}
//initilizeDeck();
//shuffleDeck();
//printFun();
return 0;
}
//To allow the player to begin the game; 1 = True 0 = False
int welcome() {
printf("Play a new round of WAR? (enter/return for yes):\t");
if(getchar()=='\n'){
return 1;
}
else
return 0;
}
// refreshes the game and players
void freePlayers () {
numDealer = 0;
numPlayer = 0;
numAllPlayer = 0;
numAllDealer = 0;
free(playerHand);
free(dealerHand);
playerHand = NULL; // needed so playerHand doesn't point to anything
dealerHand = NULL;
return;
}
// Playing of the game
int playGame() {
initilizeDeck(); // initialize Deck returns the new deck of cards
shuffleDeck(); // shuffleDeck returns the shuffled deck of cards
int gameTrue = 1; // gameTrue checks the state of the game
int war = 0;
int PlayerCardsRemaining=0;
int DealerCardsRemaining=0;
int temp,i,j=0;
while (gameTrue == 1) {
// splitting the deck
for (j=0;j<26;j++){
hitPlayer(deck[j]); // adding cards to playerHand
PlayerCardsRemaining+=1; //adding to player deck count.
}
for (j=26;j<52;j++){
hitDealer(deck[j]);
DealerCardsRemaining+=1;} // adding to dealer deck count.
i=0;
while(PlayerCardsRemaining>0 && DealerCardsRemaining>0 && i<26) {
printingGame(DealerCardsRemaining,PlayerCardsRemaining, i);
if (getComparison(playerHand, dealerHand, i)==0){
addToDealerHand(i);
DealerCardsRemaining++;
return 1;
}
else if(getComparison(playerHand,dealerHand,i)==1){
addToPlayerHand(i);
PlayerCardsRemaining++;
return 1;
}
else if(getComparison(playerHand, dealerHand, i)==2){
printf("There is an impending WAR\n");
printf("press enter to engage in the WAR");
war=1;
if(war==1 && DealerCardsRemaining>=4 && PlayerCardsRemaining>=4){
temp=getComparison(playerHand, dealerHand, i+4);
while(war==1){
if(temp==0){
for(i=i;i<i+4;i++){
addToDealerHand(i);
}
war=0;
PlayerCardsRemaining-=4;
DealerCardsRemaining+=4;
}
else if(temp==1){
for(i=i;i<i+4;i++){
addToPlayerHand(i);
}
war=0;
DealerCardsRemaining-=4;
PlayerCardsRemaining+=4;
}
else
war=1;
}
return 1;
}
if (DealerCardsRemaining<<4){
for(i=i;i<i+4;i++){
addToPlayerHand(i);
}
}
else if (PlayerCardsRemaining<<4){
for(i=i;i<i+4;i++){
addToDealerHand(i);
}
}
}
i++; // increment i
}
}
return 0;
}
void printingGame(int DealerCardsRemaining, int PlayerCardsRemaining, int i)
{
// Gameplay Prompts
//Prints interface that comes up after player(s) choose to play
printf("*********\t\t*********\n");
printf("*\t \t*\t\t*\t \t*\n");
// Cases for cards that are face cards
if(dealerHand[i].face==11){ // if dealer card is a jack
printf("*\tJ\t*\t\t");
if (playerHand[i].face<11){ // if player card isnt a face card
printf("*\t%d\t*\n",playerHand[i].face);
}
else if(playerHand[i].face==11){ // if player card is a face card
printf("*\tJ\t*\n");
}
else if(playerHand[i].face==12){
printf("*\tQ\t*\n");
}
else if(playerHand[i].face==13){
printf("*\tK\t*\n");
}
else if(playerHand[i].face==14){
printf("*\tA\t*\n");
}
}
else if(dealerHand[i].face==12){ // if dealer card is a queen
printf("*\tQ\t*\t\t");
if (playerHand[i].face<11){ // if player card isnt a face card
printf("*\t%d\t*\n",playerHand[0].face);
}
else if(playerHand[i].face==11){ // if player card is a face card
printf("*\tJ\t*\n");
}
else if(playerHand[i].face==12){
printf("*\tQ\t*\n");
}
else if(playerHand[i].face==13){
printf("*\tK\t*\n");
}
else if(playerHand[i].face==14){
printf("*\tA\t*\n");
}
}
else if(dealerHand[i].face==13){ // if dealer card is a king
printf("*\tK\t*\t\t");
if (playerHand[i].face<11){ // if player card isnt a face card
printf("*\t%d\t*\n",playerHand[i].face);
}
else if(playerHand[i].face==11){ // if player card is a face card
printf("*\tJ\t*\n");
}
else if(playerHand[i].face==12){
printf("*\tQ\t*\n");
}
else if(playerHand[i].face==13){
printf("*\tK\t*\n");
}
else if(playerHand[i].face==14){
printf("*\tA\t*\n");
}
}
else if(dealerHand[i].face==14){ // if dealer card is an ace
printf("*\tA\t*\t\t");
if (playerHand[i].face<11){ // if player card isnt a face card
printf("*\t%d\t*\n",playerHand[i].face);
}
else if(playerHand[i].face==11){ // if player card is a face card
printf("*\tJ\t*\n");
}
else if(playerHand[i].face==12){
printf("*\tQ\t*\n");
}
else if(playerHand[i].face==13){
printf("*\tK\t*\n");
}
else if(playerHand[i].face==14){
printf("*\tA\t*\n");
}
}
if (dealerHand[i].face<11 && playerHand[i].face<11){ // if both cards arent face cards
printf("*\t%d\t*\t\t*\t%d\t*\n",dealerHand[i].face,playerHand[i].face);
}
printf("*\t \t*\t\t*\t \t*\n");
printf("*********\t\t*********\n");
printf("Dealer: %d cards. ",DealerCardsRemaining); // print how many cards the 'dealer' has
printf("Player: %d cards. ",PlayerCardsRemaining); // print how many cards the player has
}
int getComparison (card *firstCard, card *secndCard, int i)
{
int a,b;
a=firstCard[i].face;
b=secndCard[i].face;
if (b>a)
return 0;
else if (a>b)
return 1;
else
return 2;
}
// gives player another card
void hitPlayer (card theCard) {
if(numPlayer == 0) { // if hitPlayer is giving playerHand its first card (for new deck or initial deck)
if (numAllPlayer == 0) // if its the first hand
numAllPlayer = 1; // there is only one card in need of space
else // if its not the first hand
numAllPlayer++; // you need space for all existing cards plus the one just added
void *_tmp = realloc(playerHand, (numAllPlayer * sizeof(card))); // realloc is used since playerHand never has a constant size
if (!_tmp)
{
fprintf(stderr, "ERROR: Couldn't realloc memory!\n"); // stderr prints
}
playerHand = (card*)_tmp; // playerHand is card type pointer which points to void pointer tmp which is reallocating memory
}
playerHand[numPlayer] = theCard;
numPlayer++;
}
// gives dealer another card
void hitDealer (card theCard) {
if(numDealer == 0) {
if (numAllDealer == 0)
numAllDealer = 1;
else
numAllDealer++;
void *_tmp = realloc(dealerHand, (numAllDealer * sizeof(card)));
if (!_tmp)
{
fprintf(stderr, "ERROR: Couldn't realloc memory!\n");
}
dealerHand = (card*)_tmp;
}
dealerHand[numDealer] = theCard;
numDealer++;
}
// creates a new deck of cards
void initilizeDeck() {
//Loop Indexes like: count, i.... etc
int i, p;
int count = 0;
card temp;
for (i = 1; i < 5; i++) {
for (p = 2; p <= 14; p++) {
//Clubs
if (i == 1) {
temp.suit = 'C';
temp.face = p;
}
//Diamonds
if (i == 2) {
temp.suit = 'D';
temp.face = p;
}
//Hearts
if (i == 3) {
temp.suit = 'H';
temp.face = p;
}
//Spades
if (i == 4) {
temp.suit = 'S';
temp.face = p;
}
addToDeck(temp, count);
count++;
}
}
}
//adds new card to deck at given index
int addToDeck(card myCards, int index) {
deck[index] = myCards;
return 1;
}
//adds new card to deck at given index
void addToPlayerHand(int i) {
int index=0;
playerHand[index+26] = deck[i+26];
index++;
}
//adds new card to deck at given index
void addToDealerHand(int i) {
int index=0;
dealerHand[index+26] = deck[i];
index++;
}
//finds deck and shuffles cards 100 times from swaping a random value from 1-52
int shuffleDeck() {
card temp; // for an individual card
int i,p;
srand(time(NULL));
for (i = 0; i < 100; i++) {
for (p = 0; p < 52; p++) {
int r = rand()%52;
temp = deck[p]; // swaps to randomly pick another card
deck[p] = deck[r];
deck[r] = temp;
}
}
return 0;
}
it keeps telling me i have a bad access code, code=2.
any help would be awesome.
I'll dispense with the "I'd never code this that way" dialogue long enough to suggest that this loop ideology:
for(i=i;i<i+4;i++)
will look well past the limits of your card arrays and into the land of undefined behavior. Think about it a minute. Then ask yourself this question: At what point will i no longer be less than i+4 ? Answer: when you reach the point when i+4 overflows to become negative (assuming the optimizer doesn't throw out the condition entirely and just assume it is always true; thanks Jeremy).
I.e. INT_MAX-3. On a 32-bit system that is only about 2147483562 slots past the end of your array.
This error is repeated 3 more times in the playGame() function.

Resources