Custom Grid Shapes in Minesweeper

Can we implement a custom grid shape instead of just rectangular?

Absolutely! Implementing a custom grid shape can add a unique twist to our Minesweeper game.

While rectangular grids are traditional, we can create various shapes like hexagonal, triangular, or even completely custom layouts. Let's explore how we might implement a hexagonal grid as an example.

Hexagonal Grid Implementation

To create a hexagonal grid, we need to adjust our MinesweeperGrid and MinesweeperCell classes. Here's a basic implementation:

#include <cmath>
#include <vector>
#include "Minesweeper/Cell.h"

class HexCell : public MinesweeperCell {
public:
  HexCell(int X, int Y, int Size, int Row,
          int Col) :
      MinesweeperCell(X, Y, Size, Size, Row,
                      Col) {}

  void Render(SDL_Surface *Surface) override {
    // Draw hexagon shape instead of rectangle
    const int centerX = X + Width / 2;
    const int centerY = Y + Height / 2;
    const int radius = Width / 2;

    std::vector<SDL_Point> points;
    for (int i = 0; i < 6; ++i) {
      const double angle =
        i * M_PI / 3 - M_PI / 6;
      points.push_back(
        {static_cast<int>(
           centerX + radius * std::cos(angle)),
         static_cast<int>(centerY +
                          radius *
                            std::sin(angle))});
    }

    // Draw filled hexagon
    filledPolygonRGBA(
      Surface,
      reinterpret_cast<const Sint16 *>(
        &points[0].x),
      reinterpret_cast<const Sint16 *>(
        &points[0].y),
      6, Color.r, Color.g, Color.b, Color.a);
  }
};

class HexGrid {
public:
  HexGrid(int x, int y) {
    using namespace Config;
    const int hexRadius = CELL_SIZE / 2;
    const int verticalSpacing =
      hexRadius * 3 / 2;

    for (int row = 0; row < GRID_ROWS; ++row) {
      for (int col = 0; col < GRID_COLUMNS;
           ++col) {
        int xPos = x +
          col * (hexRadius * sqrt(3)) +
          (row % 2) * (hexRadius * sqrt(3) / 2);
        int yPos = y + row * verticalSpacing;
        Cells.emplace_back(xPos, yPos,
                           CELL_SIZE, row, col);
      }
    }
  }

  void Render(SDL_Surface *Surface) {
    for (auto &cell : Cells) {
      cell.Render(Surface);
    }
  }

  std::vector<HexCell> Cells;
};

In this implementation:

  1. We create a HexCell class that inherits from MinesweeperCell but overrides the Render() method to draw a hexagon instead of a rectangle.
  2. The HexGrid class calculates the position of each hexagonal cell based on its row and column.
  3. We use the SDL2_gfx library's filledPolygonRGBA() function to draw the hexagonal shape.

Adapting Game Logic

Implementing a custom grid shape also requires adjusting our game logic:

  1. Neighbor calculation: In a hexagonal grid, each cell has 6 neighbors instead of 8.
  2. Cell selection: We need to implement a method to determine which cell was clicked based on the hexagonal layout.
  3. Grid navigation: Moving between cells (e.g., with keyboard controls) would need to account for the hexagonal pattern.

Here's a basic neighbor calculation for hexagonal grids:

std::vector<HexCell *> GetNeighbors(int row,
                                    int col) {
  std::vector<HexCell *> neighbors;
  const std::vector<std::pair<int, int>>
    offsets = {{-1, 0},
               {1, 0},
               {0, -1},
               {0, 1},
               {row % 2 ? 1 : -1, -1},
               {row % 2 ? 1 : -1, 1}};

  for (const auto &[rowOffset, colOffset] :
       offsets) {
    int newRow = row + rowOffset;
    int newCol = col + colOffset;
    if (newRow >= 0 && newRow < GRID_ROWS &&
        newCol >= 0 && newCol < GRID_COLUMNS) {
      neighbors.push_back(
        &Cells[newRow * GRID_COLUMNS + newCol]);
    }
  }
  return neighbors;
}

Implementing a custom grid shape adds complexity but can make your Minesweeper game stand out. Remember to adjust all parts of your game logic to accommodate the new shape, including mine placement, cell clearing, and win condition checking.

Creating the Grid

Building a two-dimensional grid of interactive minesweeper cells

Questions & Answers

Answers are generated by AI models and may not have been reviewed. Be mindful when running any code on your device.

Vector vs 2D Array in Minesweeper
Why do we use a vector to store the cells instead of a 2D array?
Cell Clearing Animations in Minesweeper
How can we add animations for cell clearing or mine explosions?
Or Ask your Own Question
Get an immediate answer to your specific question using our AI assistant