Café y Código
🟡 Mini-Game EngineMatrices 2D en Acción

Arreglos de Dos Dimensiones: El Laberinto de Pac-Man

¿Alguna vez te has preguntado cómo los videojuegos clásicos representan mapas, laberintos y mundos cuadriculados? En esta lección aprenderás arreglos de dos dimensiones (matrices 2D) construyendo la lógica del mítico Pac-Man. Descubrirás cómo funcionan las filas y columnas, la detección de colisiones contra muros, el recorrido con bucles anidados y podrás jugar con un simulador interactivo en tiempo real que muestra la memoria de la matriz mientras te mueves.

🕹️ Laboratorio Práctico

Simulador de Pac-Man: Matriz 2D en Vivo

Puntos (Score)0
Puntos Restantes--
Posición Pac-Man[f: 7, c: 7]
Estado🟡 Jugando
🎮 Vista Gráfica del JuegoUsa ⬅️ ⬆️ ⬇️ ➡️ o WASD
💾 Matriz 2D en Memoria: char mapa[11][15]

Observa cómo la posición [fila][columna] cambia en tiempo real en la estructura bidimensional:

# : Muro (Impenetrable)
. : Punto (+10 pts)
P : Pac-Man (Jugador)
G : Fantasma (Blinky)
1

¿Qué es un Arreglo de Dos Dimensiones (Matriz 2D)?

Un arreglo unidimensional (1D) representa una línea de casillas (como el inventario de Minecraft). Una matriz o arreglo bidimensional (2D) es una cuadrícula con filas y columnas, ideal para representar mapas, tableros de ajedrez, hojas de cálculo de Excel o el laberinto de Pac-Man.

📐 Regla de Oro: Primero la Fila, Luego la Columna

Para acceder a cualquier celda en C++, usamos dos corchetes consecutivos:

matriz[fila][columna]La fila indica qué tan arriba o abajo estamos (eje Y). La columna indica qué tan a la izquierda o derecha estamos (eje X).

En C++, declaramos el laberinto de Pac-Man como una matriz de caracteres (char) de 11 filas por 15 columnas:

Declaración de la Matriz 2D de Pac-Man
CPP
1const int FILAS = 11;
2const int COLS = 15;
3
4// Declaración e inicialización del laberinto de Pac-Man
5char mapa[FILAS][COLS] = {
6 {'#','#','#','#','#','#','#','#','#','#','#','#','#','#','#'},
7 {'#','.','.','.','.','.','#','.','.','.','.','.','.','.','#'},
8 {'#','.','#','#','.','#','#','#','.','#','#','.','#','.','#'},
9 {'#','.','#','#','.','.','.','.','.','.','#','.','#','.','#'},
10 {'#','.','.','.','.','#','#','#','.','.','.','.','.','.','#'},
11 {'#','#','#','.','#','#',' ','#','#','.','#','#','#','#','#'},
12 {'#','.','.','.','.','#','G','#','.','.','.','.','.','.','#'},
13 {'#','.','#','#','.','.','.','P','.','.','#','#','.','.','#'},
14 {'#','.','#','#','.','#','#','#','.','#','#','.','#','.','#'},
15 {'#','.','.','.','.','.','.','.','.','.','.','.','.','.','#'},
16 {'#','#','#','#','#','#','#','#','#','#','#','#','#','#','#'}
17};
2

Bucles Anidados: Cómo Recorrer y Dibujar la Cuadrícula

Para imprimir o procesar una matriz 2D necesitamos dos bucles for anidados:

  • Bucle exterior (f): se mueve fila por fila desde 0 hasta FILAS - 1.
  • Bucle interior (c): recorre cada columna de esa fila desde 0 hasta COLS - 1.
  • Al terminar de imprimir una fila completa, hacemos cout << endl; para saltar a la siguiente línea en consola.
Función para dibujar la matriz en consola
CPP
1void dibujarMapa(char mapa[FILAS][COLS]) {
2 // Bucle exterior: itera sobre cada FILA
3 for (int f = 0; f < FILAS; f++) {
4 // Bucle interior: itera sobre cada COLUMNA de la fila actual
5 for (int c = 0; c < COLS; c++) {
6 cout << mapa[f][c] << " ";
7 }
8 cout << "\n"; // Salto de línea al terminar la fila
9 }
10}
3

Posición del Jugador en Coordenadas 2D

En lugar de buscar a Pac-Man en toda la matriz en cada frame, guardamos sus coordenadas exactas en dos variables simples:

Fila Actual (Eje Y):int pacmanFila = 7;

Moverse arriba resta 1, moverse abajo suma 1.

Columna Actual (Eje X):int pacmanCol = 7;

Moverse a la izquierda resta 1, a la derecha suma 1.

4

Detección de Colisiones y Validación de Muros ('#')

Antes de modificar la posición de Pac-Man, calculamos la celda destino a la que desea avanzar. Si la celda contiene un muro '#', el movimiento se rechaza:

Lógica de movimiento y colisiones en 2D
CPP
1void moverPacman(char mapa[FILAS][COLS], int& pacmanFila, int& pacmanCol, char direccion, int& puntos) {
2 int nuevaFila = pacmanFila;
3 int nuevaCol = pacmanCol;
4
5 // 1. Calcular nueva coordenada tentativa según la dirección
6 if (direccion == 'w' || direccion == 'W') nuevaFila--; // Arriba
7 else if (direccion == 's' || direccion == 'S') nuevaFila++; // Abajo
8 else if (direccion == 'a' || direccion == 'A') nuevaCol--; // Izquierda
9 else if (direccion == 'd' || direccion == 'D') nuevaCol++; // Derecha
10
11 // 2. Validar que no se salga de la matriz
12 if (nuevaFila < 0 || nuevaFila >= FILAS || nuevaCol < 0 || nuevaCol >= COLS) {
13 return; // Movimiento fuera de límites
14 }
15
16 // 3. Validar colisión contra muros
17 if (mapa[nuevaFila][nuevaCol] == '#') {
18 cout << "¡Pared! No puedes atravesar muros.\n";
19 return;
20 }
21
22 // 4. Si hay un punto, sumamos score
23 if (mapa[nuevaFila][nuevaCol] == '.') {
24 puntos += 10;
25 }
26
27 // 5. Actualizar la matriz: vaciar la celda anterior y colocar a Pac-Man en la nueva
28 mapa[pacmanFila][pacmanCol] = ' ';
29 pacmanFila = nuevaFila;
30 pacmanCol = nuevaCol;
31 mapa[pacmanFila][pacmanCol] = 'P';
32}
5

Inteligencia Artificial del Fantasma: Vecindario de 4 Direcciones

El fantasma ('G') evalúa las 4 celdas adyacentes: arriba (f-1, c), abajo (f+1, c), izquierda (f, c-1) y derecha(f, c+1). Escoge una celda libre de muros y se desplaza hacia ella. Si coincide exactamente con la celda de Pac-Man, ¡el juego termina!

IA de Fantasma en Matriz 2D
CPP
1bool moverFantasma(char mapa[FILAS][COLS], int& ghostFila, int& ghostCol, int pacmanFila, int pacmanCol) {
2 // Si el fantasma toca a Pac-Man, Game Over
3 if (ghostFila == pacmanFila && ghostCol == pacmanCol) {
4 return true; // Colisión letal
5 }
6
7 // Movimiento básico hacia Pac-Man en la matriz
8 int dFila = (pacmanFila > ghostFila) ? 1 : (pacmanFila < ghostFila ? -1 : 0);
9 int dCol = (pacmanCol > ghostCol) ? 1 : (pacmanCol < ghostCol ? -1 : 0);
10
11 int nFila = ghostFila + dFila;
12 int nCol = ghostCol + dCol;
13
14 if (mapa[nFila][nCol] != '#') {
15 ghostFila = nFila;
16 ghostCol = nCol;
17 }
18
19 return (ghostFila == pacmanFila && ghostCol == pacmanCol);
20}

Código Fuente Completo en C++ (Consola)

Puedes compilar y ejecutar este programa directamente en tu terminal de C++ con g++ pacman.cpp -o pacman:

Juego Pac-Man 2D completo en C++
CPP
1#include <iostream>
2#include <vector>
3
4using namespace std;
5
6const int FILAS = 9;
7const int COLS = 13;
8
9char mapa[FILAS][COLS] = {
10 {'#','#','#','#','#','#','#','#','#','#','#','#','#'},
11 {'#','.','.','.','#','.','.','.','#','.','.','.','#'},
12 {'#','.','#','.','#','.','#','.','#','.','#','.','#'},
13 {'#','.','.','.','.','.','.','.','.','.','.','.','#'},
14 {'#','#','#','.','#','#',' ','#','#','.','#','#','#'},
15 {'#','.','.','.','.','.','.','.','.','.','.','.','#'},
16 {'#','.','#','.','#','.','#','.','#','.','#','.','#'},
17 {'#','.','.','.','#','.','P','.','#','.','.','.','#'},
18 {'#','#','#','#','#','#','#','#','#','#','#','#','#'}
19};
20
21int main() {
22 int pFila = 7, pCol = 7;
23 int puntos = 0;
24 char tecla;
25
26 cout << "=== MINI PAC-MAN 2D EN C++ ===\n";
27 cout << "Controles: W (Arriba), S (Abajo), A (Izq), D (Der), Q (Salir)\n\n";
28
29 while (true) {
30 // 1. Dibujar matriz
31 for (int f = 0; f < FILAS; f++) {
32 for (int c = 0; c < COLS; c++) {
33 cout << mapa[f][c] << " ";
34 }
35 cout << "\n";
36 }
37 cout << "Puntaje: " << puntos << " | Posicion: [" << pFila << "][" << pCol << "]\n";
38 cout << "Ingresa direccion (W/A/S/D): ";
39 cin >> tecla;
40
41 if (tecla == 'q' || tecla == 'Q') break;
42
43 int nFila = pFila;
44 int nCol = pCol;
45
46 if (tecla == 'w' || tecla == 'W') nFila--;
47 else if (tecla == 's' || tecla == 'S') nFila++;
48 else if (tecla == 'a' || tecla == 'A') nCol--;
49 else if (tecla == 'd' || tecla == 'D') nCol++;
50
51 // Validar muro
52 if (nFila >= 0 && nFila < FILAS && nCol >= 0 && nCol < COLS && mapa[nFila][nCol] != '#') {
53 if (mapa[nFila][nCol] == '.') puntos += 10;
54 mapa[pFila][pCol] = ' ';
55 pFila = nFila;
56 pCol = nCol;
57 mapa[pFila][pCol] = 'P';
58 }
59 cout << "\n----------------------------------\n";
60 }
61
62 cout << "¡Juego terminado! Puntos finales: " << puntos << "\n";
63 return 0;
64}

Dato curioso: C++ apareció en 1985; Bjarne Stroustrup en Bell Labs. Wikipedia

Ko-fi
Donaciones
Apoyá cafeycodigo con un café en Ko-fi. Colaboradores: insignia, muro y zona exclusiva.