Assignment Chef icon Assignment Chef
All English tutorials

Programming lesson

Building a Game Map Grid in C++: Arcade-Style Pathfinding with Demolition Man

Learn how to parse a 2D grid map from a text file, validate game maps, and implement movement logic for a retro arcade game using C++ and object-oriented design.

C++ game map tutorial arcade game development grid-based pathfinding parse map file C++ validate game map object-oriented design game Demolition Man game retro arcade programming Bomb Guy movement 2D vector C++ file I/O C++ game map validation AI pathfinding basics software engineering assignment C++ game development 2026

Introduction: The Retro Revival of Game Development

In 2026, the nostalgia wave for classic arcade games is stronger than ever. Companies like ArcadeRetro are bringing back the golden age of gaming with modern twists. One such title, Demolition Man, challenges players to guide Bomb Guy through a grid-based map, destroying walls while avoiding enemies. As a software engineering student, your task is to build the foundation for this game: parsing map files, validating layouts, and implementing movement rules. This tutorial will walk you through the core concepts using C++, focusing on file I/O, 2D arrays, and object-oriented design.

Understanding the Game Map Grid

The game map is a 13-row by 15-column grid, where each cell is 32x32 pixels. The map is stored in a text file as a multidimensional character array. Each character represents a tile type: W for wall, P for Bomb Guy's starting position, G for goal, E for enemy, and . for empty space. The map must have a bounding border (walls around the edges) to be valid. Your job is to read this file, store it in a data structure, and validate it.

Parsing the Map File with C++ File I/O

First, you need to read the map file specified in config.json. Use ifstream to open the file and read line by line. Store each line as a string in a vector. Here's a simple example:

#include <iostream>
#include <fstream>
#include <vector>
#include <string>

std::vector<std::string> readMap(const std::string& filename) {
    std::ifstream file(filename);
    std::vector<std::string> lines;
    std::string line;
    while (std::getline(file, line)) {
        lines.push_back(line);
    }
    return lines;
}

This gives you a raw representation. Next, convert it into a 2D vector<vector<char>> for easier access. Remember, the map is 13 rows and 15 columns, but you should handle variable sizes gracefully.

Validating the Map: Borders and Essential Tiles

A valid map must have a bounding border (first and last rows, first and last columns must be walls). It must also contain exactly one Bomb Guy start (P) and one goal (G). You can write validation functions:

bool hasBoundingBorder(const std::vector<std::vector<char>>& map) {
    int rows = map.size();
    int cols = map[0].size();
    // Check first and last row
    for (int c = 0; c < cols; ++c) {
        if (map[0][c] != 'W' || map[rows-1][c] != 'W') return false;
    }
    // Check first and last column
    for (int r = 0; r < rows; ++r) {
        if (map[r][0] != 'W' || map[r][cols-1] != 'W') return false;
    }
    return true;
}

bool hasStartAndGoal(const std::vector<std::vector<char>>& map) {
    int startCount = 0, goalCount = 0;
    for (const auto& row : map) {
        for (char cell : row) {
            if (cell == 'P') ++startCount;
            if (cell == 'G') ++goalCount;
        }
    }
    return startCount == 1 && goalCount == 1;
}

If validation fails, you can throw an exception or return an error code. In a real game, you'd want to handle invalid maps gracefully, perhaps by showing an error message.

Object-Oriented Design: The Map Class

Instead of using raw vectors, encapsulate the map in a class. This follows modern C++ best practices and makes the code reusable. Here's a skeleton:

class GameMap {
private:
    std::vector<std::vector<char>> grid;
    int startRow, startCol;
    int goalRow, goalCol;
public:
    GameMap(const std::string& filename);
    bool isValid() const;
    char getTile(int row, int col) const;
    void setTile(int row, int col, char tile);
    // ... other methods
};

The constructor would read the file and validate. You can also store the start and goal positions for quick access.

Movement Logic: Where Can Bomb Guy Go?

Bomb Guy can move up, down, left, or right, but cannot walk through walls. Enemies also move along rows and columns where there are no walls. To check if a move is valid, you need to ensure the target cell is within bounds and not a wall. For example:

bool canMove(int row, int col, int newRow, int newCol) const {
    if (newRow < 0 || newRow >= grid.size() ||
        newCol < 0 || newCol >= grid[0].size()) {
        return false;
    }
    return grid[newRow][newCol] != 'W';
}

For enemies, you might implement simple AI like moving toward Bomb Guy or patrolling. But for now, focus on the grid representation.

Trend Context: AI and Pathfinding in Modern Games

Pathfinding algorithms like A* are used in games from Minecraft to Pokémon Go. In 2026, AI-driven game design is hot, with tools like NVIDIA's GameGAN generating levels. Understanding grid-based movement is the first step toward implementing sophisticated enemy AI. Your work on Demolition Man mirrors what indie developers do daily: parse maps, validate them, and code movement.

Testing Your Map Parser

You should write unit tests for invalid maps. For example, a map without a border, or with multiple start positions. Use a testing framework like Google Test or simple assert statements. Here's a test idea:

void testInvalidMapNoBorder() {
    std::vector<std::string> lines = {
        "...............",
        ".P..........G.",
        "..............."
    };
    // Convert to 2D vector and validate
    // Assert that hasBoundingBorder returns false
}

Test-driven development (TDD) is a trend in software engineering, especially in agile teams. Writing tests first forces you to think about edge cases.

Handling Config.json

The map file path is stored in config.json. You'll need a JSON parser. For simplicity, you can use a lightweight library like nlohmann/json. Parse the file to get the path:

#include <nlohmann/json.hpp>
using json = nlohmann::json;

std::string getMapPath(const std::string& configFile) {
    std::ifstream f(configFile);
    json data = json::parse(f);
    return data["path"];
}

Make sure to handle missing keys or file errors.

Performance Considerations

For a 13x15 grid, performance isn't an issue. But if you scale up to larger maps, consider using a 1D array for cache locality, or using bitsets for walls. In modern game engines, spatial partitioning (like quadtrees) is common. Your simple 2D vector is fine for this assignment.

Conclusion: From Assignment to Real-World Skills

By completing this assignment, you've learned file I/O, 2D arrays, validation, and class design—all essential for game development and software engineering. The retro arcade trend is a fun way to practice these skills. As you move forward, consider adding features like enemy AI, power-ups, or even a level editor. The Demolition Man game is just the beginning. Happy coding!