Код:
#include "stdafx.h"
#include <vinlib/winapi.h>
#include <vinlib/ctl_std.h>
const int S=60; // Ширина и высота поля
class Live : public Window {
public:
MainMenu mainMenu;
int zoom, ox, oy;
bool map[S*S];
Live();
void redraw(DC&);
void wmLButtonDown(short,short,int);
void wmTimer(int id, TIMERPROC proc);
void go(int interval);
void clear(int=0);
void noise(int=0);
};
#define ptr(X) method(this,&Live::X)
Live::Live() {
// Создание окна
create(0,0,WS_VISIBLE|WS_OVERLAPPEDWINDOW,0,100,100,640,480, "Game of Live",0);
dblbuf = true;
// Создание главного меню (0 - без пиктограммы)
mainMenu.add(0, "Стоп", ptr(go), VK_ESCAPE, 0);
mainMenu.add(0, "Скорость х1", ptr(go), VK_F1, 1000);
mainMenu.add(0, "х3", ptr(go), VK_F2, 333);
mainMenu.add(0, "х5", ptr(go), VK_F3, 100);
mainMenu.add(0, "х10", ptr(go), VK_F4, 33);
mainMenu.add(0, "Очистить", ptr(clear));
mainMenu.add(0, "Заполнить автоматически", ptr(noise));
mainMenu.create(this);
// Очистка игрового поля
clear();
}
// Запуск и остановка игры
void Live::go(int interval) {
if(interval==0) killTimer(0);
else setTimer(0, interval);
}
// Очистка игрового поля
void Live::clear(int) {
memset(map, 0, sizeof(map));
invalidate();
}
// Заполнение игрового поля шумом
void Live::noise(int) {
for(int i=0; i<S*S; i++)
map[i] = rand()&1;
invalidate();
}
// Щелчек кнопкой мыши
void Live::wmLButtonDown(short x,short y,int) {
// Приведение экранных координат к координате ячейки
x=(x-ox)/zoom, y=(y-oy)/zoom;
if(x<0 || y<0 || x>=S || y>=S) return;
// Изменение состояния ячейки
map[x+y*S] ^= 1;
invalidate();
}
// Перерисовка окна
void Live::redraw(DC& dc) {
// Расчет размера ячейки и смещения игрового поля (для центрирования)
zoom = max(min(clientWidth/S, clientHeight/S), 1);
ox = (clientWidth-S*zoom)/2;
oy = (clientHeight-S*zoom)/2;
// Перерисовка экрана
int s = zoom>3 ? zoom-2 : zoom-1;
bool* a = map;
dc.clear(0xA0A0A0);
for(int gy=oy, my=oy+S*zoom; gy<my; gy+=zoom)
for(int gx=ox, mx=ox+S*zoom; gx<mx; gx+=zoom)
dc.fillRect(gx, gy, gx+s, gy+s, *a++ ? 0 : 0xFFFFFF);
}
// Тик таймера
void Live::wmTimer(int id, TIMERPROC proc) {
// Подсчет кол-ва соседей
char map1[S*S];
char *b = map1;
for(int y=0; y<S; y++)
for(int x=0; x<S; x++) {
int s=0;
for(int i=-1; i<=1; i++)
for(int j=-1; j<=1; j++)
if(i|j)
s += map[(x+i+S)%S+((y+j+S)%S)*S];
*b++ = s;
}
// Алгоритм игры
b = map1;
for(bool *a=map, *e=map+S*S; a<e; a++, b++)
if(*a) { if(*b!=2 && *b!=3) *a=0; }
else { if(*b==3) *a=1; }
invalidate();
}
// Запуск игры
int main(const char*) {
Live l;
l.beginModal();
return 0;
}