CS 330 Lecture 22 – Vtables and Other C++isms
Agenda
- what ?s
- O(1) dynamic dispatch
- Game of Life with conditionals
- overloading builtin operators
- copy constructor
- formatted output with stringstream
- references
TODO
- Optional participation point: write Game of Life without conditionals.
Code
Sizeof.cpp
#include <iostream>
class Int {
public:
Int() {}
virtual int Get() { return i; }
private:
int i;
};
int main(int argc, char **argv) {
std::cout << sizeof(Int) << std::endl;
return 0;
}
life.cpp
#include <fstream>
#include <iomanip>
#include <iostream>
#include <sstream>
using std::string;
class GameOfLife {
public:
typedef enum {
DEAD,
ALIVE
} cell_t;
GameOfLife(int width, int height) :
width(width),
height(height) {
cells = new cell_t[width * height];
for (int i = 0; i < width * height; ++i) {
cells[i] = DEAD;
}
}
GameOfLife(const GameOfLife& other) :
width(other.width),
height(other.height) {
cells = new cell_t[width * height];
memcpy(cells, other.cells, sizeof(cell_t) * width * height);
}
cell_t operator()(int c, int r) const {
return cells[r * width + c];
}
void Write(const string& path) const {
std::ofstream out(path.c_str());
out << "P2" << std::endl;
out << width << " " << height << std::endl;
out << 255 << std::endl;
for (int r = 0; r < height; ++r) {
for (int c = 0; c < width; ++c) {
out << ((*this)(c, r) == ALIVE ? 255 : 0) << " ";
}
out << std::endl;
}
out.close();
}
cell_t& operator()(int c, int r) {
return cells[r * width + c];
}
void Tick() {
GameOfLife oldGame = (*this);
for (int r = 0; r < height; ++r) {
for (int c = 0; c < width; ++c) {
int nliving = oldGame.GetLiveCount(c, r);
cell_t state = (*this)(c, r);
if (state == ALIVE && (nliving == 2 || nliving == 3)) {
(*this)(c, r) = ALIVE;
} else if (state == DEAD && nliving == 3) {
(*this)(c, r) = ALIVE;
} else {
(*this)(c, r) = DEAD;
}
}
}
}
private:
int GetLiveCount(int c, int r) const {
return ((*this)(c - 1, r - 1) == ALIVE) +
((*this)(c - 1, r ) == ALIVE) +
((*this)(c - 1, r + 1) == ALIVE) +
((*this)(c , r - 1) == ALIVE) +
((*this)(c , r + 1) == ALIVE) +
((*this)(c + 1, r - 1) == ALIVE) +
((*this)(c + 1, r ) == ALIVE) +
((*this)(c + 1, r + 1) == ALIVE);
}
cell_t *cells;
int width;
int height;
};
int main(int argc, char **argv) {
GameOfLife game(100, 100);
// An R-pentomino
game(50, 50) = GameOfLife::ALIVE; // center
game(49, 50) = GameOfLife::ALIVE; // left
game(50, 49) = GameOfLife::ALIVE; // top
game(51, 49) = GameOfLife::ALIVE; // top-right
game(50, 51) = GameOfLife::ALIVE; // bottom
game.Write("images/out0000.pgm");
std::stringstream ss;
for (int i = 1; i < 100; ++i) {
game.Tick();
ss.str("");
ss << "images/out" << std::setw(4) << std::setfill('0') << i << ".pgm";
game.Write(ss.str());
}
return 0;
}
Haiku
“Let’s play Game of Life”
He won’t sleep until we do
One round and he’s out
He won’t sleep until we do
One round and he’s out