CS 330 Lecture 23 – Inheritance vs. Composition, Iflessness
Agenda
- what ?s
- inheritance vs. composition
- a raffle
- Game of Life without conditionals
Code
raffle.cpp
#include <iostream>
#include <string>
#include <vector>
using std::vector;
using std::string;
class Raffle : private vector<string> {
public:
Raffle() :
vector<string>() {
}
int size() {
return vector<string>::size();
}
void Add(const string& name) {
if (name != "Jill") {
push_back(name);
}
}
string Draw() {
int random = (int) (rand() / (float) RAND_MAX * (size() - 1));
string winner = (*this)[random];
vector<string>::iterator i = begin() + random;
erase(i);
return winner;
}
};
int main(int argc, char **argv) {
Raffle raffle;
raffle.Add("Brendon");
raffle.Add("John S.");
raffle.Add("John F.");
raffle.Add("Lucas N.");
raffle.Add("Justin");
raffle.Add("Donatello");
raffle.Add("Kiernan");
for (int i = 0; i < 10000; ++i) {
raffle.Add("Jill");
}
std::cout << "raffle.size(): " << raffle.size() << std::endl;
for (int i = 0; i < 3; ++i) {
std::cout << "raffle.Draw(): " << raffle.Draw() << std::endl;
}
std::cout << "raffle.size(): " << raffle.size() << std::endl;
return 0;
}
life_sans_if.cpp
#include <fstream>
#include <iomanip>
#include <iostream>
#include <sstream>
using std::string;
class GameOfLife {
public:
class Cell {
public:
virtual bool IsNowLiving(int nliving) const = 0;
virtual int ToInt() const = 0;
Cell *Tick(int nliving) {
Cell *(*GetSingletons[2])() = {
DeadCell::GetSingleton,
LiveCell::GetSingleton
};
bool is_now_alive = IsNowLiving(nliving);
return GetSingletons[(int) is_now_alive]();
}
protected:
Cell() {}
};
class LiveCell : public Cell {
public:
bool IsNowLiving(int nliving) const {
return nliving == 2 || nliving == 3;
}
int ToInt() const {
return 255;
}
static Cell *GetSingleton() {
static LiveCell singleton;
return &singleton;
}
private:
LiveCell() {}
};
class DeadCell : public Cell {
public:
bool IsNowLiving(int nliving) const {
return nliving == 3;
}
int ToInt() const {
return 0;
}
static Cell *GetSingleton() {
static DeadCell singleton;
return &singleton;
}
private:
DeadCell() {}
};
GameOfLife(int width, int height) :
width(width),
height(height) {
cells = new Cell*[width * height];
for (int i = 0; i < width * height; ++i) {
cells[i] = DeadCell::GetSingleton();
}
}
GameOfLife(const GameOfLife& other) :
width(other.width),
height(other.height) {
cells = new Cell*[width * height];
memcpy(cells, other.cells, sizeof(Cell *) * width * height);
}
Cell * const &operator()(int c, int r) const {
return cells[r * width + c];
}
Cell *&operator()(int c, int r) {
return cells[r * width + c];
}
void Tick() {
GameOfLife oldGame = (*this);
for (int r = 1; r < height - 1; ++r) {
for (int c = 1; c < width - 1; ++c) {
int nliving = oldGame.GetLiveCount(c, r);
(*this)(c, r) = (*this)(c, r)->Tick(nliving);
}
}
}
void Write(const string& path) const {
std::ofstream out(path.c_str());
out << "P2" << std::endl;
out << width - 2 << " " << height - 2 << std::endl;
out << 255 << std::endl;
for (int r = 1; r < height - 1; ++r) {
for (int c = 1; c < width - 1; ++c) {
out << (*this)(c, r)->ToInt() << " ";
}
out << std::endl;
}
out.close();
}
private:
int GetLiveCount(int c, int r) const {
return ((*this)(c - 1, r - 1) == LiveCell::GetSingleton()) +
((*this)(c - 1, r ) == LiveCell::GetSingleton()) +
((*this)(c - 1, r + 1) == LiveCell::GetSingleton()) +
((*this)(c , r - 1) == LiveCell::GetSingleton()) +
((*this)(c , r + 1) == LiveCell::GetSingleton()) +
((*this)(c + 1, r - 1) == LiveCell::GetSingleton()) +
((*this)(c + 1, r ) == LiveCell::GetSingleton()) +
((*this)(c + 1, r + 1) == LiveCell::GetSingleton());
}
Cell **cells;
int width;
int height;
};
int main(int argc, char **argv) {
GameOfLife game(100, 100);
// An R-pentomino
/* game(100, 100) = GameOfLife::ALIVE; // center */
/* game(99, 100) = GameOfLife::ALIVE; // left */
/* game(100, 99) = GameOfLife::ALIVE; // top */
/* game(101, 99) = GameOfLife::ALIVE; // top-right */
/* game(100, 101) = GameOfLife::ALIVE; // bottom */
// A glider
#if 1
game(50, 50) = GameOfLife::LiveCell::GetSingleton(); // center
game(49, 51) = GameOfLife::LiveCell::GetSingleton(); // bottom-left
game(50, 49) = GameOfLife::LiveCell::GetSingleton(); // top
game(51, 51) = GameOfLife::LiveCell::GetSingleton(); // bottom-right
game(51, 50) = GameOfLife::LiveCell::GetSingleton(); // right
#endif
/* game(49, 50) = GameOfLife::ALIVE; */
/* game(50, 50) = GameOfLife::ALIVE; */
/* game(51, 50) = GameOfLife::ALIVE; */
/* game(52, 50) = GameOfLife::ALIVE; */
/* game(49, 51) = GameOfLife::ALIVE; */
/* game(49, 52) = GameOfLife::ALIVE; */
/* game(52, 51) = GameOfLife::ALIVE; */
/* game(52, 52) = GameOfLife::ALIVE; */
/* game(49, 53) = GameOfLife::ALIVE; */
/* game(50, 53) = GameOfLife::ALIVE; */
/* game(51, 53) = GameOfLife::ALIVE; */
/* game(52, 53) = GameOfLife::ALIVE; */
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
What should we fear more?
Having to make decisions?
Or letting others?
Having to make decisions?
Or letting others?