If you precede your main routine with the declaration
void doBasicTests();, add the following as the first two lines
of main:
doBasicTests(); // Remove this line after completing test.
return 0; // Remove this line after completing test.
append the following to your penguins.cpp file, and build and
run your project under g31, you will test a number of basic aspects of
your code. (You can leave all of the following code in the program you turn
in, but do comment out or remove the two lines above that you added to
main.)
#include <type_traits>
#include <cassert>
#define CHECKTYPE(c, f, r, a) \
static_assert(std::is_same<decltype(&c::f), r (c::*)a>::value, \
"FAILED: You changed the type of " #c "::" #f); \
{ [[gnu::unused]] auto p = static_cast<r (c::*) a>(&c::f); }
void thisFunctionWillNeverBeCalled()
{
// If the student deleted or changed the interfaces to the public
// functions, this won't compile. (This uses magic beyond the scope
// of CS 31.)
Penguin pg(static_cast<Valley*>(0), 1, 1, 'K');
CHECKTYPE(Penguin, row, int, () const);
CHECKTYPE(Penguin, col, int, () const);
CHECKTYPE(Penguin, species, char, () const);
CHECKTYPE(Penguin, isDead, bool, () const);
CHECKTYPE(Penguin, forceMove, void, (int));
CHECKTYPE(Penguin, move, void, ());
Player p(static_cast<Valley*>(0), 1, 1);
CHECKTYPE(Player, row, int, () const);
CHECKTYPE(Player, col, int, () const);
CHECKTYPE(Player, isDead, bool, () const);
CHECKTYPE(Player, stand, string, ());
CHECKTYPE(Player, move, string, (int));
CHECKTYPE(Player, setDead, void, ());
Valley v(1, 1);
CHECKTYPE(Valley, rows, int, () const);
CHECKTYPE(Valley, cols, int, () const);
CHECKTYPE(Valley, player, Player*, () const);
CHECKTYPE(Valley, penguinCount, int, () const);
CHECKTYPE(Valley, hasProtrusionAt, bool, (int, int) const);
CHECKTYPE(Valley, numberOfPenguinsAt, int, (int, int) const);
CHECKTYPE(Valley, display, void, (string) const);
CHECKTYPE(Valley, placeProtrusionAt, void, (int, int));
CHECKTYPE(Valley, addPenguin, bool, (int, int, char));
CHECKTYPE(Valley, addPlayer, bool, (int, int));
CHECKTYPE(Valley, movePenguins, string, (char, int));
Game g(1, 1, 1);
CHECKTYPE(Game, play, void, ());
}
void doBasicTests()
{
{
Valley forge(10, 20);
forge.addPlayer(2, 5);
Player* pp = forge.player();
assert(pp->row() == 2 && pp->col() == 5 && ! pp->isDead());
assert(pp->move(NORTH) == "Player moved north.");
assert(pp->row() == 1 && pp->col() == 5 && ! pp->isDead());
assert(pp->move(NORTH) == "Player couldn't move; player stands.");
assert(pp->row() == 1 && pp->col() == 5 && ! pp->isDead());
pp->setDead();
assert(pp->row() == 1 && pp->col() == 5 && pp->isDead());
}
{
Valley silicon(10, 20);
silicon.placeProtrusionAt(1, 4);
silicon.placeProtrusionAt(1, 5);
silicon.placeProtrusionAt(3, 4);
silicon.placeProtrusionAt(3, 5);
silicon.placeProtrusionAt(2, 3);
silicon.placeProtrusionAt(2, 6);
silicon.addPenguin(2, 4, 'M');
silicon.addPlayer(7, 7);
assert(silicon.penguinCount() == 1 && silicon.numberOfPenguinsAt(2, 4) == 1);
for (int k = 0; k < 100 && silicon.numberOfPenguinsAt(2, 4) == 1; k++)
silicon.movePenguins('M', EAST);
assert(silicon.numberOfPenguinsAt(2, 4) == 0 && silicon.numberOfPenguinsAt(2, 5) == 1);
for (int k = 0; k < 100 && silicon.penguinCount() == 1; k++)
silicon.movePenguins('G', EAST);
assert(silicon.penguinCount() == 1);
assert(silicon.numberOfPenguinsAt(2, 4) == 1 || silicon.numberOfPenguinsAt(2, 5) == 1);
for (int k = 0; k < 100 && silicon.penguinCount() == 1; k++)
silicon.movePenguins('M', EAST);
assert(silicon.penguinCount() == 0);
assert(silicon.numberOfPenguinsAt(2, 4) == 0 && silicon.numberOfPenguinsAt(2, 5) == 0);
for (int k = 0; k < MAXPENGUINS/4; k++)
{
silicon.addPenguin(6, 7, 'K');
silicon.addPenguin(8, 7, 'K');
silicon.addPenguin(7, 6, 'K');
silicon.addPenguin(7, 8, 'K');
}
assert(! silicon.player()->isDead());
silicon.movePenguins('M', NORTH);
assert(silicon.player()->isDead());
}
{
Valley death(1, 3);
death.addPlayer(1, 1);
death.placeProtrusionAt(1, 2);
int k;
for (k = 0; k < MAXPENGUINS/2; k++)
{
assert(death.addPenguin(1, 3, 'M'));
assert(death.addPenguin(1, 3, 'K'));
}
for (k = 0; k < 100 && death.penguinCount() > MAXPENGUINS/2; k++)
death.movePenguins('M', SOUTH);
assert(k < 100);
while (death.penguinCount() < MAXPENGUINS)
assert(death.addPenguin(1, 3, 'G'));
assert(!death.addPenguin(1, 3, 'G'));
for (k = 0; k < 100 && death.penguinCount() > 0; k++)
{
death.movePenguins('G', WEST);
death.movePenguins('M', WEST);
death.movePenguins('K', WEST);
}
assert(k < 100);
assert(death.numberOfPenguinsAt(1, 3) == 0);
// If the program crashes after leaving this compound statement, you
// are probably messing something up when you delete a dead Penguin
// (or you have mis-coded the destructor).
//
// Draw a picture of your m_penguins array before moving the penguins
// and also note the values of m_nPenguins or any other variables you
// might have that are involved with the number of Penguins. Trace
// through your code step by step as the Penguins die and are
// removed, updating the picture according to what the code says, not
// what you want it to do. If you don't see a problem then, try
// tracing through the destruction of the valley.
//
// If you execute the code, use the debugger to check on the values
// of key variables at various points. If you didn't try to learn
// to use the debugger, insert statements that write the values of
// key variables to cerr so you can trace the execution of your code
// and see the first place where something has gone amiss. (Comment
// out the call to clearScreen in Valley::display so that your output
// doesn't disappear.)
}
cout << "Passed all basic tests" << endl;
exit(0);
}