Card Game troubles

Hello everyone,
I'm working on a simple WAR game to exercise the logic involved in programming something such as this. Using an array and numeric values 0-51, I am shuffling the deck and considering the first half the player's, and the second half the computers. While it is a work in progress, I'm encountering some logic errors. Any help in pinpointing why the value for the number of cards left (tracked by the variable split) is not always correct would be greatly appreciated. Thanks! I'm sure the problems are located in either the main or war functions.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
void War(int array[],int &player,int &computer, int &split);

void shuffle(int array[])
{
    int x=1;int y=0;
        array[0]=rand()%52+1;//first number assigned
    do
    {
        array[x]=rand()%52+1;//value generated for x's position
        y=0;
        while (y<x)
        {//iterate through array while checking for duplicate values
            if (array[y]==array[x])
            {//if duplicate is found, generate another value for this position
                --x;
                break;
            }
            ++y;//increment y to check additional array positions
        }
        ++x;//increment x to assign values to additional array positions
    } while (x<52);//continue loop until whole deck is assigned
}

void Color(int color)
{
    //sample usage: Color(7); (7 is default color)
   HANDLE hCon=GetStdHandle(STD_OUTPUT_HANDLE);
   SetConsoleTextAttribute(hCon,color);
}

void Card(int array[],int x)
{
    if (array[x]<27)
        Color(12);
    else
        Color(8);
    int temp=x;
    cout<<((array[x]<14) ? "\3" : (array[x]>13 && array[x]<27) ? "\4" : (array[x]>26 && array[x]<40) ? "\5" : "\6");
    array[temp]=((array[x]>39) ? array[x]-39 : (array[x]>26 && array[x]<40) ? array[x]-26 : (array[x]<27 && array[x]>13) ? array[x]-13 : array[x]);
    if (array[temp]<11 && array[temp]!=1)
        cout<<array[temp]<<" ";//just print the value unless it is 1 or above 10
    else//output A,J,Q, or K based on value
        cout<<((array[temp]==11) ? "J" : (array[temp]==12) ? "Q" : (array[temp]==13) ? "K" : "A")<<" ";
    cout<<((array[temp]==10) ? "" : " ");//add additional space for single digit values
    Color(7);
}

int main()
{
    int array[52]={0};//array of cards
    int player=0,computer=26;//tracks starting positions of players
    int psum=0,csum=0;
    int split=26;//tracks where deck splits
    srand(time(NULL));//set random # seed
    shuffle(array);//randomized shuffle

    while (split!=0 && split<52)
    {
    cout<<"Your card:\tValue:\n   ";
    Card(array,player);
    psum=((array[player]>39) ? array[player]-39 : (array[player]>13 && array[player]<27) ? array[player]-13 :
          (array[player]>26 && array[player]<40) ? array[player]-26 : array[player]);
    player++;
    cout<<"\t\t  "<<psum<<endl;
    cout<<"My card:\n   ";
    Card(array,computer);
    csum=((array[computer]>39) ? array[computer]-39 : (array[computer]>13 && array[computer]<27) ? array[computer]-13 :
          (array[computer]>26 && array[computer]<40) ? array[computer]-26 :  array[computer]);
    computer++;
    cout<<"\t\t  "<<csum<<endl;
    cout<<((psum>csum) ? "You " : (csum>psum) ? "I " : "");
    cout<<((psum!=csum) ? "won this round.\n" : "");
    split=((psum>csum) ? split+1 : (csum>psum) ? split-1 : split);
    if (psum==csum)
        War(array,player,computer,split);
    cout<<"You now have "<<split<<" cards.\n";
    cout<<"Push a key to play another round.";
    getch();
    cout<<endl;
    }
    cout<<((split!=0) ? "I " : "You ")<<"ran out of cards.\n";
    cout<<((split==0) ? "I " : "You ")<<"win!\n";
}//end of main

void War(int array[],int &player,int &computer, int &split)
{
    int psum=0;int csum=0;//re-initialization
    cout<<"\nWAR!!!!!!!!!!!!!!!!!\n";
    for (int i=0;i<3;i++)
    {
        Card(array,player);
        psum=((array[player]>39) ? psum+array[player]-39 : (array[player]>13 && array[player]<27) ?
              psum+array[player]-13 : (array[player]>26 && array[player]<40) ? psum+array[player]-26 : psum+array[player]);
        player++;
    }
        cout<<"\t  "<<psum<<endl;
    for (int i=0;i<3;i++)
    {
        Card(array,computer);
        csum=((array[computer]>39) ? csum+array[computer]-39 : (array[computer]>13 && array[computer]<27) ?
              csum+array[computer]-13 : (array[computer]>26 && array[computer]<40) ? csum+array[computer]-26 : csum+array[computer]);
        computer++;
    }
    cout<<"\t  "<<csum<<endl;
    cout<<((psum>csum) ? "You " : (csum>psum) ? "I " : "");
    cout<<((psum!=csum)? "won this battle.\n" : "");
    split=((psum>csum) ? split+3 : (csum>psum) ? split-3 : split);
    if (psum==csum)
        cout<<"The battle was a draw.\n";
}


Most of the time, it works properly, but occasionally the number of cards left (tracked by split) will jump an inexplicable amount. It's supposed to alter by 1 within a normal round, and by 3 following War, and sometimes the value is altering by 14 or more and I am unable to pinpoint why.
Your card:        Value:
   ♠8                8    
My card:
   ♠10               10
I won this round.
You now have 25 cards.
Push a key to play another round.
Your card:        Value:
   ♥6                6
My card:
   ♦6                6

WAR!!!!!!!!!!!!!!!!!!!
Your cards:       Total:
  ♥7  ♠8  ♠9         24
My cards:
  ♥9  ♣J  ♦9         29
I won this battle.
You now have 11 cards.
Push a key to play another round.
^C
??? WTF ???
The value jumping or decrementing a large amount is not limited to the war function, and sometimes happens during normal rounds too. Attempts to use if/else increments and decrements instead of ternary operators resulted in the same behavior (lines 73 and 107).

If this problem can be properly identified, then I can add functions to shuffle the player or computer portions of the deck when necessary, ensuring the game can continue until one player runs out of cards.
Last edited on
I get access violations when I run this program from function void Card(int array[],int x). When I ran the debugger I noticed invalid values being set to int x values that our out of range of the array being sent to it.

On my machine the while loop in main runs around 21 times before I get an invalid index value to pass to the Card function.

My best guess is your issue lies somewhere between lines 60 - 69.
That's very odd. I don't experience any access violations, or invalid array positions. Just the wrong total of cards being outputted on line 76, but it's inconsistent and usually correct. The same problem occurs sometimes regardless of whether the round was a standard card vs card round, or a War round with 3 cards vs 3. While a win or loss should increment or decrement the number of cards by 1 or 3 respectively, sometimes it suddenly jumps a large amount (anywhere from 8 to 20).
Perhaps I made an error when copying and pasting into my original post, but I can't spot it. The default values for player and computer are 0 and 26 respectively, and each increments following a turn (or increments by 3 for War). I suppose that it's possible that this could eventually result in values outside of the array, but the problem I'm focusing on right now is the card count. After fixing it, I will add shuffling for each player and use a swap function to ensure the correct cards remain in each portion of the deck, and after the swap reset the player's position. It's all kind of pointless if the program can't even track the number of cards in the player's hand properly, though.
Last edited on
I'm of no help but I love the way you chain the ternary expressions. Not!
That's a shame because I love to chain ternary expressions as opposed to using multiple if/else statements. At any rate, after copying the above code to my home machine (I coded it at work), its behavior remains consistent. While I know this code has some flaws, I cannot for the life of me pinpoint how the split variable is being unintentionally altered on occasion, yet correctly outputs the majority of the time. Don't spend too much time checking the logic of each card's output or the shuffle, as this has been tested and is known to work. Instead, somehow my card count is being screwed up and I can't pinpoint the cause but it definitely resides in the main and war functions, so concentration on these are most likely to bear fruit.
Last edited on
Ok, I stand corrected, although the problem was not in 60-69 in the main function either. In the end, the problem lay in the card function itself.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
void Card(int array[],int x)
{
    if (array[x]<27)
        Color(12);
    else
        Color(8);
    int temp=array[x];
    cout<<((array[x]<14) ? "\3" : (array[x]>13 && array[x]<27) ? "\4" : (array[x]>26 && array[x]<40) ? "\5" : "\6");
    array[temp]=((array[x]>39) ? array[x]-39 : (array[x]>26 && array[x]<40) ? array[x]-26 : (array[x]<27 && array[x]>13) ? array[x]-13 : array[x]);
    if (array[temp]<11 && array[temp]!=1)
        cout<<array[temp]<<" ";//just print the value unless it is 1 or above 10
    else//output A,J,Q, or K based on value
        cout<<((array[temp]==11) ? "J" : (array[temp]==12) ? "Q" : (array[temp]==13) ? "K" : "A")<<" ";
    cout<<((array[temp]==10) ? "" : " ");//add additional space for single digit values
    Color(7);
}

became
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
void Card(int array[],int x)
{
    if (array[x]<27)
        Color(12);
    else
        Color(8);
    int temp=x;
    cout<<((array[x]<14) ? "\3" : (array[x]>13 && array[x]<27) ? "\4" : (array[x]>26 && array[x]<40) ? "\5" : "\6");
    temp=((array[x]>39) ? array[x]-39 : (array[x]>26 && array[x]<40) ? array[x]-26 : (array[x]<27 && array[x]>13) ? array[x]-13 : array[x]);
    if (temp<11 && temp!=1)
        cout<<temp<<" ";//just print the value unless it is 1 or above 10
    else//output A,J,Q, or K based on value
        cout<<((temp==11) ? "J" : (temp==12) ? "Q" : (temp==13) ? "K" : "A")<<" ";
    cout<<((temp==10) ? "" : " ");//add additional space for single digit values
    Color(7);
}

Somehow, I was inadvertently altering array values, and while I'm not sure how this negatively impacted the card count, fixing this (lines 7-12) appears to have eliminated it.
Last edited on
Glad you found it. As for worrying about multiple if/else statements. You could always structure your code so that individual functions or even class methods could separate out the control flow into logical pieces. There is no shame in creating a method for a dynamic expression is it makes the code more readable. Then you have the advantage of adding parameters to make things as generic and flexible as possible.


EDIT- Don't be afraid to use multiple classes or files.
Last edited on
Thanks IceThatJaw. You make a good point that methods,classes and secondary files can make a difference in readability and debugging. I actually have most of these functions in my header file, but condensed it to simplify my post. Now that I've corrected this problem, even if I don't know why it impacted the card count, I need to consider some options for swapping cards that have been lost, and shuffling of each half of the deck when a player reaches the end prior to resetting their position.
Last edited on
Glad you found it
Topic archived. No new replies allowed.