War Card Game - Shuffling a deck

I'm working on a C++ project using Visual Studio 2010 and I'm trying to program the card game War. I figured the steps would be
1) Declaring 52 cards (Done)
2) Giving 26 unique cards to player
3) Giving the other 26 unique cards to computer
4) Shuffling the player's 26 cards
5) Shuffling the computer's 26 cards
6) Reveal player and computer's cards
7) Distribute points & Dispose of cards
8) Pause, press any key to continue
9) Declare winner

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
// war.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include<iostream>
#include<conio.h>
#include<ctime> //needed for getRand
using namespace std;
#include"cards.cpp"

int _tmain(int argc, _TCHAR* argv[])
{
	int getRand(); //Get a random number under 52
	int rand; //See above
	const int ALLCARDS = 52;
	int split[ALLCARDS] = {0}; //Keeps track of who has what card: 0 is not used, 1 is player, 2 is computer
	int playerScore = 0;
	int comScore = 0;
	int i;
	srand((unsigned)time(NULL));

	for(i = 0;i <26;i++){
		rand = getRand();
		cout<<rand<<' ';
		if(split[rand] = 0)split[rand]=1;
		//else{
		//	//while(split[rand] = 1 || split[rand] = 2)rand = getRand();
		//	//split[rand]=2;
		//	i--;
		//	}
	}
	for(i = 0;i < ALLCARDS;i++)cout<<split[i]; //52 1s and 0s Should be only 26 1s here
	_getch();
	return 0;}

int getRand(){
	const int DIVISOR = 52;
	int result;
	result = rand() % DIVISOR;
	return result;
}


Right now, I'm on the second step and the output oddly only puts out 0s. But when I change
if(split[rand] = 0)split[rand]=1;
to
split[rand]=1;
The output is that there's twenty-some 1s, not twenty-six 1s like I desired, because the random numbers replicate.
This problem is already solved for you with the random_shuffle() function http://www.cplusplus.com/reference/algorithm/random_shuffle/ in the STL.

EDIT: I'd also like to mention by using random_shuffle and just popping of the top of each players stack you don't have to worry about keeping track of whether or not a card has been played or not.
Last edited on
Sorry about the late reply- Had a good Thanksgiving Break.

Okay, I haven't started studying on templates, and a lot of that link looks complicated. I did get 52 random numbers with it, but now I'm having trouble with how to just take one random number and give it to a computer. From what I understand, myvector is all 52 numbers?

I don't know if it was a good idea or not, but I put all of my cards into one array. I'll probably code some if statement system of numbers to make it work.

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
// war2.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include <iostream>
#include <conio.h>
#include <algorithm>
#include <functional>
#include <vector>
#include <ctime>
#include <cstdlib>
using namespace std;
#include"cards.cpp"

// random generator function:
ptrdiff_t myrandom (ptrdiff_t i) { return rand()%i;}

// pointer object to it:
ptrdiff_t (*p_myrandom)(ptrdiff_t) = myrandom;

int _tmain(int argc, _TCHAR* argv[])
{
	const int ALLCARDS = 52;
	int playerScore = 0;
	int comScore = 0;
  srand ( unsigned ( time (NULL) ) );
  vector<int> myvector;
  vector<int>::iterator it;

  // set some values:
	  for (int i=0; i<ALLCARDS; ++i ) myvector.push_back(i); // 1 2 3 4 5 6 7 8 9

  // using built-in random generator:
  random_shuffle ( myvector.begin(), myvector.end() );

  // using myrandom:
  random_shuffle ( myvector.begin(), myvector.end(), p_myrandom);

  //
  //start playing war
  //
  cout<<"\tComputer has "<<CARD[whatgoeshere]<<endl;
  cout<<"\tPlayer has "<<CARD[whatgoeshere]<<endl;

  //distribute and display score 
  cout<<"Computer score is "<<comScore<<endl;
  cout<<"Player score is "<<playerScore<<endl;
  system("PAUSE");

	_getch();
	return 0;}


EDIT: My question is, what do I put for the whatgoeshere, from that STL you posted?
Last edited on
First you need to choose which randomization method you want to use, don't just copy and paste from the link I gave you try to read the code. Next you'll want to point your iterator at the beginning of the array that you shuffled. Then dereference the iterator for the whatgoeshere part of your code, and don't forget to increment it so that you're looking at the next card in the deck.
Well, that's the thing. It might be well documented, but I'm having trouble just reading the code. I was thinking to just assign the first 26 random numbers to player and the last 26 numbers to the computer, if that's what you're talking about when it comes to randomization method.
You could do that, you'd end up with two or three vector array's instead of one but it would still get the job done.
Really? I'd figure I could just get position + 26 to get that value; I don't want to complicate it with more vectors.
That's a little messy. It could work but I'm afraid you wouldn't learn anything which should be the purpose of this assignment.
I don't know anything about vector arrays, if that's what you're getting at.

EDIT: My class is about to end. I gotta go.
Last edited on
I got it working! Well, after struggling with random_shuffle, I decided to go back to my original code and tried to go from there. Although it's done, I can't help but feel like I did too many workarounds to get the finished product. If anyone have any advice to improve it, I'd appreciate it. I still don't understand how to incorporate random_shuffle.

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
// war.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include<iostream>
#include<conio.h>
#include<ctime> //needed for getRand
using namespace std;
#include"cards.cpp"

int _tmain(int argc, _TCHAR* argv[])
{
	int getRand(); //Get a random number under 52
	int rand; //See above
	void battle(int, int, int &x, int&y); //Whose card is bigger anyway?
	void getWinner(int &a, int &b); //See if player beats computer

	const int ALLCARDS = 52;
	int split[ALLCARDS] = {0}; //Keeps track of who has what card: 0 is not used, 1 is player, 2 is computer
	int i;
	int playerScore = 0;
	int comScore = 0;
	int drip = 1;
	int playerCard = 52;
	int comCard = 52;
	srand((unsigned)time(NULL));

	//Gives 1s to player
	for(i = 0;i <26;i++){
		rand = getRand();
		//cout<<rand<<' ';
		if(split[rand] == 0)split[rand]=1;
		else{
			i--;
		}
	}
	//Gives all 0s to computer
	for(i = 0;i < ALLCARDS;i++)
		if(split[i] == 0)split[i]=2;
	//
	//start playing war
	//

	while((playerScore + comScore) != 52){
		cout<<"Deal #"<<drip<<endl;
		
		while(split[playerCard] != 1)
			playerCard = getRand();
		cout<<"\tPlayer has "<<CARD[playerCard]<<" ("<<playerCard<<')'<<endl;
		split[playerCard]=0;

		
		while(split[comCard] != 2)
			comCard = getRand();
		cout<<"\tComputer has "<<CARD[comCard]<<" ("<<comCard<<')'<<endl;
		split[comCard]=0;

		//distribute and display score
		battle(playerCard, comCard, playerScore, comScore);
		cout<<"Player score is "<<playerScore<<endl;
		cout<<"Computer score is "<<comScore<<endl;
		
		for(i=0;i<ALLCARDS;i++)cout<<split[i]; //debug
		cout<<endl; //debug

		system("PAUSE");
		cout<<endl;
		drip += 1;
	}
	getWinner(playerScore, comScore);
	_getch();
	return 0;}

int getRand(){
	const int DIVISOR = 52;
	int result;
	result = rand() % DIVISOR;
	return result;
}

void battle(int a, int b, int &x, int &y){
	while(a > 13)a -=13;
	while(b > 13)b -=13;
	if(a > b)x += 2;
	else if(a == b){
		x += 1;
		y += 1;
	}
	else if(a < b)y += 2;
}

void getWinner(int &a, int &b){
	if(a > b)
		cout<<"\n\nYou win!!  ...In this game of chance.";
	else
		cout<<"\n\nYou lost.  Haha.";
}
Hey this is pretty cool. What is in your cards and stdafx header files? Also, what is #include <conio.h>?
I don't remember what stdafx is. In the cards.cpp is just the 52 cards all in one constant array of strings. I believe conio.h is just there to get getch() working in Visual Studio, since Visual Studio doesn't pause after the code's executed.
Here's one:
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
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
#include <vector>
#include <algorithm>
#include <iostream>
#include <ctime>

typedef int Suit, Rank;

const Suit  hearts = 0, clubs = 1,   diamonds = 2,  spades = 3;
												  
const Rank  two = 0,    three = 1,   four = 2,      five = 3,
            six = 4,    seven = 5,   eight = 6,     nine = 7,
            ten = 8,     jack = 9,   queen = 10,    king = 11,
            ace = 12;

class Card
{
    Suit suit;
    Rank rank;
public:
    Card(Suit s, Rank r) : suit(s), rank(r) { }

    bool operator==(Card c) { return rank == c.rank; }
    bool operator< (Card c) { return rank <  c.rank; }
};


class CardStack
{
protected:
    std::vector<Card> cards;
public:
    Card Play()
    {
        Card c( *cards.begin() );
        cards.erase(cards.begin());
        return c;
    }

    std::vector<Card> Play(int i)
    {
        std::vector<Card> c;

        while (i-- && cards.size())
            c.push_back( Play() );

        return c;
    }

    void Draw(Card c)
    {
        cards.push_back(c);
    }
    void Draw(std::vector<Card> c)
    {
        for (std::vector<Card>::iterator it = c.begin(); it != c.end(); ++it)
            Draw(*it);
    }

    int CardsLeft() { return cards.size(); }
};

class Player : public CardStack {  };

class Deck : public CardStack
{
public:
    Deck() 
    {
        for (Rank r = two; r <= ace; ++r)
            for (Suit s = hearts; s <= spades; ++s)
                cards.push_back(Card(s,r));

        std::random_shuffle(cards.begin(), cards.end());
    }

    void Deal(Player& p1, Player& p2)
    {
        for(bool i = true; cards.size() ; i = !i)
        {
            if (i) p1.Draw( Play() );
            else   p2.Draw( Play() );
        }
    }
};

class Table
{
    CardStack theStack;
    Deck deck;
    Player p1, p2;
public:
    int iterations;

    Table() : iterations(0) {    deck.Deal(p1, p2);    }

    int Play()
    {
        int result = 0;

        while(result == 0)
            result = Attack();

        return result;
    }
    int Attack() // return 0 (no winner yet), 1 (p1 wins), 2 (p2 wins), 3 (tie)
    {
        if (++iterations > 15000) return 3;

        std::cout << std::endl << "p1: " << p1.CardsLeft() << "\t p2: " << p2.CardsLeft();

        if (p1.CardsLeft() < 1) return 2;
        if (p2.CardsLeft() < 1) return 1;

        Card left( p1.Play() ), right( p2.Play() );

        theStack.Draw(left);
        theStack.Draw(right);

        if (left == right) 
        {
            std::cout << " \t WAR!";
            if (p1.CardsLeft() < 3) return 2;
            if (p2.CardsLeft() < 3) return 1;

            theStack.Draw( p1.Play(3) );
            theStack.Draw( p2.Play(3) );

            return Attack();
        }
        else if (left < right)
        {
            std::cout << " \t p1 wins";
            p1.Draw( theStack.Play( theStack.CardsLeft() ) );
        }
        else
        {
            std::cout << " \t p2 wins";
            p2.Draw( theStack.Play( theStack.CardsLeft() ) );
        }

        return 0;
    }
};

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

    Table t;
    t.Play();
}
Last edited on
Nice!!! So have written some similar code to this, but I am trying to capture the data of wins in losses in a text file (required for my project). I want to make one column the run number, second column if player 1 wins, and third if player 2 wins. If a player wins I want it to print a 1 in their column and a 0 if they lose. Can you help me with this?
Topic archived. No new replies allowed.