Friday, May 11, 2007

Programing: Card Game War (Part 4 of 5)

In my last post in this series I talked about the deck class. This class represented the deck of cards that will be used in the game. It simply served to make all 52 cards, shuffle them, then deal them to each player. This part of the code is the most complex, and before I even post it I would like to state my question about the accuracy of this code.

First off, this is an old piece of code that I mainly just wanted to publish so I putting it out that, basically as is.

This segment of the code implements the actual logic involved in the game of war. Sadly, i think it does not do it accurately. I do know it is not efficient. I am going to post this code in its current state even though I think there is a major logical error somewhere in the game.

Again, here are the header files that were used up to this point.


#include <cstdlib>
#include <iostream>
#include <cstdlib> //Used for rand() & srand()
#include <string>
#include <fstream>
//Used to just make all kinds of crazy random numbers
#include "randomNumbers.h"
//Used to make an individual card object
#include "card.h"
//Used to hold an entire deck of cards
#include "deck.h"


So, here is the code which is stored in the header file war.h


class war
{
private:
card player1[52];
card player2[52];
card buffer1[52];
card buffer2[52];
card playingArea[52];
int indexPlayer1;
int indexPlayer2;
int indexBuffer1;
int indexBuffer2;
int indexPlayingArea;
int rounds;
card getPlayer1Card();
card getPlayer2Card();
void player1WinTrick();
void player2WinTrick();
int playTrick();
public:
war();
int returnRounds();
};

war::war()
{
//Make The Deck Shuffle The Cards
deck myDeck;
myDeck.shuffleCards();

//Set Some Default Values
indexPlayer1 = 52/2 - 1;
indexPlayer2 = 52/2 - 1;
indexBuffer1 = 0;
indexBuffer2 = 0;
indexPlayingArea = 0;

//Deal out a deck
for(int i = 0; i < 52/2; i++)
{
player1[i] = myDeck.dealCard();
player2[i] = myDeck.dealCard();
}
int winner;
int i = 0;
bool loop = true;
while(loop)
{
winner = playTrick();

if(winner == 1)
{
player1WinTrick();
}
else if(winner == 2)
{
player2WinTrick();
}

if(indexPlayer1 <= 0 && indexBuffer1 <= 0)
{
loop = false;
}
if(indexPlayer2 <= 0 && indexBuffer2 <= 0)
{
loop = false;
}
i++;
//Give up on round 10,000 - declare tie!
if(i == 10000)
{
loop = false;
}
}
rounds = i;
}
int war::returnRounds()
{
return rounds;
}
void war::player1WinTrick()
{
card nullCard;
for(int i = 0; i < indexPlayingArea; i++)
{
buffer1[indexBuffer1] = playingArea[i];
indexBuffer1++;
playingArea[i] = nullCard;
}
indexPlayingArea = 0;
}
void war::player2WinTrick()
{
card nullCard;
for(int i = 0; i < indexPlayingArea; i++)
{
buffer2[indexBuffer2] = playingArea[i];
indexBuffer2++;
playingArea[i] = nullCard;
}
indexPlayingArea = 0;
}

int war::playTrick()
{
card nullCard;
//Get Player 1's Card
card player1Card = getPlayer1Card();
//Get Player 2's Card
card player2Card = getPlayer2Card();

//Player 1 Wins The Trick
if( player1Card.getCardValue() > player2Card.getCardValue() )
{
//Put the two cards in the hand

playingArea[indexPlayingArea++] = player1Card;
playingArea[indexPlayingArea++] = player2Card;
return 1;
}
//Player 2 Wins The Trick
else if( player1Card.getCardValue() < player2Card.getCardValue() )
{
//Put the two cards in the hand
playingArea[indexPlayingArea++] = player2Card;
playingArea[indexPlayingArea++] = player1Card;
return 2;
}
//Tie Game and add 3 to the pile and play another trick
else
{
//Put the two cards in the hand
playingArea[indexPlayingArea++] = player1Card;
playingArea[indexPlayingArea++] = player2Card;
// W
player1Card = getPlayer1Card();
player2Card = getPlayer2Card();
playingArea[indexPlayingArea++] = player1Card;
playingArea[indexPlayingArea++] = player2Card;
// A
player1Card = getPlayer1Card();
player2Card = getPlayer2Card();
playingArea[indexPlayingArea++] = player1Card;
playingArea[indexPlayingArea++] = player2Card;
// R
player1Card = getPlayer1Card();
player2Card = getPlayer2Card();
playingArea[indexPlayingArea++] = player1Card;
playingArea[indexPlayingArea++] = player2Card;
// WAR
return playTrick();
}
}

card war::getPlayer1Card()
{
card nullCard;
//There are cards left in the deck and then deal a card
if(indexPlayer1 >= 0)
{
card player1Card = player1[indexPlayer1];
player1[indexPlayer1] = nullCard;
indexPlayer1--;
return player1Card;
}
//Player 1 Has No Cards Left In hand therefore needs to move buffer to hand
else
{
//If Cards Are In The Buffer
if(indexBuffer1 > 0)
{
for(int i = 0; i < indexBuffer1; i++)
{
player1[++indexPlayer1] = buffer1[i];

buffer1[i] = nullCard;
}
indexBuffer1 = 0;
return getPlayer1Card();
}
else
{
return nullCard;
}
}
}

card war::getPlayer2Card()
{
card nullCard;
//There are cards left in the deck and then deal a card
if(indexPlayer2 >= 0)
{
card player2Card = player2[indexPlayer2];
player2[indexPlayer2] = nullCard;
indexPlayer2--;
return player2Card;
}
//Player 1 Has No Cards Left In hand therefore needs to move buffer to hand
else
{
//If Cards Are In The Buffer
if(indexBuffer2 > 0)
{
for(int i = 0; i < indexBuffer2; i++)
{
player2[++indexPlayer2] = buffer2[i];

buffer2[i] = nullCard;
}
indexBuffer2 = 0;
return getPlayer2Card();
}
else
{
return nullCard;
}
}
}


First off, the actual implementation of the game is awful, primarily because of the coding practices. It is difficult to follow the code, I will admit. However, I'll explain some of the basics so at least it is a little understandable.

First off, when the constructor is called, it is passed no parameters. The constructor actually plays through all of the rounds of the game and the results can then be accessed. There is only one public method named returnRounds() which if you haven't already guessed returns the number of rounds that it took to complete the game. That is the main focus of this entire project.

The actual logic of the code involves several complex (and inefficient) interactions of arrays which very accurately mimic how the game would be played in real life. Again, program efficiency was sacrificed for realism to how the game is played.

My last post in this series will be the actual main class that creates an instance of the war class and gets some results out of this program. I'll be looking for any pattern that arise from this implementation of the game.

No comments: