How come my straight counter remains at a value of zero? - c

I am making a program in the C90 standard using GCC in Ubuntu 10.04, that randomly generates a hand of 5 card structs and calculates if the hand is a flush, straight, etc.
My function to calculate straights is:
int isStraight(card hand[]) {
int i, count = 1, result = 0;
for (i = 0; i < HAND_SIZE-1; i++) {
if (hand[i].pips == ((hand[i+1].pips) + 1)) {
count++;
}
}
if (count == HAND_SIZE)
result = 1;
return result;
}
My main function:
int main(void) {
int i, j;
int numHands = 0;
int flushCount = 0;
int straightCount = 0;
int xOfAKindCount = 0;
int straightFlushCount = 0;
int fullHouseCount = 0;
int isTwoPairCount = 0;
card deck[DECKSZ] = {0};
card hand[HAND_SIZE] = {0};
stack deckStack = {0};
stack handStack = {0};
initDeck(deck);
shuffleDeck(deck);
reset(&deckStack);
for (i = 0; i < DECKSZ; i++) {
push(deck[i], &deckStack);
}
do {
reset(&handStack);
for (i = 0; i < HAND_SIZE; i++) {
push(pop(&deckStack), &handStack);
if (isEmpty(&deckStack)) {
reset(&handStack);
shuffleDeck(deck);
reset(&deckStack);
for (j = 0; j < DECKSZ; j++) {
push(deck[j], &deckStack);
}
}
hand[i] = handStack.s[i];
}
numHands += 1;
arrangeHand(hand);
flushCount += isFlush(hand);
straightCount += isStraight(hand);
xOfAKindCount += isXOfAKind(hand, 2, 0);
straightFlushCount += isStraightFlush(hand);
fullHouseCount += isFullHouse(hand);
isTwoPairCount += isTwoPair(hand);
printf("Flushes:%d Straights:%d SF's:%d Number of Hands:%d\r",
flushCount, straightCount, straightFlushCount, numHands);
} while (1);
printf("\n");
return EXIT_SUCCESS;
}
My issue is my variable declared inside my function, result, is never set to 1 to indicate whether or not the hand is a straight, which therefore means my straightCount variable always remains at a value of zero. I do not have access to a debugger and in my mind the code I have makes sense. I'm new to programming in C, so if anybody could help me point out what is wrong with my function, I'd appreciate it. Thanks!

int isStraight(card hand[]) {
int step = 0;
for(int i = 1;i < HAND_SIZE; i++)
if(hand[i].pip != hand[i-1].pip+1)
/* Substitute step with i!=1 if over-edge invalid */
if(step || hand->pip != 1 || hand[i].pip != hand[i-1].pip+13-HAND_SIZE)
return 0;
else
step = 1;
return 1;
}

Right, after reading the code again, there are not enogh cards...
for (i = 0; i < HAND_SIZE-1; ++i)
Then you care counting pairs, not just individual cards, so
If (count == HAND_SIZE-1)

for (i = 0; i < HAND_SIZE-1; i++) { means that you are testing HAND_SIZE-1 pairs (which is correct), with i from from 0 to HAND_SIZE-2, so count will never be HAND_SIZE.
You just need to change your test to if (count == HAND_SIZE-1)

Assuming that (a) pip values are 1=Ace, 2=Deuce, ... and (b) the hand is sorted before being passed to the function, and (c) hands are exactly five cards, here's a quick one:
int isStraight(card hand[]) {
int i;
// Handle Broadway special case
if (hand[0].pips == 13 && hand[1].pips == 12 && hand[2].pips == 11 &&
hand[3].pips == 10 && hand[4].pips == 1) return 1;
// This will handle the rest
for (i = 0; i < (HAND_SIZE-1); i += 1) {
if (hand[i].pips != hand[i+1].pips) return 0;
}
return 1;
}
Also, I wouldn't use a structure for cards. Using a single integer is much faster and more versatile. Check out http://etceterology.com/blog/2013/5/23/representing-playing-cards-in-software

Related

C- Function that compares two four digit number arrays

I'm trying to create a function that compares two four digit numbers and
returns the number of similar digits between the two. For example, with a generated number of 4311 and the user entered 1488,
the score should return 2 (4 and 1).
If it was 4311 and the other is 1147,
the score should return three (1, 1 and 4). I don't know why it isn't giving me the right outputs, hope you can help.
int getSameDigitScore(int playerGuess, int generatedNum) {
int score = 0;
int i;
int j;
int k;
int generatedNumArray[4];
int playerGuessArray[4];
// turns playerGuess into an array
while (playerGuess > 0 ) {
i = 0;
playerGuessArray[i] = playerGuess % 10;
i++;
playerGuess /= 10;
}
// turns generatedNum into an array
while (generatedNum > 0) {
i = 0;
generatedNumArray[i] = generatedNum % 10;
i++;
generatedNum /= 10;
}
// compares the two arrays
for (k = 3; k >= 0; k--) {
for (j = 3; j >= 0; j--) {
if (generatedNumArray[k] == playerGuessArray[j]) {
score++;
playerGuessArray[j] = 0;
j = -5;
}
}
}
return score;
}
You are assigning i = 0 inside the while loop while generating the playerGuessArray and generatedNumArray. Due to which the playerGuess and generatedNumArray array will have elements as first digit of your number 0 0 0 .
Move the initialization out of the loop.
int getSameDigitScore(int playerGuess, int generatedNum) {
int score = 0;
int i, j, k, n;
int generatedNumArray[4];
int playerGuessArray[4];
// turns playerGuess into an array
i = 0; // This has been out of while loop
while (playerGuess > 0 ) {
playerGuessArray[i] = playerGuess % 10;
i++;
playerGuess /= 10;
}
// turns generatedNum into an array
int n = 0; // This has been out of the while loop
while (generatedNum > 0) {
generatedNumArray[n] = generatedNum % 10;
n++;
generatedNum /= 10;
}
// compares the two arrays
for (k = 3; k >= 0; k--) {
for (j = 3; j >= 0; j--) {
if (generatedNumArray[k] == playerGuessArray[j]) {
score++;
playerGuessArray[j] = 0;
j = -5;
}
}
}
return score;
}
int main() {
int m;
n = getSameDigitScore(1231, 2342);
printf("Score is: %d\n", m);
}
You're re-initializing increment variable i on every iteration which should be moved out of the while loop. With that moved out the above code works fine.
There are the following issues with the code.
You are initializing the integer i inside the while loop. This needs to be done before the loop for each loop.
You need a separate array to get the output of equal digits. See AnswerArray in code below. Also it is a good design practice to pass this array to the function and clear this array inside the function.
In the last for loop, you should break from the inner loop after getting a match. This is to take care of cases where playerGuess == 1222 and generatedNum = 1111 In the code shown this will result in a score of 1.
See the final code below with some test cases.
int getSameDigitScore(int playerGuess, int generatedNum, int *AnswerArray) {
int score = 0;
int i;
int j;
int k;
int generatedNumArray[4] = {0};
int playerGuessArray[4] = {0};
memset(AnswerArray,0,4*sizeof(int));
// turns playerGuess into an array
i = 0;
while (playerGuess > 0 ) {
playerGuessArray[i] = playerGuess % 10;
i++;
playerGuess /= 10;
}
// turns generatedNum into an array
i = 0;
while (generatedNum > 0) {
generatedNumArray[i] = generatedNum % 10;
i++;
generatedNum /= 10;
}
// compares the two arrays
score=0;
for (k = 3; k >= 0; k--) {
for (j = 3; j >= 0; j--) {
if (generatedNumArray[k] == playerGuessArray[j]) {
AnswerArray[score++] = generatedNumArray[k];
playerGuessArray[j] = -1;
break;
}
}
}
return score;
}
int main(void)
{
int AnswerArray[4],score;
score = getSameDigitScore(4311,1488,AnswerArray);
printf ("\nScore = %d \n Answer Array = ",score);
for (int i=0; i<score; i++)
{
printf ("%d ",AnswerArray[i]);
}
score = getSameDigitScore(4311,1147,AnswerArray);
printf ("\nScore = %d \n Answer Array = ",score);
for (int i=0; i<score; i++)
{
printf ("%d ",AnswerArray[i]);
}
score = getSameDigitScore(1222,1111,AnswerArray);
printf ("\nScore = %d \n Answer Array = ",score);
for (int i=0; i<score; i++)
{
printf ("%d ",AnswerArray[i]);
}
score = getSameDigitScore(1111,1222,AnswerArray);
printf ("\nScore = %d \n Answer Array = ",score);
for (int i=0; i<score; i++)
{
printf ("%d ",AnswerArray[i]);
}
}
The initializing i=0 which you made inside the loop should be outside the loop.
while (playerGuess > 0 ) {
i = 0;
playerGuessArray[i] = playerGuess % 10;
i++;
playerGuess /= 10;
}
If the initialization is inside the looop then,
Everytime playerGuessArray[0] value will be updated.
FYI:
If playerGuess can contain 0 aat the begin of four digit like 0123
For example, playerGuessValue is 0123, Then by using
while (playerGuess > 0 ) {
i = 0;
playerGuessArray[i] = playerGuess % 10;
i++;
playerGuess /= 10;
}
playerGuessArray will contain only [1,2,3] instead of [0,1,2,3].
So, the better solution would be taking two temporary variables and checking last digit one by one.
Like this:
int temp1=playerGuess, temp2=GeneratedNum;
int i=0;
bool flag = true;
while(flag && i < 4){
if(temp1%10 != temp2%10){
flag = false;
}
temp1 /= 10;
temp2 /= 10;
i++;
}
if(flag){
score++;
}
FYI:
Debugging will help you in finding out these little mistakes.So, try to debug your code with multiple inputs and verify your answer.
Here are few reference on how to debug:
https://blog.hartleybrody.com/debugging-code-beginner/
https://www.codementor.io/mattgoldspink/how-to-debug-code-efficiently-and-effectively-du107u9jh%60
Thanks.

C Program will compile and run in Linux but not Windows

I'm working on an assignment for a programming class and am having an issue with a program. The goal is to take in a set of user defined values, store them in an array, then find the closest pair of numbers (the numbers with the smallest difference). The numbers don't have to have consecutive indices. Also, the array size of 50 is defined in the assignment by the professor.
The problem I'm running into is that the program will compile in both Linux (Ubuntu 14.xx) and Windows 10, however, when I run the result in Linux, it works fine but in Windows it outputs nothing.
This is the first time I've had this issue and as far as I know I didn't use any system specific commands. Any help provided would be appreciated.
Code:
#include <stdio.h>
int main()
{
int i, j, a, b, temp, mindiff, count;
int numarray[50];
count = 0;
for (i = 0; i < 50; i++)
{
scanf("%d", &numarray[i]);
count++;
if (numarray[i] == -1)
{
numarray[i] = 0;
count--;
break;
}
}
mindiff = 100;
for (i = 0; i < count; i++)
{
for (j = 0; j < count; j++)
{
a = numarray[i];
b = numarray[j];
if (a != b)
if (a > b)
temp = a - b;
else
temp = b - a;
if (temp < mindiff)
mindiff = temp;
}
}
for (i = 0; i < count; i++)
{
for (j = 0; j < count; j++)
{
a = numarray[i];
b = numarray[j];
if (a != b)
{
if (a > b && (a - b) == mindiff)
{
printf("Closest pair: %d and %d, Difference: %d\n", a, b, mindiff);
return 0;
}
}
}
}
return 0;
}
There are at least two major problems:
Your code has undefined behavior because you use temp even if it has not been set (you should start a block after if (a != b)). undefined behavior means anything can happen, including apparent success on Linux and failure on Windows.
You initialize mindiff to 100. If all numbers are farther apart from each other, mindiff will not be changed and the second loop will not print anything.
Here is a simpler version:
#include <stdio.h>
int main(void) {
int count, i, j, mina, minb, mindiff;
int numarray[50];
for (count = 0; count < 50; count++) {
if (scanf("%d", &numarray[count]) != 1 || numarray[count] == -1)
break;
}
mindiff = mina = minb = 0;
for (i = 0; i < count; i++) {
for (j = 0; j < count; j++) {
int a = numarray[i];
int b = numarray[j];
if (a > b) {
int diff = a - b;
if (mindiff == 0 || mindiff > diff) {
mindiff = diff;
mina = a;
minb = b;
}
}
}
}
if (mindiff == 0) {
if (count == 0) {
printf("No numbers input\n");
} else {
printf("The numbers are all identical\n");
}
} else {
printf("Closest pair: %d and %d, Difference: %d\n",
mina, minb, mindiff);
}
return 0;
}
You have the following problem:
Note: temp is considered a stack variable under the main function and since you do not initialize it, it becomes garbarge (for example a large negative number):
int i, j, a, b, temp, mindiff, count;
Then if temp is a large negative number, mindiff = the garbarge value of mindiff,
if (temp < mindiff)
mindiff = temp;
And the following if statement is always false.
if (a > b && (a - b) == mindiff)
And nothing gets printed.

C: Problems Using Free() on Structs Elements, Strange Behivor

I'm having problems by freeing the elements on my struct.
long code warning
typedef struct bingo
{
char board[5][5];
int* luckNum;
int* boardNum;
} bingo;
void update(bingo *pBingo,int num); //Function that gets a struct, number and checks if he is in the board, if it does he change it to "X"
int main(void)
{
srand(time(NULL));
int i, j, m, k, temp[75], *parr;
bingo player;
//For rellocating them later
if (!(player.luckNum = (int*) malloc(sizeof(int))))
{
printf("ERROR");
}
if (!(player.boardNum = (int*) malloc(sizeof(int))))
{
printf("ERROR");
}
//giving temp values of 1-75
for ( i = 0; i < 75; i++)
{
temp[i] = i + 1;
}
//Giving the player board random values of 1-75 without repeating the same number twice
for ( i = 0; i < 5; i++) //Passing on the rows
{
for (j = 0; j < 5; j++) //Passing on the columns
{
//
do
{
k = rand() % 75; //from 0-74
}
while (temp[k] == NULL); //while temp[k] is marked
player.board[i][j] = temp[k];
temp[k] = NULL; //NULL as a "flag" that marks the cell as taken (for not taking the same number twice)
player.luckNum=(int*) malloc(sizeof(int)*(i*j+j));
player.luckNum[i*j + j] = player.board[i][j];
}
}
//sets luckNum
for ( i = 0; i < 25; i++)
{
printf("%d ", player.luckNum[i]);
update(&player, player.luckNum[i]);
}
printf("\n");
for ( i = 0; i < 25; i++)
{
printf("%d",player.luckNum);
}
free(player.boardNum);
free(player.luckNum);
getchar();
return 0;
}
void update(bingo *pBingo, int num)
{
int i, j, k;
static int counter = 0,luckCounter = 25;
for (i = 0; i < 5; i++)
{
for (j = 0; j < 5; j++)
{
if (num == (int) (pBingo->board[i][j]))
{
pBingo->board[i][j] = 'X';
counter++;
pBingo->boardNum = (int*) realloc(pBingo->boardNum, sizeof(int)*counter);
pBingo->boardNum[counter] = num;
for (k = 0; k < luckCounter; k++)
{
if (pBingo->luckNum[k] == num)
{
num = pBingo->luckNum[k];
pBingo->luckNum[k] = pBingo->luckNum[luckCounter-1];
pBingo->luckNum[luckCounter-1] = num;
pBingo->luckNum = (int*) realloc(pBingo->luckNum, sizeof(int)*luckCounter);
luckCounter--;
}
}
}
}
}
}
Can anyone recognize what interrupts the free() function from freeing the memory?. I'm new to C and working on this code about good days so sorry for my ignorance about free() function, can anyone help me?
Ilan,
Don't be afraid to post your code with the necessary includes. First of all, are you heeding to the warnings of your compiler?
A few problem areas:
while (temp[k] == NULL)
You can research the difference between 0, NULL and '\0' but reserve the use of NULL for pointers. Also:
for ( i = 0; i < 25; i++)
{
printf("%d",player.luckNum);
}
Printf is expecting an integer and you're giving it a pointer. Finally, to address what I think is your problem, when you write "..interrupts the free() function from freeing the memory?" Do you mean your program simply not returning? If so then get rid of the final getchar(). You're still going to have at least one leak in this program. This address of this malloc:
if (!(player.luckNum = (int*) malloc(sizeof(int))))
will be lost as you assigned luck.Num a new address here without freeing the first:
player.luckNum=(int*) malloc(sizeof(int)*(i*j+j));

Why are my variables not incrementing?

I'm writing a small poker application in C and I have counters for the number of flushes, straights, etc.
Main function:
int main(void) {
int i, j;
int numHands = 0;
int flushCount = 0;
int straightCount = 0;
int xOfAKindCount = 0;
int straightFlushCount = 0;
int fullHouseCount = 0;
int isTwoPairCount = 0;
card deck[DECKSZ] = {0};
card hand[HAND_SIZE] = {0};
stack deckStack = {0};
stack handStack = {0};
initDeck(deck);
shuffleDeck(deck);
reset(&deckStack);
for (i = 0; i < DECKSZ; i++) {
push(deck[i], &deckStack);
}
do {
reset(&handStack);
for (i = 0; i < HAND_SIZE; i++) {
push(pop(&deckStack), &handStack);
if (isEmpty(&deckStack)) {
reset(&handStack);
shuffleDeck(deck);
reset(&deckStack);
for (j = 0; j < DECKSZ; j++) {
push(deck[j], &deckStack);
}
}
hand[i] = handStack.s[i];
}
numHands += 1;
arrangeHand(hand);
flushCount += isFlush(hand);
straightCount += isStraight(hand);
xOfAKindCount += isXOfAKind(hand, 2, 0);
straightFlushCount += isStraightFlush(hand);
fullHouseCount += isFullHouse(hand);
isTwoPairCount += isTwoPair(hand);
printf("Flushes:%d Straights:%d SF's:%d Number of Hands:%d\r",
flushCount, straightCount, straightFlushCount, numHands);
} while (1);
printf("\n");
return EXIT_SUCCESS;
}
My function for the number of flushes:
int isFlush(card hand[]) {
int i, count = 0, result = 0;
for (i = 0; i < HAND_SIZE-1; i++) {
if (hand[i].suits != hand[i+1].suits) {
count++;
}
}
if (count == HAND_SIZE)
result = 1;
return result;
}
When I run the program, the code in the do...while loop is supposed to infinitely loop. For every hand popped off the stack, I want to calculate if it is a flush, straight, etc using functions like my isFlush() function here. The issue is these counters, such as numFlushes, remain at a value of zero. Does anybody know why the counters remain at zero, and how to fix that? Thanks!
The for loop in your isFlush function can at most increment the count HAND_SIZE-1 times. Since count starts at 0, it is never more than HAND_SIZE-1.
One option is to start your count at 1, since the first card always counts as 1 towards your flush no matter what suit it is. Anther option is to compare count to HAND_SIZE-1 in your if statement. Then you can actually return a non-zero value from isFlush.
BTW, if you step through the code with a debugger, you should easily see that your if condition is never met.

Expression cannot be evaluated. Malloc fail

I' having a problem allocating a structure in a function. Here is the code(I'm currently using visual studio 2008):
Mat3x3* ProdMat(Mat3x3 *m, Mat3x3 *n)
{
if(m == NULL || n == NULL)
{
cout << "\t[W] Cannot compute product of the two matrixes one or both are NULL." << endl;
return NULL;
}
Mat3x3 *p; // product
int i, j;
float sum = 0;
p = (Mat3x3*)malloc(sizeof(Mat3x3)); // <= Exp cannot be evaluated
for(i = 0; i < 3; i++)
{
for(j = 0; j < 3; j++)
{
sum = 0;
for(int k = 0; k < 3; k++)
{
float a = m->a[i][k];
float b = n->a[k][j];
sum += a * b;
}
p->a[i][j] = sum;
}
}
return p;
}
P contains a matrix with 9 entries. Here is the context in which the error is given:
Mat3x3* compute_final_trans(Trans **transes) // compute product of all transformation matrixes from right to left
{
int k_trans = 0, i, j;
Mat3x3 *final_trans;
if(transes == NULL)
{
printf("\t[E] Cannot compute sequence of NULL transformations.\n");
return NULL;
}
final_trans = (Mat3x3*)malloc(sizeof(final_trans));
for(i = 0; i < 3; i++) // generate eye matrix
for(j = 0; j < 3; j++)
{
if(i == j)
{
final_trans->a[i][j] = 1;
}
else
{
final_trans->a[i][j] = 0;
}
}
while(transes[k_trans++]);
for(i = k_trans - 2; i >= 0; i--)
{
final_trans = ProdMat(transes[i]->matrix, final_trans); // <= ERROR
}
return final_trans;
}
Final trans is initialised as the eye matrix and transes have been succesfully computed before this step(before calling compute_final_trans). The while is used to retreieve the number of transformations that transes contains. At line:
final_trans = ProdMat(transes[i]->matrix, final_trans);
ProdMat fails to allocate memory for p which is a pointer to a Mat3x3 structure.
perror suggests that there isn't enough memory to allocate to the structure. However I'm only using 1GB of RAM(4GB in all).
Any help/suggestion/reference will be very much appreciated.
Sebi
malloc(sizeof(final_trans))
This is bad. You are only allocating enough space for a pointer, not space for an array.

Resources