Card Game

Pages: 12
Apr 20, 2020 at 12:31am
I am trying to make a card game war, but I am having trouble getting the deck split between the player and the computer. I have been working on this all day and I feel like i'm completely lost on what to even do.

Any help would be appreciated.

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
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
  #include<cstdlib>
#include<cmath>
#include<iomanip>
#include<string>
#include<iostream>
#include<fstream>
#include<ctime>
#include<vector>


using namespace std;

//constant
const int MAX = 52;

//prototypes
void rules();
void shuffle();
void yourdeck();
void theirdeck();

//class
class card {
public:
	char value;
	string suit;

	void printcard()
	{
		cout << value << " of " << suit;
	}

};
card deck[MAX], temp;



int main()
{
	//variables
	srand(time(NULL));

	char value[]{ 'A','2','3','4','5','6','7','8','9','X','J','Q','K' };
	string suit[]{ "Hearts","Diamonds","Clubs","Spades" };
	int i, j, l=0;
	for (i = 0; i < 4; i++)
	{
		for (j = 0; j < 13; j++)
		{
			deck[l].value = value[j];
			deck[l].suit = suit[i];
			l++;
		}
	}

	//input
	cout << "Welcome to the game of WAR!";
	cout << "\n";
	rules();
	

	//calculations
	shuffle();


	//output
	cout << "\n";
	cout << "Your card \t Their card\n";
	theirdeck();
	yourdeck();
	
	
	return 0;
}


//function definitions
void rules()
{
	int ch;
	cout << "Would you like to hear the rules? Press 1 for yes or 2 for no: ";
	cin >> ch;
	if (ch == 1)
	{
		cout << "\n";
		cout << "You will be playing the Computer, each of you will be given 26 cards." << endl;
		cout << "You will both throw down one card, whoever lower card will collect both cards and put them in their decks.\n";
		cout << "If you both have the same value card then you will commence the game of war!\n";
		cout << "Both players will lay down 3 cards face down and then flip a card.\n";
		cout << "Whoever has the lower card loses and collects all the cards in the pile!\n";
		cout << "The first person with zero cards left is declared the winner!\n";
		cout << "Goodluck!\n";
		cout << "\n";
	}
	else
	{
		cout << "no rules" << endl;
	}
}

void shuffle()
{
	int n, m;
	for (n = 0; n < 52; n++)
	{
		m = rand() % 52;
		temp = deck[n];
		deck[n] = deck[m];
		deck[m] = temp;
	}
}

void yourdeck()
{
	int k;
	for (k = 0; k < 25; k++)
	{
		deck[k].printcard();
		cout << "\n";
	}
	
}

void theirdeck()
{
	int k;
	for (k = 26; k < 52; k++)
	{
		deck[k].printcard();
		cout << endl;
	}
	
}


Apr 20, 2020 at 12:45am
You need to provide more information. We do not know what any of the functions in your code do or what the purpose of them are. Even a comment above the function would have sufficed but you have nothing so nobody can help you until you specify what exactly everything does or attempts to do.
Apr 20, 2020 at 12:55am
void shuffle() is used to shuffle the deck so it is randomized

void yourdeck() and theirdeck() splits the shuffled deck into 2 so there are 26 cards in each hand.

is that what you are asking for?
Apr 20, 2020 at 1:05am
And what is your question? What do you mean "getting the deck split"? Do you mean you want to seperate arrays, one for the player and one for the computer?
Last edited on Apr 20, 2020 at 1:06am
Apr 20, 2020 at 1:10am
Yes what I ultimately am trying to do is create the deck of cards, and then split them so the user has half the deck and the computer has half the deck in array's i guess. Once they both have half the deck I them to battle like War the card game where I lay down my first card and the computer lays down his card, if I am higher he gets both cards added to his deck.
Apr 20, 2020 at 1:29am
You could use an std::stack (pseudocode):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
std::stack<card> player_cards;
std::stack<card> computer_cards;
//...
//...Code that initializes both stacks with the portions of the deck array goes here...
//...
bool player_higher = play(player_cards, computer_cards);
if(player_higher && !computer_cards.empty())
{
     computer_cards.push(player_cards.top());
     player_cards.pop()
}
else if (!player_higher && !player_cards.empty())
{
    player_cards.push(computer_cards.top());
    computer_cards.pop();
}

if(player_cards.empty()) std::cout << "Computer wins";
if(computer_cards.empty()) std::cout << "Player wins";


Or something along those lines.
http://www.cplusplus.com/reference/stack/stack/

You could also just use std::vector if you don't want to deal with having to manually insert into the stack.
Last edited on Apr 20, 2020 at 1:30am
Apr 20, 2020 at 1:41am
if its the one pass war game (most # of hands won is winner) just use an offset.

shuffle(deck);
deal and compare:
player card = deck[x]; //0-25
computer card = deck[x+26]; //26-51
x++

logic to deal with ties etc … ties with no cards left … couple of basic scenarios.

war can be kinda cool with multiple decks.
Last edited on Apr 20, 2020 at 1:42am
Apr 20, 2020 at 2:07am
I am trying to understand the stack that you put in to the comments, sorry i'm struggling with this.

Would i use it inside of main or as another function, should I change the way I am splitting my deck as of right now?
Apr 20, 2020 at 3:09am
I changed my two deck functions from void to int
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
int yourdeck(int player_hand)
{
	int k;
	for (k = 0; k < 25; k++)
	{
		card player_hand;
		player_hand = deck[k];
		
	}
	return player_hand;
}

int theirdeck(int computer_hand)
{
	int k;
	for (k = 26; k < 52; k++)
	{
		card computer_hand;
		computer_hand = deck[k];
	}
	return computer_hand;
}


but then I don't know how to infuse them into the stack as I get errors for using too few arguments on the stack.

Also the play function i'm not sure if that goes where it is.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
stack<card> player_cards = yourdeck();
	stack<card> computer_cards = theirdeck();
	

	bool player_higher = play(player_cards, computer_cards);
	if (player_higher && !computer_cards.empty())
	{
		computer_cards.push(player_cards.top());
		player_cards.pop();
	}
	else if (!player_higher && !player_cards.empty())
	{
		player_cards.push(computer_cards.top());
		computer_cards.pop();
	}

	if (player_cards.empty()) std::cout << "Computer wins";
	if (computer_cards.empty()) std::cout << "Player wins";


Apr 20, 2020 at 1:27pm
I was also wondering if I should just scrap the deck I have and re do it all will a vector or something like that.
Apr 20, 2020 at 1:41pm
I would. You don't even need to change much, all you would have to do is create two new vectors for the player and the computer based on the deck array:

1
2
3
4
5
6
7
8
9
10
11
12
std::vector<card> player_cards(deck, deck+25);
std::vector<card> comp_cards(deck+25, deck+52);

//Now you have two vectors that have the respective card positions
//All you have to do is play the game. When the computer wins, add the
//player's cards to comp_cards by doing the following:

//auto& the_card = player_cards.back();
//player_cards.pop_back()
//comp_cards.push_back(std::move(the_card));

//And vice versa 


Of course, I would also recommend using std::stack, since it has an easier interface. The problem with stack is adding the cards to it initially, but using its interface is easier for this problem since a deck of cards is basically a "stack" of cards.
Last edited on Apr 20, 2020 at 1:42pm
Apr 20, 2020 at 1:47pm
Yes, redo some of this with vectors. The deck is a vector of cards. Each player's hand is a vector of cards. So you start by creating the deck. Then shuffle the deck. Then transfer every other card in the deck to one of the players' hands.

You may discover that a hand should be a class. It's hard to say.

Also, I think you'll find it easier to represent the suit and value of a card by a single integer id. Then the suit is id/4 and the value is id%4. This will make it easier to compare cards and suits.
Apr 20, 2020 at 2:06pm
Thanks for the help, I think i'm getting somewhere with this now.
I did the vectors and set them with some if else logic but when I try and run it
I get some xutility errors on lines 1108 and 3381.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
shuffle();
	vector<card> player_cards(deck, deck + 25);
	vector<card> computer_cards(deck + 25, deck + 52);
	auto& the_card = player_cards.back();
	if (player_cards > computer_cards)
	{
		cout << "You win this hand";
		player_cards.push_back(computer_cards.back());
		player_cards.pop_back();
	}
	else if (player_cards < computer_cards)
	{
		cout << "Computer wins this hand";
		computer_cards.push_back(player_cards.back());
		computer_cards.pop_back();
	}
	if (player_cards.empty())
	{
		cout << "Computer wins the game!";
	}
	if (computer_cards.empty())
	{
		cout << "Player wins the game!";
	}
Apr 20, 2020 at 2:14pm
Line 5if (player_cards > computer_cards)
Is it really proper to compare 2 vectors?
Apr 20, 2020 at 2:24pm
First of all, What is the purpose of doing this:
1
2
		player_cards.push_back(computer_cards.back());
		player_cards.pop_back();


You are adding a card to the players deck and then immediately removing it. There is no point in doing this.
You need to obtain a reference to the back card, and then pop it, and push it into the computer's deck.

1
2
3
4
5
6
7
8
9
/*IF THE COMPUTER WINS*/
auto& ref = player_cards.back() //Get a reference to the top card
player_cards.pop_back()            //Take it out of the players deck
computer_cards.push_back(std::move(ref)); //Add it to the comp's deck

/*IF THE PLAYER WINS*/
auto& ref = computer_cards.back()
computer_cards.pop_back()
player_cards.push_back(std::move(ref));


Secondly, where is the code to play the game? You aren't doing anything by comparing the vectors using operator<. You need to write code that plays the game. Essentially, you can do this by creating some sort of play function that returns true if the player wins and false if the player loses, something similar to this:
1
2
3
4
5
6
7
8
9
10
//THIS IS EXAMPLE CODE
bool play(std::vector<card> const& player, std::vector<card> const& comp)
{
    auto const& p = player.back();
    auto const& c = comp.back();

    if(p.value > c.value) return true;
    else return false;
}


This is just a simplified version. Obviously you can see I don't take into consideration the suits, the exact value, or even what happens when they both draw the same number. You can take this code as a starting point to write the play function.

I would also recommend overloading operator< for your Card class so you can compare cards directly instead of having to do a complicated calculation that takes into account suit and value.
Last edited on Apr 20, 2020 at 2:26pm
Apr 20, 2020 at 2:34pm
The rules are not clear.
"You will both throw down one card, whoever lower card will collect both cards and put them in their deck

Where does the card come from - top, bottom or random?
whoever lower card will collect both cards and put them in their deck

Put them where - top, bottom, random?
Last edited on Apr 20, 2020 at 2:35pm
Apr 20, 2020 at 2:56pm
you need to take care with ties... one or the other player may not have enough cards left to do a tie-breaker.

my technique above won't work with the recycle cards back to your hand version.

war is the top card of each player's half deck, traditionally. Its a kiddie game, no strategy or anything. Might be a little more exciting to have both sides pick a card, lay it face down, flip over to resolve. But the recycle to deck thing lasts forever: if both sides have an ace, you have to have the 2 aces against each other, then a tie breaker, until one side has all the aces and slowly wins by attrition.

Apr 20, 2020 at 3:19pm
I got it working somewhat! It is running but when I had to put a for loop to get it to run more than once in the calculations section.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
vector<card> player_cards(deck, deck + 25);
	vector<card> computer_cards(deck + 25, deck + 52);
	for (i = 0; i < 300; i++)
	{
		bool player_higher = play(player_cards, computer_cards);
		if (player_higher && !computer_cards.empty())
		{
			computer_cards.push_back(player_cards.front());
			player_cards.pop_back();
		}
		else if (!player_higher && !player_cards.empty())
		{
			player_cards.push_back(computer_cards.front());
			computer_cards.pop_back();
		}

		if (player_cards.empty()) std::cout << "Computer wins";
		if (computer_cards.empty()) std::cout << "Player wins";
	}


and I am still working on the tie and keeping score but I think I can get that figured out
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
bool play(vector<card> const& player, vector<card> const&comp)
{
	auto const& p = player.back();
	auto const& c = comp.back();
		if (p.value > c.value)
		{
			cout << p.value << " is higher than " << c.value << endl;
			cout << "Player wins this hand" << endl;
			return true;
		}
		else if (p.value < c.value)
		{
			cout << c.value << " is higher than " << p.value << endl;
			cout << "Computer wins this hand" << endl;
			return false;
		}
		else
		{
			cout << c.value << " is the same as " << p.value << endl;
			cout << "THIS MEANS WAR!" << endl;
		}
	
}



One question I had was when I run it with the for loop it seems to run the same 2 cards over and over again, and I assume this has to do with the push_back part in the code. Should I just try switching them around?

here is an example of what I mean:

A is higher than 5
Player wins this hand
X is the same as X
THIS MEANS WAR!
X is higher than 9
Computer wins this hand
X is higher than 9
Computer wins this hand
9 is higher than 5
Player wins this hand
X is higher than 9
Computer wins this hand
9 is higher than 5
Player wins this hand
X is higher than 9
Computer wins this hand

Apr 20, 2020 at 3:21pm
EDITED:
You want the card removed from the player to be inserted at the BOTTOM of the computer's deck, correct?

Let's assume that back = top of the deck, and front = bottom of the deck.

Also, you are going to have to change your play function somehow. You need to return a value from play when p.value == c.value, you can't just omit the return value. The bool was just a suggestion. Now it is clear that you need three states of information, not just true or false. You need to know if the player won, if the computer won, or whether it is a war. Find out how to implement that and what kind of type to use.
Last edited on Apr 20, 2020 at 3:44pm
Apr 20, 2020 at 3:37pm
Yes that is correct I want them inserted on the bottom so they dont draw it again till they have been through their whole deck.
I tried insert() in place of push_back() but that came back with the error

Severity Code Description Project File Line Suppression State
Error C2661 'std::vector<card,std::allocator<_Ty>>::insert': no overloaded function takes 1 arguments Project27 c:\users\ryans_000\source\repos\project27\project27\source.cpp 78

and push_front() wasn't popping up at all.
Pages: 12