#include //library used to access functions such as cin and cout #include //srand, which is used in order to find a random immortal peg #include #include #include #include using namespace std; const int NUMCOLUMNS = 5; //the number of columns const int NUMROWS = 5; //the number of rows //This subprogram fills the board initially void MakeGrid(char Board[NUMROWS][NUMCOLUMNS] /*inout*/, char& pegSpace, bool& startNewGame /*inout*/) { if (startNewGame == true) //if a new game is started { char Peg = 'O'; // O is used as a peg for (int xCoord = 5; xCoord > 0; xCoord--) //filling the X coordinates //from row 5 (at the top) to row 1 (at the bottom) { for (int yCoord = 1; yCoord < 6; yCoord++) //filling the Y coordinates //from column 1 (left) to column 5 (right) { Board[xCoord][yCoord] = Peg; //both the X and Y coordinates in the for //loops will store a peg (O) } } Board[3][3] = pegSpace; //except the location 3,3 (centre) has a space } } //This subprogram shows the board once it is made void ShowGrid(char Board[NUMROWS][NUMCOLUMNS]/*inout*/, char pegSpace /*in*/, int pegsRemaining /*in*/, int& highscore /*inout*/) { cout << "\n" << endl; cout << " Solitaire " << endl; cout << "\n Highscore: " << highscore; cout << " Pegs Remaining: " << pegsRemaining; cout << "\n\n\n\n"; for (int xCoord = 5; xCoord > 0; xCoord--) //for loop displays the board { if (xCoord == 5) //if loop displays a Y next to 5, or spaces instead //next to numbers instead { cout << " Y " << xCoord << " | "; //displays a Y, # } else { cout << " " << xCoord << " | "; //or displays spaces, # } for (int yCoord = 1; yCoord < 6; yCoord++) { cout << Board[yCoord][xCoord] << " "; } //end of Y Coordinate if (xCoord != 1) { cout << "\n \n"; } }//end of X Coordinate cout << "\n --------------------\n"; cout << " 1 2 3 4 5 \n"; cout << "\n X \n"; } //This subprogram takes the user's input of the X and Y coordinates and //the direction the player wishes to move, works out the peg to be removed //and if the move is valid. If the user has selected the immortal peg, the //moves of its new position are worked out. void CalculateMoves(int& playerCoordinateX /*inout*/, int& newSpaceX /*inout*/, char directionToMove /*in*/, char Board[NUMROWS][NUMCOLUMNS]/*inout*/, int& playerCoordinateY /*inout*/, int& newSpaceY/*inout*/, int& immortalX /*inout*/, int& immortalY /*inout*/) { if (directionToMove == 'n' || directionToMove == 'N') { //if the user inputted direction is N //---------------- X ----------------- if (playerCoordinateX == immortalX) { immortalX = immortalX; } //the immortal peg's X coordinates are not changed, if the user has //selected it newSpaceX = playerCoordinateX; playerCoordinateX = playerCoordinateX; //no changes are made to the coordinates //---------------- Y ----------------- if (playerCoordinateY == immortalY) { immortalY = immortalY + 2; } //the immortal peg's Y coordinate is moved two spaces up //if the user has selected it newSpaceY = playerCoordinateY + 1; //the peg to be deleted in one space up from the inputted peg playerCoordinateY = playerCoordinateY + 2; //the new peg coordinate is two spaces up from the inputted peg } else if (directionToMove == 'e' || directionToMove == 'E') { //if the user inputted direction is E //---------------- X ----------------- if (playerCoordinateX == immortalX) { immortalX = immortalX + 2; } //the immortal peg's X coordinate is moved two spaces right //if the user has selected it newSpaceX = playerCoordinateX + 1; //the deleted peg is one space more than the inputted peg playerCoordinateX = playerCoordinateX + 2; //the new coordinate is two spaces more than the inputted peg //---------------- Y ----------------- if (playerCoordinateY == immortalY) { immortalY = immortalY; } //the immortal peg's Y coordinate is not changed, if the user has //selected it newSpaceY = playerCoordinateY; playerCoordinateY = playerCoordinateY; //no changes are made to the peg } else if (directionToMove == 'w' || directionToMove == 'W') { //if the user inputted direction is W //---------------- X ----------------- if (playerCoordinateX == immortalX) { immortalX = immortalX - 2; } //the immortal peg's X coordinate is moved two spaces left //if the user has selected it newSpaceX = playerCoordinateX - 1; //the deleted peg is one space less than the inputted peg playerCoordinateX = playerCoordinateX - 2; //the new coordinate is two spaces less than the inputted peg //---------------- Y ----------------- if (playerCoordinateY == immortalY) { immortalY = immortalY; } //the immortal peg's Y coordiante is not changed, if the user has //selected it newSpaceY = playerCoordinateY; playerCoordinateY = playerCoordinateY; //no changes are made to the peg } else if (directionToMove == 's' || directionToMove == 'S') { //if the user inputted direction is S //---------------- X ----------------- if (playerCoordinateX == immortalX) { immortalX = immortalX; } //the immortal peg's X coordinate is not changed, if the user has //selected it newSpaceX = playerCoordinateX; playerCoordinateX = playerCoordinateX; //no changes are made to the pegs //---------------- Y ----------------- if (playerCoordinateY == immortalY) { immortalY = immortalY - 2; } //the immortal peg's Y coordinate is moved two spaces down, //if the user has selected it newSpaceY = playerCoordinateY - 1; //the peg to be deleted is one space down from the peg inputted playerCoordinateY = playerCoordinateY - 2; //the new peg location is two spaces down from the peg inputted } } //This subprogram validates user moves void MoveValidation(char Board[NUMROWS][NUMCOLUMNS] /*inout*/, int playerCoordinateX /*in*/, int playerCoordinateY /*in*/, int newSpaceX /*in*/, int newSpaceY /*in*/, bool& makeAMove /*inout*/, bool& validMove /*inout*/, int lastMoveX/*in*/, int lastMoveY/*in*/) { if (Board[lastMoveX][lastMoveY] == ' ') { //if the last move (i.e. the original user coordinates) is //a space: cout << "~~~ Error 0 - there is no peg to start with" << endl; //output error 0 as there is no peg to start with makeAMove = true; //return the user to the move making stage validMove = false; //set to invalid move } else if (Board[newSpaceX][newSpaceY] != 'O') { //if the peg that is to be deleted is not a peg (is a space instead): cout << "~~~ Error 1 - there is no peg to jump over" << endl; //output error 1 as there is no peg to jump over makeAMove = true; //returns user to move making stage validMove = false; //set to invalid move } else if (playerCoordinateX < 0 || playerCoordinateX > 5 || playerCoordinateY < 0 || playerCoordinateY > 5 || newSpaceX < 0 || newSpaceX > 5 || newSpaceY < 0 || newSpaceY > 5) { //if the new coordinates or deleted peg coordinates are not within //the range of 1 to 5 (the original coordinates are dealt with in //the main subprogram): cout << "~~~ Error 2 - a peg will move off the board" << endl; //output error 2 as a peg would move off the board and the array //would break makeAMove = true; //returns user to move making stage validMove = false; //set to invalid move } else if (Board[playerCoordinateX][playerCoordinateY] == 'O') { //if the new coordinates already have an O (a peg) in: cout << "~~~ Error 3 - a peg already occupies this space!" << endl; //output error 3 as a peg already exists in the selected location makeAMove = true; //returns user to move making stage validMove = false; //set to invalid move } } //This subprogram updates the user inputted moves on the board after //the program has validated the user's moves void UpdateMoves(char Board[NUMROWS][NUMCOLUMNS], int& playerCoordinateX, int& playerCoordinateY, int& newSpaceX, int& newSpaceY, int& lastMoveX, int& lastMoveY, bool& validMove, int& immortalX, int& immortalY) { Board[playerCoordinateX][playerCoordinateY] = 'O'; Board[newSpaceX][newSpaceY] = ' '; Board[lastMoveX][lastMoveY] = ' '; Board[immortalX][immortalY] = 'O'; } void DisplayHighscores(int& currentScore, int& highscore) /*both inout*/ { } void DisplayRules() { } //This subprogram is the very first run and asks the player whether they need //to see the rules or not void IntroductionToGame(bool& gameActive, bool& startNewGame, bool& makeAMove) //all parameters are inout { bool validChar = false; //used to determine inputted character char userInput = '\0'; //the letter that the user inputs cout << "Welcome to Peg Solitaire!" << endl; //prints out line cout << "To start the game input"; //prints out line cout << " (A): "; //prints out next to input cin >> userInput; //user inputs choice if (userInput == 'a' || userInput == 'A') { //if the user inputs N or n validChar = true; }else {cout << "Please input 'A' to start the Game";} while (validChar == false) { cout << "Please input 'A' to start the Game"; cout << "\n"; cin >> userInput; if (userInput == 'a' || userInput == 'A') { validChar==true; break; } } } //This subprogram contains the game void PlayTheGame(char Board[NUMROWS][NUMCOLUMNS], char pegSpace, bool& startNewGame, int& pegsRemaining, bool& validMove, bool& gameActive, int& playerCoordinateX, int& playerCoordinateY, int& lastMoveX, int& lastMoveY, bool& makeAMove, int& newSpaceX, int& newSpaceY, char& inputKey, char& directionToMove, int& currentScore, int& highscore, int& moveCounter, int& immortalX, int& immortalY) //all are 'inout' except pegSpace { while (gameActive == true) { //while the game is being played MakeGrid(Board, pegSpace, startNewGame); //the board is generated ShowGrid(Board, pegSpace, pegsRemaining, highscore); //the board and UI is //shown while (makeAMove == true) { //while the player is making a move validMove = true; //valid move reset to true cout << "\nWhat move would you like to make?" << endl; //asks user to input a move cout << "X: "; cin >> playerCoordinateX; //X coordinate is inputted first while (!cin >> playerCoordinateX) { //if the input is invalid - e.g. a letter is inputted cin.clear(); //the input stream is cleared cin.ignore(999, '\n'); //all input is discarded cout << "Please enter a valid X coordinate: " << endl; cin >> playerCoordinateX; //a valid input must be used } cout << endl; //a new line is started if (playerCoordinateX < 0 || playerCoordinateX > 5) { //if coordinates are not between 1 and 5, then error is printed out cout << "Error 2 - X Coordinate is off the board"; //error message //is displayed and cout << endl; //a new line printed cout << "Please enter a valid coordinate: "; cin >> playerCoordinateX; //user asked to re-enter X coordinate while (!cin >> playerCoordinateX) { //if the input is invalid - e.g. a letter is inputted cin.clear(); //the input stream is cleared cin.ignore(999, '\n'); //all input is discarded cout << "Please enter a valid X coordinate: " << endl; cin >> playerCoordinateX; //a valid input must be used } } cout << "Y: "; cin >> playerCoordinateY; //the user then inputs the Y coordinate while (!cin >> playerCoordinateY) { //if the input is invalid - e.g. a letter is inputted cin.clear(); //the input stream is cleared cin.ignore(999, '\n'); //all input is discarded cout << "Please enter a valid Y coordinate: " << endl; cin >> playerCoordinateY; //a valid input must be used } cout << endl; //a new line is printed if (playerCoordinateY < 0 || playerCoordinateY > 5) { //if coordinates are not between 1 and 5, then error is printed out cout << "Error 2 - Y Coordinate is off the board"; //error message is //printed out cout << "\nPlease enter a valid coordinate: "; cin >> playerCoordinateY; //user asked to re-enter the Y coordinate while (!cin >> playerCoordinateY) { //if the input is invalid - e.g. a letter is inputted cin.clear(); //the input stream is cleared cin.ignore(999, '\n'); //all input is discarded cout << "Please enter a valid X coordinate: " << endl; cin >> playerCoordinateX; //a valid input must be used } cout << endl; //prints out new line } if (playerCoordinateX == 0 && playerCoordinateY == 0) { //if 0,0 is input, the game is stopped cout << "The game will be stopped... are you sure?" << endl; cout << "Y/N: "; //user asked to confirm exit cin >> inputKey; //user inputs Y or N to stop game if (inputKey == 'y' || inputKey == 'Y') { //if y or Y is input and game is stopped gameActive = false; //game loop ends startNewGame = false; //resets new game variable makeAMove = false; //move making ends //Final Score Calculator if (pegsRemaining > 8) { //if 9 or more pegs remain, score is 0 currentScore = 0; } else if (pegsRemaining == 8) { //if 8 pegs remain, score is 10 currentScore = 10; } else if (pegsRemaining == 7) { //if 7 pegs remain, score is 20 currentScore = 20; } else if (pegsRemaining == 6) { //if 6 pegs remain, score is 30 currentScore = 30; } else if (pegsRemaining == 5) { //if 5 pegs remain, score is 40 currentScore = 40; } else if (pegsRemaining == 4) { //if 4 pegs remain, score is 50 currentScore = 50; } else if (pegsRemaining == 3) { //if 3 pegs remain, score is 60 currentScore = 60; } else if (pegsRemaining == 2) { //if 2 pegs remain, score is 70 currentScore = 70; } else if (pegsRemaining == 1) { //if 1 peg remains, score is 80 currentScore = 80; } if (Board[3][3] == 'O' && pegsRemaining == 1) { //if one peg is the centre hole (3,3) remains, score is //80 with a 20 point bonus (totalling 100) currentScore = currentScore + 20; cout << "Congratulations, you performed the expert finish"; cout << " and receive an extra 20 points!" << endl; } cout << "\nYour final score is: " << currentScore << "!" << endl; if (currentScore > highscore) { highscore = currentScore; cout << "Congratulations! You've set a new high "; cout << "score!" << endl; //congratulatory message is printed } cout << "You made " << moveCounter << " moves!\n\n"; break; } else if (inputKey == 'n' || inputKey == 'N') { cout << "Please change your coordinates -" << endl; cout << "X: "; cin >> playerCoordinateX; cout << endl; cout << "Y: "; cin >> playerCoordinateY; cout << endl; } else { cout << "Please input Y or N:" << endl; cin >> inputKey; } } if (playerCoordinateX == immortalX && playerCoordinateY == immortalY) { cout << "\nYou have selected the immortal peg!" << endl; cout << "This peg can jump over others, but if jumped over, will "; cout << "not be removed from the board" << endl; } { cout << "In which direction: N, E, S or W?" << endl; cin >> directionToMove; cout << endl; if (directionToMove == 'n' || directionToMove == 'N' || directionToMove == 'e' || directionToMove == 'E' || directionToMove == 's' || directionToMove == 'S' || directionToMove == 'w' || directionToMove == 'W') { lastMoveX = playerCoordinateX; lastMoveY = playerCoordinateY; } while ( directionToMove != 'n' && directionToMove != 'N' && directionToMove != 'e' && directionToMove != 'E' && directionToMove != 's' && directionToMove != 'S' && directionToMove != 'w' && directionToMove != 'W') { cout << "Please enter a valid direction: "; cin >> directionToMove; cout << "\n"; if (directionToMove == 'n' || directionToMove == 'N' || directionToMove == 'e' || directionToMove == 'E' || directionToMove == 's' || directionToMove == 'S' || directionToMove == 'w' || directionToMove == 'W') { lastMoveX = playerCoordinateX; lastMoveY = playerCoordinateY; break; } } cout << "So, you want peg " << lastMoveX << "," << lastMoveY; cout << " to move "; if (directionToMove == 'n' || directionToMove == 'N') { cout << "up?" << endl; } else if (directionToMove == 'e' || directionToMove == 'E') { cout << "right?" << endl; } else if (directionToMove == 'w' || directionToMove == 'W') { cout << "left?" << endl; } else if (directionToMove == 's' || directionToMove == 'S') { cout << "down?" << endl; } cout << "If so, press 'Y' or press 'Q' to choose again:" << endl; cin >> inputKey; cout << "\n" << endl; if (inputKey == 'y' || inputKey == 'Y') { makeAMove = false; } else if (inputKey == 'q' || inputKey == 'Q' || inputKey == 'n' || inputKey == 'N') { makeAMove = false; makeAMove = true; ShowGrid(Board, pegSpace, pegsRemaining, highscore); } else { cout << "Please enter a valid key: "; cin >> inputKey; if (inputKey == 'y' || inputKey == 'Y') { makeAMove = false; } else if (inputKey == 'q' || inputKey == 'Q') { makeAMove = false; makeAMove = true; } } } while (makeAMove == false) { CalculateMoves(playerCoordinateX, newSpaceX, directionToMove, Board, playerCoordinateY, newSpaceY, immortalX, immortalY); MoveValidation(Board, playerCoordinateX, playerCoordinateY, newSpaceX, newSpaceY, makeAMove, validMove, lastMoveX, lastMoveY); while (validMove == true) { UpdateMoves(Board, playerCoordinateX, playerCoordinateY, newSpaceX, newSpaceY, lastMoveX, lastMoveY, validMove, immortalX, immortalY); pegsRemaining--; moveCounter++; validMove = false; } ShowGrid(Board, pegSpace, pegsRemaining, highscore); makeAMove = true; } } } } void ShowMenu(bool& gameActive, bool& startNewGame, bool& makeAMove, char Board[NUMROWS][NUMCOLUMNS], char pegSpace, int& currentScore, int& highscore, int pegsRemaining, bool validMove, int playerCoordinateX, int playerCoordinateY, int lastMoveX, int lastMoveY, int newSpaceX, int newSpaceY, char inputKey, char directionToMove, int& moveCounter, int& immortalX, int& immortalY) { int menuInput = '\0'; cout << "\n------- MENU -------\n" << endl; cout << "1) Play Game" << endl; cout << "2) Exit Game" << endl; cout << "Option: "; cin >> menuInput; if (!cin >> menuInput) { cin.clear(); cin.ignore(999, '\n'); cout << "Please enter a valid menu option: " << endl; cin >> menuInput; } switch (menuInput) { case 1: gameActive = true; startNewGame = true; makeAMove = true; PlayTheGame(Board, pegSpace, startNewGame, pegsRemaining, validMove, gameActive, playerCoordinateX, playerCoordinateY, lastMoveX, lastMoveY, makeAMove, newSpaceX, newSpaceY, inputKey, directionToMove, currentScore, highscore, moveCounter, immortalX, immortalY); break; case 2: cout << "2) Exit Game" << endl; exit(0); break; default: cout << "Please enter a valid menu input!" << endl; } } int main() { srand((unsigned)time(NULL)); bool gameActive = false; bool makeAMove = false; bool validMove = true; bool startNewGame = true; char Board[NUMROWS][NUMCOLUMNS]; char pegSpace = ' '; char directionToMove = '\0'; char inputKey = '\0'; int pegsRemaining = 24; int playerCoordinateX = '\0'; int newSpaceX = '\0'; int lastMoveX = '\0'; int playerCoordinateY = '\0'; int newSpaceY = '\0'; int lastMoveY = '\0'; int highscore = 0; int currentScore = 0; int immortalX = rand()% 5+1; int immortalY = rand()% 5+1; int moveCounter = 0; IntroductionToGame(gameActive, startNewGame, makeAMove); ShowMenu(gameActive, startNewGame, makeAMove, Board, pegSpace, currentScore, highscore, pegsRemaining, validMove, playerCoordinateX, playerCoordinateY, lastMoveX, lastMoveY, newSpaceX, newSpaceY, inputKey, directionToMove, moveCounter, immortalX, immortalY); PlayTheGame(Board, pegSpace, startNewGame, pegsRemaining, validMove, gameActive, playerCoordinateX, playerCoordinateY, lastMoveX, lastMoveY, makeAMove, newSpaceX, newSpaceY, inputKey, directionToMove, currentScore, highscore, moveCounter, immortalX, immortalY); while (gameActive == false) { ShowMenu(gameActive, startNewGame, makeAMove, Board, pegSpace, currentScore, highscore, pegsRemaining, validMove, playerCoordinateX, playerCoordinateY, lastMoveX, lastMoveY, newSpaceX, newSpaceY, inputKey, directionToMove, moveCounter, immortalX, immortalY); } }