Lógica detrás de un juego tipo joya

12

En un prototipo que estoy haciendo, hay un minijuego similar al de joyas. Usando una cuadrícula que es una matriz 2d ( int[,]), ¿cómo puedo saber cuándo el usuario formó una coincidencia? Solo me importa horizontal y verticalmente.

Desde lo alto de mi cabeza estaba pensando que solo miraría en cada dirección. Algo como:

int item = grid[x,y];
if(grid[x-1,y]==item)
{
    int step=x;
    int matches =2;
    while(grid[step-1,y]==item)
    {
        step++;
        matches++
    }
    if(matches>2)
        //remove all matching items
}
else if(grid[x+1,y]==item
    //....
else if(grid[x,y-1==item)
    //...
else if(grid[x,y+1]==item)
    //...

Parece que debería haber una mejor manera. ¿Esta ahí?


fuente
Recordé que escribí tedioso for loop para hacer eso (para un connect-n)
Ming-Tang

Respuestas:

6

Recorre cada elemento en el mismo eje (x o y), si son iguales al elemento anterior, incrementan las coincidencias. Cuando el siguiente elemento se vuelva diferente, verifique si las coincidencias son o mayores que 3, llame a una función que elimine los elementos coincidentes y continúe.

Código AS3:

var grid:Array = [[2,3,2,2,2,4],
                  [ .. ]]; //multidimensional array
var matches:uint;
var gemType:uint;
for(col = 0; col < grid.length; col++){
    matches = 0;        
    gemType = 0; //Reserve 0 for the empty state. If we make it a normal gem type, then only 2 are needed to match for the start.
    for(i = 0; i < grid[0].length; i++){
        if(grid[col][i] == gemType){
            matches++;
        }
        if(grid[col][i] != gemType || i == grid[0].length - 1){ //subtract 1 because arrays start at 0
            if(matches >= 3){
                removeMatches(blah);
            }
            gemType = grid[col][i];
            matches = 1;
        }
    }
}

Esto es solo para el eje x, para y, la cuadrícula [col] [i] se convertiría en la cuadrícula [i] [fila], etc. Estoy seguro de que puedes resolverlo :)

apscience
fuente
4

Solo pensé en opinar sobre nuestra experiencia en la construcción de un juego tipo Match-3.

Hemos construido un prototipo para un juego de palabras basado en Match-3, un poco como mezclar scrabble y Bejeweled. Desde el principio nos dimos cuenta de que el motor que suministra nuevas gemas / fichas para llenar espacios vacíos tendría que ser altamente introspectivo (ejecutamos heurística híbrida y muestreo MonteCarlo) para crear oportunidades reales para que un jugador ensarte letras para formar palabras a través del Mecánico Match-3. Es mucho más elaborado que la descripción, pero lo mantengo breve porque tendríamos que escribir un artículo.

Para responder al OP, estamos haciendo comprobaciones de patrones para puntuar cuántas coincidencias hay en un ceñidor dado, en el momento actual, a través de un método muy similar al fragmento de código "gladoscc". Si bien funciona de manera sólida, el costo computacional para ejecutarlo de manera recursiva durante la reproducción de la búsqueda de árbol se convierte en una carga sustancial, por lo que estamos en el proceso de reescribir esta parte de la lógica y la representación de datos con la metodología de tablero de bits ( comúnmente implementado en otros juegos de cuadrícula como el ajedrez, las damas, Othello, etc.) En las pruebas, hemos demostrado que puede ejecutarse más de 20 veces más rápido en ActionScript, por lo que para nosotros la necesidad de hacerlo es un slam-dunk: y libera ciclos esenciales para la capacidad de respuesta, sonido, animación, etc.

Wissam
fuente
3
Su respuesta debe ser una respuesta y no agregar otra pregunta. Si tiene una pregunta, cree una nueva pregunta con el botón "HACER PREGUNTA". Este no es un foro de discusión.
bummzack
1
bummzack .... gracias por eso. Mi razonamiento fue que teníamos una idea que ofrecer, especialmente en lo que se refiere al rendimiento de lo que se propuso anteriormente cuando se agregó al contexto la búsqueda de árboles / introspección. Y siguió siendo relevante ya que todavía estamos hablando esencialmente de la "Lógica detrás de un juego Bejeweled". Si esto sigue siendo de mala forma, estaré encantado de editar / volver a publicar según su consejo.
Wissam
2
Esta bien. Pero debe eliminar la parte de "pregunta" de su respuesta. Las preguntas deben ser preguntas nuevas y no parte de una respuesta ...
bummzack
1
editado y publicado la pregunta en otro lugar
Wissam
2

La recursión, yo. Es para cuando no conoces tus límites.

   public int getHMatchSize(int row, int column)
    {
        int returnMe = getMatchValue(row, 0, column, 1);

        if (returnMe < 3)
        {
            return 0;
        }
        else return returnMe;
    }


    public int getVMatchSize(int row, int column)
    {
        int returnMe = getMatchValue(row, 1, column, 0);

        if (returnMe < 3)
        {
            return 0;
        }
        else return returnMe;
    }

    /// <summary>
    /// I return the match size.
    /// </summary>
    /// <param name="row"></param>
    /// <param name="rowDelta">1 means look vertically.  Dont set both deltas to 1.</param>
    /// <param name="column"></param>
    /// <param name="columnDelta">1 means look horizontally.  Dont set both deltas to 1.</param>
    /// <returns>The number of contiguous matching things</returns>
    public int getMatchValue(int row, int rowDelta, int column, int columnDelta)
    {
        int[] start = getEndItem(row, -1 * rowDelta, column, -1 * columnDelta);
        int[] end = getEndItem(row, rowDelta, column, columnDelta);

        int returnMe = 0;
        returnMe += end[0] - start[0];
        returnMe += end[1] - start[1];
        return returnMe;
    }

    /// <summary>
    /// I will return the end of a sequence of matching items.
    /// </summary>
    /// <param name="row">start here</param>
    /// <param name="column">start here</param>
    private int[] getEndItem(int row, int rowDelta, int column, int columnDelta)
    {
        Gem matchGem = new Gem(-1);
        int[] returnMe = new int[2];

        if (boardSpace[row + rowDelta][column + columnDelta] == boardSpace[row][column])
        {
            return getEndItem(row + rowDelta, rowDelta, column + columnDelta, columnDelta);
        }
        else
        {
            returnMe[0] = row;
            returnMe[1] = column;
            return returnMe;
        }
    }
Arconom
fuente
0

Puede usar el algoritmo de relleno de inundación . Es realmente útil para este tipo de problema.

ktornai
fuente
1
No, en realidad no tiene nada que ver con la pregunta. El OP pregunta cómo detectar tres elementos coincidentes en una fila.
Cyclops
2
Si comienza el relleno con los elementos invertidos, el algoritmo pasa por los elementos coincidentes. Pero solo para verificar 3 (y no más) elementos coincidentes en una fila (y sin columnas cruzadas), tal vez sea una exageración. Usamos esto en un juego tipo Bubble Puzzle, y hace exactamente lo que necesitamos.
ktornai
2
Tal vez debería explicar un poco más que simplemente "usar el relleno de inundación" porque me confundió por un segundo cómo eso es relevante para este problema.
jhocking