Code:
//include standard libraries
#include <iostream> //for output and input: getch(), cout <<, cin >>
#include <conio.h> //for kbhit
#include <iomanip> //for formatted output
#include <string> //for string
using namespace std;
//include our own libraries
#include "RandomUtils.h" //for Seed, Random,
#include "ConsoleUtils.h" //for Clrscr, Gotoxy, etc.
//---------------------------------------------------------------------------
//----- define constants
//---------------------------------------------------------------------------
//defining the size of the grid
#define SIZEY (11) //vertical dimension
#define SIZEX (19) //horizontal dimension
//defining symbols used for display of the grid & content
#define MOUSE ('@') //mouse
#define APPLE ('O') //apple
#define TUNNEL (' ') //tunnel
#define WALL ('#') //border
#define STORAGE ('+') //store area
//defining the command letters to move the mouse on the maze
#define UP (72) //up arrow
#define DOWN (80) //down arrow
#define RIGHT (77) //right arrow
#define LEFT (75) //left arrow
//defining the other command letters
#define QUIT ('Q') //to end the game
//---------------------------------------------------------------------------
//----- run game
//---------------------------------------------------------------------------
int main()
{
//function declarations (prototypes)
void initialiseGame( char g[][ SIZEX+1], char m[][ SIZEX+1], int mouse[]);
void paintGame( const char g[][ SIZEX+1], string& mess);
bool isArrowKey( int k);
void setKeyDirection( int k, int& dx, int& dy);
int getKeyPress();
void moveMouse( const char g[][ SIZEX+1], int m[], int dx, int dy, string& mess);
void updateGrid( char g[][ SIZEX+1], const char m[][ SIZEX+1], int mouse[]);
void endProgram();
//local variable declarations //arrays that store ...
char grid[ SIZEY+1][ SIZEX+1]; //grid for display
char maze[ SIZEY+1][ SIZEX+1]; //structure of the maze
int mouse[2]; //mouse's position ([y-coordinate][x-coordinate])
string message = "LET'S START..."; //current message to player
int key; //arrow or letter command
//action...
Clrscr();
Seed(); //seed the random number generator
initialiseGame( grid, maze, mouse); //initialise grid (incl. walls & mouse)
paintGame( grid, message); //display game info, modified grid & messages
key = getKeyPress(); //display menu & read in selected option
while (key != QUIT) //while user does not want to quit
{
if ( isArrowKey( key))
{
int dx( 0), dy( 0);
setKeyDirection( key, dx, dy); //find direction indicated by key
moveMouse( grid, mouse, dx, dy, message); //move mouse in that direction
updateGrid( grid, maze, mouse); //update grid information
}
else
message = "INVALID KEY!"; //set 'Invalid key' message
paintGame( grid, message); //display game info, modified grid & messages
key = getKeyPress(); //display menu & read in next option
}
endProgram(); //display final message
return 0;
} //end main
//---------------------------------------------------------------------------
//----- initialise game state
//---------------------------------------------------------------------------
void initialiseGame( char grid[][ SIZEX+1], char maze[][ SIZEX+1], int mouse[])
{ //initialise grid & place mouse in middle
void setInitialMazeStructure( char g[][ SIZEX+1]);
void setInitialMouseCoordinates( int mouse[]);
void updateGrid( char g[][ SIZEX+1], const char m[][ SIZEX+1], int mouse[]);
setInitialMazeStructure( maze); //initialise maze
setInitialMouseCoordinates( mouse); //initialise mouse's position
updateGrid( grid, maze, mouse); //prepare grid
} //end of initialiseGrid
void setInitialMazeStructure( char maze[][ SIZEX+1])
{ //set the position of the walls in the maze
//initialise maze configuration
char initialMaze[ SIZEY+1][ SIZEX+1] //local array to store the maze structure
= {{'X', 'X', 'X', 'X', 'X', 'X', 'X', 'X', 'X', 'X', 'X', 'X', 'X', 'X', 'X', 'X', 'X', 'X', 'X', 'X'},
{'X', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#'},
{'X', '#', '#', '#', '#', '#', ' ', ' ', ' ', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#'},
{'X', '#', '#', '#', '#', '#', 'O', ' ', ' ', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#'},
{'X', '#', '#', '#', '#', '#', ' ', ' ', 'O', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#'},
{'X', '#', '#', '#', ' ', ' ', 'O', ' ', 'O', ' ', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#'},
{'X', '#', '#', '#', ' ', '#', ' ', '#', '#', ' ', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#'},
{'X', '#', ' ', ' ', ' ', '#', ' ', '#', '#', ' ', '#', '#', '#', '#', '#', ' ', ' ', '+', '+', '#'},
{'X', '#', ' ', 'O', ' ', ' ', 'O', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', '+', '+', '#'},
{'X', '#', '#', '#', '#', '#', ' ', '#', '#', '#', ' ', '#', ' ', '#', '#', ' ', ' ', '+', '+', '#'},
{'X', '#', '#', '#', '#', '#', ' ', ' ', ' ', ' ', ' ', '#', '#', '#', '#', '#', '#', '#', '#', '#'},
{'X', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#'}};
// with '#' for wall, ' ' for tunnel and 'X' for unused part of array
//copy into maze structure
for ( int row( 1); row <= SIZEY; ++row) //for each row (vertically)
for ( int col( 1); col <= SIZEX; ++col) //for each column (horizontally)
maze[row][col] = initialMaze[row][col];
} //end of setMazeStructure
void setInitialMouseCoordinates( int mouse[])
{ //calculate mouse's coordinates at beginning of game
mouse[0] = 9; //y-coordinate: vertically
mouse [1] = 15; //x-coordinate: horizontally
} //end of setInitialMouseCoordinates
//---------------------------------------------------------------------------
//----- update grid state
//---------------------------------------------------------------------------
void updateGrid( char grid[][ SIZEX+1], const char maze[][ SIZEX+1], int mouse[])
{ //update grid configuration after each move
void setMaze( char g[][ SIZEX+1], const char m[][ SIZEX+1]);
void placeMouse( char g[][ SIZEX+1], int mouse[]);
setMaze( grid, maze); //reset the empty maze configuration into grid
placeMouse( grid, mouse); //set mouse in grid
} //end of updateGrid
void setMaze( char grid[][ SIZEX+1], const char maze[][ SIZEX+1])
{ //reset the empty/fixed maze configuration into grid
for ( int row( 1); row <= SIZEY; ++row) //for each row (vertically)
for ( int col( 1); col <= SIZEX; ++col) //for each column (horizontally)
grid[row][col] = maze[row][col];
} //end of setFrame
void placeMouse( char g[][ SIZEX+1], int m[])
{ //place mouse at its new position in grid
g[m[0]][m[1]] = MOUSE;
} //end of placeMouse
//---------------------------------------------------------------------------
//----- move the mouse
//---------------------------------------------------------------------------
void moveMouse( const char g[][ SIZEX+1], int m[], int dx, int dy, string& mess)
{ //move mouse in required direction
//check new target position in grid & update mouse coordinates if move is possible
switch( g[m[0]+dy][m[1]+dx])
{ //...depending on what's on the target position in grid...
case TUNNEL: //can move
m[0] += dy; //go in that Y direction
m[1] += dx; //go in that X direction
break;
case WALL: //hit a wall & stay there
cout << '\a'; //beep the alarm
mess = "CANNOT GO THERE!";
break;
case STORAGE: //can move and store
m[0] += dy; //go in that Y direction
m[1] += dx; //go in that X direction
break;
case APPLE:
m[0] += dy; //go in that Y direction
m[1] += dx; //go in that X direction
break;
}
} //end of moveMouse
//---------------------------------------------------------------------------
//----- process key
//---------------------------------------------------------------------------
void setKeyDirection( int key, int& dx, int& dy)
{ //
switch( key) //...depending on the selected key...
{
case LEFT: //when LEFT arrow pressed...
dx = -1; //decrease the X coordinate
dy = 0;
break;
case RIGHT: //when RIGHT arrow pressed...
dx = +1; //increase the X coordinate
dy = 0;
break;
case UP: //when UP arrow pressed...
dx = 0;
dy = -1; //decrease the Y coordinate
break;
case DOWN: //when DOWN arrow pressed...
dx = 0;
dy = +1; //increase the Y coordinate
break;
}
} //end of setKeyDirection
int getKeyPress()
{ //get key or command selected by user
int keyPressed( getch()); //read in the selected arrow key or command letter
while ( keyPressed == 224) //ignore symbol following cursor key
keyPressed = getch();
keyPressed = toupper( keyPressed); //put it in uppercase
return( keyPressed);
} //end of getKeyPress
bool isArrowKey( int key)
{ //check if the key pressed is an arrow key (also accept 'K', 'M', 'H' and 'P')
return ((key == LEFT) || (key == RIGHT) || (key == UP) || ( key == DOWN));
}
//---------------------------------------------------------------------------
//----- display info on screen
//---------------------------------------------------------------------------
void paintGame( const char gd[][ SIZEX+1], string& mess)
{ //display game title, messages, maze, mouse & apples on screen
void paintGrid( const char g[][ SIZEX+1]);
Clrscr();
//display game title
SelectTextColour( clYellow);
Gotoxy(0, 0);
cout << "___MOUSE AND APPLES GAME___\n" << endl;
SelectBackColour( clWhite);
SelectTextColour( clRed);
Gotoxy(40, 0);
cout << "Anna";
// display grid contents
paintGrid( gd);
//display menu options available
SelectBackColour( clRed);
SelectTextColour( clYellow);
Gotoxy(40, 3);
cout << "TO MOVE USE KEYBOARD ARROWS ";
Gotoxy(40, 4);
cout << "TO QUIT ENTER 'Q' ";
//print auxiliary messages if any
SelectBackColour( clBlack);
SelectTextColour( clWhite);
Gotoxy(40, 8);
cout << mess; //display current message
mess = ""; //reset message to blank
} //end of paintGame
void paintGrid( const char g[][ SIZEX+1])
{ //display grid content on screen
SelectBackColour( clBlack);
SelectTextColour( clWhite);
Gotoxy(0, 2);
for ( int row( 1); row <= SIZEY; ++row) //for each row (vertically)
{
for ( int col( 1); col <= SIZEX; ++col) //for each column (horizontally)
{
cout << g[row][col]; //output cell content
} //end of col-loop
cout << '\n';
} //end of row-loop
} //end of paintGrid
void endProgram()
{
SelectBackColour( clRed);
SelectTextColour( clYellow);
Gotoxy(40, 8);
//hold output screen until a keyboard key is hit
cout << "PRESS ANY KEY TO END PROGRAM!";
while (!_kbhit()) /* do nothing */;
}