Skip to content
Snippets Groups Projects
Commit 888395e2 authored by W. Spencer Smith's avatar W. Spencer Smith
Browse files

Addition of second A4 sample solution by Chris Schankula

parent e612eed7
No related branches found
No related tags found
No related merge requests found
Showing
with 4185 additions and 0 deletions
SRC_DIRS := src
C_SRCS := $(foreach srcdir,$(SRC_DIRS),$(wildcard $(srcdir)/*.c))
CXX_SRCS := $(foreach srcdir,$(SRC_DIRS),$(wildcard $(srcdir)/*.cpp))
C_OBJS := ${C_SRCS:.c=.o}
CXX_OBJS := ${CXX_SRCS:.cpp=.o}
OBJS := $(C_OBJS) $(CXX_OBJS)
INCLUDE_DIRS := include
LIBRARY_DIRS :=
LIBRARIES :=
prog_NAME := experiment
prog_DIR := bin
prog_FULL := $(prog_DIR)/$(prog_NAME)
prog_SRC_DIRS := experiment
prog_C_SRCS := $(foreach srcdir,$(prog_SRC_DIRS),$(wildcard $(srcdir)/*.c))
prog_CXX_SRCS := $(foreach srcdir,$(prog_SRC_DIRS),$(wildcard $(srcdir)/*.cpp))
prog_C_OBJS := ${prog_C_SRCS:.c=.o}
prog_CXX_OBJS := ${prog_CXX_SRCS:.cpp=.o}
prog_OBJS := $(prog_C_OBJS) $(prog_CXX_OBJS)
prog_INCLUDE_DIRS :=
prog_LIBRARY_DIRS :=
prog_LIBRARIES :=
test_NAME := test
test_DIR := bin
test_FULL := $(test_DIR)/$(test_NAME)
test_SRC_DIRS := test
test_C_SRCS := $(foreach srcdir,$(test_SRC_DIRS),$(wildcard $(srcdir)/*.c))
test_CXX_SRCS := $(foreach srcdir,$(test_SRC_DIRS),$(wildcard $(srcdir)/*.cpp))
test_C_OBJS := ${test_C_SRCS:.c=.o}
test_CXX_OBJS := ${test_CXX_SRCS:.cpp=.o}
test_OBJS := $(test_C_OBJS) $(test_CXX_OBJS)
test_INCLUDE_DIRS := catch
test_LIBRARY_DIRS :=
test_LIBRARIES :=
all_OBJS := $(OBJS) $(prog_OBJS) $(test_OBJS)
DEP := $(all_OBJS:%.o=%.d)
CXXFLAGS += -std=c++11
CXXFLAGS += $(foreach includedir,$(INCLUDE_DIRS),-I$(includedir))
LDFLAGS += $(foreach librarydir,$(LIBRARY_DIRS),-L$(librarydir))
LDFLAGS += $(foreach library,$(LIBRARIES),-l$(library))
.PHONY: test experiment doc clean
test: CXXFLAGS += $(foreach includedir,$(test_INCLUDE_DIRS),-I$(includedir))
test: LDFLAGS += $(foreach librarydir,$(test_LIBRARY_DIRS),-L$(librarydir))
test: LDFLAGS += $(foreach library,$(test_LIBRARIES),-l$(library))
experiment: CXXFLAGS += $(foreach includedir,$(prog_INCLUDE_DIRS),-I$(includedir))
experiment: LDFLAGS += $(foreach librarydir,$(prog_LIBRARY_DIRS),-L$(librarydir))
experiment: LDFLAGS += $(foreach library,$(prog_LIBRARIES),-l$(library))
test: $(test_FULL)
./$(test_FULL)
experiment: $(prog_FULL)
./$(prog_FULL)
doc:
doxygen doxConfig
cd latex;make;cd ..
$(test_FULL): $(test_OBJS) $(OBJS)
$(LINK.cc) $^ -o $@
$(prog_FULL): $(prog_OBJS) $(OBJS)
$(LINK.cc) $^ -o $@
-include $(DEP)
%.o: %.cpp
$(CXX) $(CXXFLAGS) -MMD -c $< -o $@
clean:
@- $(RM) $(prog_FULL)
@- $(RM) $(prog_OBJS)
@- $(RM) $(test_FULL)
@- $(RM) $(test_OBJS)
@- $(RM) $(OBJS)
@- $(RM) $(DEP)
The executables created will appear here.
\ No newline at end of file
File added
This diff is collapsed.
/*
* use this file for experimenting with your code,
* testing things that don't work, debugging, etc.
*
* you can compile and run this via 'make experiment'
*
* this file will not be graded
*/
#include "GameBoard.h"
#include "CardDeckUtils.h"
#include "CardTypes.h"
#include <vector>
#include <iostream>
int main()
{
// std::vector<CardT> deck = CardDeckUtils::randomDeck();
// std::cout << deck.size() << std::endl;
// std::vector<CardStackT> cardStacks = GameBoard::tableauDeck(deck);
// std::cout << cardStacks.size() << std::endl;
GameBoardT gb = GameBoardT();
CardT c0(H, A);
CardT c1(C, C2);
CardT c2(D, C3);
CardStackT stack = CardStackT(19,std::vector<CardT>());
stack = stack.push(c0);
stack = stack.pop();
//stack = stack.pop();
gb.place(Tableau, 0, c0);
gb.place(Tableau, 1, c1);
gb.place(Tableau, 2, c2);
std::cout << "Move T1 to T0: " << gb.isValidMove(Tableau, 1, Tableau, 0) << std::endl;
std::cout << "Move T0 to T1: " << gb.isValidMove(Tableau, 0, Tableau, 1) << std::endl;
std::cout << "Move T1 to T2: " << gb.isValidMove(Tableau, 1, Tableau, 2) << std::endl;
std::cout << "Move T0 to T2: " << gb.isValidMove(Tableau, 0, Tableau, 2) << std::endl;
gb.makeMove(Tableau, 1, Tableau, 2);
std::cout << "Move T1 to T0: " << gb.isValidMove(Tableau, 1, Tableau, 0) << std::endl;
std::cout << "Move T0 to T1: " << gb.isValidMove(Tableau, 0, Tableau, 1) << std::endl;
std::cout << "Move T1 to T2: " << gb.isValidMove(Tableau, 1, Tableau, 2) << std::endl;
std::cout << "Move T0 to T2: " << gb.isValidMove(Tableau, 0, Tableau, 2) << std::endl;
gb.makeMove(Tableau, 0, Tableau, 2);
std::cout << "Move T1 to T0: " << gb.isValidMove(Tableau, 1, Tableau, 0) << std::endl;
std::cout << "Move T0 to T1: " << gb.isValidMove(Tableau, 0, Tableau, 1) << std::endl;
std::cout << "Move T1 to T2: " << gb.isValidMove(Tableau, 1, Tableau, 2) << std::endl;
std::cout << "Move T0 to T2: " << gb.isValidMove(Tableau, 0, Tableau, 2) << std::endl;
std::cout << "Move T2 to T0: " << gb.isValidMove(Tableau, 2, Tableau, 0) << std::endl;
std::cout << std::endl;
std::cout << "validMoveExists: " << gb.validMoveExists() << std::endl;
std::cout << "isInWinState: " << gb.isInWinState() << std::endl;
gb = GameBoardT(CardDeckUtils::randomDeck());
return 0;
}
\ No newline at end of file
/**
* \file CardADT.h
* \brief Provides the CardADT class for representing a card in a standard 52-card deck of cards.
* \author Christopher W. Schankula, MacID: schankuc
* \date April 8th, 2018
*/
#ifndef CARDADT_H
#define CARDADT_H
#include "CardTypes.h"
#include <map>
/**
* \brief Class for representing a card in a deck of cards given a suit and a rank.
* \details Implements a class for representing a card in a deck of cards. Stores the
suit and the rank of the card. Also provides functions for outputting the rank, suit
and colour of the card.
*/
class CardT {
private:
SuitT suit;
RankT rank;
public:
/**
* \brief Creates a new card
* \details Create a new card given a suit and a rank for the card.
* \param s The suit of the card (H, D, C, S).
* \param r The rank of the card (A,2-10,J,Q,K).
*/
CardT (SuitT s, RankT r);
/**
* \brief Returns the suit of the current card.
* \return The suit of the given card.
*/
SuitT getSuit();
/**
* \brief Returns the colour of the current card.
* \return The colour of the given card.
*/
ColourT getColour();
/**
* \brief Returns the rank of the current card.
* \return The rank of the given card.
*/
RankT getRank();
};
#endif
\ No newline at end of file
/**
* \file CardDeckUtils.h
* \brief A module providing functions to generate and randomize sequences representing decks of cards.
* \author Christopher W. Schankula, MacID: schankuc
* \date April 8th, 2018
*/
#ifndef CARDDECKUTILS_H
#define CARDDECKUTILS_H
#include <vector>
#include "CardStack.h"
#include "GameBoardTypes.h"
/**
* \brief A static class for generating and shuffling sequences of playing cards,
* representing a deck of cards.
*/
class CardDeckUtils{
private:
//private to avoid instances of this class being created.
CardDeckUtils();
static std::vector<CardT> deckSet();
static std::vector<CardT> permute(std::vector<CardT> inSet);
public:
/**
* \brief Returns a random sequence of CardT object, representing a shuffled deck of cards.
* \returns A sequence of all 52 playing cards in a randomized order.
*/
static std::vector<CardT> randomDeck();
};
#endif
\ No newline at end of file
/**
* \file LanduseMap.h
* \brief The header file for the LanduseMap type definition.
* \author Christopher W. Schankula, MacID: schankuc
* \date March 26th, 2018
*/
#ifndef CARDSTACK_H
#define CARDSTACK_H
#include "CardADT.h"
#include "Stack.h"
/**
* \brief A Seq2D instance consisting of LanduseT, used for representing land use on a two-dimensional map
*/
typedef Stack<CardT> CardStackT;
#endif
\ No newline at end of file
/**
* \file CardTypes.h
* \brief Provides enumerated types for representing a card in a deck of cards.
* \author Christopher W. Schankula, MacID: schankuc
* \date April 8th, 2018
*/
#ifndef CARDTYPES_H
#define CARDTYPES_H
/**
* \brief Enumerated type representing the four suits of a card: Hearts (H), Diamonds (D), Clubs (C) and Spades (S).
*/
enum SuitT {H, D, C, S};
/**
* \brief Enumerated type representing the ranks of a card in a deck of cards (Ace, 2-10, Jack, Queen, King).
*/
enum RankT {A, C2, C3, C4, C5, C6, C7, C8, C9, C10, J, Q, K};
/**
* \brief Enumerated type representing the possible colours of a card in a deck of cards (Red or Black).
*/
enum ColourT {Red, Black};
#endif
\ No newline at end of file
/**
* \file Exceptions.h
* \brief Defines exceptions for use in this project.
* \author Christopher W. Schankula, MacID: schankuc
* \date April 9th, 2018
*/
#ifndef EXCEPTIONS_H
#define EXCEPTIONS_H
#include <exception>
class invalid_argument : public std::exception {
const char * what () const throw () {
return "invalid argument";
}
};
class invalid_config : public std::exception {
const char * what () const throw () {
return "invalid board configuration";
}
};
class invalid_cell : public std::exception {
const char * what () const throw () {
return "invalid cell, cell does not exist on gameboard";
}
};
class invalid_move : public std::exception {
const char * what () const throw () {
return "invalid move, this move cannot be made according to the rules of FreeCell.";
}
};
class stack_full : public std::exception {
const char * what () const throw () {
return "cannot push to stack, stack is full";
}
};
class stack_empty : public std::exception {
const char * what () const throw () {
return "cannot perform top or pop operation, stack is empty";
}
};
#endif
\ No newline at end of file
/**
* \file GameBoard.h
* \brief An abstract data type (ADT) for representing the state of a game of FreeCell Solitaire.
* \author Christopher W. Schankula, MacID: schankuc
* \date April 8th, 2018
*/
#ifndef GAMEBOARD_H
#define GAMEBOARD_H
#include <vector>
#include "CardStack.h"
#include "GameBoardTypes.h"
/**
* \brief Class for representing the gameboard of a game of Freecell Solitaire.
* \details Implements a class for representing the gameboard of a Freecell Solitaire game,
* as well as functions for making and validating moves and verifying win states and states with no
* possible moves. Implemented as an Abstract Data Type (ADT) so that client code could create and manage
* multiple games at once, for example in a server model.
*/
class GameBoardT {
private:
std::vector<CardStackT> T;
std::vector<CardStackT> F;
std::vector<CardStackT> H;
std::vector<CardStackT> stackSeq(unsigned int l, unsigned int n);
std::vector<CardStackT> tableauDeck(std::vector<CardT> deck);
bool isValidCell(CellT c, unsigned int n);
bool validTabTab(unsigned int t0, unsigned int t1);
bool validTabFree(unsigned int t, unsigned int f);
bool validTabHome(unsigned int t, unsigned int h);
bool validFreeTab(unsigned int f, unsigned int t);
bool validFreeFree(unsigned int f0, unsigned int f1);
bool validFreeHome(unsigned int f, unsigned int h);
bool oneLess(CardT c0, CardT c1);
bool oneMore(CardT c0, CardT c1);
bool tabPlaceable(CardT c0, CardT c1);
bool homePlaceable(CardT c0, CardT c1);
bool isWinningHomeCell(unsigned int i);
public:
/**
* \brief Construct a new Freecell gameboard.
* \details Create a new instance of a Freecell gameboard with all cells empty. This can be
* populated manually by a client.
*/
GameBoardT();
/**
* \brief Construct a new Freecell gameboard from a deck of cards
* \details Create a new instance of a Freecell gameboard by placing the given deck
* on the tableau cells of the gameboard.
* \throws invalid_argument The given initial deck does not have 52 cards.
*/
GameBoardT(std::vector<CardT> deck);
/**
* \brief Place a card on a given cell of the gameboard.
* \details Place a card on a given cell of the gameboard. Used to manually construct an
* initial game state.
* \param cell The type of cell on which to place the code
* \param i The identifier of the cell of type cell at which to place the new card on the gameboard.
* \param card The new card to place on the top of the cell given.
* \throws invalid_config The placement of the card would result in an invalid
* configuration of the game board (beyond the possible sizes of the cell in question).
* \throw invalid_cell The given cell does not exist on the gameboard.
*/
void place(CellT cell, unsigned int i, CardT card);
/**
* \brief Determine whether a given move is valid given the current gameboard state.
* \details Returns whether moving a potential card from a given cell to another given cell
* is a valid move according to Freecell game rules.
* \returns true if the card on the top (if any) of the given cell represented by c0 and n0
* can be moved to the given cell represented by c1 and n1. false if the move is invalid or
* if the cell at c0 and n0 is empty.
* \param c0 The type of cell for the "from" cell to move the card from.
* \param n0 The identifier of the cell of type cell from which to move a card.
* \param c1 The type of cell for the "to" cell to move the card to.
* \param n1 The identifier of the cell of type cell to which to move the card.
* \throws invalid_cell One or both of the cells provided are not valid cells on the gameboard.
*/
bool isValidMove(CellT c0, unsigned int n0, CellT c1, unsigned int n1);
/**
* \brief Make a move from one cell to another, if it's valid.
* \details Moves the card from the top of the cell represented by c0 and n0 to the cell
* represented by c1 and n1.
* \param c0 The type of cell for the "from" cell to move the card from.
* \param n0 The identifier of the cell of type cell from which to move a card.
* \param c1 The type of cell for the "to" cell to move the card to.
* \param n1 The identifier of the cell of type cell to which to move the card.
* \throws invalid_cell One or both of the cells provided are not valid cells on the gameboard.
*/
void makeMove(CellT c0, unsigned int n0, CellT c1, unsigned int n1);
/**
* \brief Return the cards in the cell given as a CardStackT object.
* \details Returns the cards in the cell on the gameboard given as a CardStackT object.
* \param cell The type of cell on which to place the code
* \param i The identifier of the cell of type cell at which to place the new card on the gameboard.
* \return The CardStackT representation of the given cell.
* \throws invalid_cell One or both of the cells provided are not valid cells on the gameboard.
*/
CardStackT getCell(CellT cell, unsigned int n);
/**
* \brief Return whether a valid move exists.
* \details Returns whether the current game state contains a valid move. This means that it is possible
* to move a card from a given cell to any other cell on the board. Note that it is possible to have a valid move
* but still be in an unwinnable game (e.g. the card can be moved back and forth between two Tableau cell).
* This function does not check for this condition.
* \return true if a valid move exists on the gameboard, and false if no valid move exists.
*/
bool validMoveExists();
/**
* \brief Return whether the gameboard is currently in the win state.
* \details Returns whether the current game state is a win state. This would mean that all HomeCells
* are stacked from Ace to King of each suit.
* \return true if the gameboard is currently in a winning state, false otherwise.
*/
bool isInWinState();
};
#endif
\ No newline at end of file
/**
* \file GameBoardTypes.h
* \brief A module providing types for representing a Freecell Solitaire game board.
* \author Christopher W. Schankula, MacID: schankuc
* \date April 8th, 2018
*/
#ifndef GAMEBOARDTYPES_H
#define GAMEBOARDTYPES_H
/**
* \brief Enumerated type representing the three types of card cells in a Freecell Solitaire game board: FreeCell, HomeCell and Tableau cells.
*/
enum CellT {FreeCell, HomeCell, Tableau};
#endif
\ No newline at end of file
/**
* \file Stack.h
* \brief A template module for a stack of a given type of elements.
* \author Christopher W. Schankula, MacID: schankuc
* \date April 8th, 2018
*/
#ifndef STACK_H
#define STACK_H
#include <vector>
/**
* \brief Template class for storing values in a first in, last out (FILO) stack.
* \details Implements a template for a first in, last out (FILO) stack.
*/
template<class T>
class Stack{
private:
std::vector<T> S;
unsigned int max_size;
public:
/**
* \brief Construct a new stack.
* \details Create a new instance of stack given some initial elements and a maximum size.
* \param n The maximum size of the given stack.
* \param s The initial elements to push on to the stack. Elements are pushed in an order where
* the first elements (i.e s[0]) are pushed on to the stack first and thus would be the last to be popped.
* \throw invalid_argument The number of elements in the initial stack given is greater than
the maximum stack size.
*/
Stack(unsigned int n, std::vector<T> s);
/**
* \brief Creates a new stack by pushing the given value on to the current stack.
* \details Create a new instance of stack identical to the last one except with one more value, the one given,
* placed on top.
* \param e The new element of type T to place on top of the stack.
* \return A new instance of stack with the same elements as the current one, with the new value e on the top
* of the stack.
* \throw stack_full The number of elements on the current stack already equals the maximum
* capacity of the stack.
*/
Stack<T> push(T e);
/**
* \brief Creates a new stack by popping the top value off the current one.
* \details Create a new instance of stack identical to the last one except with one less value:
* the topmost value on the stack is deleted.
* \return A new instance of stack with one less value than the current one, the top having been
* removed.
* \throw stack_empty The current stack does not have any more values to pop off.
*/
Stack<T> pop();
/**
* \brief Get the top value of the current stack.
* \details Returns the topmost value on the current stack, the value most recently added to the stack.
* \return The top value of type T of the current stack.
* \throw stack_empty The current stack does not have values to return.
*/
T top();
/**
* \brief Get the current size of the stack.
* \details Returns the number of elements currently stored on the current stack.
* \return The number of elements on the current stack.
*/
unsigned int getSize();
/**
* \brief Get the maximum size of the stack.
* \details Returns the maximum number of elements of type T which can be stored on the current stack.
* \return The maximum number of elements which can be stored the current stack.
*/
unsigned int getMaxSize();
/**
* \brief Get a sequence representation of the current stack.
* \details Returns a sequence representing the elements in the current stack. The beginning of the sequence
* represents the bottommost values on the stack.
* \return The sequence representation of the current stack.
*/
std::vector<T> toSeq();
};
#endif
\ No newline at end of file
Assignments/A4/A4Soln-CS/report/FreeCellBoard.jpg

55.9 KiB

File added
This diff is collapsed.
/**
* \file CardADT.cpp
* \brief The implementation of the CardT class.
* \author Christopher W. Schankula, MacID: schankuc
* \date April 8th, 2018
*/
#include "CardTypes.h"
#include "../include/CardADT.h"
CardT::CardT(SuitT s, RankT r){
this->suit = s;
this->rank = r;
}
SuitT CardT::getSuit(){
return this->suit;
}
ColourT CardT::getColour(){
if (this->suit == H || this->suit == D)
return Red;
else
return Black;
}
RankT CardT::getRank(){
return this->rank;
}
\ No newline at end of file
/**
* \file CardDeckUtils.cpp
* \brief Implementation of functions described by CardDeckUtils.h. Provides funcitons for generating
* and shuffling a deck of cards.
* \author Christopher W. Schankula, MacID: schankuc
* \date April 8th, 2018
*/
#include "CardDeckUtils.h"
#include "CardADT.h"
#include "CardTypes.h"
#include <vector>
#include <stdlib.h>
std::vector<CardT> CardDeckUtils::deckSet(){
RankT ranks[] = {A, C2, C3, C4, C5, C6, C7, C8, C9, C10, J, Q, K};
SuitT suits[] = {H, D, S, C};
std::vector<CardT> deck = std::vector<CardT>();
for (int i = 0; i < 4; i++)
for (int j = 0; j < 13; j++)
deck.push_back(CardT(suits[i], ranks[j]));
return deck;
}
std::vector<CardT> CardDeckUtils::permute(std::vector<CardT> inSet){
srand(time(NULL));
for (int i = 0; i < 1000; i++){
int j = rand() % 52;
int k = rand() % 52;
CardT tmp = inSet[j];
inSet[j] = inSet[k];
inSet[k] = tmp;
}
return inSet;
}
std::vector<CardT> CardDeckUtils::randomDeck(){
return permute(deckSet());
}
\ No newline at end of file
/**
* \file GameBoard.cpp
* \brief The implementation of the Freecell gameboard ADT described in GameBoard.h.
* \author Christopher W. Schankula, MacID: schankuc
* \date April 8th, 2018
*/
#include "GameBoard.h"
#include "CardStack.h"
#include "CardTypes.h"
#include "GameBoardTypes.h"
#include "Exceptions.h"
#include <stddef.h>
GameBoardT::GameBoardT(){
this->T = GameBoardT::stackSeq(8,19);
this->F = GameBoardT::stackSeq(4,1);
this->H = GameBoardT::stackSeq(4,13);
}
GameBoardT::GameBoardT(std::vector<CardT> deck){
if(deck.size() != 52) throw invalid_argument();
this->T = GameBoardT::tableauDeck(deck);
this->F = GameBoardT::stackSeq(4,1);
this->H = GameBoardT::stackSeq(4,13);
}
void GameBoardT::place(CellT cell, unsigned int i, CardT card){
switch (cell){
case Tableau:
if ((i < 8) && (this->T[i].getSize() == this->T[i].getMaxSize()))
throw invalid_config();
else if (i >= 8)
throw invalid_cell();
break;
case FreeCell:
if ((i < 4) && (this->F[i].getSize() == this->F[i].getMaxSize()))
throw invalid_config();
else if (i >= 4)
throw invalid_cell();
break;
case HomeCell:
if ((i < 4) && (this->H[i].getSize() == this->H[i].getMaxSize()))
throw invalid_config();
else if (i >= 4)
throw invalid_cell();
break;
}
switch (cell){
case Tableau:
this->T[i] = this->T[i].push(card);
break;
case FreeCell:
this->F[i] = this->F[i].push(card);
break;
case HomeCell:
this->H[i] = this->H[i].push(card);
break;
}
}
bool GameBoardT::isValidMove(CellT c0, unsigned int n0, CellT c1, unsigned int n1){
if (!isValidCell(c0, n0) || !isValidCell(c1, n1)) throw invalid_cell();
switch (c0){
case Tableau:
switch (c1){
case Tableau:
return validTabTab(n0, n1);
case FreeCell:
return validTabFree(n0, n1);
case HomeCell:
return validTabHome(n0, n1);
}
case FreeCell:
switch (c1){
case Tableau:
return validFreeTab(n0, n1);
case FreeCell:
return validFreeFree(n0, n1);
case HomeCell:
return validFreeHome(n0, n1);
}
case HomeCell:
return false;
}
}
void GameBoardT::makeMove(CellT c0, unsigned int n0, CellT c1, unsigned int n1){
if (!isValidMove(c0, n0, c1, n1)) throw invalid_move();
if (!isValidCell(c0, n0) || !isValidCell(c1, n1)) throw invalid_cell();
switch (c0){
case Tableau:
switch (c1){
case Tableau:
this->T[n1] = this->T[n1].push(this->T[n0].top());
this->T[n0] = this->T[n0].pop();
return;
case FreeCell:
this->F[n1] = this->F[n1].push(this->T[n0].top());
this->T[n0] = this->T[n0].pop();
return;
case HomeCell:
this->H[n1] = this->H[n1].push(this->T[n0].top());
this->T[n0] = this->T[n0].pop();
return;
}
case FreeCell:
switch (c1){
case Tableau:
this->T[n1] = this->T[n1].push(this->F[n0].top());
this->F[n0] = this->F[n0].pop();
return;
case FreeCell:
this->F[n1] = this->F[n1].push(this->F[n0].top());
this->F[n0] = this->F[n0].pop();
return;
case HomeCell:
this->H[n1] = this->H[n1].push(this->F[n0].top());
this->F[n0] = this->F[n0].pop();
return;
}
case HomeCell: return;
}
}
CardStackT GameBoardT::getCell(CellT cell, unsigned int n){
if (!isValidCell(cell, n)) throw invalid_cell();
switch (cell){
case Tableau:
return this->T[n];
case FreeCell:
return this->F[n];
case HomeCell:
return this->H[n];
}
}
bool GameBoardT::validMoveExists(){
CellT cells[] = {Tableau, FreeCell, HomeCell};
unsigned int size[] = {8, 4, 4};
for(int i = 0; i < 3; i++){
CellT c0 = cells[i];
for (int n0 = 0; n0 < size[i]; n0++){
for (int j = 0; j < 3; j++){
CellT c1 = cells[j];
for(int n1 = 0; n1 < size[j]; n1++){
if (isValidMove(c0, n0, c1, n1)) return true;
}
}
}
}
return false;
}
bool GameBoardT::isInWinState(){
return isWinningHomeCell(0) && isWinningHomeCell(1) && isWinningHomeCell(2) && isWinningHomeCell(3);
}
/****** private local functions ******/
std::vector<CardStackT> GameBoardT::stackSeq(unsigned int l, unsigned int n){
std::vector<CardStackT> stSeq = std::vector<CardStackT>();
for(int i = 0; i < l; i++){
stSeq.push_back(CardStackT(n, std::vector<CardT>()));
}
return stSeq;
}
std::vector<CardStackT> GameBoardT::tableauDeck(std::vector<CardT> deck){
std::vector<CardStackT> stSeq = std::vector<CardStackT>();
unsigned int lengths[] = {7, 7, 7, 7, 6, 6, 6, 6};
unsigned int sizes[] = {19,19,19,19,18,18,18,18};
int n = 0;
for (int i = 0; i < 8; i++){
std::vector<CardT> slice(deck.begin() + n, deck.begin() + n + lengths[i]);
stSeq.push_back(CardStackT(sizes[i], slice));
n += lengths[i];
}
return stSeq;
}
bool GameBoardT::isValidCell(CellT c, unsigned int n){
switch (c){
case Tableau:
return n < 8;
case FreeCell:
return n < 4;
case HomeCell:
return n < 4;
}
}
bool GameBoardT::validTabTab(unsigned int t0, unsigned int t1){
if (this->T[t0].getSize() > 0){
if(this->T[t1].getSize() > 0)
return tabPlaceable(this->T[t0].top(), this->T[t1].top());
else if (this->T[t1].getSize() == 0)
return true;
}
return false;
}
bool GameBoardT::validTabFree(unsigned int t, unsigned int f){
if (this->T[t].getSize() > 0){
if(this->F[f].getSize() > 0)
return false;
else if (this->F[f].getSize() == 0)
return true;
}
return false;
}
bool GameBoardT::validTabHome(unsigned int t, unsigned int h){
if (this->T[t].getSize() > 0){
if(H[h].getSize() > 0)
return homePlaceable(T[t].top(), H[h].top());
else if (this->H[h].getSize() == 0)
return this->T[t].top().getRank() == A;
}
return false;
}
bool GameBoardT::validFreeTab(unsigned int f, unsigned int t){
if (this->F[f].getSize() > 0){
if(this->T[t].getSize() > 0)
return tabPlaceable(this->F[f].top(), this->T[t].top());
else if (this->T[t].getSize() == 0)
return true;
}
return false;
}
bool GameBoardT::validFreeFree(unsigned int f0, unsigned int f1){
return (this->F[f0].getSize() > 0 && this->F[f1].getSize() == 0);
}
bool GameBoardT::validFreeHome(unsigned int f, unsigned int h){
if (this->F[f].getSize() > 0){
if(this->H[h].getSize() > 0)
return homePlaceable(F[f].top(), this->H[h].top());
else if (this->H[h].getSize() == 0)
return this->F[f].top().getRank() == A;
}
return false;
}
bool GameBoardT::oneLess(CardT c0, CardT c1){
RankT ranks[] = {A, C2, C3, C4, C5, C6, C7, C8, C9, C10, J, Q, K};
for(int i = 0; i < 12; i++)
if (c0.getRank() == ranks[i] && c1.getRank() == ranks[i + 1]) return true;
return false;
}
bool GameBoardT::oneMore(CardT c0, CardT c1){
RankT ranks[] = {A, C2, C3, C4, C5, C6, C7, C8, C9, C10, J, Q, K};
for(int i = 0; i < 12; i++)
if (c1.getRank() == ranks[i] && c0.getRank() == ranks[i + 1]) return true;
return false;
}
bool GameBoardT::tabPlaceable(CardT c0, CardT c1){
if (c0.getColour() != c1.getColour()) return oneLess(c0, c1);
else return false;
}
bool GameBoardT::homePlaceable(CardT c0, CardT c1){
if (c0.getSuit() == c1.getSuit()) return oneMore(c0, c1);
else return false;
}
bool GameBoardT::isWinningHomeCell(unsigned int i){
std::vector<CardT> stSeq = H[i].toSeq();
if (!(stSeq.size() == 13)) return false;
if (!(stSeq[0].getRank() == A)) return false;
bool winning = true;
for (int j = 0; j < H[i].getSize() - 1; j++)
winning = winning && oneLess(stSeq[j], stSeq[j + 1]);
return winning;
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment