Contenido del curso

Mecánica Principal

Evitar matches por defecto en Match 3

Resumen

Cuando generas la cuadrícula de un juego Match 3 en Unity, es común que aparezcan tres piezas iguales alineadas desde el inicio. Para evitar esos matches por defecto necesitas un algoritmo que verifique cada pieza creada y la reemplace si forma combinaciones con las anteriores. Esta lógica es clave para que la partida arranque limpia y el jugador construya sus propios matches.

¿Por qué aparecen matches por defecto al crear la cuadrícula?

El tablero se genera desde la esquina inferior izquierda hacia arriba y hacia la derecha. Si tres piezas iguales caen seguidas en una fila o columna, se forma un match automático que rompe la experiencia del jugador.

La solución pasa por separar la creación de piezas en su propia función y luego validar, pieza por pieza, si genera coincidencias con las que ya existen [01:00].

¿Qué es un match por defecto? Es una alineación de tres o más piezas iguales que aparece automáticamente al generar el tablero, sin que el jugador haya hecho ningún movimiento.

¿Cómo separar la creación de piezas en una función dedicada?

El primer paso es mover el código que instancia las piezas fuera de SetupPieces y encapsularlo en una nueva función llamada CreatePieceAt [01:20]. Esta función recibe dos parámetros, la posición en X y la posición en Y, y devuelve el componente Piece recién creado.

En lugar de declarar la función como void, la cambias a tipo Piece y al final agregas un return con la pieza ubicada en esa coordenada. Así, SetupPieces puede seguir trabajando con la referencia que recibe.

csharp Piece CreatePieceAt(int x, int y) { // instancia la pieza en (x, y) return Pieces[x, y]; }

Dentro de SetupPieces, llamas a la nueva función y guardas el resultado en una variable newPiece. Antes de continuar, conviene volver a Unity y darle play para confirmar que el refactor no rompió nada [02:30].

¿Cómo detectar matches solo hacia abajo e izquierda?

No puedes reutilizar GetMatchByPiece porque esa función revisa las cuatro direcciones. Como las piezas se crean de abajo hacia arriba y de izquierda a derecha, al momento de validar una pieza nueva solo existen vecinos hacia abajo y hacia la izquierda [03:10].

Por eso creas una función nueva llamada HasPreviousMatches que devuelve un booleano y recibe posX y posY [03:40]. Dentro, llamas a GetMatchByDirection dos veces:

  • downMatches con el vector (0, -1) y mínimo de dos piezas iguales.
  • leftMatches con el vector (-1, 0) y mínimo de dos piezas iguales.
  • Si alguna lista llega nula, la inicializas como lista vacía para evitar errores.

La función retorna true si downMatches.Count o leftMatches.Count son mayores a cero. Es decir, si encontró aunque sea una coincidencia previa.

¿Cómo usar un while loop sin caer en un bucle infinito?

En SetupPieces declaras dos variables fuera del for: maxIterations en 50 y currentIteration en cero [05:00]. Después de crear cada pieza, abres un while que se ejecute mientras HasPreviousMatches sea verdadero.

Dentro del while:

  1. Llamas a ClearPieceAt(x, y) para destruir la pieza problemática.
  2. Vuelves a generar una pieza con CreatePieceAt(x, y).
  3. Aumentas currentIteration en uno.
  4. Si currentIteration supera maxIterations, ejecutas un break.

Este tope es la red de seguridad. Sin él, si por alguna razón el algoritmo nunca encuentra una pieza válida, el juego se congela. Además, al inicio de cada iteración del for reinicias currentIteration a cero para que el contador sea local a cada celda [06:15].

¿Para qué sirve un while loop con límite de iteraciones? Permite repetir una acción hasta cumplir una condición, pero corta la ejecución si tarda demasiado. Así evitas que el programa se cuelgue en un bucle infinito.

¿Qué hace la función ClearPieceAt?

Es una función auxiliar que centraliza la lógica para destruir una pieza en una coordenada [06:50]. Dentro guardas una referencia pieceToClear, llamas a Destroy(pieceToClear.gameObject) y luego dejas en null la posición correspondiente del arreglo de piezas.

Esta misma función reemplaza el código duplicado que había dentro de SwapTiles, donde antes borrabas piezas con dos líneas repetidas. Ahora solo invocas ClearPieceAt(piece.x, piece.y) y el código queda más limpio.

¿Cómo probar que el tablero ya no genera matches por defecto?

Al volver a Unity y darle play, la cuadrícula debería aparecer sin coincidencias automáticas. Una forma rápida de estresar la prueba es reducir la cantidad de piezas disponibles en el objeto Board [07:50].

Mientras menos variedad de piezas, mayor la probabilidad de generar matches por defecto. En el ejemplo se baja a solo cuatro tipos de piezas y aun así el tablero arranca sin alineaciones automáticas. Esa es la señal de que el algoritmo funciona.

Con esto, tu Match 3 en Unity arranca limpio y queda listo para el siguiente paso, que es colapsar las piezas cuando se eliminan. ¿Qué otros casos límite vale la pena cubrir antes de avanzar? Comparte tu experiencia en los comentarios.