Question

In: Computer Science

Given the header file (grid.h) and the source file,(grid.cpp) create the file trap.cpp. Here are the...

Given the header file (grid.h) and the source file,(grid.cpp) create the file trap.cpp. Here are the requirements for trap.cpp:

Write a main program in a file called trap.cpp that solves the following scenario, using your Grid class:

Giant Mole People have risen from their underground lairs and are taking over the world. You have been taken prisoner and placed in an underground jail cell. Since the Mole People are blind and don't know how to build doors, your cell has one open exit (no door). Since you are deep underground, it is completely dark and you cannot see. Your task is to escape your prison to join the human resistance!

Your program should ask the user to input the number of rows, then columns, for the grid. (Note that this is the ONLY keyboard input for this program). Create a grid with the specified number of rows and columns, using the constructor with two parameters -- (this is the one that should automatically create a fenced-in grid containing one exit and a randomly placed mover). Display the initial grid. Since the placement of the exit and the mover is random, execution of this program will look a little different every time. Your task is to escape the trap! You will need to create an algorithm that will instruct the mover to find its way to the exit. (Hint: Think about how to use the Predicate functions before you move). Upon reaching the exit, you should print a message of success, like "We escaped!", and then output the final position of the mover. Keep the path toggled ON. You only need to display the initial setup grid and the final grid for this program.

Here is the header file grid.h:

#include <iostream>
using namespace std;

class Grid
{
public:
static const int NORTH = 0;
static const int WEST = 1;
static const int SOUTH = 2;
static const int EAST = 3;

Grid(); // build 1 x 1 grid with mover in only
// square, facing east

Grid(int r, int c); // build grid with r rows, c cols, blocks around edge with random exit
// and random mover position and direction

Grid(int r, int c, int mr, int mc, int d); // build empty grid with r rows, c cols, and mover at row mr, col mc, and facing direction d

bool Move(int s); // move forward s spaces, if possible

void TogglePath(); // toggle whether or not moved path is shown

void TurnLeft(); // turn the mover to the left

void PutDown(); // put down an item at the mover's position

bool PutDown(int r, int c); // put down an item at (r,c), if possible

bool PickUp(); // pick up item at current position

bool PlaceBlock(int r, int c); // put a block at (r,c), if possible

void Grow(int gr, int gc); // grow the grid by gr rows, gc columns

void Display() const; // display the grid on screen. Accessors

bool FrontIsClear() const; // check to see if space in front of mover is clear

bool RightIsClear() const; // check to see if space to right of mover is clear

int GetRow() const; // return row of the mover

int GetCol() const; // return column of the mover

int GetNumRows() const; // return number of rows in the grid

int GetNumCols() const; // return number of columns in the grid

private:

char** grid;

int mover_r, mover_c, mover_d, maxRow, maxCol;

bool path;
  
};

Task

You will write a class called Grid, and test it with a couple of programs. A Grid object will be made up of a grid of positions, numbered with rows and columns. Row and column numbering start at 0, at the top left corner of the grid. A grid object also has a "mover", which can move around to different locations on the grid. Obstacles (which block the mover) and other objects (that can be placed or picked up) are also available. Here is a sample picture of a Grid object in its display format:

0 . . .    This is a Grid object with 4 rows and 4 columns (numbered 0 - 3). 
. . > .    The mover '>' is at row 1, column 2, facing east. 
. . . .    The obstacle '#' is at row 3, column 1 
. # . .    The other item '0' is at row 0, column 0

The @ character indicates that the mover and an item (0) currently occupy the same position on the grid.

Program Details and Requirements

1) Grid class

Download this starter file: grid_starter.h and rename it as grid.h. Your member function prototypes are already given in this file. You will need to add appropriate member data. You will also need to define each of the member functions in the file grid.cpp. You may add whatever member data you need, but you must store the grid itself as a two-dimensional array. Maximum grid size will be 40 rows and 40 columns. (Note that this means dynamic allocation will NOT be needed for this assignment).

Meaning of Grid symbols

.       empty spot on the grid
0       an item that can be placed, or picked up
#       a block (an obstacle).  Mover cannot move through it
<    mover facing WEST
>    mover facing EAST
^       mover facing NORTH
v       mover facing SOUTH
@       mover occupying same place as item (0)

A printed space ' ' in a grid position represents a spot that the mover has already moved through when the path display is toggled on

public Member function descriptions

  • Grid()
    The default constructor should create a 1 x 1 grid, with the mover in the only position, facing EAST
  • Grid(int r, int c)
    The two-parameter constructor will accept two integers, representing rows and columns. Create a grid with r rows and c columns. If either of these is less than 3, default it to 3. If either is greater than the max number of rows or columns, default it to the max number. This grid should be built such that blocks are placed all around the edge, with one random exit (i.e. with no block). The mover should be in a random position and facing a random direction within the grid. When setting up the randomness, make sure each possibility has an equal chance of happening. For example, the random direction has 4 possibilities, so each one should happen about 25% of the time. For the random exit, it will be sufficient to pick a random wall first, then pick a random location on that wall (note that the exit cannot be in a corner spot).

    You'll need the library cstdlib for the srand and rand functions. While it's not normally the best place to do it, you can go ahead and seed the random number generator here in the constructor in some appropriate way so that it's different for seperate program runs.

    If you need a refresher on pseudo-random number generation, see this notes set from COP 3014: http://www.cs.fsu.edu/~myers/c++/notes/rand.html

  • Grid(int r, int c, int mr, int mc, int d)
    This constructor (5 parameters) takes in the following information, in this order:
    • number of starting rows for the grid (if out of range, adjust like in the 2-parameter constructor, although minimum in this case is 1)
    • number of starting columns for the grid (if out of range, adjust like in the 2-parameter constructor, although minimum in this case is 1)
    • The starting row position of the mover (if out of range, adjust to the first or last row, whichever is closer)
    • The starting column position of the mover (if out of range, adjust to the first or last column, whichever is closer)
    • The starting direction of the mover
    Build the starting grid based on the incoming parameters and their descriptions above. Other than the mover, this grid starts out empty.
  • Display()
    This function should print out "The Grid:" on one line, then output the full grid below it -- place spaces between columns so that outputs line up more evenly. End with a newline (so that any next output will be on a separate line). If the path setting is toggled to ON, then any position the mover has already moved through should show up blank. If the path setting is toggled to OFF, then all empty grid spaces show up as dots '.'
    Examples of the full Display format can be seen in the sample run for test1.cpp linked below under "Test Programs".
    For description of the path setting, see the funtion TogglePath() below
  • TogglePath()
    This function, when called, should reverse whatever the current "path" setting is. The path setting can be either ON or OFF. If it's ON, it means that displays of the grid should indicate where the mover has been by showing those positions as spaces. If the path is OFF, then all blank spots on the grid show as the dot character '.' no matter what. The initial default setting for any grid should be ON.
  • Simple Accessors (Getters)
    These are "getter" functions that should return the requested information:
    • GetRow() should return the current row of the mover
    • GetCol() should return the current column of the mover
    • GetNumRows() should return the number of rows in the grid
    • GetNumCols() should return the number of columns in the grid
  • Predicate functions
    These two functions return boolean values (true or false) to answer simple questions:
    • FrontIsClear() should return an indication of whether the space in front of the mover is clear (i.e. not blocked and on the grid)
    • RightIsClear() should return an indication of whether the space to the right of the mover is clear (i.e. not blocked and on the grid)
  • Placing blocks and/or items
    These functions involve placing things on the grid:
    • PutDown(): This function should place an "item" at the current location of the mover. If the location already contains an item, then nothing changes (i.e. the item is still there)
    • PutDown(int r, int c): This function should place an "item" at position (r,c) where r is the row and c is the column. This function should return true for a successful placement, and false for failure. For successful placement, the position has to exist within the grid boundaries and not already contain a block or another item. (It can, however, be placed in a spot where only the mover is located).
    • PlaceBlock(int r, int c): This function should place a "block" at position (r,c) where r is the row and c is the column. This function should return true for a successful placement, and false for failure. For successful placement, the position has to exist within the grid boundaries and be an empty space (i.e. not containing a block, an item, or the mover)
  • PickUp()
    This function should pick up the "item" at the mover's position. This means removing it from the grid. This function should return true for a successful pick-up (i.e. the item is at the mover's current position), and false for failure (there is no item there).
  • Move(int s)
    This function should move the mover forward, in the current direction, for s spaces. Return true for success, false for failure. A successful move must be a positive number of spaces, must remain on the grid, and must not attempt to move through a "block". On a failed move, the mover should remain in the original position. (i.e. the move must be all or nothing, based on the number of spaces given by the parameter).
  • TurnLeft()
    This function will cause the mover to turn 90 degrees to the left, from whichever way it is currently facing. (example: if the mover is facing NORTH, then TurnLeft() will make it face WEST).
  • void Grow(int gr, int gc)
    This function should increase the size of the grid by gr rows and gc columns. If the increase causes either the number of rows or columns to exceed the maximum, simply set that (rows or columns) to the maximum. The grow should not change the current position of any item, mover, or block on the grid.
  • Note that the list of member functions given in the provided starter file (and described above) constitute the entire public interface of the class. These should be the ONLY public member functions in your class. If you create any extra member functions as helpers, put them in the private section of the class

Solutions

Expert Solution

Code:

#include <iostream>
#include <cstring>
#include <iomanip>
#include <cstdlib>
#include <ctime>
#include "grid.h" 

Grid::Grid()                    // check task: build the grid with mover in only square, facing east
{
   grid = new char* [1];    // may I need to remove * in order to make this less painfull 
   grid[0] = new char [1];
   mover_r = 0;
   mover_c = 0;
   mover_d = EAST;
   path = true;
}

Grid::Grid(int r, int c) // build grid with r rows, c cols,  blocks around edge with random exit
// and random mover position and direction
{
   if(r < 4 || c < 4)
   {
      maxRow = 3;
      maxCol = 3;
   }
   else if(r > 40 || c > 40)
   {
      maxRow = 40;
      maxCol = 40;
   }
   else
   {
      maxRow = r;
      maxCol = c;
   }
   grid = new char* [maxRow];
   for(int i = 0; i < maxRow; i++)
      grid[i] = new char [maxCol];
   
   //populates grid with '#' and '.'
   for(int i = 0; i <  maxRow; i++)
   {
      for(int j = 0; j < maxCol; j++)
      {
         if(i == 0 || i == maxRow-1)
            grid[i][j] = '#';
         else if(j == 0 || j == maxCol-1)
            grid[i][j] = '#';
         else
            grid[i][j] = '.';
      }
   }
   
   path = true;
   srand(time(0));

   int r_n = rand() % maxRow,
   r_exit = rand() % maxRow,
   c_n = rand() % maxCol,
   c_exit = rand() % maxCol,
   direction = rand() % 4,
   edge = rand() % 4;
   
   //exit
   switch(edge)
   {
      case NORTH:
         grid[0][c_exit] = ' ';
         break;
      case SOUTH:
         grid[maxRow-1][c_exit] = ' ';
         break;
      case WEST:
         grid[r_exit][0] = ' ';
         break;
      case EAST:
         grid[r_exit][maxCol-1] = ' ';
         break;
   }
   //mover placement
   mover_r = r_n;
   mover_c = c_n;
   mover_d = direction;
}                       

Grid::Grid(int r, int c, int mr, int mc, int d) //make empty grid with r rows, c cols, and mover, at row mr, col mc, and facing direction d
{
   if(r < 0 || c < 0)
   {
      maxRow = 1;
      maxCol = 1;
   }
   else if(r > 40 || c > 40)
   {
      maxRow = 40;
      maxCol = 40;
   }
   else
   {
      maxRow = r;    //inicializado correctamente
      maxCol = c;
   }
   
   grid = new char* [maxRow];
   for(int i = 0; i < maxRow; i++)
      grid[i] = new char [maxCol];

   path = true;
   
   //set up grid
   for(int i = 0; i < maxRow; i++)
      for(int j = 0; j < maxCol; j++)
         grid[i][j] = '.';
   
   if(mr > maxRow)
      mr = maxRow-1;
   else if(mr < 0)
      mr = 0;
   
   if(mc > maxCol)
      mc = maxCol-1;
   else if(mc < 0)
      mc = 0;
      
   mover_r = mr;
   mover_c = mc;
   mover_d = d;
}

bool Grid::Move(int s)  // move forward s spaces, if possible
{
   int temp;
   bool flag = false;
   
   switch(mover_d) {
      
      case NORTH:
         if(s > 0) {
            
            if(mover_r - s >= 0) {
               
               temp = mover_r;
               
               for(int i = 0; i < s; i++)
               {
                  if( FrontIsClear())
                  {
                     flag = true;
                     if(grid[mover_r][mover_c] != '0')
                        grid[mover_r][mover_c] = ' ';
                     mover_r--;
                     
                  } else    flag = false;
               }
               
               if(flag == false)  mover_r = temp;
               
               else return true;
            }
         }
         return false;
         break;
      case SOUTH:
        if(s > 0) {
           
            if(mover_r + s <= maxRow)
            {
               temp = mover_r;
               for(int i = 0; i < s; i++)
               {
                  if( FrontIsClear())  {
                     
                     flag = true;
                     if(grid[mover_r][mover_c] != '0')
                        grid[mover_r][mover_c] = ' ';
                     mover_r++; 
                     
                  } else flag = false;
               }
               
               if(flag == false) mover_r = temp;
               
               else  return true;
            }
         }
         return false;
         break;
      case EAST:
      if(s > 0)
         {
            if(mover_c + s <= maxCol)
            {
               temp = mover_c;
               for(int i = 0; i < s; i++)
               {
                  if( FrontIsClear())
                  {
                     flag = true;
                     if(grid[mover_r][mover_c] != '0')
                        grid[mover_r][mover_c] = ' ';
                     mover_c++;
                     
                  } else flag = false;
               }
               
               if(flag == false)
                  mover_c = temp;
                  
               else  return true;
            }
         }
         return false;
         break;
      case WEST:
      if(s > 0)
         {
            if(mover_c - s >= 0) {
               
               temp = mover_c;
              for(int i = 0; i < s; i++)
              {
                  if( FrontIsClear())
                  {
                     flag = true;
                     if(grid[mover_r][mover_c] != '0')
                        grid[mover_r][mover_c] = ' ';
                     mover_c--; 
                     
                  } else flag = false;
               }
               
               if(flag == false)
                  mover_c = temp;
                  
               else  return true;
            }
         }
         return false;
         break;
   }
} 
   
void Grid::TogglePath()         // toggle whether or not moved path is shown
{
   path = !path;
}
   
void Grid::TurnLeft()           // turn the mover to the left
{
   switch(mover_d)
   {
      case NORTH:
         mover_d = WEST;
         break;
      case WEST:
         mover_d = SOUTH;
         break;
      case SOUTH:
         mover_d = EAST;
         break;
      case EAST:
         mover_d = NORTH;
         break;
   }
}
   
void Grid::PutDown()            // put down an item at the mover's position
{
   grid[mover_r][mover_c] = '0';
}
   
bool Grid::PutDown(int r, int c)  // put down an item at (r,c), if possible
{
   if(r < maxRow && c < maxCol && grid[r][c] != '#')
   {
      grid[r][c] = '0';
      return true;
   }
   return false;
}

bool Grid::PickUp()             // pick up item at current position
{
   if(grid[mover_r][mover_c] == '0')
   {
      grid[mover_r][mover_c] = '.';
      return true;
   }else
      return false;
}
   
bool Grid::PlaceBlock(int r, int c)     // put a block at (r,c), if possible
{
   if(r < maxRow && r > 0 && c < maxCol && c > 0 && grid[r][c] != '#')
   {
      grid[r][c] = '#';
      return true;
   }
   return false;
}

void Grid::Grow(int gr, int gc) // grow the grid by gr maxRow, gc columns
{
   if(maxRow + gr <= 40)
        maxRow += gr;
    else 
        maxRow = 40;
        
    if(maxCol + gc <= 40)
        maxCol += gc;
    else 
        maxCol = 40;
        
    char **newGrid = new char * [maxRow];
    for(int i = 0; i < maxRow; i++)
        newGrid[i] = new char [maxCol];
        
    for(int i = 0; i < maxRow; i++)
        for(int j = 0; j < maxCol;j++)
            newGrid[i][j] = grid[i][j];
    
    for(int i = 0; i < maxRow; i++)
    {
        for(int j = 0; j < maxCol; j++)
            delete [] &grid[i][j];
            
        delete [] grid[i];
    }
    delete [] grid;
    
    grid = newGrid;
}

void Grid::Display() const      // display the grid on screen
{
   cout << "The Grid:\n";
   
   for(int i = 0; i < maxRow; i++)
   {
      for(int j = 0; j < maxCol; j++)
      {
         if(i == mover_r && j == mover_c)
         {
            if(grid[i][j] == '0')
               cout << '@';
            else
               switch(mover_d)
               {
                  case NORTH:
                     cout << '^';
                     break;
                  case WEST:
                     cout << '<';
                     break;
                  case SOUTH:
                     cout << 'v';
                     break;
                  case EAST:
                     cout << '>';
                     break;
               }
         }
         else if(grid[i][j] == ' ' && path == false)
               cout << '.';
         else if(path == true)
            cout << grid[i][j];
            
         cout << " ";
      }
      cout << endl;
   }
}

// Accessors
bool Grid::FrontIsClear() const // check to see if space in front of mover is clear
{
   switch(mover_d)
   {
      case NORTH:
         if(grid[mover_r-1][mover_c] != '#')
            return true;
         else
            return false;
         break;
      case WEST:
         if(grid[mover_r][mover_c-1] != '#')
            return true;
         else
            return false;
         break;
      case EAST:
         if(grid[mover_r][mover_c+1] != '#')
            return true;
         else
            return false;
         break;
      case SOUTH:
         if(grid[mover_r+1][mover_c] != '#')
            return true;
         else
            return false;
         break;
   }
}

bool Grid::RightIsClear() const // check to see if space to right of mover is clear
{
   switch(mover_d)
   {
      case NORTH:
         if(grid[mover_r][mover_c+1] != '#')
            return true;
         else
            return false;
         break;
      case WEST:
         if(grid[mover_r-1][mover_c] != '#')
            return true;
         else
            return false;
         break;
      case EAST:
         if(grid[mover_r+1][mover_c] != '#')
            return true;
         else
            return false;
         break;
      case SOUTH:
         if(grid[mover_r][mover_c-1] != '#')
            return true;
         else
            return false;
         break;
   }
}                               
                                
int Grid:: GetRow() const               // return row of the mover
{
   return mover_r;     
}
   
int Grid:: GetCol() const               // return column of the mover
{
   return mover_c;
}   
   
int Grid:: GetNumRows() const // return number of rows in the grid
{
   return maxRow;
}
   
int Grid:: GetNumCols() const   // return number of columns in the grid
{
   return maxCol;
}   

Screenshots:

-------------------------END---------------------

Please give a thumbs up(upvote) if you liked the answer.


Related Solutions

Using C++ Create the UML, the header, the cpp, and the test file for an ArtWork...
Using C++ Create the UML, the header, the cpp, and the test file for an ArtWork class. The features of an ArtWork are: Artist name (e.g. Vincent vanGogh or Stan Getz) Medium (e.g. oil painting or music composition) Name of piece (e.g. Starry Night or Late night blues) Year (e.g. 1837 or 1958)
The requirements for this program are as follows: Create a header file named “Employee.h”. Inside this...
The requirements for this program are as follows: Create a header file named “Employee.h”. Inside this header file, declare an Employee class with the following features: Private members a std::string for the employee’s first name a std::string for the employee’s last name an unsigned int for the employee’s identification number a std::string for the city in which the employee works Public members A constructor that takes no arguments A constructor that takes two arguments, representing: the employee’s first name the...
In a header file Record.h, create a Record structure that contains the following information: recordID, firstName,...
In a header file Record.h, create a Record structure that contains the following information: recordID, firstName, lastName, startYear. recordID is an integer. In testRecord, first create a record (record1) using “normal” pointers. Set the values to 1001, Fred, Flintstone, 1995 In testRecord, create a new record (record2) using a unique smart pointer. Set the values to 1002, Barney, Rubble, 2000 Create a function (or functions) that will print the records to any output stream. Since the print function does not...
Create a Namespaces.h header file containing a namespace declaration yourname. The declaration should include: a method...
Create a Namespaces.h header file containing a namespace declaration yourname. The declaration should include: a method with the signature void message (string, ostream &) that prints a string to the output stream. a method with the signature void message (double, ostream &) that prints a double to the output stream. Create a testNamespaces.cpp that uses the yourname namespace, and invokes the message() string method with a message of your choice and cout as input parameters, and invokes the message double...
Create a header file, iofunctions.h, containing the following function prototypes. (don't forget to follow the coding...
Create a header file, iofunctions.h, containing the following function prototypes. (don't forget to follow the coding style) int readfile( struct pokemon pokearray[ ], int* num, char filename[ ] ); int writefile( struct pokemon pokearray[ ], int num, char filename[ ] ); Then, create a source file, iofunctions.c, defining the functions above. Specifications The readfile function will read the data from a text file and store it in the array called by pokearray. It must not load the pokemons more than...
Using C++ In a separate header file: Create a new type called "Patient" - you must...
Using C++ In a separate header file: Create a new type called "Patient" - you must use a  class. Give your "Patient" type at least five (5) member elements of your choosing, and at least one member function. You should have member elements to hold patient name, and visitReason (which can change), and other items of your choosing. In your cpp file: Create at least one instance of Patient type (example: CurrentPatient ). Create a menu-driven program OF YOUR OWN DESIGN...
Objective You are given a partial implementation of one header file, GildedRose.h. Item is a class...
Objective You are given a partial implementation of one header file, GildedRose.h. Item is a class that holds the information for each item for the inn. GildedRose is a class that holds an internal listing of many Item objects. This inventory should hold at least 10 items. For this you can use arrays, the std::array class, or even the vector class. Complete the implementation of these classes, adding public/private member variables and functions as needed. You should choose an appropriate...
using the header: #include <pthread.h> // This is a header file for a Read/Right Lock Library....
using the header: #include <pthread.h> // This is a header file for a Read/Right Lock Library. Your C code //SHOULD access your routines using these exact function // prototypes typedef struct RW_lock_s { } RW_lock_t; void RW_lock_init(RW_lock_t *lock); /* This routine should be called on a pointer to a struct variable of RW_lock_t to initialize it and ready it for use. */ void RW_read_lock(RW_lock_t *lock); /* This routine should be called at the beginning of a READER critical section */...
Create a schema file that captures the requirements for a <student> element> Here are the specifications...
Create a schema file that captures the requirements for a <student> element> Here are the specifications for student: 3.1. A student must have a first name and last name. 3.2. A student may have a middle name, but it’s optional. 3.3. A student may have a home address, a work address, or both.             3.3.1. Use a complex type to connect to a single schema definition for “address” 3.4. An address has: a street address, city, state, and zip code....
Create a class Student (in the separate c# file but in the project’s source files folder)...
Create a class Student (in the separate c# file but in the project’s source files folder) with those attributes (i.e. instance variables): Student Attribute Data type (student) id String firstName String lastName String courses Array of Course objects Student class must have 2 constructors: one default (without parameters), another with 4 parameters (for setting the instance variables listed in the above table) In addition Student class must have setter and getter methods for the 4 instance variables, and getGPA method...
ADVERTISEMENT
ADVERTISEMENT
ADVERTISEMENT