In my project I am trying to implement the Game of Life on a 40*40 grid. There is a button which starts/stop the animation and there are 3 numbers that will decide how the next generation of living cells is created: the repRule, the underRule and the overRule.
These three numbers are initialized at the beginning of mainwindow.cpp and I have a slider for each one of them as I want the user to be able to change them while running the application, the problem is that when I connect the sliders to a lambda function, the value of these integers do not change outside the scope of the lambda function. I have read some documentation on lambda functions, I have tried adding "&" before the variables like I did with a variable named "play" and I have tried to add the "mutable" keyword, but it still doesn't work.
Here is a minimal example that shows the problem I'm having: (I am debugging the values of the integers when using the sliders and when the animation is running)

mainwindow.h:

Qt Code:
  1. #ifndef MAINWINDOW_H
  2. #define MAINWINDOW_H
  3.  
  4. #include <QMainWindow>
  5. #include <vector>
  6. #include <iostream>
  7.  
  8. #include <QApplication>
  9. #include <QPushButton>
  10. #include <QGraphicsScene>
  11. #include <QGraphicsItem>
  12. #include <QGraphicsView>
  13. #include <QTimer>
  14.  
  15.  
  16. QT_BEGIN_NAMESPACE
  17. namespace Ui
  18. {
  19. class MainWindow;
  20. }
  21. QT_END_NAMESPACE
  22.  
  23. using namespace std;
  24.  
  25. // global variables:
  26. const int WIDTH = 660;
  27. const int HEIGHT = 400;
  28. const int SIZE = 10;
  29. const int NCOL = HEIGHT/SIZE; //SIZE must be a divisor of HEIGHT
  30.  
  31. const QColor aliveCol = QColor(200,200,200);
  32. const QColor deadCol = QColor(50,50,50);
  33. const QColor textColor = Qt::white;
  34.  
  35. class Cell {
  36. public:
  37. int x;
  38. int y;
  39. bool alive;
  40. vector<pair<int,int>> neigh;
  41.  
  42. Cell(int a = 0, int b = 0) {
  43. x = a;
  44. y = b;
  45. alive = false;
  46. vector<pair<int,int>> neigh;
  47. }
  48.  
  49. void draw(QGraphicsScene *scene){
  50. QGraphicsRectItem *cell1 = new QGraphicsRectItem(this->x*SIZE,this->y*SIZE,SIZE,SIZE);
  51. if (this->alive) {
  52. cell1->setBrush(QBrush(aliveCol));
  53. }
  54. else {
  55. cell1->setBrush(QBrush(deadCol));
  56. }
  57. scene->addItem(cell1);
  58. }
  59.  
  60. };
  61.  
  62. class MainWindow : public QMainWindow
  63. {
  64. Q_OBJECT
  65.  
  66. public:
  67. MainWindow(QWidget *parent = nullptr);
  68. ~MainWindow();
  69.  
  70. void updateScene(Cell mat[NCOL][NCOL], QGraphicsScene *scene);
  71.  
  72. int countAlive(Cell c, Cell mat[NCOL][NCOL]);
  73.  
  74. void step(Cell mat[NCOL][NCOL], int rep, int under, int over);
  75.  
  76. private:
  77. Ui::MainWindow *ui;
  78. Cell mat[NCOL][NCOL] = {};
  79. };
  80. #endif // MAINWINDOW_H
To copy to clipboard, switch view to plain text mode 

mainwindow.cpp:
Qt Code:
  1. #include "mainwindow.h"
  2. #include "ui_mainwindow.h"
  3. #include <QtCore/QRandomGenerator>
  4. #include <algorithm>
  5. #include <QDebug>
  6. #include <QSlider>
  7.  
  8. MainWindow::MainWindow(QWidget *parent)
  9. : QMainWindow(parent)
  10. , ui(new Ui::MainWindow)
  11. {
  12. ui->setupUi(this);
  13. QGraphicsScene *scene = new QGraphicsScene(0, 0, WIDTH, HEIGHT+70);
  14.  
  15. //Rules:
  16. int repRule = 3; //reproduction rule
  17. int underRule = 1; //underpopulation rule
  18. int overRule = 4; //overpopulation rule
  19.  
  20. //background:
  21. scene->setBackgroundBrush(Qt::gray);
  22.  
  23. for (int i = 0; i <= NCOL; i++)
  24. {
  25. scene->addLine(SIZE*i,0,SIZE*i,HEIGHT);
  26. scene->addLine(0,SIZE*i,HEIGHT,SIZE*i);
  27. }
  28.  
  29. //adding the button:
  30. QPushButton *button1;
  31. button1 = new QPushButton();
  32. button1->setGeometry(QRect(420, 20, 100, 30));
  33. button1->setText("Start / Stop");
  34. scene->addWidget(button1);
  35.  
  36. //adding sliders:
  37. //reproduction slider
  38. QSlider *repSlider;
  39. repSlider = new QSlider(Qt::Horizontal);
  40. repSlider->setGeometry(20,440,100,20);
  41. repSlider->setRange(0,8);
  42. repSlider->setValue(repRule);
  43. scene->addWidget(repSlider);
  44.  
  45. QGraphicsTextItem *sl1Text = new QGraphicsTextItem("Reprodution:");
  46. sl1Text->setPos(20,420);
  47. sl1Text->setDefaultTextColor(textColor);
  48. scene->addItem(sl1Text);
  49.  
  50. //underpopulation slider
  51. QSlider *underPopSlider;
  52. underPopSlider = new QSlider(Qt::Horizontal);
  53. underPopSlider->setGeometry(140,440,100,20);
  54. underPopSlider->setRange(0,8);
  55. underPopSlider->setValue(underRule);
  56. scene->addWidget(underPopSlider);
  57.  
  58. QGraphicsTextItem *sl2Text = new QGraphicsTextItem("Underpopulation:");
  59. sl2Text->setPos(140,420);
  60. sl2Text->setDefaultTextColor(textColor);
  61. scene->addItem(sl2Text);
  62.  
  63. //overpopulation slider
  64. QSlider *overPopSlider;
  65. overPopSlider = new QSlider(Qt::Horizontal);
  66. overPopSlider->setGeometry(260,440,100,20);
  67. overPopSlider->setRange(0,8);
  68. overPopSlider->setValue(overRule);
  69. scene->addWidget(overPopSlider);
  70.  
  71. QGraphicsTextItem *sl3Text = new QGraphicsTextItem("Overpopulation:");
  72. sl3Text->setPos(260,420);
  73. sl3Text->setDefaultTextColor(textColor);
  74. scene->addItem(sl3Text);
  75.  
  76. //building the cells matrix:
  77. for (int i = 0; i<NCOL; i++) {
  78. for (int j = 0; j<NCOL; j++) {
  79. mat[i][j] = Cell(i,j);
  80. }
  81. }
  82.  
  83. //adding the neighbours:
  84. for (int i = 0; i<NCOL; i++) {
  85. for (int j = 0; j<NCOL; j++) {
  86. mat[i][j].neigh.push_back(make_pair((i-1+NCOL)%NCOL,(j-1+NCOL)%NCOL));
  87. mat[i][j].neigh.push_back(make_pair(i,(j-1+NCOL)%NCOL));
  88. mat[i][j].neigh.push_back(make_pair((i+1)%NCOL,(j-1+NCOL)%NCOL));
  89. mat[i][j].neigh.push_back(make_pair((i-1+NCOL)%NCOL,j));
  90. mat[i][j].neigh.push_back(make_pair((i+1)%NCOL,j));
  91. mat[i][j].neigh.push_back(make_pair((i-1+NCOL)%NCOL,(j+1)%NCOL));
  92. mat[i][j].neigh.push_back(make_pair(i,(j+1)%NCOL));
  93. mat[i][j].neigh.push_back(make_pair((i+1)%NCOL,(j+1)%NCOL));
  94. }
  95. }
  96.  
  97. //have an initial layout for debugging
  98. mat[20][19].alive = true;
  99. mat[20][20].alive = true;
  100. mat[20][21].alive = true;
  101.  
  102. bool play = false;
  103.  
  104. updateScene(mat, scene);
  105.  
  106. //make scene
  107. QGraphicsView *view = new QGraphicsView(scene);
  108. view->setFixedSize(670, 480);
  109. view->show();
  110.  
  111. QTimer *_timer = new QTimer; //for the animation
  112.  
  113. //connect the button:
  114. connect(button1, &QPushButton::clicked, this, [&play]()
  115. {
  116. play = !play;
  117. }
  118. );
  119.  
  120. //connect the sliders:
  121. connect(repSlider, &QSlider::valueChanged, this, [&play, repSlider, &repRule](){
  122. if(!play) {
  123. repRule = repSlider->value();
  124. qDebug() << repRule;
  125. }
  126. });
  127.  
  128. connect(underPopSlider, &QSlider::valueChanged, this, [&play, underPopSlider, &underRule](){
  129. if(!play) {
  130. underRule = underPopSlider->value();
  131. qDebug() << underRule;
  132. }
  133. });
  134.  
  135. connect(overPopSlider, &QSlider::valueChanged, scene, [&play, overPopSlider, &overRule](){
  136. if(!play) {
  137. overRule = overPopSlider->value();
  138. qDebug() << overRule;
  139. }
  140. });
  141.  
  142. connect(_timer, &QTimer::timeout, scene, [this, &play, scene, repRule, underRule, overRule]()
  143. {
  144. if (play) {
  145. step(mat, repRule, underRule, overRule);
  146. updateScene(mat, scene);
  147. }
  148. }
  149. );
  150.  
  151. _timer->start(200);
  152. }
  153.  
  154. MainWindow::~MainWindow()
  155. {
  156. delete ui;
  157. }
  158.  
  159. void MainWindow::updateScene(Cell mat[NCOL][NCOL], QGraphicsScene *scene)
  160. {
  161. for (int i = 0; i<NCOL; i++) {
  162. for (int j = 0; j<NCOL; j++) {
  163. mat[i][j].draw(scene);
  164. }
  165. }
  166. }
  167.  
  168. int MainWindow::countAlive(Cell c, Cell mat[NCOL][NCOL]) //auxiliary function for the step function
  169. {
  170. int r = 0;
  171. for (pair<int,int> p : c.neigh) {
  172. if (mat[get<0>(p)][get<1>(p)].alive) {r++;}
  173. }
  174. return r;
  175. }
  176.  
  177. void MainWindow::step(Cell mat[NCOL][NCOL], int repN, int underN, int overN) //animation step
  178. {
  179. int aliveCount;
  180. vector<pair<int,int>> living = {};
  181. for (int i = 0; i < NCOL; i++) {
  182. for (int j = 0; j < NCOL; j++) {
  183. aliveCount = countAlive(mat[i][j],mat);
  184. //rules:
  185. if(!mat[i][j].alive){
  186. if(aliveCount == repN) {
  187. living.push_back(make_pair(i,j));
  188. }
  189. }
  190. else if (aliveCount > underN && aliveCount < overN) {
  191. living.push_back(make_pair(i,j));
  192. }
  193. }
  194. }
  195. for (int i = 0; i < NCOL; i++) {
  196. for (int j = 0; j < NCOL; j++) {
  197. mat[i][j].alive = std::find(living.begin(), living.end(), make_pair(i,j)) != living.end();
  198. }
  199. }
  200. qDebug() << repN << underN << overN;
  201. }
To copy to clipboard, switch view to plain text mode 

I will also take this opportunity to say that the animation runs slower with the time so there is probably a memory leak somewhere which I can't catch, so I'd appreciate is someone could help me with that aswell