Objective in C++ Implement clear board functionality Instructions The clear button can now be implemented. The clear
Question:
Objective in C++
Implement clear board functionality
Instructions
- The clear button can now be implemented.
- The clear button should reset the game board to all values being false. The living cell count and generation count should also be set to zero.
- The status text will need to be updated.
- Finally, the drawing panel will need to be refreshed.
class DrawingPanel : public wxPanel
{
public:
DrawingPanel(wxFrame* parent, std::vector
~DrawingPanel();
void CalculateCellSize();
void OnPaint(wxPaintEvent& event);
void SetGridSize(int size);
void OnMouseUp(wxMouseEvent& event);
private:
int gridSize = 15;
int cellWidth;
int cellHeight;
std::vector
wxDECLARE_EVENT_TABLE();
};
#include "DrawingPanel.h"
#include "wx/graphics.h"
#include "wx/dcbuffer.h"
wxBEGIN_EVENT_TABLE(DrawingPanel, wxPanel)
EVT_PAINT(DrawingPanel::OnPaint)
EVT_LEFT_UP(DrawingPanel::OnMouseUp)
wxEND_EVENT_TABLE()
DrawingPanel::DrawingPanel(wxFrame* parent, std::vector
{
this->SetBackgroundStyle(wxBG_STYLE_PAINT);
CalculateCellSize();
}
DrawingPanel::~DrawingPanel()
{
}
void DrawingPanel::CalculateCellSize()
{
wxSize panelSize = GetParent()->GetClientSize();
cellWidth = panelSize.GetWidth() / gridSize;
cellHeight = panelSize.GetHeight() / gridSize;
}
void DrawingPanel::OnPaint(wxPaintEvent& event)
{
wxAutoBufferedPaintDC dc(this);
dc.Clear();
wxGraphicsContext* context = wxGraphicsContext::Create(dc);
if (!context)
{
return;
}
context->SetPen(*wxBLACK);
context->SetBrush(*wxWHITE);
for (int row = 0; row < gridSize; row++)
{
for (int col = 0; col < gridSize; col++)
{
int x = col * cellWidth;
int y = row * cellHeight;
// Check the corresponding bool in the game board
if (_gameBoard[row][col])
{
context->SetBrush(*wxLIGHT_GREY); // Living cell color
}
else
{
context->SetBrush(*wxWHITE); // Dead cell color
}
context->DrawRectangle(x, y, cellWidth, cellHeight);
}
}
}
void DrawingPanel::SetGridSize(int size)
{
gridSize = size;
CalculateCellSize(); // Recalculate cell size based on the new grid size
}
void DrawingPanel::OnMouseUp(wxMouseEvent& event)
{
int mouseX = event.GetX();
int mouseY = event.GetY();
int row = mouseY / cellHeight;
int col = mouseX / cellWidth;
if (row >= 0 && row < gridSize && col >= 0 && col < gridSize)
{
// Toggle the state of the clicked cell
_gameBoard[row][col] = !_gameBoard[row][col];
Refresh();
}
}
class MainWindow : public wxFrame
{
private:
DrawingPanel* _drawingPanel = nullptr;
wxBoxSizer* _sizer = nullptr;
wxToolBar* _toolbar = nullptr;
std::vector
int gridSize = 15;
int generationCount;
int livingCellsCount;
wxStatusBar* statusBar;
int GetNeighborCount(int row, int col);
public:
MainWindow();
~MainWindow();
void OnSizeChanged(wxSizeEvent& event);
void InitializeGameBoard();
void UpdateStatusBar();
void OnPlay(wxCommandEvent& event); // New method for the Play button
void OnPause(wxCommandEvent& event); // New method for the Pause button
void OnNext(wxCommandEvent& event); // New method for the Next button
void OnTrash(wxCommandEvent& event); // New method for the Trash button
int CountLivingNeighbors(int row, int col) {
int neighborCount = 0;
// Check all 8 surrounding cells within the grid boundaries
for (int i = row - 1; i <= row + 1; i++) {
for (int j = col - 1; j <= col + 1; j++) {
// Skip the cell itself
if (i == row && j == col) {
continue;
}
// Check if the neighbor is within bounds and alive
if (i >= 0 && i < gridSize && j >= 0 && j < gridSize && _gameBoard[i][j]) {
neighborCount++;
}
}
}
return neighborCount;
}
void CalculateNextGeneration();
wxDECLARE_EVENT_TABLE();
};
#define TOOLBAR_PLAY_ICON 10001
#include "MainWindow.h"
#include "DrawingPanel.h"
#include "play.xpm"
#include "pause.xpm"
#include "next.xpm"
#include "trash.xpm"
wxBEGIN_EVENT_TABLE(MainWindow, wxFrame)
EVT_SIZE(MainWindow::OnSizeChanged)
wxEND_EVENT_TABLE();
MainWindow::MainWindow() :wxFrame(nullptr, wxID_ANY, "Game of Life", wxPoint(0, 0), wxSize(200, 200))
{
_drawingPanel = new DrawingPanel(this, _gameBoard);
_sizer = new wxBoxSizer(wxVERTICAL);
_toolbar = CreateToolBar();
// Add Play button to the toolbar
wxBitmap playIcon(play_xpm);
_toolbar->AddTool(TOOLBAR_PLAY_ICON, "Play", playIcon);
// Add Pause button to the toolbar
wxBitmap pauseIcon(pause_xpm);
_toolbar->AddTool(TOOLBAR_PLAY_ICON, "Pause", pauseIcon);
// Add Next button to the toolbar
wxBitmap nextIcon(next_xpm);
_toolbar->AddTool(TOOLBAR_PLAY_ICON, "Next", nextIcon);
// Add Trash button to the toolbar
wxBitmap trashIcon(trash_xpm);
_toolbar->AddTool(TOOLBAR_PLAY_ICON, "Trash", trashIcon);
_toolbar->Realize();
_sizer->Add(_toolbar, 0, wxEXPAND); // Add the toolbar to the sizer
_sizer->Add(_drawingPanel, 1, wxEXPAND | wxALL);
// Initialize the status bar
statusBar = CreateStatusBar();
SetSizer(_sizer);
InitializeGameBoard();
this->Layout();
}
MainWindow::~MainWindow()
{
}
void MainWindow::OnSizeChanged(wxSizeEvent& event)
{
_drawingPanel->SetSize(event.GetSize());
_drawingPanel->Refresh();
}
void MainWindow::InitializeGameBoard()
{
_gameBoard.resize(gridSize); // Resize the game board vector to the grid size
for (int i = 0; i < gridSize; i++)
{
_gameBoard[i].resize(gridSize); // Resize each sub-vector to the grid size
}
_drawingPanel->SetGridSize(gridSize); // Pass the grid size to the drawing panel
}
void MainWindow::UpdateStatusBar()
{
wxString statusText = wxString::Format("Generation: %d Living Cells: %d", generationCount, livingCellsCount);
statusBar->SetStatusText(statusText, 0);
}
// Event handler for the Play button
void MainWindow::OnPlay(wxCommandEvent& event)
{
}
// Event handler for the Pause button
void MainWindow::OnPause(wxCommandEvent& event)
{
}
// Event handler for the Next button
void MainWindow::OnNext(wxCommandEvent& event)
{
CalculateNextGeneration();
}
// Event handler for the Trash button
void MainWindow::OnTrash(wxCommandEvent& event)
{
}
int MainWindow::GetNeighborCount(int row, int col)
{
int count = 0;
for (int r = row - 1; r <= row + 1; r++)
{
for (int c = col - 1; c <= col + 1; c++)
{
// Make sure index is valid
if (r >= 0 && r < gridSize && c >= 0 && c < gridSize)
{
if (!(r == row && c == col))
{
if (_gameBoard[r][c])
{
count++;
}
}
}
}
}
return count;
}
void MainWindow::CalculateNextGeneration()
{
// Create a sandbox with the same data type as the game board
std::vector
// Iterate through the game board to calculate the next generation
int newLivingCellsCount = 0;
for (int row = 0; row < gridSize; ++row)
{
for (int col = 0; col < gridSize; ++col)
{
// Count the number of living neighbors for the current cell
int neighborCount = GetNeighborCount(row, col);
// Apply Conway's Game of Life rules
if (_gameBoard[row][col])
{
if (neighborCount < 2 || neighborCount > 3)
{
// Cell dies in the next generation
sandbox[row][col] = false;
}
else
{
// Cell survives to the next generation
sandbox[row][col] = true;
++newLivingCellsCount;
}
}
else
{
if (neighborCount == 3)
{
// Dead cell becomes alive in the next generation
sandbox[row][col] = true;
++newLivingCellsCount;
}
}
}
}
// Update the game board with the new generation using swap
_gameBoard.swap(sandbox);
// Update counts and status bar
++generationCount;
livingCellsCount = newLivingCellsCount;
UpdateStatusBar();
// Refresh the drawing panel
_drawingPanel->Refresh();
}