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.
Related
I am creating an minimax player for a game called Specker in c++.
The rules are simple:
There are p players (0 to p - 1) and n heaps (0 to n - 1)
Starting with player 0 each player takes k > 0 coins from a heap x and places m coins (0 <= m < k) on heap y
The winning player is the one which plays last when all coins from all heaps are removed
So I have created the game and some player classes (GreedyPlayer, SpartanPlayer etc.) but they all are a little bit predictable on what they will do. They aren't clever.
so i am creating a player who plays according to minimax (pt18a038)code compiles fine but the program stops responding on execution.
the clever player class:
class pt18a038 : public Player {
private:
string player_type;
public:
pt18a038(const string &n) : Player(n) {
player_type = "Asder aka theRunner";
}
virtual const string &getType() const override {
return player_type;
}
virtual Move play(const State &s) override {
int source_heap = 0;
int target_heap = 0;
int source_coins = 0;
int target_coins = 0;
int sum = 0;
for (source_heap = 0; source_heap < s.getHeaps(); source_heap++) {
for (source_coins = 1; source_coins <= s.getCoins(source_heap); source_coins++) {
for (target_heap = 0; target_heap < s.getHeaps(); target_heap++) {
for (target_coins = 0; target_coins <= source_coins; target_coins++) {
Move m(source_heap, source_coins, target_heap, target_coins);
sum = minimax(s, 3, 0, m);
cout << "Play:" << source_heap << "," << source_coins << "," << target_heap << ","
<< target_coins << ":" << sum << endl;
}
}
}
}
cout << sum << endl;
// ///////////// for debbuging only until minimax is working...
source_heap = 0;
source_coins = 0;
for (int i = 0; i < s.getHeaps(); i++) {
if (s.getCoins(i) > source_coins) {
source_heap = i;
source_coins = s.getCoins(i);
}
}
Move SpartanObject(source_heap, 1, 0, 0);
return SpartanObject;
// /////////////
}
static int minimax(State s, const int &players, int depth, const Move move) {
if (s.winning()) {
cout << "game end!" << endl;
return 1000;
if (depth % players == 0) return 1000; //Maximazing player
else return -1000; //Minimazing player
}
if (depth > 4) {
//cout<<"optimazing"<<endl;
return 0;
}
//cout << s << endl;
s.next(move);
int source_heap = 0;
int target_heap = 0;
int source_coins = 0;
int target_coins = 0;
int max = -100000;
int min = 100000;
int result;
for (source_heap = 0; source_heap < s.getHeaps(); source_heap++) {
for (source_coins = 1; source_coins <= s.getCoins(source_heap); source_coins++) {
for (target_heap = 0; target_heap < s.getHeaps(); target_heap++) {
for (target_coins = 0; target_coins <= source_coins; target_coins++) {
//cout << "Move:" << source_heap << "," << source_coins << "," << target_heap << ","<< target_coins << endl;
Move m(source_heap, source_coins, target_heap, target_coins);
result = minimax(s, players, depth + 1, m);
if (depth % players == 0) {
max = result ? (result > max) : result;
} else {
min = result ? (result < min) : result;
}
}
}
}
}
return max ? (depth % players == 0) : min;
}
};
Here is my code for the rest of the game(it's tested and works fine)
#include <iostream>
#include <stdexcept>
using namespace std;
class Move {
private:
int source_heap, source_coins, target_heap, target_coins;
public:
Move(int sh, int sc, int th, int tc) {
source_heap = sh;
source_coins = sc;
target_heap = th;
target_coins = tc;
}
int getSource() const {
return source_heap;
}
int getSourceCoins() const {
return source_coins;
}
int getTarget() const {
return target_heap;
}
int getTargetCoins() const {
return target_coins;
}
// Let's do some operator overloading
friend ostream &operator<<(ostream &out, const Move &move) {
if (move.getTargetCoins()) {
out << "takes " << move.getSourceCoins() << " coins from heap "
<< move.getSource() << " and puts " << move.getTargetCoins()
<< " coins to heap " << move.getTarget();
} else {
out << "takes " << move.getSourceCoins() << " coins from heap "
<< move.getSource() << " and puts nothing";
}
}
};
class State {
// State with h heaps, where the i-th heap starts with c[i] coins.
private:
int heaps, *heap_coins;
public:
State(int h, const int c[]) {
heaps = h;
heap_coins = new int[heaps];
for (int i = 0; i < heaps; i++)
heap_coins[i] = c[i];
}
~State() {
delete[] heap_coins;
return;
}
int getCoins(int h) const throw(logic_error) {
if (h < 0 || h > heaps) {
throw logic_error(
"Invalid heap number, enter a number between 1 and heaps!");
return 1;
} else {
return heap_coins[h];
}
}
void next(const Move &move) throw(logic_error) {
if ((move.getSource() < 0) || (move.getSource() > heaps) ||
(move.getTarget() < 0) || (move.getTarget() > heaps)) {
throw logic_error("Invalid Heap!");
return;
} else if (
(move.getSourceCoins() < 1) || (move.getTargetCoins() < 0) ||
(move.getSourceCoins() <= move.getTargetCoins()) ||
(move.getSourceCoins() > getCoins(move.getSource()))) {
throw logic_error("Invalid Coin number!");
} else {
heap_coins[move.getSource()] -= move.getSourceCoins();
heap_coins[move.getTarget()] += move.getTargetCoins();
}
}
bool winning() const {
int s = 0;
for (int i = 0; i < heaps; i++)
s += getCoins(i);
return not s; // yeah i know how booleans work :P
}
int getHeaps() const {
return heaps;
}
friend ostream &operator<<(ostream &out, const State &state) {
for (int i = 0; i < state.getHeaps(); i++) {
out << state.heap_coins[i];
if (i != state.getHeaps() - 1)
out << ", ";
}
return out;
}
};
class Player {
public:
Player(const string &n);
virtual ~Player();
virtual const string &getType() const = 0;
virtual Move play(const State &s) = 0;
friend ostream &operator<<(ostream &out, const Player &player);
protected:
string player_name;
};
class GreedyPlayer : public Player {
private:
string player_type;
public:
GreedyPlayer(const string &n) : Player(n) {
player_type = "Greedy";
}
virtual const string &getType() const override {
return player_type;
}
virtual Move play(const State &s) override {
int source_heap = 0;
int source_coins = 0;
for (int i = 0; i < s.getHeaps(); i++) {
if (s.getCoins(i) > source_coins) {
source_heap = i;
source_coins = s.getCoins(i);
}
}
Move GreedyObject(source_heap, source_coins, 0, 0);
return GreedyObject;
}
};
class SpartanPlayer : public Player {
public:
SpartanPlayer(const string &n) : Player(n) {
player_type = "Spartan";
}
virtual const string &getType() const override {
return player_type;
}
virtual Move play(const State &s) override {
int source_heap = 0;
int source_coins = 0;
for (int i = 0; i < s.getHeaps(); i++) {
if (s.getCoins(i) > source_coins) {
source_heap = i;
source_coins = s.getCoins(i);
}
}
Move SpartanObject(source_heap, 1, 0, 0);
return SpartanObject;
}
private:
string player_type;
};
class SneakyPlayer : public Player {
public:
SneakyPlayer(const string &n) : Player(n) {
player_type = "Sneaky";
}
virtual const string &getType() const override {
return player_type;
}
virtual Move play(const State &s) override {
int j = 0;
while (s.getCoins(j) == 0) {
j++;
}
int source_heap = j;
int source_coins = s.getCoins(j);
for (int i = j + 1; i < s.getHeaps(); i++) {
if ((s.getCoins(i) < source_coins) && (s.getCoins(i) > 0)) {
source_heap = i;
source_coins = s.getCoins(i);
}
}
Move SneakyObject(source_heap, source_coins, 0, 0);
return SneakyObject;
}
private:
string player_type;
};
class RighteousPlayer : public Player {
public:
RighteousPlayer(const string &n) : Player(n) {
player_type = "Righteous";
}
virtual const string &getType() const override {
return player_type;
}
virtual Move play(const State &s) override {
int target_heap = 0;
int source_heap = 0;
int source_coins = s.getCoins(0);
int target_coins = source_coins;
for (int i = 1; i < s.getHeaps(); i++) {
if (s.getCoins(i) > source_coins) {
source_heap = i;
source_coins = s.getCoins(i);
} else if (s.getCoins(i) < target_coins) {
target_heap = i;
target_coins = s.getCoins(i);
}
}
source_coins -= source_coins / 2;
Move RighteousObject(
source_heap, source_coins, target_heap, source_coins - 1);
return RighteousObject;
}
private:
string player_type;
};
Player::Player(const string &n) {
player_name = n;
}
Player::~Player() {
player_name.clear();
}
ostream &operator<<(ostream &out, const Player &player) {
out << player.getType() << " player " << player.player_name;
return out;
}
class Game {
private:
int game_heaps, game_players, current_heap, current_player;
int *heap_coins;
Player **players_list;
public:
Game(int heaps, int players) {
heap_coins= new int [heaps];
game_heaps = heaps;
game_players = players;
current_heap = 0;
current_player = 0;
players_list = new Player*[players];
}
~Game() {
delete[] heap_coins;
delete[] players_list;
}
void addHeap(int coins) throw(logic_error) {
if (current_heap > game_heaps)
throw logic_error("All heaps are full with coins!");
else if (coins < 0)
throw logic_error("Coins must be a positive number!");
else {
heap_coins[current_heap++] = coins;
}
}
void addPlayer(Player *player) throw(logic_error) {
if (current_player > game_players)
throw logic_error("All players are added!");
else {
players_list[current_player++] = player;
}
}
void play(ostream &out) throw(logic_error) {
if ((current_player != game_players) && (current_heap != game_heaps)) {
throw logic_error("Have you added all heaps and players?");
} else {
int i = 0;
State currentState(game_heaps, heap_coins);
while (!currentState.winning()) {
out << "State: " << currentState << endl;
out << *players_list[i % game_players] << " "
<< players_list[i % game_players]->play(currentState) << endl;
currentState.next(
players_list[i % game_players]->play(currentState));
i++;
}
out << "State: " << currentState << endl;
i--;
out << *players_list[i % game_players] << " wins" << endl;
}
}
};
int main() {
Game specker(6, 5);
specker.addHeap(10);
specker.addHeap(20);
specker.addHeap(17);
specker.addHeap(17);
specker.addHeap(17);
specker.addHeap(17);
specker.addPlayer(new GreedyPlayer("Alan"));
specker.addPlayer(new SneakyPlayer("Tom"));
specker.addPlayer(new SpartanPlayer("Mary"));
specker.addPlayer(new RighteousPlayer("Robin"));
specker.addPlayer(new pt18a038("Stavros"));
specker.play(cout);
}
Updated
I see a couple of issues in your minimax program, some are serious in nature :
1) Use Alpha Beta pruning to reduce the size of the search tree.
2) There is no proper boundary condition (if depth >5 return score or something) in the minimax recursive call ( see my code snippet for details), the CPU may hang while calling.
3)Your leaf node evaluation is weak, so the evaluated moves , in spite of using minimax algorithm, is not likely to be intelligent ones.
4)To increase the search speed, you may use multi-threading only at the top level branch.
5) If a leaf node gives a winning move while maximizing, you may skip further evaluation by returning a high score.
6) Once your code is functional, refer it at code-review with 'ai' tag , rather than at SO, for more detailed analysis.
int EvaluateLeafNode(State s, const int &players)
{
//TODO analyze here
return score;
}
int minimax(State s, const int &players, int depth , const Move move, int alpha, int beta)
{
if( depth >= 5) return EvaluateLeafNode(s,players); // this was missing in your code
//don't analyze here
//rest of minimax recursive code
}
I am a beginner with C++ and have tried a few different things, but no matter what I try it doesn’t seem to recognize when a card has already been drawn...
I have tried to utilize to bool isDrawn, but after a few attempts of that with no success I am not 100% sure where to go from here
class Card {
public:
string suitName;
int cardNumber;
void printCard() {
if (cardNumber == 1) {
cout << "Ace";
} else if (cardNumber == 11) {
cout << "Jack";
} else if (cardNumber == 12) {
cout << "Queen";
} else if (cardNumber == 13) {
cout << "King";
} else
cout << cardNumber;
cout << " of " << suitName << endl;
}
bool isDrawn = false;
};
class Deck {
public:
Card deck[52];
void makeDeck(){
int counter = 0;
string suits[] = { "Spades", "Hearts", "Clubs", "Diamonds" };
string face[] = { "Ace", "Jack", "Queen", "King" };
for (int i = 0; i <= 3; i++) {
for (int j = 0; j < 13; j++) {
deck[counter].isDrawn = false;
deck[counter].cardNumber = (j + 1);
deck[counter].suitName = suits[i];
counter++;
}
}
}
Card drawCard() {
int randcard;
do {
randcard = rand() % 52;
} while (deck[randcard].isDrawn == true);
return deck[randcard];
}
};
class Player {
public:
vector<Card> hand;
void setName(string s){
name = s;
}
string printName(){
return name;
}
void printHand() {
for (int i = 0; i < hand.size(); i++){
hand.at(i).printCard();}
}
private:
string name;
};
int main() {
Deck my_deck;
Player p1;
p1.setName("HAL 9000");
cout << p1.printName() << endl;
my_deck.makeDeck();
p1.hand.push_back(my_deck.drawCard());
p1.hand.push_back(my_deck.drawCard());
p1.hand.push_back(my_deck.drawCard());
p1.printHand();
cout << endl;
}
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;
}
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;
}