dimanche 3 mai 2020

C++ Beginning classes for a card game. Shuffling, drawing, comparing values, and out_of_range checking

I am trying to create a basic card game of war. Drawing 3 cards and comparing them one at a time, then best out of three wins. To begin I am just starting with making classes for the cards and deck. Later I will be making a Player class which will hold more mechanics of the game.

I am currently having trouble with populating the deck with the cards and drawing the top card. In my main() I'm trying to do error checking to see if I have implemented things correctly before moving on. It is supposed to then shuffle the deck and draw a card, which is read back. This will ensure that the cards are all made correctly and when I have drawn over 52 it will throw out of range. There is also a special Joker which determines which player will go first, this isn't implemented completely yet but is represented by the non-overloaded Card() constructor.

What it does so far is throw the out of range without populating the deck and writing out the cards, so the try I have written is incorrect and I don't really understand how to write the proper cout in it to show which card was just drawn. The comparison operators are not implemented in main yet either, I have the commented out at the moment.

Here are my following files.

main.cpp

#include <iostream>
#include <string>
#include <stdexcept>

#include "Card.h"
#include "Deck.h"


int main(){

    Deck deckA; //create a deck
    deckA.shuffle(); //shuffle cards into deck


        try{
            for(int i = 0; i < 52; i++){ //draw cards till deck is empty
                deckA.draw();
            std::cout << deckA; //not sure how to properly write out a card's suit and value using the overloaded <<




            //comparison operators, not implemented buy my idea for how to go about it.
            /** for(int i = 0; i < 51; i++){
                if (deckA[i + 1] < deckA[i]){
                return std::cout << deckA[i], " is greater than ", deckA[i + 1];
                }

                if(deckA(i + 1) == deckA(i)){
                    return std::cout << deckA[i], " is equal to ", deckA[i + 1];
                }
            } **/


            }
        }
        catch(std::out_of_range&){      //catch for thrown out of range
            std::cout << "Empty Deck";
            deckA.shuffle(); //shuffle new deck
        }

}

Card.h

#ifndef CARD_H_
#define CARD_H_

#include <iostream>
#include <string>

/**
 * String constants for the suits. Use these for the << operator. Use the ordinal value
 * of the Suit enum as an index to fetch the Card suit name
 */
static const std::string suitNames[] =
        { "Spades", "Hearts", "Diamonds", "Clubs" };

/**
 * String constants for the rank. Use these for the << operator. Use the ordinal value
 * of the Rank enum as an index to fetch the Card rank name
 */
static const std::string rankNames[] = { "Joker", "Two", "Three", "Four",
        "Five", "Six", "Seven", "Eight", "Nine", "Ten", "Jack", "Queen", "King",
        "Ace" };

/**
 * Card class to represent a single playing card
 */
class Card {
public:
    /**
     * Suit enumerations
     */
    enum Suit {
        Spades = 0, Hearts, Diamonds, Clubs
    };

    /**
     * Rank enumerations ordered by value for game of war
     */
    enum Rank {
        Joker = 0,
        Two,
        Three,
        Four,
        Five,
        Six,
        Seven,
        Eight,
        Nine,
        Ten,
        Jack,
        Queen,
        King,
        Ace
    };

    /**
     * Constructor
     *
     * @param s
     * @param r
     */
    Card(Suit s, Rank r);

    /**
     * Constructor. This empty constructor will create a joker card.
     * The joker card is a special card given to the player going first.
     */
    Card();

    /**
     * Destructor
     */
    virtual ~Card();

    /**
     * Return true if this card is a joker
     */
    bool isJoker() const {
        return (cardRank == Joker);
    }

    /**
     * Output the card to an output stream as "rank of suit", except for the joker which is just output as "Joker"
     */
    friend std::ostream& operator <<(std::ostream&, const Card&);

    /**
     * Compare operators. For the game of war we only care about the rank value
     */
    friend bool operator ==(const Card &lhs, const Card &rhs);
    friend bool operator <(const Card &lhs, const Card &rhs);

private:
    Suit cardSuit;
    Rank cardRank;
};

#endif /* CARD_H_ */

Card.cpp

#include <string>
#include <iostream>

#include "Card.h"


    Card::Card(Suit s, Rank r){
        cardSuit = s;
        cardRank = r;
    }

    /**
     * Constructor. This empty constructor will create a joker card.
     * The joker card is a special card given to the player going first.
     */
    Card::Card() {
        //joker
    }

    /**
     * Destructor
     */
    Card::~Card() {
        // empty
    }

    /**
     * Output the card to an output stream as "rank of suit", except for the joker which is just output as "Joker"
     */
    std::ostream& operator <<(std::ostream& os, const Card& r){

         //if joker cout Joker, else cout rank of suit
     if (r == Card() ){
         return os << "Joker";
     }

     else{
        return os << r.cardRank << " of " << r.cardSuit;
     }
 }

    /**
     * Compare operators. For the game of war we only care about the rank value
     */
bool operator ==(const Card &lhs, const Card &rhs){
    return (lhs == rhs);
}

bool operator <(const Card &lhs, const Card &rhs)
{
    return (lhs.cardRank < rhs.cardRank);
};

Deck.h

#ifndef DECK_H_
#define DECK_H_

#include <vector>

#include "Card.h"

#define MaxCards 52

/**
 * The Deck class holds a deck of 52 cards. Cards are not removed
 * from the Deck.
 */
class Deck {
public:
    /**
     * Constructor and destructor
     */
    Deck();
    virtual ~Deck();

    /**
     * Shuffle the deck and reset the next available card to the beginning of the deck
     */
    void shuffle();

    /**
     * Return true if the deck is empty (next available card is past the end of the deck)
     */
    bool isEmpty() const;

    /**
     * Draw a card from the deck. If someone attempts to draw a card when the deck is
     * empty then throw an out-of-range exception.
     */
    const Card draw();

private:
    unsigned nextCard;
    std::vector<Card> cardDeck;
};

#endif /* DECK_H_ */

Deck.cpp

#include <iostream>
#include <vector>
#include <exception>
#include <algorithm>
#include <random>
#include "Deck.h"
#include "Card.h"

    /**
     * Constructor and destructor
     */
    Deck::Deck() { //warning due to uninitialized  Member nextCard.
        unsigned nextCard = 0;
        std::vector<Card> cardDeck[nextCard];
    }



    Deck::~Deck() {
        // empty
    }

    /**
     * Shuffle the deck and reset the next available card to the beginning of the deck
     */
    void Deck::shuffle() {

         std::shuffle(cardDeck.begin(), cardDeck.end(), std::default_random_engine());
         nextCard = 0; //set index to top card.
    }

    /**
     * Return true if the deck is empty (next available card is past the end of the deck)
     */
    bool Deck::isEmpty() const{
        unsigned nextCard;
        if( nextCard == 52){
            return true;
        }
    }

    /**
     * Draw a card from the deck. If someone attempts to draw a card when the deck is
     * empty then throw an out-of-range exception.
     */
    const Card Deck::draw(){

        if (isEmpty() == true){
            throw std::out_of_range("Out of range");
        }
        else{
            cardDeck[nextCard++]; //draw card
            return cardDeck[0]; //return top card
        }
    }

Aucun commentaire:

Enregistrer un commentaire