Saturday, May 5, 2007

Programing: Card Game War (Part 1 of 5)

It has been a while since I looked at this program and I thought it would be worth publishing. It was a simple concept, play a game of war (the card game that is). This is going to be a five part series because the program written in C++ and is object oriented. This first part is going to be the object oriented wrapper class for a random number generator. I'm also going to explain some basics about how the program is going to work and some problems that arise. It might seem pointless to mention, but this game is not interactive, it is the computer playing the computer. It is probably important to note that this code was compiled and tested using Bloodshed Dev-C++ under Windows XP (but now I use Vista and it works fine).

First, I'll post the C++ code for the Random Number Generator class. The code was implemented using multiple files (one for each class) but it could just as simply be implemented using one long source file. To make things simple here are all of the header files I have used for all of classes.


#include <cstdlib>
#include <iostream>
#include <cstdlib> //Used for rand() & srand()
#include <string>
#include <fstream>


For a multiple file project this part of the code was in the file randomNumber.h

This part of the code actually has more features than were used in the game of War, but I left them in because they are still useful and don't take up that much room.


class RandomGenerator
{
private:
int seed;
public:
RandomGenerator();
RandomGenerator(int);

void setSeed(int);
int getSeed();
int getInt();
int getInt(int max);
int getInt(int min, int max);
int rollDie();
int rollTwoDice();
int cardIndex();
bool coinFlip();
};

RandomGenerator::RandomGenerator()
{
//Do nothing...
}
RandomGenerator::RandomGenerator(int mySeed)
{
if(mySeed == -1)
{
//Don't do anything
}
else
{
setSeed(mySeed);
}
}
void RandomGenerator::setSeed(int mySeed)
{
seed = mySeed;
srand(seed);
}
int RandomGenerator::getSeed()
{
return seed;
}
int RandomGenerator::getInt()
{
return rand();
}
int RandomGenerator::getInt(int max)
{
//Assumes a minimum of zero
return getInt(0,max);
}
int RandomGenerator::getInt(int min, int max)
{
return rand()%(max-min+1)+min;
}
int RandomGenerator::rollDie()
{
return getInt(1,6);
}
int RandomGenerator::rollTwoDice()
{
return rollDie() + rollDie();
}
int RandomGenerator::cardIndex()
{
return getInt(51);
}
bool RandomGenerator::coinFlip()
{
return getInt(0,1);
}


I'm not going to spend time explaining the code because I tried to make it self explanatory. In my code the only method that I am going to use is cardIndex(). All this method really does is return a number between 0 and 51 (the array containing the 52 cards in a deck is zero indexed).

That about wraps up all of the information about the random class. Now I'm going to talk a little bit about some of the problems that arise while trying to code the game War. First off, there are many different ways to play the game. Below I am going to spell out the rules.

The Rules
1) Each player is dealt half of the deck.
2) Players lie down cards at the same time and the player with the higher card wins. An ace is the highest card and the two is the lowest card.
3) If there is a tie then each player burns three cards (put them into the playing area), W.A.R., and then the next card decides who gets all of the cards. It is possible to tie again, but the same rules apply for this tie.
4) The player who wins is the first to get all of the cards. Also, if the other player runs out of cards during a War, that player loses.

Problems to Test For
There are several problems with implementing this game. First off, the way the cards go back into each players deck. In real life, they get mixed up on purpose or on accident. In this simulation, the cards will be very precisely tracked. In this way given a deck in a certain order, the results of the game will always be the same. The way I'll implement this is by having different piles of cards that move in very specific ways. There will be more about this later on when I actually post the code for this part.

Another problem is the question of having a game tie. I'm not going to spoil my results, but my attempts in trying to determine if it is actually possible to tie at a game of war did surprised me. This will probably be in the last section because it involves running multiple games of War and looking for patterns.

Hopefully this series on War is interesting. It has actually been a while since I wrote this code. I'm just going to be cleaning it up for this publication. Hopefully someone finds it interesting.

Lastly, feel free to use the code I publish for no commercial pourposes, just be sure to give me credit.

No comments: