Foreword
In general, I was going to start writing mini-projects of various games and tasks in order to restore and improve this very programmer form. The first choice fell on chess problems and the math game of J. Conva "Life".
Today I will talk about how I implemented the Life game simulator based on the Qt cross-platform library. I did everything on Qt Widgets without using QML.
')
Idea
The first thing that comes to mind is the choice to use a ready-made widget such as QTableView or make your own. I decided to make my widget, to simplify all the work, it will be implemented without a scroll and will display as many cells of the “Life” game field as it will fit. This is not very convenient, and classically, in professional versions of the “Life” simulator, the opposite is done: there, the size of the universe is constant, and only the scale and scrolling of the display of the same universe changes. I will do it in a simple way: the size of the universe will be determined by the size of the widget itself, as many cells fit on the widget - as many cells will be in the grid of the universe. In addition, an interesting service will be made: the ability to view a list of pre-compiled configurations of populations with the possibility of placing them in an arbitrary place in the grid of the simulator.
Architecture
The architecture will be simple. One object will encapsulate the grid of the simulator and be responsible for all aspects of the simulation, including the miscalculation of populations by the signal of the QTimer timer. Another object is a classic widget with an overridden paintEvent, which renders the current population on the screen using Qt. The third object is an object that encapsulates work with samples (ready-made populations-configurations stored in files) and allows you to download them from files for further placement on the screen. In addition, you will need to implement the objects of the program's windows and write in them the logic of working with the user.
Implementation
It was decided to make the universe itself in the form of an ordinary dynamic matrix, that is, an array of dimension 2. Dynamism is needed for more flexible work with the object. So, the main object of the simulator should provide the calculation of the matrix of the universe and the other related functions. The matrix is composed of the structure of the form:
struct Cell {// Matrix cell for game simulation
bool current;
bool next;
};
Where current represents the current cell, which is shown in the interface and which is modified from the interface, and next sets up a temporary cell that serves to render the next population in the main loop of the simulator.
The object that stores the matrix from this structure is called LifeObject. I will give the definition of the object:
/// Object containing the main code of the game simulator
class LifeObject: public QObject
{
Q_OBJECT
public:
explicit LifeObject (QObject * parent = 0);
~ LifeObject ();
signals:
void signal_on_timer ();
public slots:
void slot_on_timer ();
public:
Cell ** matrix; // matrix simulator
QTimer * timer; // timer object for simulation
uint col_count, row_count; // matrix dimension
uint timer_duration; //
void init_matrix (uint row_count, uint col_count);
void reinit_matix (uint row_count, uint col_count);
void deinit_matix ();
void start_simulation ();
void stop_simulation ();
void process_population ();
uint get_neighbor_count (uint row, uint col);
void random_population ();
void clean_population ();
void test_population ();
void qdebug_matrix ();
};
The widget inherited from QWidget with the overridden paintEvent method is responsible for displaying the image. This widget itself draws on itself the current simulation state in the form of a grid with squares:

The definition of a LifeWidget object is:
/// Object representing a widget for displaying game grid cells
class LifeWidget: public QWidget
{
Q_OBJECT
public:
explicit LifeWidget (QWidget * parent = 0);
~ LifeWidget ();
void paintEvent (QPaintEvent * event);
signals:
public slots:
void slot_on_timer ();
public:
uint row_height, col_width;
uint cell_padding;
Sample * sample;
bool draw_numbers;
void load_sample (QString path, QString filename);
bool putting_sample;
uint sample_row, sample_col;
void put_sample ();
protected:
virtual void resizeEvent (QResizeEvent *);
void mousePressEvent (QMouseEvent * event);
void mouseMoveEvent (QMouseEvent * event);
public:
LifeObject * life_object;
void autoresize_widget ();
};
Pictures and links
Lastly, I’ll give screenshots and links to the source code and distribution kit with a simulator.

Sample selection window:

Source code can be obtained from the
repository on BitBuket.Download the compiled version of the simulator
can also be on BitBuket.