Situatie
Solutie
Pasi de urmat
/*=================main.cpp===========================*/
#include <iostream>
#include "Solitaire.h"
using namespace std;
void HandleMove(Solitaire& game);
void HandleMoveToAnswer(Solitaire& game);
void ClearScreen();
int main(int argc, char** argv)
{
Solitaire game = Solitaire();
game.PrintAllDetails();
bool running = true;
do{
char option = ' ';
cout<<endl<<endl;
cout<<"1. move card between rows";
cout<<"\n2. move to answers";
cout<<"\n3. deal";
cout<<"\n0. quit";
cout<<"\nEnter option:";
cin >> option;
/* 48 - 55 ascii code is 0 - 7 */
if(game.GameCompleted())
{
ClearScreen();
cout<<"\n\n\n\t\t\t CONGRATULATIONS YOU WON!!!\n\n";
cin.get();
running = false;
}
else
{
switch((int)option)
{
case 48:
running = false;
break;
case 49:
HandleMove(game);
break;
case 50:
HandleMoveToAnswer(game);
break;
case 51:
game.Deal(3);
break;
default:
cout<<"\ninvalid option";
cin.ignore(80,'\n');
break;
}
ClearScreen();
game.PrintAllDetails();
}
}while(running);
return 0;
}
void HandleMove(Solitaire& game)
{
char from = '0' ,to = '0';
cout<<endl <<endl;
cout<<"From (7 for deck):";
cin >> from;
cout<< "To: ";
cin>> to;
if( ((int)from >= 48 && (int)from <= 55) &&
((int)from >= 48 && (int)to <= 54) )
{
game.MakeMoveRowToRow((int)from - 48,(int)to - 48);
}
else
{
cout<<"invalid input";
cin.get();
cin.get();
}
}
void HandleMoveToAnswer(Solitaire& game)
{
char from = 0;
cout<<endl <<endl;
cout<< "From (7 for deck): ";
cin>> from;
if((int)from >= 48 && (int)from <= 55)
game.MakeSuitMove((int)from - 48);
else
{
cout<<"invalid input";
cin.get();
cin.get();
}
}
void ClearScreen()
{
#ifdef __linux__
system("clear");
#elif _WIN32
system("cls");
#endif
}
/*=============================================*/
/*=================Card.h=======================*/
#pragma once
#include <iostream>
#ifdef _WIN32
#include<windows.h>
const static int BLACK = 0;
const static int BLUE = 9;
const static int RED = 12;
const static int WHITE = 15;
#elif __linux__
#include "stdlib.h"
#endif
class Card
{
public:
Card(void);
Card(char rank,char suit);
~Card(void);
void Flip();
bool GetIsFaceUp();
int GetSolitaireValue();
char GetCardSuit();
char GetCardRank();
friend std::ostream & operator<< (std::ostream & os, Card& c);
/*
Used to navigate up and
down the cards in a row
*/
Card* parent;
Card* child;
private:
char rank;
char suit;
bool isFaceUp;
};
/*=============================================*/
/*====================Card.cpp===================*/
#include "Card.h"
Card::Card(void)
{
}
Card::Card(char r, char s)
:rank(r)
,suit(s)
,isFaceUp(false)
,child(NULL)
,parent(NULL)
{
}
Card::~Card(void)
{
}
void Card::Flip()
{
isFaceUp = !isFaceUp;
}
bool Card::GetIsFaceUp()
{
return isFaceUp;
}
char Card::GetCardSuit()
{
return suit;
}
char Card::GetCardRank()
{
return rank;
}
int Card::GetSolitaireValue()
{
if(rank == 'A')
return 1;
else if(rank == 'T')
return 10;
else if(rank == 'J')
return 11;
else if(rank == 'Q')
return 12;
else if(rank == 'K')
return 13;
else
{
char c[] = {rank, '\0'};
return atoi(c);
}
}
std::ostream & operator<< (std::ostream & os, Card& c)
{
#ifdef _WIN32
HANDLE handle = GetStdHandle(STD_OUTPUT_HANDLE);
if(c.suit == 'c' || c.suit == 's')
SetConsoleTextAttribute(handle, BLUE);
else
SetConsoleTextAttribute(handle,RED);
os<< c.suit << c.rank;
SetConsoleTextAttribute(handle,WHITE);
#elif __linux__
if(c.suit == 'c' || c.suit == 's')
os<<"\033[22;34m";
else
os<<"\033[22;31m";
os<< c.suit << c.rank;
os<<"\033[22;30m";
#endif
return os;
}
/*=============================================*/
/*====================Deck.h====================*/
#pragma once
#include "Card.h"
#include <ctime>
#include <iostream>
#include "TableCard.h"
const static int RANK_SIZE = 13;
const static int SUIT_SIZE = 4;
const static char RANKS[] = {'A','2','3','4','5','6','7','8','9','T','J','Q','K'};
const static char SUITS[] = {'h','d','s','c'};
class Deck
{
public:
Deck(void);
~Deck(void);
void Populate(void);
void Shuffle(void);
void PrintDeck(void);
void PopulateVector(TableCard& aDeck);
private:
Card _deck[52];
int currentIndex;
};
/*==============================================*/
/*====================Deck.cpp====================*/
#include "Deck.h"
Deck::Deck(void)
:currentIndex(0)
{
srand((unsigned)time(0));
Populate();
}
Deck::~Deck(void)
{
}
void Deck::Populate()
{
int index = 0;
for(int i=0; i<SUIT_SIZE; i++)
{
for(int j=0; j<RANK_SIZE;j++)
{
_deck[index] = Card(RANKS[j],SUITS[i]);
index++;
}
}
}
void Deck::Shuffle()
{
int max = SUIT_SIZE * RANK_SIZE;
for(int i=0; i<max-1; i++)
{
int randNum = rand() % 52;
std::swap(_deck[i],_deck[randNum]);
}
}
void Deck::PrintDeck(void)
{
int max = SUIT_SIZE * RANK_SIZE;
for(int i=0; i<max; i++)
{
if(i %13 == 0)
std::cout<< '\n' <<'\n';
std::cout<< _deck[i] << " " << _deck[i].GetBlackjackValue() << " ";
}
}
void Deck::PopulateVector(TableCard& aDeck)
{
int max = SUIT_SIZE * RANK_SIZE;
aDeck.Clear();
for(int i=0; i<max; i++)
aDeck.PushValueCopy(_deck[i]);
}
/*===============================================*/
/*====================TableCard.h===================*/
#pragma once
#include "Card.h"
#include <vector>
class TableCard
{
public:
TableCard(int maxSize);
~TableCard(void);
Card& operator[](int index);
bool Push(Card& card);
bool PushValueCopy(Card card);
int Size();
bool empty();
Card& top(void);
bool RemoveAt(int index);
bool Pop();
void Clear();
static void MoveBetween(TableCard& from, TableCard& to);
private:
int _maxSize;
int _size;
std::vector<Card*> _cards;
};
/*=============================================*/
/*====================TableCard.cpp================*/
#include "TableCard.h"
TableCard::TableCard(int maxSize)
:_size(0)
,_maxSize(maxSize)
{
_cards.resize(maxSize);
}
TableCard::~TableCard(void)
{
}
bool TableCard::Push(Card& card)
{
if(_size < _maxSize)
{
_cards[_size] = &card;
_size++;
return true;
}
return false;
}
bool TableCard::PushValueCopy(Card card)
{
if(_size < _maxSize);
{
_cards[_size] = new Card(card);
_size++;
return true;
}
return false;
}
void TableCard::Clear()
{
for(int i=0; i<_size; i++)
_cards[i] = NULL;
_size = 0;
}
bool TableCard::empty()
{
if(_size == 0)
return true;
return false;
}
Card& TableCard::top(void)
{
if(_size > 0)
return *_cards[_size-1];
}
bool TableCard::RemoveAt(int index)
{
if(index >= 0 && index < _maxSize)
{
_cards[index] = NULL;
_size--;
return true;
}
return false;
}
int TableCard::Size()
{
return _size;
}
bool TableCard::Pop()
{
if(_size > 0)
{
_cards[_size - 1] = NULL;
_size--;
return true;
}
return false;
}
Card& TableCard::operator[](int index)
{
if(index >= 0 && index <= _size)
return *_cards[index];
}
void TableCard::MoveBetween(TableCard& from, TableCard& to)
{
to.Push(from.top());
from.Pop();
}
/*=============================================*/
/*====================Solitaire.h==================*/
#pragma once
#include <iostream>
#include <vector>
#include "Deck.h"
#include "Card.h"
#include "TableCard.h"
const static int TABLE_SIZE = 7;
class Solitaire
{
public:
Solitaire(void);
~Solitaire(void);
void PopulateTable(void);
void Deal(int numToDeal=1);
/* Functions for validating and moving cards */
void MakeSuitMove(int from);
void MakeMoveBetweenRows(int from, int to);
void MakeMoveDeckToRow(int to);
void MakeMoveRowToRow(int from, int to);
bool ValidMove(int from, int to);
bool ValidRowToRowMove(Card* fromCard, int to);
bool ValidSuitMove(int from);
/* Checks to see if all answer sections full */
bool GameCompleted();
/* Functions for printing card details */
void PrintAllDetails(void);
void PrintSuitDetails(void);
void PrintDeckDetails(void);
private:
TableCard _deck;
TableCard _discardedCards;
std::vector<TableCard> _tableCards;
//Destination of cards. When all filled player wins
std::vector<TableCard> _suitCards;
};
/*==============================================*/
/*====================Solitaire.cpp=================*/
#include "Solitaire.h"
using namespace std;
Solitaire::Solitaire(void)
:_deck(52)
,_discardedCards(52)
{
//Uses the deck class to populate solitaire deck
//Shuffle the deck to randomize
Deck deck = Deck();
deck.Shuffle();
deck.PopulateVector(_deck);
for(int i=0; i<TABLE_SIZE; i++)
{
TableCard tableCard = TableCard(20);
_tableCards.push_back(tableCard);
}
//_suitCards.resize(4);
for(int i=0; i<4; i++)
{
TableCard suitCard = TableCard(13);
_suitCards.push_back(suitCard);
}
PopulateTable();
}
Solitaire::~Solitaire(void)
{
}
void Solitaire::PopulateTable(void)
{
for(int i=0; i<TABLE_SIZE; i++)
{
for(int j=0; j<TABLE_SIZE -i; j++)
{
if(j == (TABLE_SIZE - i) - 1)
_deck.top().Flip();
_tableCards[j].Push(_deck.top());
_deck.Pop();
}
}
}
void Solitaire::Deal(int numToDeal)
{
int size = _deck.Size();
for(int i=0; i<size; i++)
{
if(_deck.top().GetIsFaceUp())
{
_deck.top().Flip();
_discardedCards.Push(_deck.top());
_deck.Pop();
}
}
if(_deck.empty())
{
for(int i=_discardedCards.Size()-1; i>=0; i--)
_deck.Push(_discardedCards[i]);
_discardedCards.Clear();
}
int index = 0;
for(int i=0; i<numToDeal; i++)
{
index = _deck.Size() -i -1;
if(index >= 0)
{
_deck[index].Flip();
}
else
break;
}
}
void Solitaire::PrintSuitDetails()
{
cout<<"=============================================\n";
for(int j=0; j<_suitCards.size(); j++)
{
switch(j)
{
case 0:
cout<< "h :";
break;
case 1:
cout<< "d :";
break;
case 2:
cout<< "s :";
break;
case 3:
cout<< "c :";
break;
}
for(int i=0; i<_suitCards[j].Size(); i++)
{
if(&_suitCards[j][i] != NULL)
cout<<_suitCards[j][i] << " ";
else
break;
}
cout<< endl;
}
cout<<"=============================================\n";
cout<<endl;
}
void Solitaire::PrintDeckDetails()
{
cout<<"--------------------------------------------\n";
cout<<"|Deck: ";
for(unsigned int i=0; i<_deck.Size(); i++)
{
if(_deck[i].GetIsFaceUp())
cout<<_deck[i] << " ";
}
cout<<"\n--------------------------------------------\n";
}
void Solitaire::PrintAllDetails()
{
PrintDeckDetails();
PrintSuitDetails();
cout<< "| 6 | \t | 5 | \t | 4 | \t | 3 | \t | 2 | \t | 1 | \t | 0 |\n";
cout<< "----- \t ----- \t ----- \t ----- \t ----- \t ----- \t -----\n";
//Cannot be unsigned as number is always greater than or equal to 0 --
int colMax = _tableCards.size();
int rowMax = 0;
for(int i=0; i<colMax; i++)
{
if(_tableCards[i].Size() > rowMax)
{
rowMax = _tableCards[i].Size();
}
}
for(int i=0; i<rowMax; i++)
{
for(int j=colMax-1; j>=0; j--)
{
if(i >= _tableCards[j].Size())
{
cout<< " \t " ;
continue;
}
if(_tableCards[j][i].GetIsFaceUp())
cout << " " << _tableCards[j][i] << " \t ";
else
cout << " " <<(char)254 << " \t ";
}
cout<<endl;
}
cout<<endl<<endl;
//SHOW DISCARDED CARDS
/*cout<<"\nCards in the used pile: \n\n";
for(unsigned int i=0; i<_discardedCards.Size(); i++)
cout<<_discardedCards[i] << " ";
cout<<endl<<endl;
*/
//DISPLAYS CHILDREN AND PARENTS
/*for(int i=0; i<_tableCards.size(); i++)
{
cout<< i << ": \n" ;
for(int j= 0; j< _tableCards[i].Size(); j++)
{
if(_tableCards[i][j].child != NULL)
{
cout<< _tableCards[i][j] << "'s child is " << *_tableCards[i][j].child << endl;
}
if(_tableCards[i][j].parent != NULL)
{
cout<< _tableCards[i][j] << "'s parent is " << *_tableCards[i][j].parent << endl;
}
}
}*/
}
bool Solitaire::ValidMove(int from, int to)
{
//start move and end move the same
if(from == to && from != 7)
return false;
Card* toCard;
Card* fromCard;
if(from == 7)
{
if(!_deck.empty())
{
if(!_deck.top().GetIsFaceUp())
{
return false;
}
else
{
fromCard = &_deck.top();
}
}
else
{
return false;
}
}
else
{
//if no card in moving from row not valid
if(!_tableCards[from].empty())
fromCard = &_tableCards[from].top();
else
return false;
}
if(!_tableCards[to].empty())
toCard = &_tableCards[to].top();
//move king to empty space
if(_tableCards[to].empty())
{
if(fromCard->GetCardRank() == 'K')
return true;
else
return false;
}
else if(fromCard->GetSolitaireValue() == toCard->GetSolitaireValue()-1 )
{
int toColor = 0, fromColor = 0;
if(toCard->GetCardSuit() == 'h' || toCard->GetCardSuit() == 'd')
toColor = 0;
else
toColor = 1;
if(fromCard->GetCardSuit() =='h' || fromCard->GetCardSuit() == 'd')
fromColor = 0;
else
fromColor = 1;
if(fromColor == toColor)
return false;
else
return true;
}
return false;
}
bool Solitaire::ValidSuitMove(int from)
{
Card* fromCard;
if(from == 7)
{
if(!_deck.empty())
{
if(!_deck.top().GetIsFaceUp())
{
return false;
}
else
{
fromCard = &_deck.top();
}
}
else
{
return false;
}
}
else
{
if(!_tableCards[from].empty())
fromCard = &_tableCards[from].top();
else
return false;
}
char suit = fromCard->GetCardSuit();
int moveIndex = 0;
switch(suit)
{
case 'h':
moveIndex = 0;
break;
case 'd':
moveIndex = 1;
break;
case 's':
moveIndex = 2;
break;
case 'c':
moveIndex = 3;
break;
}
if(fromCard->GetSolitaireValue() ==
_suitCards[moveIndex].Size() + 1 )
{
if(!_suitCards[moveIndex].Size() == 0)
{
if(fromCard->parent != NULL)
fromCard->parent->child = NULL;
fromCard->parent = &_suitCards[moveIndex].top();
_suitCards[moveIndex].top().child = fromCard;
fromCard->child = NULL;
}
if(from != 7){
TableCard::MoveBetween(_tableCards[from],_suitCards[moveIndex]);
if(!_tableCards[from].empty())
{
if(!_tableCards[from].top().GetIsFaceUp())
_tableCards[from].top().Flip();
}
}
else
{
_suitCards[moveIndex].Push(_deck.top());
_deck.Pop();
}
}
return false;
}
void Solitaire::MakeSuitMove(int from)
{
/* validSuit move also makes move */
ValidSuitMove(from) ;
}
void Solitaire::MakeMoveBetweenRows(int from, int to)
{
if(ValidMove(from,to))
{
if(!_tableCards[to].empty())
_tableCards[to].top().child = &_tableCards[from].top();
if(_tableCards[from].top().GetCardRank() != 'K')
_tableCards[from].top().parent = &_tableCards[to].top();
TableCard::MoveBetween(_tableCards[from], _tableCards[to]);
if(!_tableCards[from].empty())
if(!_tableCards[from].top().GetIsFaceUp())
_tableCards[from].top().Flip();
}
}
void Solitaire::MakeMoveDeckToRow(int to)
{
if(ValidMove(7 ,to))
{
if(!_tableCards[to].empty())
_tableCards[to].top().child = &_deck.top();
if(_deck.top().GetCardRank() != 'K')
_deck.top().parent = & _tableCards[to].top();
_tableCards[to].Push(_deck.top());
_deck.Pop();
}
}
void Solitaire::MakeMoveRowToRow(int from, int to)
{
if(from == 7)
{
MakeMoveDeckToRow(to);
return;
}
else if(_tableCards[from].Size() == 0)
return;
Card* fromCard;
fromCard = &_tableCards[from].top();
if(fromCard->parent == NULL)
MakeMoveBetweenRows(from,to);
else
{
int pos = _tableCards[from].Size()-1;
bool checkParent = true;
bool found = false;
while(checkParent && !found)
{
if(ValidRowToRowMove(fromCard,to))
found = true;
else if(fromCard->parent == NULL)
checkParent = false;
else
{
fromCard = fromCard->parent;
pos--;
}
}
if(found)
{
bool hasChildren = true;
if(fromCard->parent != NULL)
fromCard->parent->child = NULL;
while(hasChildren)
{
if(!_tableCards[to].empty())
{
fromCard->parent = &_tableCards[to].top();
_tableCards[to].top().child = fromCard;
}
_tableCards[to].Push(*fromCard);
_tableCards[from].RemoveAt(pos);
fromCard = fromCard->child;
pos++;
if(fromCard == NULL)
hasChildren = false;
}
}
if(!_tableCards[from].empty())
if(!_tableCards[from].top().GetIsFaceUp())
_tableCards[from].top().Flip();
}
}
bool Solitaire::ValidRowToRowMove(Card* fromCard, int to)
{
Card* toCard;
if(!_tableCards[to].empty())
toCard = &_tableCards[to].top();
//move king to empty space
if(_tableCards[to].empty())
{
if(fromCard->GetCardRank() == 'K')
return true;
else
return false;
}
else if(fromCard->GetSolitaireValue() == toCard->GetSolitaireValue()-1 )
{
int toColor = 0, fromColor = 0;
if(toCard->GetCardSuit() == 'h' || toCard->GetCardSuit() == 'd')
toColor = 0;
else
toColor = 1;
if(fromCard->GetCardSuit() =='h' || fromCard->GetCardSuit() == 'd')
fromColor = 0;
else
fromColor = 1;
if(fromColor == toColor)
return false;
else
return true;
}
return false;
}
bool Solitaire::GameCompleted()
{
for(int i=0; i<_suitCards.size(); i++)
if(_suitCards[i].Size() < 13)
return false;
return true;
}
/*==============================================*/
Leave A Comment?