Royal Flush not working for Card Hand Assignment [C] - c

I have tried everything! I'm supposed to add on the Royal Flush part. I understand the straight, flush, and straight flush part, but I cannot seem to get the Royal Flush part. In the end, the code is supposed to print how many straight, flushes, straight flushes, and royal flushes were in the deck of 50000 cards. This started out as a lab that I had with a partner, but now for extra credit, I'm supposed to add on the royal flush part and I'm clueless. Thanks in advance.
#include <stdio.h>
#define SIZE 50000
typedef struct card_t_struct{
int value; // 1 through 13
int suit; // 0 is clubes, 1 is diamonds, 2 is spades, 3 is hearts
} card_t;
void printCard(card_t card){
if(card.value == 1){
printf("Ace");
}else if(card.value == 11){
printf("Jack");
}else if(card.value == 12){
printf("Queen");
}else if(card.value == 13){
printf("King");
}else{
printf("%d", card.value);
}
printf(" of ");
if(card.suit == 0){
printf("Clubs.");
}else if(card.suit == 1){
printf("Diamonds.");
}else if(card.suit == 2){
printf("Spades.");
}else if(card.suit == 3){
printf("Hearts.");
}else{
printf("%d not a suit", card.suit); // Error message
}
printf("\n");
}
void hand(card_t* a){
int i = 0;
for(i = 0; i < 5; i++){
printCard(a[i]);
}
}
void shuffle(card_t* array, int length){
int i = 0;
for(i = 0; i < length * 2; i++){
int from = rand() % length;
int to = rand() % length;
card_t temp = array[from];
array[from] = array[to];
array[to] = temp;
}
}
void bubble(card_t* f, int length){
int i = 0;
int bub_num = 0;
for(bub_num = 0; bub_num < length; bub_num++){
for(i = 0; i < length - 1; i++){
if(f[i].value > f[i+1].value){ // Wrong order
int temp = f[i].value;
f[i].value = f[i+1].value;
f[i+1].value = temp;
}else{
}
}
}
}
int isFlush(card_t* deck){
int i = 0;
for(i = 1; i < 5; i++){
if(deck[i].suit != deck[0].suit){
return 0;
}
}
return 1;
}
int isStraight(card_t* deck){
int i = 0;
for(i = 1; i < 5; i++){
if(deck[i+1].value != deck[i].value + 1){
return 0;
}
}
return 1;
}
int isSFlush(card_t* deck){
int i = 0;
for(i = 1; i < 5; i++){
if(deck[i+1].value != deck[i].value + 1){
return 0;
}
}
for(i = 1; i < 5; i++){
if(deck[i].suit != deck[0].suit){
return 0;
}
}
return 1;
}
int isRFlush(card_t* deck){
int i = 0;
for(i = 1; i < 5; i++){
if(deck[i].value != deck[i].value){
return 0;
}
}
for(i = 1; i < 5; i++){
if(deck[i].suit != deck[0].suit){
return 0;
}
}
return 1;
}
int main(){
srand(time(0));
card_t deck[52] = {};
int i = 0;
int flush = 0;
int straight = 0;
int straight_flush = 0;
int royal_flush = 0;
int suit = 0;
for(suit = 0; suit < 4; suit++){
int value = 1;
for(value = 1; value <= 13; value++){
deck[i].suit = suit;
deck[i].value = value;
i++;
}
}
for(i = 0; i < SIZE; i++){
shuffle(deck, 52);
hand(deck);
if(isFlush(deck) ){
flush++;
}
printf("\n");
bubble(deck, 5);
if(isStraight(deck) ){
straight++;
}
if(isSFlush(deck) ){
straight_flush++;
}
if(isRFlush(deck) ){
royal_flush++;
}
}
printf("The number of flushes you have is: %d\n", flush);
printf("The number of straights you have is: %d\n", straight);
printf("The number of straight flushes you have is: %d\n", straight_flush);
printf("The number of royal flushes you have is: %d\n", royal_flush);
}

Based on the existing IsStraight(...) function, I'm assuming that your isRFlush(...) functions are being passed a five-card hand (not an entire deck) whose cards are in ascending order?
int isRFlush(card_t* deck) {
int i = 0; // zero-based index into your hand of five cards (0-4)
// This next bit DOESN'T ACTUALLY DO ANYTHING. The reason is that comparing anything
// with itself will always result in an equality (i.e. 1==1, 3.14==3.14, a==a, etc),
// so this comparison always returns false, and the return 0 after the if statement
// is never taken, regardless of the value of the cards passed in.
/*
for (i = 1; i < 5; i++) {
if (deck[i].value != deck[i].value) { // <--- Never false, no matter what
return 0;
}
}
*/
// What the other isXxxx methods above were doing was ensuring that each 'next' card
// was 'one higher' than the card that came before it in the hand. If that's found to
// be untrue for any card in the hand, then the function exits with a zero.
//
// That's the logic for a STRAIGHT, but we're looking for a ROYAL STRAIGHT, so the
// hand HAS to be "10 J Q K A" (all of the same suit, but we'll check that part later).
//
// Since the Ace represents a non-sequential value, I think you may as well just do
// this using five comparisons without the loop:
if ( deck[0].value != 1 // if 1st card isn't Ace
|| deck[1].value != 10 // or 2nd card isn't 10
|| deck[2].value != 11 // or 3rd card isn't Jack
|| deck[3].value != 12 // or 4th card isn't Queen
|| deck[4].value != 13) { // or 5th card isn't King
return 0; // Not a royal straight
}
// If we've made it this far, we know that we have a ROYAL STRAIGHT (e.g. 10, J, Q, K, A)
// Now, we need to ensure that we also have a FLUSH
// Loop through the 2nd to last cards, ensuring they are all
// of the same suit as the first card in the hand
for (i = 1; i < 5; i++) {
if (deck[i].suit != deck[0].suit) {
return 0; // Not a flush
}
}
return 1; // This hand IS a Royal Straight Flush (aka Royal Flush)
}
Final notes:
There may be other bugs in this program. For example, isStraight(...) skips the first card and loops over the last four cards, but it's ADDING ONE to the index i when it should be SUBTRACTING ONE:
// Note: This function doesn't recognize a non-sequential "ace-high" flush
// (e.g. 10,J,Q,K,A).
int isStraight(card_t* deck) {
int i = 0;
for (i = 1; i < 5; i++) {
// Loop values of i will be [1, 2, 3, 4], which correspond to the 2nd through 5th card in the hand passed in.
// To check these against the previous card, you should subtract one (vs adding one).
/*
if (deck[i+1].value != deck[i].value + 1) { // <--- Array Index Out Of Bounds
*/
// If card in hand isn't 'one higher' than the previous card...
if (deck[i-1].value != deck[i].value + 1) {
return 0;
}
}
return 1;
}
Since you already have a function that checks a hand for flush, you could leverage that to save some typing by calling it in your isRFlush(...) function:
int isRFlush(card_t* deck) {
if ( deck[0].value != 1 // if 1st card isn't Ace
|| deck[1].value != 10 // or 2nd card isn't 10
|| deck[2].value != 11 // or 3rd card isn't Jack
|| deck[3].value != 12 // or 4th card isn't Queen
|| deck[4].value != 13) { // or 5th card isn't King
return 0; // Not a royal straight
}
// At this point, you know it's a ROYAL STRAIGHT, so just return whether or not it's also
// a FLUSH
return isFlush(deck);
}

Related

Is there a way to include more than one 'if' conditional for output?

I have this code below (whole code after this section). I am wanting to include more than one casse for this section of the code:
for(i = 0; i < length; i++)
{
if(numberArray[i] == 1)
{
casse = 2;
}
if(numberArray[i] == 2)
{
casse = 3;
}
if(numberArray[i] == 1 || numberArray[i] == 2)
{
casse = 4;
}
}
So far, the above prints '4' when the value '8213' is entered. This is expected since for each round of for loop the 'casse' variable gets updated, by the time it runs the last integer in the array, the value for 'casse' has undergone many replacements and the end result is the last replacement of '4'.
The objective of the code is to determine which cases (casse) have
been met. There can be more than one case (casse) being met, but as it
stands now, it only has room for one case.
#include <stdio.h>
#include <math.h>
int main(void) {
int odo, value, casse;
int i;
printf("please enter a value for the odometer:\n");
scanf("%d", &odo);
value = odo;
casse = 0;
int length = floor(log10(abs(odo))) + 1;
/* count number of digits */
int c = 0; /* digit position */
int n = value;
while (n != 0)
{
n /= 10;
c++;
}
int numberArray[c];
c = 0;
n = value;
/* extract each digit */
while (n != 0)
{
numberArray[c] = n % 10;
n /= 10;
c++;
}
for(i = 0; i < length; i++)
{
printf("%d, ", numberArray[i]);
}
for(i = 0; i < length; i++)
{
if(numberArray[i] == 1)
{
casse = 2;
}
if(numberArray[i] == 2)
{
casse = 3;
}
if(numberArray[i] == 1 || numberArray[i] == 2)
{
casse = 4;
}
}
printf("\n%d\n", casse);
return 0;
}
Output:
please enter a value for the odometer:
8213
3, 1, 2, 8,
4
Expected output:
please enter a value for the odometer:
8213
3, 1, 2, 8,
Not only '4', but also '3', '2'.
Rather than a single variable that keeps track of the last case, you want an array which keeps track of all cases. For a small number of cases, the array can be a fixed size, with the index as case number and the value in the array as the number of times that case was triggered:
int cases[5] = {0};
for(i = 0; i < length; i++)
{
if(numberArray[i] == 1)
{
cases[2]++;
}
if(numberArray[i] == 2)
{
cases[3]++;
}
if(numberArray[i] == 1 || numberArray[i] == 2)
{
cases[4]++;
}
}

character i.e. 'a' or any other letter other then 0-9 the program loops infinitely

I am a beginner at programming and am making a tic tac to game in c. My problem as the title suggest is that when I input a character i.e. 'a' other then an integer i.e. 0-9 the program loops through the while loop in main() infinitely or until it reaches the temporary limit I placed with out asking for user input. I can't for the life of me figure out what is wrong.
#include<stdio.h>
#define TRUE 1
#define FALSE 0
void greet_players();
void draw_grid(int loc, char cur_player, char point[]);
char swap_player(char *cur_player, int *is_turn);
int player_loc();
int check_win();
int main(){
int i;
int is_turn;
int loc = 0;
char point[9];
char cur_player;
greet_players(); //greet players.
for(i = 0; i < 9; i++){ point[i] = '_'; }// set the point array to '_'.
int temp = 0;
is_turn = TRUE; // set the first turn to true.
cur_player = 'X'; // set the first player before the grid is printed.
while(/*!check_win()*/temp<3){
swap_player(&cur_player, &is_turn); // change player for the next loop.
if(is_turn == TRUE) { is_turn = FALSE; }
draw_grid(loc, cur_player, point);
temp++;
};
return 0;
}
/***************************************************************************/
// Function prints out a greeting to players.
void greet_players(){
puts("***********************************************************************************");
puts("Hello this is tic tac toe.");
puts("The rules are simple: ");
puts("#1 two players each place their pieces (X,O) on a 9x9 grid.");
puts("#2 when a player has placed three pieces either horizontal or vertical they win.");
puts("#3 and thats it, have fun.");
puts("***********************************************************************************\n");
// print the first grid empty
puts("Tic_Tac_Toe.");
puts(" |1|2|3|");
puts(" |4|5|6|");
puts(" |7|8|9|");
puts("***********************************************************************************");
}
/***************************************************************************/
// Function draws grid.
void draw_grid(int loc, char cur_player, char point[]){
int i, j, p;
p = player_loc()-1;
printf("%d\n", p);
puts("Tic_Tac_Toe.");
if(point[p] == '_'){
point[p] = cur_player;
for(i = 0; i < 3; i++){
printf(" ");
for(j = 0; j < 3; j++){
printf("|%c", point[loc]);
loc++;
}
puts("|");
}
puts("***********************************************************************************");
}
else{ puts("\nSpace invalid,please choose an empty Location('_')."); }
}
/***************************************************************************/
// Function gets the current players inputed locition.
int player_loc(){
int player_loc = 0;
scanf(" %d", &player_loc);
if(player_loc >= 1 && player_loc <= 9 ){ return (player_loc); }
else{ return (0); }
}
/***************************************************************************/
// Function changes player icon to the next icon when the current player inputs their location.
char swap_player(char *cur_player, int *is_turn){
if(*cur_player == 'X' && *is_turn == FALSE){
*cur_player = 'O';
*is_turn = TRUE;
}
if(*cur_player == 'O' && *is_turn == FALSE){
*cur_player = 'X';
*is_turn = TRUE;
}
return (*cur_player);
}
/***************************************************************************/
int check_win(){ return (0); }

C language - operation replaces mutiple array elements instead of one

I am in the process of creating hangman in C language, but there is one problem that I cannot quite grasp. When a user correctly guesses one of the letters that the word that is being guessed has, the program replaces all of previously guessed letters to the one user just put. What is the source of this problem?
#include<stdio.h>
#include <stdlib.h>
int main()
{
srand(time(NULL));
int x = 0, isCompleted, matchFound, numberOfTries = 7;
char letterGuess[1];
int randomIndex = rand()%14;
const char *wordArray[14];
const char *guessedWord[10];
const char *usedLetters[17];
for (int k = 0; k < 10; k++) {
guessedWord[k] = "_";
}
wordArray[0] = "butonierka";
wordArray[1] = "centyfolia";
wordArray[2] = "chiroplast";
wordArray[3] = "cmentarzyk";
wordArray[4] = "chrustniak";
wordArray[5] = "budowniczy";
wordArray[6] = "cholewkarz";
wordArray[7] = "cornflakes";
wordArray[8] = "brzydactwo";
wordArray[9] = "germanofil";
wordArray[10] = "lichtarzyk";
wordArray[11] = "lutowniczy";
wordArray[12] = "mikrocysta";
wordArray[13] = "tryskawiec";
const char *wordToGuess = wordArray[randomIndex];
for(int i = 0; i < 10; i++) {
printf(" %s ", guessedWord[i]);
}
printf("\n");
while(numberOfTries != 0 && isCompleted != 10) {
matchFound = 0;
isCompleted = 0;
printf("Please give a lowercase letter\n");
printf("Left tries: %d\n", numberOfTries);
scanf("%s", &letterGuess);
for (int z = 0; z < 17; z++) {
if (usedLetters[z] == letterGuess[0]) {
matchFound = 1;
}
}
if (letterGuess[0] >= 'a' && letterGuess[0] <= 'z' && matchFound == 0) {
usedLetters[x] = letterGuess[0];
x++;
for (int j = 0; j < 10; j++) {
if (letterGuess[0] == wordArray[randomIndex][j])
guessedWord[j] = letterGuess;
matchFound = 1;
}
}
if (matchFound == 0) {
numberOfTries--;
}
for(int z = 0; z < 10; z++) {
printf(" %s ", guessedWord[z]);
}
printf("\n");
} else {
if (matchFound == 1) {
printf("You've already given such letter!!\n");
} else {
printf("Wrong input, please try again!\n");
}
}
for (int k = 0; k < 10; k++) {
if (guessedWord[k] != "_") {
isCompleted++;
}
}
if (isCompleted == 10) {
printf("You have correctly guessed a word! Congrats!!\n");
}
printf("\n\n");
}
printf("The word was: %s\n", wordArray[randomIndex]);
printf("Game over!!\n");
}
The problem is that you're storing letterGuess, rather than individual characters. So each time letterGuess is updated with a new guess, all references to it change. Also, letterGuess is too short, leaving no room for the terminating null character.
The best solution is to make letterGuess a char (or an int), not an array, and to make guessedWord a char [] rather than a char *[]. There is no reason to use strings for single characters. That will solve the string-sharing problem.

Why is array[i][-1] == 0? How does one prevent undefined variables from being used? [duplicate]

This question already has answers here:
Are negative array indexes allowed in C?
(9 answers)
Closed 6 years ago.
/**
* fifteen.c
*
* Computer Science 50
* Problem Set 3
*
* Implements Game of Fifteen (generalized to d x d).
*
* Usage: fifteen d
*
* whereby the board's dimensions are to be d x d,
* where d must be in [DIM_MIN,DIM_MAX]
*
* Note that usleep is obsolete, but it offers more granularity than
* sleep and is simpler to use than nanosleep; `man usleep` for more.
*/
#define _XOPEN_SOURCE 500
#include <cs50.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
// constants
#define DIM_MIN 3
#define DIM_MAX 9
// board
int board[DIM_MAX][DIM_MAX];
int b;
// dimensions
int d;
// prototypes
void clear(void);
void greet(void);
void init(void);
void draw(void);
bool move(int tile);
bool won(void);
int main(int argc, string argv[])
{
// ensure proper usage
if (argc != 2)
{
printf("Usage: fifteen d\n");
return 1;
}
// ensure valid dimensions
d = atoi(argv[1]);
if (d < DIM_MIN || d > DIM_MAX)
{
printf("Board must be between %i x %i and %i x %i, inclusive.\n",
DIM_MIN, DIM_MIN, DIM_MAX, DIM_MAX);
return 2;
}
// open log
FILE* file = fopen("log.txt", "w");
if (file == NULL)
{
return 3;
}
// greet user with instructions
greet();
// initialize the board
init();
// accept moves until game is won
while (true)
{
// clear the screen
clear();
// draw the current state of the board
draw();
// log the current state of the board (for testing)
for (int i = 0; i < d; i++)
{
for (int j = 0; j < d; j++)
{
fprintf(file, "%i", board[i][j]);
if (j < d - 1)
{
fprintf(file, "|");
}
}
fprintf(file, "\n");
}
fflush(file);
// check for win
if (won())
{
printf("ftw!\n");
break;
}
// prompt for move
printf("Tile to move: ");
int tile = GetInt();
// quit if user inputs 0 (for testing)
if (tile == 0)
{
break;
}
// log move (for testing)
fprintf(file, "%i\n", tile);
fflush(file);
// move if possible, else report illegality
if (!move(tile))
{
printf("\nIllegal move.\n");
usleep(500000);
}
// sleep thread for animation's sake
usleep(500000);
}
// close log
fclose(file);
// success
return 0;
}
/**
* Clears screen using ANSI escape sequences.
*/
void clear(void)
{
printf("\033[2J");
printf("\033[%d;%dH", 0, 0);
}
/**
* Greets player.
*/
void greet(void)
{
clear();
printf("WELCOME TO GAME OF FIFTEEN\n");
usleep(2000000);
}
/**
* Initializes the game's board with tiles numbered 1 through d*d - 1
* (i.e., fills 2D array with values but does not actually print them).
*/
void init(void)
{
for(int i = 0, j = 0, k = ((d*d)-1); i < d; j++, k--)
{
if(j == d)
{
i = i + 1;
j = 0;
}
board[i][j] = k;
}
if((d*d)%2 == 0)
{
board[(d-1)][(d-2)] = 2;
board[(d-1)][(d-3)] = 1;
}
board[(d-1)][(d-1)] = 0;
b = board[(d-1)][(d-1)];
}
/**
* Prints the board in its current state.
*/
void draw(void)
{
for(int i = 0, j = 0; i !=(d-1) || j!=d; j++)
{
if(j == d)
{
i = i + 1;
j = 0;
printf("\n");
}
if(board[i][j] == 0) //b used to be 99
{
printf(" _");
}
else
{
printf(" %2d", board[i][j]);
}
}
printf("\n");
}
/**
* If tile borders empty space, moves tile and returns true, else
* returns false.
*/
bool move(int tile)
{
//find tile
for(int i = 0, j = 0; i !=(d-1) || j!=d; j++)
{
if(j == d)
{
i = i + 1;
j = 0;
}
if (board[i][j] == tile)
{
//check if tile position is in valid perimeter of blank space
if (board[i+1][j] == b)
{
board[i+1][j] = tile;
board[i][j] = 0;
b = board[i][j];
return true;
}
if (board[i-1][j] == b)
{
board[i-1][j] = tile;
board[i][j] = 0;
b = board[i][j];
return true;
}
if (board[i][j+1] == b)
{
board[i][j+1] = tile;
board[i][j] = 0;
b = board[i][j];
return true;
}
if (board[i][j-1] == b)
{
printf("%i", board[i][j-1]);
board[i][j-1] = tile;
board[i][j] = 0;
b = board[i][j];
return true;
}
}
}
return false;
}
/**
* Returns true if game is won (i.e., board is in winning configuration),
* else false.
*/
bool won(void)
{
for(int i = 0, j = 0, k = 1; i !=(d-1) || j!=d; j++)
{
if(j == d)
{
i = i + 1;
j = 0;
}
if (k == (d*d)-1)
{
return true;
}
if (board[i][j] == k)
{
k = k + 1;
}
}
return false;
}
I originally had
board[(d-1)][(d-1)] = 0;
equal to 99 along with the move function look for 99. For my problem set I was supposed to use 0. Once I changed 99 to 0, for some reason 0 is being found if board[i][j-1] even if that means board[2][-1]. Why is that allow/why does that equal 0? and how can I disable this?
You have int board[DIM_MAX][DIM_MAX]; where #define DIM_MIN 3 and the memory allocated for elements are contiguous, so typically you will access board[1][2] by using board[2][-1]. But this is undefined behavior, which allows anything to happen, and you mustn't use that.
Quote from N1570 J.2 Undefined behavior:
An array subscript is out of range, even if an object is apparently accessible with the
given subscript (as in the lvalue expression a[1][7] given the declaration int
a[4][5]) (6.5.6).
board[2][-1]. Why is that allow
C does allow you access out of range of an array. But it is Undefined Behavior.
why does that equal 0?
By accident. It's Undefined Behavior and it could be anything.

Segmentation fault in base number program?

I keep trying to test this code but I keep getting a segmentation fault in my power() function. The code is supposed to take a word made up of lowercase letters and change the word to a number of base 10. The word is supposed to take on the form of a number of base 20, where 'a' = 0, 'b' = 1,...., 't' = 19;
int power(int i){
if(i==1){
return 20;
}else{
return 20*power(i--);
}
}
int main(){
int len;
char mayan[6];
int n;
int val;
while(scanf("%s", mayan)){
val = 0;
n = 0;
for(len = 0; mayan[len] != '\0'; len++){
mayan[len] = tolower(mayan[len]);
mayan[len] = mayan[len] - 'a';
}
for(i = 0; len >= 0; len--, i++){
if(mayan[len] <= 19){
n = n + mayan[len] * power(i);
}else{
fprintf(stderr, "Error, not a base 20 input \n");
val = 1;
break;
}
}
if(val==0){
printf("%d \n", n);
}
}
return val;
}
There were three mistakes in your code.
Case for i==0 not added in the power function, which basically translates to any number to the power of zero is one i.e. x^0 = 1;.
Instead of using return 20*power(i--); for your recursive call, use return 20*power(i-1);. i-- is post decrement operator, which means that, it will return the value of i as it is and will the decrement it for further use, which is not what you want. Also, you altogether don't even want to change the value of i for this iteration too; what you want to do is use a value one less than i for the next iteration, which is what, passing i-1, will do.
Add a len-- in the initialization of the for(i = 0; len >= 0; len--, i++) loop, because len is now over the last index of the input because of the previous loop.
Correcting these mistakes the final code is:
#include<stdio.h>
int power(int i)
{
if(i==0)
{
return 1;
}
if(i==1)
{
return 20;
}
else
{
return 20*power(i-1);
}
}
int main()
{
int len,i;
char mayan[6];
int n;
int val;
while(scanf("%s", mayan))
{
val = 0;
n = 0;
for(len = 0; mayan[len] != '\0'; len++)
{
mayan[len] = tolower(mayan[len]);
mayan[len] = mayan[len] - 'a';
}
for(i = 0, len--; len >= 0; len--, i++)
{
if(mayan[len] <= 19)
{
n = n + mayan[len] * power(i);
}
else
{
fprintf(stderr, "Error, not a base 20 input \n");
val = 1;
break;
}
}
if(val==0)
{
printf("%d \n", n);
}
}
return val;
}
Note that, your code would essentially only work for at most a five digit base 20 number, because, the array mayan that you are using to store it has size 6, of which, one character will be spent for storing the terminating character \0. I recommend that you increase the size of the array mayan unless you want to support only five digit base 20 numbers.

Resources