| | |
Game: Robots (Class, Constructors, etc.)
Please support our C++ advertiser: Intel Parallel Studio Home
![]() |
•
•
Join Date: Oct 2006
Posts: 73
Reputation:
Solved Threads: 0
I'm also working on a game project, and I'm stuck. I guess I'll have to post the specs so you guys can see what I have to do.
Here are the specs:
I will post my code below.
Here are the specs:
•
•
•
•
The valley floor can be viewed as a 10 by 10 grid. The northwest corner (upper left on the screen display) is consider to have coordinates (0,0). The northeast corner (upper right) is (0,9), the southwest is (9,0) and the southeast is (9,9). At any time, each robot is at one of the 100 grid points, facing north, east, south, or west. More than one robot may occupy the same spot. Each time a step elapses in the history of the valley, every robot with any energy remaining may turn and then move one grid unit in the direction it is facing. A robot starts out with 60 units of energy, and each attempt to move costs it one unit of energy. A grid point in the valley may contain an energy source, and if a robot arrives at such a point, its energy level goes back up to 60.
The program skeleton you are to flesh out defines three classes that represent the three kinds of objects this program works with: Valley, Robot, and EnergySource. Details of the interface to these classes are in the program skeleton, but here are the essential responsibilites of each class:
Valley
* When a valley object is created, it has no robots or energy sources.
* When a valley object goes away, any robots or energy sources it contains must be destroyed.
* A robot may be created and added to a valley object.
* An energy source may be created and added to a valley object.
* A valley object may be displayed on the screen, showing the locations of the robots and energy sources, and the energy remaining for each robot in the valley. (If a robot is at an energy source, only the robot appears in the display; if two robots are at the same spot, only one of them appears in the display.)
* Given a robot, a valley object may be asked if there is another robot at the same location as the one given.
* A valley object may be asked if there is an energy source at a given position.
* A valley object may be told to direct each robot in the valley to take a step.
EnergySource
* This simple class merely records and reports an energy source's position.
Robot
* A robot is created with a name, a position, and the direction it is initially facing. A robot starts life with 60 energy units.
* A robot may be told to take a step. A robot with no remaining energy will not move. Otherwise, the robot will attempt to move. In detail, this means: With 1/3 probability, the robot will pick a random direction to face; otherwise, it will stay facing in its current direction. The robot will attempt to move one grid unit in the direction it is facing. (It may not be able to move if its way is blocked by the mountains at the edge of the valley.) The move attempt costs one energy unit. If the robot moves onto an energy source, it is recharged to 60 energy units. If a robot with at least 30 energy units moves onto a spot occupied by a robot with 0 units, it will transfer 10 units to that other robot to give it a chance to get to an energy source.
* Robots have no memory of where they've been or what they've seen there. Robots don't know where other robots are; at best, a robot may find out from the valley object it belongs to what other robot, if any, is where it's currently standing.
* If when a robot takes a step, it arrives at a spot where there are at least two other robots, we'll keep things simple: it finds out about one of them and donates energy if appropriate. Then it's done with its step. It does not try to check for other robots at that spot.
You must not make any deletions, additions, or changes to the public interface of any of the classes -- we're depending on them staying the same so that we can test your programs.
•
•
Join Date: Oct 2006
Posts: 73
Reputation:
Solved Threads: 0
C++ Syntax (Toggle Plain Text)
// Portions you are to complete are marked with a TODO: comment. // The first thing you probably want to do is implement the trivial // functions. Then get Valley::addEnergySource and Valley::display going. // That gives you more flexibility in the order you tackle the rest // of the functionality. #include <iostream> #include <string> #include <cstdlib> #include <ctime> using namespace std; /////////////////////////////////////////////////////////////////////////// // Manifest constants /////////////////////////////////////////////////////////////////////////// const int NROWS = 10; // number of rows in the valley const int NCOLS = 10; // number of columns in the valley const int MAXROBOTS = 10; // max number of robots allowed const int MAXSOURCES = NROWS*NCOLS; // max number of energy sources const int FULL_ENERGY = 60; // number of units when fully charged const int SHARE_THRESHHOLD = 30; // will share energy if have at least this const int SHARE_AMOUNT = 10; // amount of energy to share /////////////////////////////////////////////////////////////////////////// // Type definitions /////////////////////////////////////////////////////////////////////////// enum Dir { NORTH, EAST, SOUTH, WEST }; class Valley; // This is needed to let compiler know that Valley is a type // name, since it's mentioned in the Robot declaration. class Robot { public: // Constructor Robot(string nm, Valley* vp, int r, int c, Dir d); // Accessors string name() const; int energy() const; int row() const; int col() const; Dir dir() const; // Mutators bool step(); private: string m_name; int m_energy; int m_row; int m_col; Dir m_dir; Valley* m_valley; }; class EnergySource { public: // Constructor EnergySource(int r, int c); // Accessors int row() const; int col() const; private: int m_row; int m_col; }; class Valley { public: // Constructor Valley(); ~Valley(); // Accessors Robot* otherRobotAt(Robot* rp) const; bool energySourceAt(int r, int c) const; void display() const; // Mutators bool addRobot(string name, int r, int c, Dir dir); bool addEnergySource(int r, int c); bool step(); private: Robot* m_robots[MAXROBOTS]; int m_nrobots; EnergySource* m_sources[MAXROBOTS]; int m_nsources; }; /////////////////////////////////////////////////////////////////////////// // Robot implementation /////////////////////////////////////////////////////////////////////////// Robot::Robot(string nm, Valley* vp, int r, int c, Dir d) : m_name(nm), m_energy(FULL_ENERGY), m_row(r), m_col(c), m_dir(d), m_valley(vp) { // Since the first character of the Robot's name shows up in the // display, there had better be a first character. if (nm.size() == 0) { cout << "***** A robot must have a non-empty name!" << endl; exit(1); } if (r < 0 || r >= NROWS || c < 0 || c >= NCOLS) { cout << "***** Robot created with invalid coordinates (" << r << "," << c << ")!" << endl; exit(1); } } // TODO: Implement the other four accessor functions. These should be trivial. string Robot::name() const { return m_name; } int Robot::energy() const { return m_energy; } int Robot::row() const { return m_row; } int Robot::col() const { return m_col; } Dir Robot::dir() const { return m_dir; } // TODO: Implement the step function. Here's an outline: bool Robot::step() { // If the robot has no energy left, return false // Otherwise, // Randomly change direction with probability 1/3 if (rand() % 3 == 0) // 1/3 probability to pick a direction m_dir = Dir(rand() % 4); // pick a random direction // Attempt to move one step in the direction we're currently facing. // (E.g., to move north, decrement the row coordinate.) If we can't // move in that direction, don't move. switch (m_dir) { case NORTH: // TODO: Move one step north, if possible. break; case SOUTH: case WEST: case EAST: // TODO: Implement the other movements break; } // The attempt to move consumes one unit of energy. // If as a result of the attempt to move, the robot is at an energy // source, it's recharged to the FULL_ENERGY level. // If at this spot there's another robot whose energy level is 0, // then if we have at least SHARE_THRESHHOLD units of energy, // transfer SHARE_AMOUNT units to that other robot. (If there // are two or more dead robots here, we donate to only one.) // Return true, indicating the robot attempted to move. return true; } /////////////////////////////////////////////////////////////////////////// // EnergySource implementations /////////////////////////////////////////////////////////////////////////// // TODO: Implement the constructor // EnergySource(int r, int c) // The constructed EnergySource's location will be at coordinates (r,c). EnergySource::EnergySource(int r, int c) : m_row(r), m_col(c) { if (r < 0 || r >= NROWS || c < 0 || c >= NCOLS) { cout << "***** EnergySource created with invalid coordinates (" << r << "," << c << ")!" << endl; exit(1); } } // TODO: Implement the two accessor functions. These should be trivial. int EnergySource::row() const { return m_row; } int EnergySource::col() const { return m_col; } /////////////////////////////////////////////////////////////////////////// // Valley implementations /////////////////////////////////////////////////////////////////////////// Valley::Valley() : m_nrobots(0), m_nsources(0) { // TODO: Implement the constructor // Make the valley have no robots or energy sources. } Valley::~Valley() { // delete [] ; // TODO: Implement the destructor // Delete any dynamically allocated objects held by the Valley. } // TODO: Implement the accessors // // Robot* otherRobotAt(Robot* rp) const // If there is at least one robot (other than the one rp points to) // at the same (r,c) coordinates as the one rp points to, return a // pointer to the one of those other robots with the least amount // of energy remaining (if there's a tie, any one of the tied robots // will do); otherwise, return NULL. // // bool energySourceAt(int r, int c) const // If there is an energy source at coordinates (r,c), return true; // otherwise, return false. // // Fill in the rest of the display function void Valley::display() const { char grid[NROWS][NCOLS]; int r, c; // fill the grid with dots for (r = 0; r < NROWS; r++) for (c = 0; c < NCOLS; c++) grid[r][c] = '.'; // TODO: mark each energy source with a star // for each energy source in the valley, // set the appropriate element of the grid to '*' // TODO: indicate each robot's position // for each robot in the valley, // set the appropriate element of the grid to the first character // of the robot's name. // Clear the screen system("cls"); // Under LINUX, try system("clear"); // Draw the grid for (r = 0; r < NROWS; r++) { for (c = 0; c < NCOLS; c++) cout << grid[r][c]; cout << endl; } cout << endl; // TODO: Write robot energy info // for each robot in the valley, // write the robot's name and remaining energy level. } // TODO: Implement the mutators bool Valley::addRobot(string name, int r, int c, Dir dir) { // TODO: implement addRobot // If MAXROBOTS have already been added, return false. Otherwise, // dynamically allocate a new robot whose name is name, at coordinates // (r,c) facing in direction dir. Save the pointer to the newly // allocated robot and return true. (Hint: The Valley class could // contain a private array with MAXROBOTS elements.) return true; } bool Valley::addEnergySource(int r, int c) { // TODO: implement addEnergySource // If MAXSOURCES have already been added, return false. Otherwise, // dynamically allocate a new energy source at coordinates (r,c). // Save the pointer to the newly allocated energy source and return true. // (Hint: The Valley class could contain a private array with MAXSOURCES // elements.) return true; } bool Valley::step() { // TODO: implement step // Have each robot in the valley step. If any of them attempted to move, // return true. If none of them did, they're all dead, so return false. return true; // This is here for now just so this will compile. } /////////////////////////////////////////////////////////////////////////// // main() /////////////////////////////////////////////////////////////////////////// // You can use whatever main routine you want. In fact, try different // things that will thoroughly test your classes. This main routine is // the one that the sample executable uses. int main() { // Initialize the random number generator srand(time(0)); // Create a valley Valley v; // Populate it with three robots v.addRobot("Abner", 0, 0, SOUTH); v.addRobot("Betty", 9, 9, NORTH); v.addRobot("Chris", 0, 9, SOUTH); // Add energy sources at (2,2), (2,5), (2,8), (5,2), ..., (8,8) for (int r = 2; r <= 8; r += 3) for (int c = 2; c <= 8; c += 3) v.addEnergySource(r, c); // Step until all robots are dead, displaying the valley each time do { v.display(); cout << "Press Enter to continue "; cin.ignore(100000, '\n'); } while(v.step()); cout << "All robots are dead" << endl; }
And I will post my question / problem (working on one part of the function) in the next post.
•
•
Join Date: Oct 2006
Posts: 73
Reputation:
Solved Threads: 0
I've done the robot accessors, the EnergySource constructor and accessors, and the Valley constructor.
The Valley accessor looks hard, so I'll skip that for now. I'm trying to tackle the now.
I believe I'm getting ideas confused. I'll show you what I have:
the task:
Here's my code:
The Valley accessor looks hard, so I'll skip that for now. I'm trying to tackle the
C++ Syntax (Toggle Plain Text)
bool Valley::addEnergySource (int r, int c)
I believe I'm getting ideas confused. I'll show you what I have:
the task:
C++ Syntax (Toggle Plain Text)
bool Valley::addEnergySource(int r, int c) { // TODO: implement addEnergySource // If MAXSOURCES have already been added, return false. Otherwise, // dynamically allocate a new energy source at coordinates (r,c). // Save the pointer to the newly allocated energy source and return true. // (Hint: The Valley class could contain a private array with MAXSOURCES // elements.) return true; }
C++ Syntax (Toggle Plain Text)
if (MAXSOURCES) return false; else // ? = new Energysource();
•
•
Join Date: Oct 2006
Posts: 73
Reputation:
Solved Threads: 0
Disregard the previous post, I have this now:
Anyways, I'm trying to extend this example to another mutator function:
I get one compilation error, that vp is not declared (true). If I take it out, it says I can't overload wtih 4 arguments. What's the wrongdoing here?
C++ Syntax (Toggle Plain Text)
bool Valley::addEnergySource(int r, int c) { // TODO: implement addEnergySource // If MAXSOURCES have already been added, return false. Otherwise, // dynamically allocate a new energy source at coordinates (r,c). // Save the pointer to the newly allocated energy source and return true. // (Hint: The Valley class could contain a private array with MAXSOURCES // elements.) if (m_nsources == MAXSOURCES) return false; else { EnergySource* es = new EnergySource(r,c); return true; } }
Anyways, I'm trying to extend this example to another mutator function:
C++ Syntax (Toggle Plain Text)
// TODO: implement addRobot // If MAXROBOTS have already been added, return false. Otherwise, // dynamically allocate a new robot whose name is name, at coordinates // (r,c) facing in direction dir. Save the pointer to the newly // allocated robot and return true. (Hint: The Valley class could // contain a private array with MAXROBOTS elements.) bool Valley::addRobot(string name, int r, int c, Dir dir) { if (m_nrobots == MAXROBOTS) return false; else { Robot* rob = new Robot(name, r, vp, c, dir); return true; } }
•
•
•
•
I get one compilation error, that vp is not declared (true). If I take it out, it says I can't overload wtih 4 arguments. What's the wrongdoing here?
C++ Syntax (Toggle Plain Text)
Robot(string nm, Valley* vp, int r, int c, Dir d);
C++ Syntax (Toggle Plain Text)
Robot* rob = new Robot(name, r, vp, c, dir);
a) the compiler will let you use a variable that you've never declared before to use a parameter for a function?
b) removing it will make the compiler omit the 3rd argument in Robot::Robot(), Valley, and just randomly play with the code?
You obviously need to pass some sort of Valley instance to Robot::Robot(), or overload the function so that you can initalize the object without a Valley object. If you choose the former, you'll need to either make one yourself, or pass it in to the function as a parameter.
Hope this helps
"Technological progress is like an axe in the hands of a pathological criminal."
All my posts may be freely redistributed under the terms of the MIT license.
All my posts may be freely redistributed under the terms of the MIT license.
•
•
Join Date: Oct 2006
Posts: 73
Reputation:
Solved Threads: 0
•
•
•
•
You obviously need to pass some sort of Valley instance to Robot::Robot(), or overload the function so that you can initalize the object without a Valley object. If you choose the former, you'll need to either make one yourself, or pass it in to the function as a parameter.
How do I do that? Do I just use one parameter (Valley* vp) and have an empty body?
•
•
•
•
This is the part I don't get. I choose to create a new function, Robot::Robot() to pass the Valley stuff.
How do I do that?
vp later, then you will need to create an overloaded constructor that lacks the vp parameter. "Technological progress is like an axe in the hands of a pathological criminal."
All my posts may be freely redistributed under the terms of the MIT license.
All my posts may be freely redistributed under the terms of the MIT license.
•
•
Join Date: Oct 2006
Posts: 73
Reputation:
Solved Threads: 0
I tried something like this:
and I get a compilation error.
I finally got it to work later, when someone pointed out that I could use the this
I don't understand how that could work though.
C++ Syntax (Toggle Plain Text)
Robot::Robot(string nm, int r, int c, Dir d) { }
and I get a compilation error.
I finally got it to work later, when someone pointed out that I could use the this
C++ Syntax (Toggle Plain Text)
bool Valley::addRobot(string name, int r, int c, Dir dir) { if (m_nrobots == MAXROBOTS) return false; else { m_robots[m_nrobots] = new Robot(name, this, r, c, dir); m_nrobots ++; return true; } }
I don't understand how that could work though.
•
•
•
•
I tried something like this:
and I get a compilation error.C++ Syntax (Toggle Plain Text)
Robot::Robot(string nm, int r, int c, Dir d) { }
I finally got it to work later, when someone pointed out that I could use the this
C++ Syntax (Toggle Plain Text)
bool Valley::addRobot(string name, int r, int c, Dir dir) { if (m_nrobots == MAXROBOTS) return false; else { m_robots[m_nrobots] = new Robot(name, this, r, c, dir); m_nrobots ++; return true; } }
•
•
•
•
I don't understand how that could work though.
Valley to Robot::Robot().How do you do that? The
this pointer points to the current instance of Valley that you're working with, so passing it to the function makes it quick and easy.(This is what I get for not reading entire posts before answering.)
"Technological progress is like an axe in the hands of a pathological criminal."
All my posts may be freely redistributed under the terms of the MIT license.
All my posts may be freely redistributed under the terms of the MIT license.
•
•
Join Date: Oct 2006
Posts: 73
Reputation:
Solved Threads: 0
Thanks for clarifying this. I'm on the right track. Just a few more tasks I believe.Next task I tried to do, but can't think of how, is the step function. (This is inside Robot) I think knowing this would help me think of ideas for other functions:
I'm on bool Robot::step().
EDIT:
I fixed some parts of it.
C++ Syntax (Toggle Plain Text)
bool Robot::step() { // If the robot has no energy left, return false if (m_energy == 0) return false; // Otherwise, else { // Randomly change direction with probability 1/3 if (rand() % 3 == 0) // 1/3 probability to pick a direction m_dir = Dir(rand() % 4); // pick a random direction // Attempt to move one step in the direction we're currently facing. // (E.g., to move north, decrement the row coordinate.) If we can't // move in that direction, don't move. switch (m_dir) { case NORTH: // TODO: Move one step north, if possible. m_row--; break; // TODO: Implement the other movements case SOUTH: m_row++; break; case WEST: m_col--; break; case EAST: m_col++; break; } }
C++ Syntax (Toggle Plain Text)
// The attempt to move consumes one unit of energy. // If as a result of the attempt to move, the robot is at an energy // source, it's recharged to the FULL_ENERGY level. m_energy--; if (m_sources[m_nsources] = new EnergySource(r,c)) m_energy = FULL_ENERGY; // If at this spot there's another robot whose energy level is 0, // then if we have at least SHARE_THRESHHOLD units of energy, // transfer SHARE_AMOUNT units to that other robot. (If there // are two or more dead robots here, we donate to only one.) // Return true, indicating the robot attempted to move. else if (// another robot's energy is 0) if (m_energy > SHARE_THRESHHOLD) // that robot's energy = SHARE_AMOUNT return true;
I don't know what to stick in the parts I // out.
Last edited by aznballerlee; Nov 30th, 2006 at 9:53 pm.
![]() |
Other Threads in the C++ Forum
- Previous Thread: program to read from a file...
- Next Thread: Won't Output to File
Views: 3769 | Replies: 13
| Thread Tools | Search this Thread |
Tag cloud for C++
6 api application array arrays based beginner binary c++ c/c++ calculator char char* class classes code coding compile compiler console conversion convert count data database delete developer display dll dynamiccharacterarray email encryption error file format forms fstream function functions game generator givemetehcodez graph iamthwee ifstream image input int java lib list loop looping loops map math matrix memory multiple newbie news number numbertoword output pointer problem program programming project python random read recursion recursive reference return rpg search simple sort sorting spoonfeeding string strings struct template templates text tree url variable vector video visual visualstudio win32 windows winsock wordfrequency wxwidgets






