Project 7 Test Data

There were 27 test cases. The first 23 were worth 4 points each, while the last 4 were worth 2 points each. Each test case is represented by an assertion that must be true for you to pass that test. To run the test cases:

  1. Remove the main routine from your zombies.cpp file.
  2. Replace the body of the implementation of clearScreen with {} (an empty function body).
  3. Append the following text to the end of your zombies.cpp file, and build the resulting program.
  4. For any test case you wish to try, run the program, providing as input the test number.

#include <iostream> #include <sstream> #include <streambuf> #include <string> #include <map> #include <algorithm> #include <cstdlib> #include <cassert> using namespace std; class StreambufSwitcher { public: StreambufSwitcher(ios& dest, streambuf* sb, ios::iostate exceptions = ios::goodbit) : dest_stream(dest), oldsb(dest.rdbuf(sb)), oldex(dest.exceptions()) { dest_stream.exceptions(exceptions); } StreambufSwitcher(ios& dest, ios& src) : StreambufSwitcher(dest, src.rdbuf(), src.exceptions()) {} ~StreambufSwitcher() { dest_stream.rdbuf(oldsb); dest_stream.exceptions(oldex); } private: ios& dest_stream; streambuf* oldsb; ios::iostate oldex; }; map<void*, size_t> allocMap; bool recordaddrs = false; inline bool isRecordedSize(size_t n) { return n == sizeof(Zombie) || n == sizeof(Player); } void* operator new(size_t n) { void* p = malloc(n); fill_n(static_cast<char*>(p), n, 0xCA); if (recordaddrs && isRecordedSize(n)) { recordaddrs = false; allocMap.insert(make_pair(p, n)); recordaddrs = true; } return p; } void unrecordaddr(void* p) { recordaddrs = false; auto it = allocMap.find(p); if (it != allocMap.end()) { fill_n(static_cast<char*>(p), it->second, 0xCB); allocMap.erase(it); } recordaddrs = true; } #if __cplusplus >= 201402L && ! defined(__clang__) // Unless clang is supplied the -fsized-deallocation flag, it will // not call the C++14/17 sized operator delete. void operator delete(void* p) noexcept { free(p); } void operator delete(void* p, size_t n) noexcept { if (recordaddrs && isRecordedSize(n)) unrecordaddr(p); operator delete(p); } #else void operator delete(void* p) noexcept { if (recordaddrs) unrecordaddr(p); free(p); } #endif bool recommendMove(const Arena& a, int r, int c, int& bestDir); struct Pos { int r; int c; }; bool noZombiesAround(const Arena& a, Pos z) { for (int dr = -1; dr <= 1; dr++) { for (int dc = -1; dc <= 1; dc++) { if ((dr != 0 || dc != 0) && a.numberOfZombiesAt(z.r+dr, z.c+dc) != 0) return false; } } return true; } bool locateTheZombie(const Arena& a, Pos& z, bool shouldHaveMoved) { if (!shouldHaveMoved) { if (a.numberOfZombiesAt(z.r, z.c) != 1) return false; } else { if (a.numberOfZombiesAt(z.r-1, z.c) == 1) z.r--; else if (a.numberOfZombiesAt(z.r+1, z.c) == 1) z.r++; else if (a.numberOfZombiesAt(z.r, z.c-1) == 1) z.c--; else if (a.numberOfZombiesAt(z.r, z.c+1) == 1) z.c++; else return false; } return noZombiesAround(a, z); } void encircleWithPoison(Arena& a, Pos z) { a.setCellStatus(z.r-1, z.c, HAS_POISON); a.setCellStatus(z.r+1, z.c, HAS_POISON); a.setCellStatus(z.r, z.c-1, HAS_POISON); a.setCellStatus(z.r, z.c+1, HAS_POISON); } void testone(int n) { StreambufSwitcher sso(cout, cerr); switch (n) { default: { cout << "Bad argument" << endl; } break; case 1: { int k; for (k = 0; k < 300; k++) { Arena a(1, 20); a.addPlayer(1, 3); Zombie z(&a, 1, 18); assert(z.row() == 1 && z.col() == 18); z.move(); assert(z.row() == 1); if (z.col() != 19) { assert(z.col() == 17 || z.col() == 18); continue; } z.move(); assert(z.row() == 1); if (z.col() == 20) break; assert(z.col() == 18 || z.col() == 19); } assert(k < 300); } break; case 2: { int k; for (k = 0; k < 600; k++) { Arena a(1, 20); a.addPlayer(1, 3); Zombie z(&a, 1, 19); assert(z.row() == 1 && z.col() == 19); z.move(); assert(z.row() == 1); if (z.col() != 19) { assert(z.col() == 18 || z.col() == 20); continue; } z.move(); assert(z.row() == 1); if (z.col() != 19) { assert(z.col() == 18 || z.col() == 20); continue; } z.move(); assert(z.row() == 1); if (z.col() != 19) { assert(z.col() == 18 || z.col() == 20); continue; } z.move(); assert(z.row() == 1); if (z.col() != 19) { assert(z.col() == 18 || z.col() == 20); continue; } z.move(); assert(z.row() == 1); if (z.col() == 18 || z.col() == 20) break; assert(z.col() == 19); } assert(k < 600); } break; case 3: { int k; for (k = 0; k < 600; k++) { Arena a(20, 1); a.addPlayer(3, 1); Zombie z(&a, 19, 1); assert(z.row() == 19 && z.col() == 1); z.move(); assert(z.col() == 1); if (z.row() != 19) { assert(z.row() == 18 || z.row() == 20); continue; } z.move(); assert(z.col() == 1); if (z.row() != 19) { assert(z.row() == 18 || z.row() == 20); continue; } z.move(); assert(z.col() == 1); if (z.row() != 19) { assert(z.row() == 18 || z.row() == 20); continue; } z.move(); assert(z.col() == 1); if (z.row() != 19) { assert(z.row() == 18 || z.row() == 20); continue; } z.move(); assert(z.col() == 1); if (z.row() == 18 || z.row() == 20) break; assert(z.row() == 19); } assert(k < 600); } break; case 4: { Arena a(10,20); a.addPlayer(9, 19); for (int r = 5-2; r <= 5+2; r++) for (int c = 10-2; c <= 10+2; c++) a.setCellStatus(r, c, HAS_POISON); Zombie z(&a, 5, 10); z.move(); assert((z.row() == 5 && abs(z.col() - 10) == 1) || (z.col() == 10 && abs(z.row() - 5) == 1)); int oldr = z.row(); int oldc = z.col(); z.move(); assert(z.row() == oldr && z.col() == oldc); z.move(); assert((z.row() == oldr && abs(z.col() - oldc) == 1) || (z.col() == oldc && abs(z.row() - oldr) == 1)); } break; case 5: { Arena a(10,20); a.addPlayer(9, 19); for (int r = 5-2; r <= 5+2; r++) for (int c = 10-2; c <= 10+2; c++) if (r != 5 || c != 10) a.setCellStatus(r, c, HAS_POISON); Zombie z(&a, 5, 10); assert(!z.isDead()); z.move(); assert((z.row() == 5 && abs(z.col() - 10) == 1) || (z.col() == 10 && abs(z.row() - 5) == 1)); int oldr = z.row(); int oldc = z.col(); assert(!z.isDead()); a.setCellStatus(5, 10, HAS_POISON); z.move(); assert(z.row() == oldr && z.col() == oldc); assert(!z.isDead()); z.move(); assert((z.row() == oldr && abs(z.col() - oldc) == 1) || (z.col() == oldc && abs(z.row() - oldr) == 1)); assert(z.isDead()); } break; case 6: { Arena a(10,20); a.addPlayer(9, 19); a.setCellStatus(4, 10, HAS_POISON); a.setCellStatus(6, 10, HAS_POISON); a.setCellStatus(5, 9, HAS_POISON); a.setCellStatus(5, 11, HAS_POISON); Zombie z(&a, 5, 10); z.move(); assert((z.row() == 5 && abs(z.col() - 10) == 1) || (z.col() == 10 && abs(z.row() - 5) == 1)); int oldr = z.row(); int oldc = z.col(); z.move(); assert(z.row() == oldr && z.col() == oldc); z.move(); assert((z.row() == oldr && abs(z.col() - oldc) == 1) || (z.col() == oldc && abs(z.row() - oldr) == 1)); oldr = z.row(); oldc = z.col(); z.move(); assert(z.row() == oldr && z.col() == oldc); a.setCellStatus(oldr-1, oldc, EMPTY); a.setCellStatus(oldr+1, oldc, EMPTY); a.setCellStatus(oldr, oldc-1, EMPTY); a.setCellStatus(oldr, oldc+1, EMPTY); z.move(); assert((z.row() == oldr && abs(z.col() - oldc) == 1) || (z.col() == oldc && abs(z.row() - oldr) == 1)); } break; case 7: { Arena a(1, 20); a.addPlayer(1, 3); Player* p = a.player(); assert(p->row() == 1 && p->col() == 3); p->move(WEST); assert(p->row() == 1 && p->col() == 2); p->move(WEST); assert(p->row() == 1 && p->col() == 1); } break; case 8: { Arena a(1, 20); a.addPlayer(1, 3); Player* p = a.player(); p->move(WEST); assert(p->row() == 1 && p->col() == 2); p->move(WEST); assert(p->row() == 1 && p->col() == 1); p->move(WEST); assert(p->row() == 1 && p->col() == 1); p->move(NORTH); assert(p->row() == 1 && p->col() == 1); p->move(SOUTH); assert(p->row() == 1 && p->col() == 1); } break; case 9: { Arena a(10, 20); a.addPlayer(3, 6); Player* p = a.player(); assert( ! p->isDead()); p->setDead(); assert(p->isDead()); } break; case 10: { Arena a(20, 1); a.addPlayer(1, 1); Player* p = a.player(); assert(p->move(WEST).find(" stands") != string::npos); assert(p->move(EAST).find(" stands") != string::npos); assert(p->move(NORTH).find(" stands") != string::npos); assert(p->move(SOUTH).find(" south") != string::npos); } break; case 11: { Arena a(20, 1); a.addPlayer(1, 1); Player* p = a.player(); a.addZombie(2, 1); assert(p->move(SOUTH).find(" died") != string::npos); } break; case 12: { Arena a(20, 1); a.addPlayer(1, 1); Player* p = a.player(); a.addZombie(2, 1); assert(!p->isDead()); p->move(SOUTH); assert(p->isDead()); } break; case 13: { Arena a(6, 15); assert(a.rows() == 6 && a.cols() == 15); } break; case 14: { Arena a(10, 20); a.addPlayer(3, 6); a.addZombie(7, 5); assert(a.numberOfZombiesAt(7, 5) == 1 && a.zombieCount() == 1); } break; case 15: { Arena a(10, 20); a.addPlayer(3, 6); a.addZombie(7, 5); a.addZombie(4, 7); a.addZombie(7, 5); assert(a.numberOfZombiesAt(7, 5) == 2 && a.zombieCount() == 3); } break; case 16: { Arena a(1, 20); a.addPlayer(1, 8); a.addZombie(1, 1); a.setCellStatus(1, 2, HAS_POISON); a.setCellStatus(1, 3, HAS_POISON); a.addZombie(1, 16); a.setCellStatus(1, 14, HAS_POISON); a.setCellStatus(1, 15, HAS_POISON); a.setCellStatus(1, 17, HAS_POISON); a.setCellStatus(1, 18, HAS_POISON); assert(a.zombieCount() == 2); int k; for (k = 0; k < 200; k++) { a.moveZombies(); int nb1 = (a.getCellStatus(1, 2) == HAS_POISON) + (a.getCellStatus(1, 3) == HAS_POISON); int nb2 = (a.getCellStatus(1, 14) == HAS_POISON) + (a.getCellStatus(1, 15) == HAS_POISON) + (a.getCellStatus(1, 17) == HAS_POISON) + (a.getCellStatus(1, 18) == HAS_POISON); assert(a.zombieCount() == (nb1 > 0) + (nb2 > 2)); if (a.zombieCount() == 0) break; } assert(k < 200); } break; case 17: { Arena a(1, 3); a.addPlayer(1, 1); Player* p = a.player(); for (int j = 0; j < 10; j++) a.addZombie(1, 3); assert(!p->isDead()); a.moveZombies(); int k; for (k = 0; k < 100; k++) { assert(!p->isDead()); a.moveZombies(); if (a.numberOfZombiesAt(1, 1) > 0) { assert(p->isDead()); break; } } assert(k < 100); } break; case 18: { ostringstream oss; StreambufSwitcher sso2(cout, oss); Arena a(2, 3); a.addPlayer(2, 3); a.addZombie(2, 1); a.addZombie(2, 1); a.addZombie(2, 2); a.display(""); assert(oss.str().find("2Z@") != string::npos); } break; case 19: { ostringstream oss; StreambufSwitcher sso2(cout, oss); Arena a(2, 3); a.addPlayer(2, 3); for (int k = 1; k <= 20; k++) a.addZombie(2, 1); a.display(""); assert(oss.str().find("9.@") != string::npos); } break; case 20: { recordaddrs = true; int n = allocMap.size(); { Arena a(20, 20); for (int r = 1; r <= 5; r++) for (int c = 11; c <= 20; c++) a.setCellStatus(r, c, HAS_POISON); for (int r = 16; r <= 20; r++) for (int c = 15; c <= 20; c++) a.setCellStatus(r, c, HAS_POISON); a.addPlayer(19, 19); int n2 = allocMap.size(); a.setCellStatus(3, 13, EMPTY); a.setCellStatus(3, 18, EMPTY); a.addZombie(3, 13); a.addZombie(3, 18); for (int k = 0; k < 4; k++) { a.addZombie(1, 1); a.addZombie(1, 4); a.addZombie(4, 1); a.addZombie(4, 4); } assert(allocMap.size() >= n2 + 18); a.moveZombies(); a.setCellStatus(3, 13, HAS_POISON); a.setCellStatus(3, 18, HAS_POISON); a.moveZombies(); a.moveZombies(); assert(a.zombieCount() == 18-2); for (int k = a.zombieCount(); k < MAXZOMBIES; k++) assert(a.addZombie(1, 1)); int j; for (j = 0; j < 1000 && a.zombieCount() > 20; j++) { for (int r = 1; r <= 20; r++) for (int c = 1; c <= 20; c++) if (a.numberOfZombiesAt(r, c) == 0 && !(r == 19 && c == 19)) a.setCellStatus(r, c, HAS_POISON); a.moveZombies(); } assert(j < 1000); a.setCellStatus(1, 1, EMPTY); for (int k = a.zombieCount(); k < MAXZOMBIES; k++) assert(a.addZombie(1, 1)); assert(allocMap.size() >= n2 + MAXZOMBIES); } assert(allocMap.size() == n); recordaddrs = false; } break; case 21: { Arena a(20, 20); a.addPlayer(19, 19); for (int r = 1; r < 19; r++) for (int c = 1; c < 19; c++) if (r != 10 || c != 10) a.setCellStatus(r, c, HAS_POISON); for (int k = 0; k < 100; k++) a.addZombie(10, 10); assert(a.zombieCount() == 100 && a.numberOfZombiesAt(10, 10) == 100); int nr[1+20][1+20]; a.moveZombies(); int tot = 0; for (int r = 1; r < 19; r++) { for (int c = 1; c < 19; c++) { nr[r][c] = a.numberOfZombiesAt(r, c); tot += nr[r][c]; assert((r == 10 && c >= 9 && c <= 11) || (c == 10 && r >= 9 && r <= 11) || nr[r][c] == 0); } } assert(nr[10][10] == 0 && tot == a.zombieCount()); assert(nr[9][10] == 0 || a.getCellStatus(9, 10) == EMPTY); assert(nr[11][10] == 0 || a.getCellStatus(11, 10) == EMPTY); assert(nr[10][9] == 0 || a.getCellStatus(10, 9) == EMPTY); assert(nr[10][11] == 0 || a.getCellStatus(10, 11) == EMPTY); a.setCellStatus(10, 10, HAS_POISON); a.moveZombies(); assert(a.numberOfZombiesAt(9, 10) == (nr[9][10] == 0 ? 0 : 1)); assert(a.numberOfZombiesAt(11, 10) == (nr[11][10] == 0 ? 0 : 1)); assert(a.numberOfZombiesAt(10, 9) == (nr[10][9] == 0 ? 0 : 1)); assert(a.numberOfZombiesAt(10, 11) == (nr[10][11] == 0 ? 0 : 1)); for (int k = 0; k < 17; k++) { for (int r = 1; r < 19; r++) for (int c = 1; c < 19; c++) if (a.numberOfZombiesAt(r, c) == 0) a.setCellStatus(r, c, HAS_POISON); a.moveZombies(); } tot = 0; for (int r = 1; r < 19; r++) for (int c = 1; c < 19; c++) tot += a.numberOfZombiesAt(r, c); assert(a.zombieCount() == tot && tot < 100); } break; case 22: { Arena a(18, 22); Pos z[4] = { { 6, 6 }, { 6, 17 }, { 13, 6 }, { 13, 17 } }; for (int k = 0; k < 4; k++) a.addZombie(z[k].r, z[k].c); assert(a.zombieCount() == 4); for (int k = 0; k < 4; k++) { assert(locateTheZombie(a, z[k], false)); // none moved at start if (k <= 1) encircleWithPoison(a, z[k]); } a.moveZombies(); assert(a.zombieCount() == 4); for (int k = 0; k < 4; k++) { assert(locateTheZombie(a, z[k], true)); // all moved if (k <= 1) encircleWithPoison(a, z[k]); } a.moveZombies(); assert(a.zombieCount() == 4); for (int k = 0; k < 4; k++) assert(locateTheZombie(a, z[k], k >= 2)); // two slept, two moved a.moveZombies(); assert(a.zombieCount() == 2); for (int k = 0; k < 2; k++) { assert(a.numberOfZombiesAt(z[k].r, z[k].c) == 0); // these two died assert(noZombiesAround(a, z[k])); } for (int k = 2; k < 4; k++) assert(locateTheZombie(a, z[k], true)); // these two moved encircleWithPoison(a, z[2]); a.moveZombies(); assert(a.zombieCount() == 2); for (int k = 2; k < 4; k++) assert(locateTheZombie(a, z[k], true)); // both moved encircleWithPoison(a, z[2]); a.moveZombies(); assert(a.zombieCount() == 2); assert(locateTheZombie(a, z[2], false)); // this one slept assert(locateTheZombie(a, z[3], true)); // this one moved a.moveZombies(); assert(a.zombieCount() == 1); assert(a.numberOfZombiesAt(z[2].r, z[2].c) == 0); // this one died assert(noZombiesAround(a, z[2])); assert(locateTheZombie(a, z[3], true)); // this one moved } break; case 23: { Arena a(4, 2); a.addPlayer(1, 1); Player* p = a.player(); a.addZombie(4, 2); for (int k = 0; k < 10000 && ! a.player()->isDead() && a.zombieCount() != 0; k++) { int dir; if (recommendMove(a, p->row(), p->col(), dir)) p->move(dir); else p->dropPoisonedBrain(); a.moveZombies(); } assert(! a.player()->isDead() && a.zombieCount() == 0); } break; case 24: { Arena a(10, 10); a.addPlayer(6, 6); a.addZombie(5, 6); a.addZombie(7, 6); a.addZombie(6, 7); int dir; assert(recommendMove(a, 6, 6, dir) && dir == WEST); } break; case 25: { Arena a(10, 10); a.addPlayer(6, 6); a.addZombie(4, 6); a.addZombie(5, 7); a.addZombie(6, 8); a.addZombie(7, 7); a.addZombie(8, 6); a.addZombie(7, 5); a.addZombie(6, 4); a.addZombie(5, 5); int dir; assert(!recommendMove(a, 6, 6, dir)); } break; case 26: { Arena a(2, 3); a.addPlayer(1, 2); a.addZombie(1, 1); for (int k = 0; k < 10; k++) a.addZombie(2, 3); int dir; assert(!recommendMove(a, 1, 2, dir)); } break; case 27: { Arena a(3, 2); a.addPlayer(3, 1); a.addZombie(1, 1); for (int k = 0; k < 10; k++) a.addZombie(3, 2); int dir; assert(recommendMove(a, 3, 1, dir) && dir == NORTH); } break; } } int main() { cout << "Enter test number (1-27): "; int n; cin >> n; testone(n); cout << "Passed!" << endl; }