Координата = координата * (длина вектора + скаляр) / длина вектора;
Координата = координата * (длина вектора - скаляр) / длина вектора;
Координата = координата * скаляр / длина вектора;
template<typename T, qualifier Q>
template<typename U>
GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<3, T, Q> & vec<3, T, Q>::operator+=(U scalar)
{
this->x += static_cast<T>(scalar);
this->y += static_cast<T>(scalar);
this->z += static_cast<T>(scalar);
return *this;
}
template<typename T, qualifier Q>
template<typename U>
GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<3, T, Q> & vec<3, T, Q>::operator-=(U scalar)
{
this->x -= static_cast<T>(scalar);
this->y -= static_cast<T>(scalar);
this->z -= static_cast<T>(scalar);
return *this;
}
#include <iostream>
#include <stdint.h>
#include <thread>
#include <chrono>
#include <random>
class Cell {
private:
bool value;
bool* ptr[8];
public:
Cell() : value(std::rand() % 2) {}
operator bool() const {
return value;
}
public:
friend class Rules;
template<size_t Y, size_t X, class type_rules>
friend class Game_of_life;
};
class Rules {
public:
virtual bool is_life(const Cell& cell) = 0;
protected:
bool check(const Cell& cell, uint8_t index) {
return *cell.ptr[index];
}
};
class Standard_rules : public Rules {
public:
bool is_life(const Cell& cell) override {
uint8_t count = 254;
for (uint8_t i = 0; i < 8; ++i) {
count += check(cell, i);
}
return (cell && count < 2) || (!cell && count == 1);
}
};
template<size_t Y, size_t X, class type_rules = Standard_rules>
class Game_of_life {
private:
type_rules rules;
bool buffer;
Cell board1[Y][X];
Cell board2[Y][X];
public:
Game_of_life()
: buffer(true) {
init(board1);
init(board2);
}
void draw() const {
draw_(buffer ? board1 : board2);
}
void swap_buffer() {
buffer ? swap(board2, board1) : swap(board1, board2);
}
private:
void draw_line() const {
for (size_t i = 0; i <= X; ++i) {
std::cout << "##";
}
std::cout << std::endl;
}
void draw_(const Cell(*board)[X]) const {
draw_line();
for (size_t y = 0; y < Y; ++y) {
std::cout << '#';
for (size_t x = 0; x < X; ++x) {
std::cout << (board[y][x] ? "[]" : " ");
}
std::cout << '#' << std::endl;
}
draw_line();
}
void init_cell(Cell(*board)[X], size_t y, size_t x) {
size_t start_y = (y == 0 ? Y : y) - 1;
size_t start_x = (x == 0 ? X : x) - 1;
size_t end_y = y == Y - 1 ? 0 : (y + 1);
size_t end_x = x == X - 1 ? 0 : (x + 1);
board[y][x].ptr[0] = &board[start_y][start_x].value;
board[y][x].ptr[1] = &board[start_y][x].value;
board[y][x].ptr[2] = &board[start_y][end_x].value;
board[y][x].ptr[3] = &board[y][start_x].value;
board[y][x].ptr[4] = &board[y][end_x].value;
board[y][x].ptr[5] = &board[end_y][start_x].value;
board[y][x].ptr[6] = &board[end_y][x].value;
board[y][x].ptr[7] = &board[end_y][end_x].value;
}
void init(Cell(*board)[X]) {
for (size_t y = 0; y < Y; ++y) {
for (size_t x = 0; x < X; ++x) {
init_cell(board, y, x);
}
}
}
void swap(Cell(*first)[X], Cell(*second)[X]) {
for (size_t y = 0; y < Y; ++y) {
for (size_t x = 0; x < X; ++x) {
first[y][x].value = rules.is_life(second[y][x]);
}
}
buffer = !buffer;
}
};
int main() {
std::srand(time(0));
Game_of_life<19,19, Standard_rules> play;
for (;;) {
play.draw();
play.swap_buffer();
std::this_thread::sleep_for(std::chrono::milliseconds(500));
system("cls);
}
return 0;
}
Cell
, который хранит bool value
и bool* ptr[8]
.Rules
он представлял интерфейс для обеспечения правил мира. Так как клеточный автомат может быть с разными правилами. И просто новые правила наследовал от него и реализовал уже в них. (Например количество соседей только сверху, снизу и по бокам, или количество соседей только по углам).#
, я использовал []
. Так клетки выглядят более квадратными и более читабельными.