Sliding Tile Puzzle Simulator (Procedural Paradigm) C++ Introduction In this ass
ID: 3673941 • Letter: S
Question
Sliding Tile Puzzle Simulator (Procedural Paradigm)
C++
Introduction
In this assignment, you will be writing a C++ command-line program that simulates a 3x3 sliding puzzle game. In a sliding puzzle game, 8 tiles with the numerals 1-8 are placed onto a 3x3 square grid. One of the positions is left open for tiles coming from the top, bottom, left, or right (depending on the puzzle configuration). The goal of the game is to slide the tiles around so they appear in order on the puzzle board. When writing this program, you should adhere to the procedural programming paradigm.
Assignment
When completing this program, it would be useful to write a number of functions that perform elementary operations on the board. Once these functions have been written and tested, you can proceed with writing driver control logic that takes the user's input and frames an appropriate call to a function to handle the move.
We should conceptualize the board as a 3x3 two-dimensional array.
int puzzleBoard[3][3];
By writing the following functions, you can create a framework for making moves on the board.
void initializeBoard(int[3][3]);
Description: This function takes the board as a single 3x3 integer array. This function should fill the board with values that represent the tiles on the sliding puzzle. Initially the puzzle should look like this:
1 2 3
4 5 6
7 8 * <=== the * represents the blank space on the board
void printBoard(int[3][3]);
Description: This function takes the board as its only argument. It displays the board on the screen. Initially, I suggest you write this function to give a quick and dirty display so you can move onto coding the core logic of the program. Later, you can come back and upgrade the function to display grid-work and color (see the hints section to learn how to change the console display color).
bool isBoardSolved(int[3][3]);
Description: This function takes the board and determines if it is in the solved state. The solved state looks exactly like the initialization state where the numbers read in order and the empty tile is in the lower-right corner. After the function determines if the board is in the solved state, a boolean value reflecting this should be returned. Later, your driver code will use this value to determine when the puzzle has been solved. You may want to upgrade your return value to an integer if you decide to have additional reporting codes returned from this function. For example, it would help during design to have a return value that indicates if the board has reached a corrupted state (i.e. there are two 5s on the board, an extra empty space was created, etc...)
void slideTile(int[3][3], int);
Description: This function takes two arguments and will attempt to slide a single tile in a single direction on the board. The first argument is the board. This is needed for obvious reasons. The second argument is a "direction code". I suggest coming up with a number scheme to label to four different directions in which the player can move (UP, DOWN, LEFT, RIGHT). The function will take the move direction and first determine if a tile can be slid in that direction. If the move isn't possible at this time, the board should remain unchanged. However, if the move is possible, you should exchange the values on the faces of the two involved tiles to reflect the move.
void scrambleBoard(int[3][3]);
Description: This function takes a board and makes a series of random moves. Write this function after you have written slideTile() and just have it use a random number generator to send a few thousand random moves at the board from the initialized state.
Hints
The following function demonstrates color printing. You can compile and play with the code to learn the basics of color. Keep in mind that you must include the Windows API in order for this to work.
#include <windows.h>
void printTheRainbow();
void printTheRainbow() {
int currentColor = 7;
// get the handle for the console
HANDLE hConsole;
hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
// exhaustively print the colors
cout << left;
for(currentColor = 0; currentColor <= 255; currentColor++) {
SetConsoleTextAttribute(hConsole, currentColor);
cout << setw(5) << currentColor
<< "Look at the pretty COLORS!" << endl;
}
}
P01 - Screen Shot 1
P01 - Screen Shot 2
P01 - Screen Shot 3
P01 - Screen Shot 4
P01 - Screen Shot 5
P01 - Screen Shot 6
P01 - Screen Shot 7
Explanation / Answer
main.cpp
# include "includes.h"
# include "CSlidingPuzzle.h"
using namespace std;
int
main()
{
CSlidingPuzzle CMyPuzzle;
while(CMyPuzzle.SetEvent());
return 0;
}
CSlidingPuzzle.h
# include <iostream>
# include <string>
# include <conio.h>
# include <ctype.h>
# include <Windows.h>
# include <stdlib.h>
# include <time.h>
using namespace std;
# ifndef __CSLIDING_PUZZLE__
class //-----------------------------------------------------------------------
CSlidingPuzzle
{
private:
// ints
int blank_y;
int blank_x;
int lastEvent;
// structs
struct
ArrowKeys
{
int SlideUp, SlideDown, SlideRight, SlideLeft;
}
BoardEvent;
// enums
enum eventCodes {QUIT = 'q', SCRAMBLE = 32, RESET = 'r', CALIBRATE = 'c'};
enum keyPress {W = 'w', S = 's', D = 'd', A = 'a'};
enum directions {UP, DOWN, LEFT, RIGHT};
enum Colors {WHITE = 15, GREEN = 10, RED = 12, YELLOW = 14} oColor;
enum boardStuff {ROWS = 3, COLS = 3, BLANK = 0};
// private methods
int theBoard[ROWS][COLS];
void InitializeBoard();
bool IsBoardSolved();
void GetBlankLocation();
bool IsScrambled();
void ScrambleBoard();
bool SlideTile(int);
bool CalibrateBoard(); // credit goes to Miles for the calibration idea
int GetKeyStroke();
public:
// public methods
CSlidingPuzzle();
void PrintBoard();
bool SetEvent();
}; // end CSlidingPuzzle definition
# endif
CSlidingPuzzle.cpp
# include "CSlidingPuzzle.h"
// CTOR // --------------------------------------------------------------------
CSlidingPuzzle::CSlidingPuzzle()
{
InitializeBoard();
oColor = WHITE;
srand(unsigned int (time(NULL)));
CalibrateBoard();
system("cls");
} // end CSlidingPuzzle::CSlidingPuzzle()
void // -----------------------------------------------------------------------
CSlidingPuzzle::InitializeBoard()
{
for(int i = 0; i < ROWS; ++i)
{
for(int j = 0; j < COLS; ++j)
{ // populate the board with numbers 1 to 9 then 0
theBoard[i][j] = (3 * i + j + 1 ) % 9;
}
}
} // end CSlidingPuzzle::InitializeBoard()
bool // -----------------------------------------------------------------------
CSlidingPuzzle::IsBoardSolved()
{
int solvedElements = 0;
for(int i = 0; i < ROWS; ++i)
{
for(int j = 0; j < COLS; ++j)
{ // tally correctly positioned elements
if(theBoard[i][j] == (3 * i + j + 1 ) % 9)
++solvedElements;
}
}
// compare tally to number of elements
if(solvedElements == ROWS * COLS)
return true;
else
return false;
} // end CSlidingPuzzle::IsBoardSolved()
void // -----------------------------------------------------------------------
CSlidingPuzzle::GetBlankLocation()
{
for(int i = 0; i < COLS; ++i)
{
for(int j = 0; j < ROWS; ++j)
{
if(theBoard[i][j] == BLANK)
{
blank_x = j;
blank_y = i;
break;
}
}
}
} // end CSlidingPuzzle::GetBlankLocation()
bool // -----------------------------------------------------------------------
CSlidingPuzzle::IsScrambled()
{
for(int i = 0; i < ROWS; ++i)
{
for(int j = 0; j < COLS; ++j)
{
// if a piece is in correct position, then board not scrambled
if(theBoard[i][j] == (3 * i + j + 1 ) % 9)
return false;
}
}
// if we've made it this far without returning, then board is scrambled
return true;
}
void // -----------------------------------------------------------------------
CSlidingPuzzle::ScrambleBoard()
{
InitializeBoard();
do // a series of random moves to create solvable and scrambled board
{
SlideTile(rand() % 4);
}
while( !(IsScrambled()) );
} // end ScrambleBoard()
bool // -----------------------------------------------------------------------
CSlidingPuzzle::SlideTile(int direction)
{
GetBlankLocation();
// slide tiles if movement key is pressed
if(direction == UP && blank_y < ROWS - 1)
{
theBoard[blank_y][blank_x] = theBoard[blank_y + 1][blank_x];
theBoard[blank_y + 1][blank_x] = BLANK;
}
else if(direction == DOWN && blank_y > 0)
{
theBoard[blank_y][blank_x] = theBoard[blank_y - 1][blank_x];
theBoard[blank_y - 1][blank_x] = BLANK;
}
else if(direction == RIGHT && blank_x > 0)
{
theBoard[blank_y][blank_x] = theBoard[blank_y][blank_x - 1];
theBoard[blank_y][blank_x - 1] = BLANK;
}
else if(direction == LEFT && blank_x < COLS - 1)
{
theBoard[blank_y][blank_x] = theBoard[blank_y][blank_x + 1];
theBoard[blank_y][blank_x + 1] = BLANK;
}
else
{
return false;
}
return true;
} // end SlideTile()
bool // -----------------------------------------------------------------------
CSlidingPuzzle::SetEvent()
{
PrintBoard();
int keyStroke = GetKeyStroke();
cout << keyStroke << endl;
system("cls");
if(keyStroke == BoardEvent.SlideUp || keyStroke == W)
{ // take appropriate action
SlideTile(UP);
}
else if(keyStroke == BoardEvent.SlideDown || keyStroke == S)
{ // take appropriate action
SlideTile(DOWN);
}
else if(keyStroke == BoardEvent.SlideRight || keyStroke == D)
{ // take appropriate action
SlideTile(RIGHT);
}
else if(keyStroke == BoardEvent.SlideLeft || keyStroke == A)
{ // take appropriate action
SlideTile(LEFT);
}
else if(keyStroke == QUIT)
{ // take appropriate action
return false;
}
else if(keyStroke == SCRAMBLE)
{ // take appropriate action
ScrambleBoard();
}
else if(keyStroke == RESET)
{ // take appropriate action
InitializeBoard();
}
else if(keyStroke == CALIBRATE)
{ // credit goes to Miles for calibration idea
CalibrateBoard();
}
return true;
}
void // -----------------------------------------------------------------------
CSlidingPuzzle::PrintBoard()
{
bool boardSolved = IsBoardSolved();
int puzzleColor;
// used to create dynamic UI)
string UIStrings[ROWS] = {" | | Up: W ^",
" | | Down: S |",
" | | Left: A A<--->D"};
string solutionMessage[2] = {" Not ", " "};
// get the handle for the console
HANDLE hConsole;
hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
// set the puzzle color based on board state
if(boardSolved)
puzzleColor = GREEN;
else
puzzleColor = RED;
SetConsoleTextAttribute(hConsole, WHITE);
// begin to print user interface
cout << "========================================" << endl
<< " Realtime Sliding Puzzle " << endl
<< "========================================" << endl
<< " Puzzle | Direction Keys:" << endl
<< "+-------+ | W" << endl;
// print sliding puzzle pieces
for(int i = 0; i < ROWS; ++i)
{
cout << "|";
for(int j = 0; j < COLS; ++j)
{
if(theBoard[i][j] == 0)
{
cout << " ";
}
else
{ // if the board is solved, but position correct, then...
if(!(boardSolved) && theBoard[i][j] == (3 * i + j + 1 ) % 9)
{ // display pieces in yellow
SetConsoleTextAttribute(hConsole, YELLOW);
}
else
{ // otherwise just use the predetermined puzzle color
SetConsoleTextAttribute(hConsole, puzzleColor);
}
cout << " " << theBoard[i][j];
SetConsoleTextAttribute(hConsole, WHITE);
}
}
cout << UIStrings[i] << endl;
}
// continue to print user interface
cout << "+-------+ | Right: D |" << endl
<< solutionMessage[boardSolved]
<< " | v" << endl
<< " Solved. | Quit: Q S" << endl;
cout << " | Calibrate: C" << endl
<< " | Reset: R" << endl
<< " | Scramble: spacebar" << endl
<< "----------+-----------------------------" << endl;
cout << "To slide the puzzle pieces, press a" << endl
<< " direction key from the list above." << endl
<< "To scramble the tiles, press the space" << endl
<< " bar. Press Q to quit." << endl;
// end UI code
} // end PrintBoard()
bool // -----------------------------------------------------------------------
CSlidingPuzzle::CalibrateBoard()
{ // credit goes to Miles for the idea of calibration screen
cout << "Please press your up arrow key. ";
BoardEvent.SlideUp = GetKeyStroke();
cout << "Please press your down arrow key. ";
BoardEvent.SlideDown = GetKeyStroke();
cout << "Please press your right arrow key. ";
BoardEvent.SlideRight = GetKeyStroke();
cout << "Please press your left arrow key. ";
BoardEvent.SlideLeft = GetKeyStroke();
system("cls");
return 0;
}
int // ------------------------------------------------------------------------
CSlidingPuzzle::GetKeyStroke()
{
int keyPress;
keyPress = getch();
if(!(keyPress) || keyPress == 224)
keyPress = getch();
return tolower(keyPress);
} // end GetKeyStroke()
include.h
# pragma once
# include <iostream>
# include <string>
# include <conio.h>
# include <ctype.h>
# include <Windows.h>
# include <stdlib.h>
# include <time.h>
Related Questions
drjack9650@gmail.com
Navigate
Integrity-first tutoring: explanations and feedback only — we do not complete graded work. Learn more.