The program I've written creates a deck of card that can be shuffled and player that takes four cards and puts them into for corresponding columns.
I can display a single card by doing this:
int main()
{
Card card;
cout << card << endl;
}
The problem is, I want to display my player class, which is made up of a vector of cards and should display four cards and put them into four separate columns. But using this:
int main()
{
Deck deck;
deck.shuffle();
Player player;
cout << player;
}
does not display anything, in fact, it gives me an error.
How can I properly display my four cards in their corresponding four columns?
Also, here is the entire code I have so far, in case you want to go through it yourself:
#include <iostream>
#include <algorithm>
#include <vector>
#include <cstdlib>
#include <ctime>
using namespace std;
enum suits
{
diamond, club, heart, spade
};
class Card
{
private:
int rank;
suits suit;
public:
Card();
Card(suits, int);
int getRank() { return rank; }
suits getSuit() { return suit; }
void setRank(int rankvalue) { rank = rankvalue; }
void setSuit(suits suitvalue) { suit = suitvalue; }
};
ostream & operator<<(ostream &, Card);
Card::Card()
{
rank = 1;
suit = spade;
}
Card::Card(suits suitvalue, int rankvalue)
{
rank = rankvalue;
suit = suitvalue;
}
ostream & operator<<(ostream & out, Card aCard)
{
switch (int rank = aCard.getRank())
{
case 1: out << "Ace"; break;
case 11: out << "Jack"; break;
case 12: out << "Queen"; break;
case 13: out << "King"; break;
default: out << rank;
}
switch (suits suit = aCard.getSuit())
{
case diamond: out << " of Diamonds"; break;
case spade: out << " of Spades"; break;
case heart: out << " of Hearts"; break;
case club: out << " of Clubs"; break;
}
return out;
}
class RandomInteger
{
public:
RandomInteger();
unsigned int operator() (unsigned int max);
};
RandomInteger::RandomInteger()
{
srand(time(0));
}
unsigned int RandomInteger::operator()(unsigned int max)
{
unsigned int rval = rand();
return rval % max;
}
RandomInteger randomizer;
class Deck
{
Card cards[52];
int topCard;
public:
Deck();
void shuffle();
bool isEmpty() { return topCard <= 0; }
Card draw();
};
extern RandomInteger randomizer;
Deck::Deck()
{
topCard = 0;
for (int i = 1; i <= 13; i++)
{
Card c1(diamond, i), c2(spade, i), c3(heart, i), c4(club, i);
cards[topCard++] = c1;
cards[topCard++] = c2;
cards[topCard++] = c3;
cards[topCard++] = c4;
}
}
Card Deck::draw()
{
if (!isEmpty())
return cards[--topCard];
else
{
Card spadeAce(spade, 1);
return spadeAce;
}
}
void Deck::shuffle()
{
random_shuffle(cards, cards+52, randomizer);
}
class Player
{
public:
Player();
void print();
Card draw(Deck &);
typedef vector<Card> cards;
vector<cards> column;
};
Player::Player()
{
column.push_back(vector<Card>());
column.push_back(vector<Card>());
column.push_back(vector<Card>());
column.push_back(vector<Card>());
}
Card Player::draw(Deck & aDeck)
{
for (int i = 0; i < 4; i++)
column[i].push_back(aDeck.draw());
}
void Player::print()
{
cout << "Col 1 \t Col 2 \t Col 3 \t Col 4 \n";
bool more = true;
for (int j = 0; more; j++)
{
more = false;
for (int i = 0; i < 4; i++)
if (j < column[i].size())
{
cout << column[i][j] << "\t";
more = true;
}
else
cout << "\t\t";
cout << endl;
}
}
int main()
{
Deck deck;
deck.shuffle();
Player player;
while (!deck.isEmpty());
cout << player;
}
Sorry for the amateur question, I know it's something simple, and thanks in advance.
cout << player;
This would not work, because you've not overloaded operator<< for type Player. Please first implement this:
ostream & operator<<(ostream &out, const Player & player)
{
//your implementation
}
If it needs to access private members, then make this friend of Player.
I just noticed that your class Player has a function called print, maybe you would like to call it from operator<<(). If you call it, then I would suggest you to use the following function signature:
void print(ostream &out) const
{
//use `out`, instead of `cout` now!
}
And then call this from operator<<, as:
ostream & operator<<(ostream &out, const Player & player)
{
player.print(out);
return out;
}
Advantage of this implementation is that you can output to console as well as file also.
You need to implement the overloaded operator "<<" for Player:
ostream & operator<<(ostream &, Player&);
to output the relevant information exactly as it was done for Card class.
Well the first call works because of the code "you wrote" here:
ostream & operator<<(ostream &, Card);
in the second player class "you wrote" a print class. So im assuming you can just call player.print(). But I didn't go through print to see if it works.
You need to define an operator << for your Player class as well as your Card class
ostream & operator<<(ostream & out, Player& aPlayer) {
//print out each card in turn
out << "Col 1 \t Col 2 \t Col 3 \t Col 4 \n";
bool more = true;
for (int j = 0; more; j++)
{
more = false;
for (int i = 0; i < 4; i++)
if (j < aPlayer.column[i].size())
{
out << aPlayer.column[i][j] << "\t";
more = true;
}
else
out << "\t\t";
out << endl;
return out;
}
Related
Problem
When I load game and hit ship the game shows the ship is missed.This problem doesnt show up in normal game(without load).
I have serializaiotn for loading game board for user and opponent.
I think the error is about loading in serialzation vector but i have no idea how to do this.
vector is portected object in board class.
Implementation of serialzation
ostream &operator<<(ostream &out, const Board &b) {
for (int row = 0; row < BOARDSIZE; row++) {
for (int col = 0; col < BOARDSIZE; col++) {
out << b.board[row][col]<< ' ';
}
out << '\n';
}
out << '\n';
return out;
}
istream & operator>>(istream & in, Board &b){
for (int row = 0; row < BOARDSIZE; row++) {
for (int col = 0; col < BOARDSIZE; col++) {
in >> b.board[row][col];
}
}
return in;
}
And this is my function for attack made for player:
getSpaceValue return the value of board for example M is miss,X hit etc.
recordHit return boolean,if user hitted the ship it returns true and change board value in this palce to X if not returns false(miss).
void Game::atack(Board &b){
int attemptCounter = 0;
int xEntry, yEntry;
bool goodMove=false;
string entryTemp;
while(!goodMove){
if(attemptCounter>0)
cout << "Wykonales juz ten ruch sprobuj jeszcze raz"<<endl;
cout <<"Wpisz lokalizacje statku ktory chcesz zatakowac "<<endl;
entryTemp = validLoc();
xEntry=static_cast<int>(entryTemp[0]);
yEntry=static_cast<int>(entryTemp[1]);
cout<<"Get value wartoswc: "<<(b.getSpaceValue(xEntry-A_ASCII,yEntry-N_ASCII)!=HITTED && b.getSpaceValue(xEntry-A_ASCII, yEntry-N_ASCII)!=MISSED)<<endl;
if(b.getSpaceValue(xEntry-A_ASCII,yEntry-N_ASCII)!=HITTED && b.getSpaceValue(xEntry-A_ASCII, yEntry-N_ASCII)!=MISSED){
b.recordHit(xEntry-A_ASCII, yEntry-N_ASCII);
goodMove = true;
}
attemptCounter++;
}
}
And thats the recordHit function on the normal game(whiut loading the board) evrything works fine but when we load its returns always false even if ship is hitted.
bool Board::recordHit(int x, int y){
for(int i=0; i<SHIPS_NUM;i++){
if(ship[i].recordHit(x,y)){
board[y][x]=HITTED;
return true;
}
}
board[y][x]=MISSED;
return false;
}
Edit:
Board::Board(){
for(int i=0; i<BOARDSIZE; i++){
for(int j=0; j<BOARDSIZE;j++){
board[i][j]=WATER;
}
}
for(int i=0;i<SHIPS_NUM;i++){
ship.push_back(Ship5(SHIP_LENGTH[i]));
}
}
Board.h
#include <iostream>
#include <vector>
#include "const.h"
#include "ship.h"
using namespace std;
/**
* Klasa planszy oraz jej metody
*/
class Board{
protected:
char board[BOARDSIZE][BOARDSIZE];
vector<Ship5> ship;
public:
Board();
Board& operator=(const Board &board1);
~Board()= default;
void printBoard();
void showUnhiddenBoard();
bool setShip(int shipID, int x, int y, bool horizontal);
bool recordHit(int x, int y);
int HitsNumber();
int HitsMiss();
char getSpaceValue(int x,int y);
friend ostream & operator<<(ostream & out,const Board & b);
friend istream & operator>>(istream & in, Board &b);
};
Posibble values of board
const char WATER = '~';
const char SHIP = '-';
const char MISSED = 'M';
const char HITTED = 'X';
const char UNKNOWN = '?';
I am creating a program called 3 card high card. I am using deck, card, and hand classes. The point of the program is to compare the players hand and the computers hand. Whoever has the highest card wins. If the highest two cards from each hand are equal, then the highest of the two middle cards wins, and if those are equal, the highest of the lowest cards. If not, it's a tie. My problem is where the compare function is comparing two hands. I am getting erroneous results for my computer high card, and my computer middle card (c.hc and c.mc). The results are correct in the sort function, but when they are pulled up in the compare function, it's not the right numbers. However, the players hc, mc, and lc are correct as well as the computers lc.
Disregard the strange words in my compare function. I have them there to figure out where the program is pulling the winner result in my if statements. Also disregard how weird it looks that the results of hc, mc, and lc come after the word "winner is". I only did this to see if my strange results were a result of the wrong numbers being in those parameters, and yes that was the problem.
Here is my main.cpp:
#include "3chc.h"
#include <iostream>
#include <cstdlib>
#include <ctime>
using namespace std;
int main() {
srand(time(0));
Deck d;
d.shuffle();
cout << "computer: " << endl;
Hand comp(3);
comp.dealFrom(d);
comp.reveal();
comp.sort();
cout << "player: " << endl;
Hand player(3);
player.dealFrom(d);
player.reveal();
player.sort();
cout << "Winner is " << player.compare(comp, player) << endl;
return 0;
}
--------------------------------------------
here is my 3chc.h:
//3chc.h Deck, Card, and Hand classes
#include <iostream>
#include <string>
class Card {
friend class Deck;
private:
int card_index; //card number 0 to 51
Card(int index) { card_index = index; } //made this private so user can't say card at index 100..can use it because of friend class
public:
Card() { card_index = 52; }
char suit() const;
char value() const;
std::string str() const;
int getValue(std::string c);
};
class Deck {
private:
Card cards[52];
int pos;
public:
Deck();
Card deal() { return cards[pos++]; };
void shuffle();
int size() const { return 52 - pos; };
};
class Hand {
friend class Deck;
friend class Card;
private:
int handSize;
int hc; //high card
int mc; //middle card
int lc; //low card
Card myCards[];
public:
Hand() { handSize = 1; };
Hand(int n) { handSize = n; };
void dealFrom(Deck& d);
void reveal();
//int getHandValues();
int total();
void sort();
std::string compare(Hand& c, Hand&p);
};
std::ostream& operator<< (std::ostream& out, const Card& c);
----------------------------------------------
and here is my 3chc.cpp:
//3chc.cpp - Implementations of the Deck, Card, and Hand classes
#include "3chc.h"
#include <cstdlib>
char Card::suit() const {
static char suits[] = { 'H', 'S', 'D', 'C' };
//return card_index < 52 ? suits[card_index % 4] : 'X';
return suits[card_index % 4];
}
char Card::value() const {
static char values[] =
{ '2', '3', '4', '5', '6', '7', '8', '9', 'T', 'J', 'Q', 'K', 'A' };
//return card_index < 52 ? values[card_index / 4] : 'X';
return values[card_index / 4];
}
std::string Card::str() const {
std::string s;
s += value();
s += suit();
return s;
}
Deck::Deck() {
for (int i = 0; i < 52; i ++) {
// Card c(i);
// cards[i] = c;
cards[i] = Card(i);
}
pos = 0;
}
void Deck::shuffle() {
for (int i = 0; i < 52; i++) {
int j = rand() % 52;
Card tmp = cards[i];
cards[i] = cards[j];
cards[j] = tmp;
}
pos = 0;
}
std::ostream& operator<< (std::ostream& out, const Card& c) {
out << c.str();
return out;
}
int Card::getValue(std::string c) {
char v = c[0];
int val = v - '0';
if (val > 9) {
switch(v){
case 'T':
val = 10;
break;
case 'J':
val = 11;
break;
case 'Q':
val = 12;
break;
case 'K':
val = 13;
break;
case 'A':
val = 14;
}
}
return val;
}
void Hand::dealFrom(Deck& d) {
for(int i = 0; i < handSize; i++)
myCards[i] = d.deal();
}
void Hand::reveal(){
for (int i = 0; i < handSize; i++)
std::cout << myCards[i] << " " << std::endl;
}
int Hand::total() {
int total = 0;
for (int i = 0; i < handSize; i ++) {
total += myCards[i].getValue(myCards[i].str());
}
return total;
}
void Hand::sort() {
hc = myCards[0].getValue(myCards[0].str());
mc = myCards[1].getValue(myCards[1].str());
lc = myCards[2].getValue(myCards[2].str());
int temp = 0;
if (mc > hc) {
temp = mc;
mc = hc;
hc = temp;
};
if (lc > hc) {
temp = lc;
lc = hc;
hc = temp;
};
if (lc > mc) {
temp = lc;
lc = mc;
mc = temp;
};
std::cout << "hc = " << hc << ", mc = " << mc << ", lc = " << lc << std::endl;
}
std::string Hand::compare(Hand& c, Hand&p) {
std::string winner;
while (c.hc == p.hc) {
if (c.mc == p.mc) {
if (c.lc == p.lc){
winner = "tie";
} else if (c.lc > p.lc) {
winner = "cat";
} else if (c.lc < p.lc) {
winner = "pig";
}
} else if (c.mc > p.mc) {
winner = "cell";
} else if (c.mc < p.mc) {
winner = "penguin";
}
}
if (c.hc > p.hc) {
winner = "computer";
}
if (c.hc < p.hc) {
winner = "player";
}
std::cout << "c hc = " << c.hc << " mc= " << c.mc << " lc= " << c.lc << std::endl;
std::cout << "p hc = " << p.hc << " mc= " << p.mc << " lc= " << p.lc << std::endl;
return winner;
}
I expect to have the c.hc and c.mc to be equal to what they are in the sort function. I apologize if I didn't write this post correctly. I have never posted here before. This assignment is due tonight at midnight, and I could not find the answer to my question anywhere else on this site. Your help is greatly appreciated.
Card myCards[]; is a pointer, not an array. You don't allocate memory for it but dereference it. That's undefined behavior and probably the source of your problem.
Use std::vector<Card> myCards; instead of Card myCards[]; and set the vector size in the constructors
Hand() { handSize = 1; myCards.resize(1); }
and
Hand(int n) { handSize = n; myCards.resize(n); }
The sort function only works with 3 cards. You could use a fixed hand size of 3 as a quick fix
Card myCards[3];
instead of the fix with std::vector.
I am making a card game, Crazy Eights, I have everything done except I am having a problem with this AI. The AI needs to delete the card it just played from its card options. (Each player is dealt 5 cards, and if the card matches the suit, value, or an 8, it can play). SO far, the computer does play the correct card, it just doesn't remove the card so it can just keep playing and playing.
Main Function
#include <iostream>
#include <time.h>
#include "CCrazyEight.h"
#include "stdafx.h"
using namespace std;
void main()
{
// Calls Crazy eight and declares a variable, then runs the game
CCrazyEight E1;
E1.Menu();
}
CCard Header File
#pragma once
#include <iostream>
#include <time.h>
#include "stdafx.h"
using namespace std;
enum CardSuit { Hearts, Diamonds, Spades, Clubs };
class CCard
{
friend ostream & operator << (ostream &left, CCard right);
private:
int value;
CardSuit suit;
public:
// Constructor, sets default values to suit and value
CCard()
{
value = 1;
suit = Hearts;
}
// return thes value of the card
int GetValue()
{
return value;
}
// returns the suit of the card
CardSuit GetSuit()
{
return suit;
}
// Passes values to CDeck constructor, which then randomizes values for the cards
void InitCard(CardSuit s, int v)
{
suit = s;
if (v > 0 && v < 14)
{
value = v;
}
}
};
// outputs value and suit of the card
ostream & operator << (ostream &left, CCard right)
{
if (right.value < 11 && right.value > 1)
{
left << right.value;
}
else if (right.value == 1)
{
left << "Ace";
}
else if (right.value == 11)
{
left << "Jack";
}
else if (right.value == 12)
{
left << "Queen";
}
else if (right.value == 13)
{
left << "King";
}
left << " of ";
if (right.suit == Hearts)
{
left << "Hearts";
}
else if (right.suit == Diamonds)
{
left << "Diamonds";
}
else if (right.suit == Spades)
{
left << "Spades";
}
else if (right.suit == Clubs)
{
left << "Clubs";
}
return left;
}
CDeck Header File
#pragma once
#include <iostream>
#include "CCard.h"
#include <time.h>
using namespace std;
class CDeck
{
private:
CCard Deck[52];
int TopCard;
public:
// constructor
// randomizes the card numbers for suit and value
CDeck()
{
srand(time(NULL));
TopCard = 0;
for (int suit = 0; suit < 4; suit++)
{
for (int value = 1; value <= 13; value++)
{
Deck[((suit * 13) + value) - 1].InitCard((CardSuit)suit, value);
}
}
}
// shuffles the deck, completely randomizes the cards
void Shuffle()
{
TopCard = 0;
for (int y = 0; y < 10; y++)
{
for (int x = 0; x < 52; x++)
{
int SwapPosition = rand() % 52;
CCard temp;
temp = Deck[x];
Deck[x] = Deck[SwapPosition];
Deck[SwapPosition] = temp;
}
}
}
// Draw a card function that gives out a card when called for in crazy eight
CCard DrawCard()
{
if (TopCard > 51)
{
cout << "Deck is Empty." << endl;
}
else
{
return Deck[TopCard++];
}
}
};
CrazyEight header file
#pragma once
#include <iostream>
#include <time.h>
#include "CCard.h"
#include "CDeck.h"
#include "CPlayer.h"
using namespace std;
// Having an issue trying to get the computer to play something different
class CCrazyEight
{
private:
CDeck d1;
CCard c1;
int index;
CCard Topcard;
CPlayer Computer;
CPlayer Human;
public:
// constructor
// shuffles the deck to the played, and assigns the topcard to start the game
CCrazyEight()
{
d1.Shuffle();
c1 = d1.DrawCard();
Topcard = c1;
}
// plays the game, dealing cards to computer and human
void PlayGame()
{
cout << "Welcome to Crazy Eight!" << endl;
cout << "You get to go first!" << endl;
cout << endl;
for (int k = 0; k < 5; k++)
{
Computer.GetCard(d1.DrawCard());
Human.GetCard(d1.DrawCard());
}
}
// displays the topmost card
void TopCard()
{
cout << Topcard << endl;
}
// displays the cards for the human, and the options they can chose, and anything else they need about the game
void Menu()
{
PlayGame();
while (Human.NumCards() != 0 || Computer.NumCards() != 0)
{
cout << endl;
cout << "Top Card is: "; TopCard();
cout << endl;
cout << "You Have " << Human.NumCards() << " Cards Left." << endl;
cout << "Your play: " << endl;
cout << "0) Draw Card" << endl;
cout << Human << endl;
cin >> index;
if (index == 0)
{
Human.GetCard(d1.DrawCard());
Topcard = Topcard;
}
else if (index > 0 && index <= Human.NumCards())
{
Topcard = Human.CardPlayed(index, Topcard);
}
cout << endl;
Topcard = Computer.ComputerAI(Topcard);
cout << "Computer Played: " << Topcard << endl;
if (Computer.NumCards() > 0)
{
cout << "Computer has " << Computer.NumCards() << " Cards Left." << endl;
}
else
cout << "You Lose!" << endl;
}
}
};
CPlayer Header File
#pragma once
#include "CCard.h"
#include <time.h>
#include <iostream>
using namespace std;
class CPlayer
{
friend ostream & operator << (ostream &left, CPlayer right);
private:
CCard Hand[25];
CDeck d1;
int NumberOfCard;
bool Computer;
const int MaxHand = 26;
bool TopCard;
public:
// Constructor for the computer, sets computer to true
CPlayer(bool computer = true)
{
Computer = computer;
NumberOfCard = 0;
}
// Computers AI, checks and sees if they can play, if not then they draw until they can play, or they play a card that is playable******Easy mode**** Lol
CCard ComputerAI(CCard Topcard)
{
for (int i = 0; i < NumberOfCard; i++)
{
if (Hand[i].GetSuit() == Topcard.GetSuit() || Hand[i].GetValue() == 8 || Hand[i].GetValue() == Topcard.GetValue())
{
for (int i = 0; i < NumberOfCard; i++)
{
if (Topcard.GetSuit() == Hand[i].GetSuit() && Hand[i].GetValue() != 8)
{
NumberOfCard--;
return Hand[i];
}
}
for (int i = 0; i < NumberOfCard; i++)
{
if (Topcard.GetValue() == Hand[i].GetValue() && Hand[i].GetValue() != 8)
{
NumberOfCard--;
return Hand[i];
}
}
for (int i = 0; i < NumberOfCard; i++)
{
if (Hand[i].GetValue() == 8)
{
NumberOfCard--;
return Hand[i];
}
}
}
else
{
GetCard(d1.DrawCard());
}
}
}
// Is not the computer, sets computer to fasle. i.e. its the human
void Human()
{
Computer = false;
}
int NumCards()
{
return NumberOfCard;
}
// will hand out a card
bool GetCard(CCard NewCard)
{
if (NumberOfCard < MaxHand)
{
// Now is taking the card
Hand[NumberOfCard] = NewCard;
NumberOfCard++;
return true;
}
else
return false;
}
// subtracts the card that was played from the deck of the human user
CCard CardPlayed(int index, CCard Topcard)
{
if (CheckCard(index, Topcard) == true)
{
CCard TempTopcard = Hand[index - 1];
for (int i = index - 1; i <= NumberOfCard - 1; i++)
{
Hand[i] = Hand[i + 1];
}
NumberOfCard--;
return TempTopcard;
}
else
cout << "Not a valid Card." << endl;
return Topcard;
}
// checks the card and see's if it is playable or not
bool CheckCard(int index, CCard Topcard)
{
if (Hand[index - 1].GetSuit() == Topcard.GetSuit() || Hand[index - 1].GetValue() == 8 || Hand[index - 1].GetValue() == Topcard.GetValue())
{
return true;
}
else
return false;
}
};
// overloads the output to cout the card
ostream & operator << (ostream &left, CPlayer right)
{
for (int i = 0; i < right.NumberOfCard; i++)
{
left << i + 1 << ") " << right.Hand[i] << endl;
}
return left;
}
Okay, first off I have looked at various of the questions that were asked about creating a deck of Cards but every single one I looked was using the vector thing, I'm not sure how to write it, cause I have not taken that subject in class so I don't know how to apply it.
The Card.H and Card.cpp are all fine, no need to change a thing in them
I need help in Deck.H and Deck.cpp.
My initialize() function is not finished and I cant seem to know how to finish it and with the other methods in the Deck class I have not tried to write any of them since I cant generate a deck of cards.
CARD.H
Class Card
{
int m_face;
char m_suit;
public:
Card(int _face = 2 , char _suit = 3);
~Card();
int GetFace() const;
char GetSuit() const;
void SetFace(int _face);
void SetSuit(char _suit);
void Show() const;
}
CARD.CPP
#include "Card.h"
Card::Card(int _face, char _suit)
{
m_face = _face;
m_suit = _suit;
}
Card::~Card()
{
}
int Card ::GetFace() const
{
return m_face;
}
char Card ::GetSuit() const
{
return m_suit;
}
void Card::SetFace(int _face)
{
m_face = _face;
}
void Card::SetSuit(char _suit)
{
m_suit = _suit;
}
void Card::Show() const
{
if (m_face == 11)
cout << " J " << m_suit << endl;
else if (m_face == 12)
cout << " Q " << m_suit << endl;
else if (m_face == 13)
cout << " K " << m_suit << endl;
else if (m_face == 14)
cout << " A " << m_suit << endl;
else
cout << m_face << m_suit << endl;
}
DECK.H
#pragma once
#include "stdafx.h"
#include "Card.h"
Class Deck
{
Card m_cards[52];
public:
Deck();
void Initialize();
void Shuffle();
bool Draw(Card& _card);
void Clear();
bool IsEmpty() const;
}
DECK.CPP
#include "Deck.h"
#include"Card.h"
void Deck::Initialize()
{
int count = 0;
char Suits[] = { 3, 4, 5, 6 };
for (int i = 0; i < 4; ++i) //Suits
{
for (int F = 2; F < 14; ++F) //faces
{
m_cards[count].SetSuit(Suits[i]);
m_cards[count].SetFace(F);
}
}
}
void Deck::Shuffle()
{
}
bool Deck::Draw(Card& _card
{
}
void Deck::Clear()
{
}
bool Deck::IsEmpty() const
{
}
I don't think your Initialize function needs much more work.
Only 2 remarks:
You forgot a ++count at the end of the inner for loop (now you're setting the same card every time).
As you wrote the inner for loop, the F variable will only be allowed to go up to 13 (because you used < 14). This means your deck won't contain any aces ... most logical thing for me would be to use <= 14 instead.
A little tweaking and it works.
#include <iostream>
#include <algorithm>
using namespace std;
class Card
{
private:
int m_face;
char m_suit;
public:
Card(int _face = 2 , char _suit = 3)
{
m_face = _face;
m_suit = _suit;
}
~Card(){}
int GetFace() const { return m_face; }
char GetSuit() const { return m_suit; }
void SetFace(int _face) { m_face = _face; }
void SetSuit(char _suit) { m_suit = _suit; }
void Show() const
{
if (m_face == 11)
cout << " J " << m_suit << endl;
else if (m_face == 12)
cout << " Q " << m_suit << endl;
else if (m_face == 13)
cout << " K " << m_suit << endl;
else if (m_face == 14)
cout << " A " << m_suit << endl;
else
cout << m_face << m_suit << endl;
}
};
class Deck
{
private:
Card m_cards[52];
int current;
public:
Deck() { Initialize(); }
void Initialize()
{
current = 51;
int count = 0;
char Suits[] = { 3, 4, 5, 6 };
for (int i = 0; i < 4; ++i) //Suits
{
for (int F = 2; F <= 14; ++F) //faces
{
m_cards[count++].SetSuit(Suits[i]);
m_cards[count++].SetFace(F);
}
}
}
void Shuffle() { std::random_shuffle(m_cards, m_cards + current + 1); }
bool Draw(Card& _card)
{
if (IsEmpty()) return false;
_card = m_cards[current--];
return true;
}
void Clear() { current = -1; }
bool IsEmpty() const { return current < 0; }
};
int main()
{
Deck deck;
while(!deck.IsEmpty())
{
Card c;
deck.Draw(c);
c.Show();
}
return 0;
}
This is for an assignment before you tell me not to use an array. Unfortunately I have to.
I've troubleshot this for a good amount of time and I've finally given up and come to ask the smart people here. I know this is something to do with how I'm allocating the array, but I can't figure what's wrong. It goes through the inner loop once and then freeze on the second run. Sorry if I left anything important out. I will add any needed info.
Variables from Card
private:
string *cardRank;
string *suit;
int rankNum;
int value;
Problem Function
void initArray(Card **cPtr)
{
int i;
int j;
int index=0;
cPtr = new Card*[DECK]; //deck is const int 52
for(i=0; i < 4; ++i)
{
for(j=1; j < 14; ++j)
{
cPtr[index] = new Card(j, j, i); //freezes here. does not make it to the first
//function in the constructor
cout << cPtr[index] << endl;
++index;
}
}
}
Constructor
Card::Card(int cRank, int cValue, int suitNum)
{
setRankNum(cRank);
cout << "rank num set\n";
setValue(cValue);
cout << "val set\n";
setSuit(suitNum);
cout << "suit set\n";
setRank(cRank);
cout << "rank set\n";
}
Overloaded <<
ostream &operator << (ostream &strm, Card &aCard)
{
strm << aCard.getRank() << " of " << aCard.getSuit();
return strm;
}
whole program
#include <string>
#include "Card.h"
using namespace std;
const int DECK = 52;
void initArray(Card **&cPtr);
void shufflePArray(Card **pArray);
void determineHand(Card **pArray);
bool isFlush(Card *hand);
bool isStraight(Card *hand);
bool isFour(Card *hand);
bool isThree(Card *hand);
bool isTwo(Card *hand);
void drawHand(Card *hand, Card **pArray);
void displayHand(Card **hand);
int main()
{
Card **cArray;
initArray(cArray);
cout << "done.";
shufflePArray(cArray);
determineHand(cArray);
delete [] cArray;
return 0;
}
void initArray(Card **&cPtr)
{
int i;
int j;
int index=0;
cPtr = new Card*[DECK];
for(i=0; i < 4; ++i)
{
for(j=1; j < 13; ++j)
{ cout << "inner loop " << index << endl;
cPtr[index] = new Card(j, j, i);
cout << cPtr[index] << endl;
++index;
}
}
}
void shufflePArray(Card **pArray)
{
//code here
}
void determineHand(Card ***pArray)
{
Card hand[5];
drawHand(hand, pArray);
displayHand(pArray);
if (isFlush(hand) == true)
{
if(isStraight(hand) == true)
cout << "Straight flush!!!" << endl;
else
cout << "You got a flush!" << endl;
}
else if(isStraight(hand) == true)
{
cout << "You got a straight!" << endl;
}
else if(isFour(hand) == true)
{
cout << "Four of a kind!!!" << endl;
}
else if(isThree(hand)==true)
{
cout << "Three of a kind!" << endl;
}
else if(isTwo(hand) == true)
{
cout << "That's a pair";
}
}
bool isFlush(Card *hand)
{
int i;
int match;
for (i=0; i<5;++i)
{
if (hand[0].getSuit() == hand[i].getSuit())
match++;
}
if (match == 5)
return true;
else
return false;
}
bool isStraight(Card *hand)
{
int match;
for (int i=0; i<5;++i)
{
if (hand[0].getValue() == hand[i].getValue() - 1)
match++;
}
if (match == 5)
return true;
else
return false;
}
bool isFour(Card *hand)
{
int match = 0;
for(int i=0; i<5; ++i)
{
match=0;
for(int j=0;j<5;++j)
{
if (hand[i] == hand[j])
match++;
if (match == 4)
return true;
else
return false;
}
}
}
bool isThree(Card *hand)
{
int match = 0;
for(int i=0; i<5; ++i)
{
match=0;
for(int j=0;j<5;++j)
{
if (hand[i] == hand[j])
match++;
if (match == 3)
return true;
else
return false;
}
}
}
bool isTwo(Card *hand)
{
int match = 0;
for(int i=0; i<5; ++i)
{
match=0;
for(int j=0;j<5;++j)
{
if (hand[i] == hand[j])
match++;
if (match == 2)
return true;
else
return false;
}
}
}
void drawHand(Card *hand, Card **pArray)
{
for(int i=0; i<5;++i)
cout << hand[i];
}
}
{
hand[i] = *pArray[i];
}
}
void displayHand(Card **hand)
{
Card temp;
for (int i = 0; i < 5; ++i)
{
contents of card.h
#ifndef CARD_H
#define CARD_H
#include <string>
#include <iostream>
using namespace std;
class Card
{
private:
string *cardRank;
string *suit;
int rankNum;
int value;
public:
Card();
Card(int cRank, int cValue, int suitNum);
friend ostream &operator << (ostream &strm, Card &aCard);
bool operator > (const Card &aCard);
bool operator < (const Card &aCard);
bool operator == (const Card &aCard);
void setRank(int r);
void setSuit(int s);
void setValue(int v);
void setRankNum(int n);
string getRank();
string getSuit();
int getRankNum();
int getValue();
};
#endif // CARD_H
contents of Card.cpp
#include "Card.h"
#include <string>
#include <iostream>
Card::Card()
{
cardRank = NULL;
suit = NULL;
rankNum = 0;
value = 0;
}
Card::Card(int cRank, int cValue, int suitNum)
{
setRankNum(cRank);
cout << "rank num set\n";
setValue(cValue);
cout << "val set\n";
setSuit(suitNum);
cout << "suit set\n";
setRank(cRank);
cout << "rank set\n";
}
ostream &operator << (ostream &strm, Card &aCard)
{
strm << aCard.getRank() << " of " << aCard.getSuit();
return strm;
}
bool Card::operator > (const Card &aCard)
{
if (aCard.value > value)
return true;
else
return false;
}
bool Card::operator < (const Card &aCard)
{
if (aCard.value < value)
return true;
else
return false;
}
bool Card::operator == (const Card &aCard)
{
if (value == aCard.value)
return true;
else
return false;
}
void Card::setRank(int r)
{
switch(r)
{
case 13:
*cardRank = "Ace";
case 1:
*cardRank = "Two";
case 2:
*cardRank = "Three";
case 3:
*cardRank = "Four";
case 4:
*cardRank = "Five";
case 5:
*cardRank = "Six";
case 6:
*cardRank = "Seven";
case 7:
*cardRank = "Eight";
case 8:
*cardRank = "Nine";
case 9:
*cardRank = "Ten";
case 10:
*cardRank = "Jack";
case 11:
*cardRank = "Queen";
case 12:
*cardRank = "King";
}
}
void Card::setSuit(int s)
{
if(s==0){
*suit = "Hearts";
cout << "suit set";}
else if(s==1)
*suit = "Diamonds";
else if (s==2)
*suit = "Clubs";
else if (s==3)
*suit = "Spades";
else
cout << "Invalid suit num.";
}
void Card::setValue(int v)
{
if (v > 0)
value = v;
}
void Card::setRankNum(int n)
{
rankNum = n;
}
string Card::getRank()
{
return *cardRank;
}
string Card::getSuit()
{
return *suit;
}
int Card::getRankNum()
{
return rankNum;
}
int Card::getValue()
{
return value;
}
One possible reason for your troubles is that you are dereferencing a NULL pointer:
void Card::setRank(int r)
{
switch(r)
{
case 13:
*cardRank = "Ace";
case 1:
*cardRank = "Two";
//...
The cardRank is NULL. You now try to dereference a NULL pointer. Unless I missed something, where is the call to "cardRank = new std::string;"?
But that brings up a bigger point -- in your comment you stated that your professor wants you to use pointers. But honestly, there is no reason whatsoever to use pointers for those string members -- absolutely none.
You do need pointers to implement your dynamic array, but that's it. Either you are reading the professor's intentions incorrectly, or the professor needs to get another profession.
You're passing a pointer to a pointer as value in : initArray(Card **cPtr), apparently your intention is to change it (i.e return the allocated Card array.
I cannot really say what is happening exactly but some memory gets overwritten, the return address in the stack probably
Anyway either change it to reference i.e. initArray(Card **&cPtr) or use initArray(Card ***cPtr) and change the code accordingly.
The second problem in the use of strings, change string *cardRank to string cardRank and suit as well, you don't need pointers to strings (it's not like char*, those are objects any way, the assignments should be changed from *cardRank = "Ace" to cardRank = "Ace"