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

Objective in C++

Implement clear board functionality

Instructions

  1. The clear button can now be implemented.
  2. 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.
  3. The status text will need to be updated.
  4. Finally, the drawing panel will need to be refreshed.



class DrawingPanel : public wxPanel
{
public:
   DrawingPanel(wxFrame* parent, std::vector>& gameBoard);
   ~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>& _gameBoard;

   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>& gameBoard) : wxPanel(parent, wxID_ANY, wxPoint(0, 0), wxSize(200, 200)), _gameBoard(gameBoard)
{
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> _gameBoard;
   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> sandbox(gridSize, std::vector(gridSize, false));

// 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();
}

 



Step by Step Solution

There are 3 Steps involved in it

1 Expert Approved Answer
Step: 1 Unlock blur-text-image
Question Has Been Solved by an Expert!

Get step-by-step solutions from verified subject matter experts

Step: 2 Unlock
Step: 3 Unlock

Students Have Also Explored These Related Algorithms Questions!