Lógica por trás de um jogo parecido com uma joia

12

Em um protótipo que estou fazendo, existe um minijogo semelhante ao bejeweled. Usando uma grade que é uma matriz 2D ( int[,]), como posso saber quando o usuário formou uma correspondência? Só me preocupo horizontal e verticalmente.

Do alto da minha cabeça, eu estava pensando em olhar para cada direção. 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 deveria haver uma maneira melhor. Existe?


fonte
Lembrei-me de que eu escrevi tedioso para loop para fazer isso (para uma conexão-n)
Ming-Tang

Respostas:

6

Faça um loop através de cada item no mesmo eixo (x ou y), se eles forem iguais ao item anterior com o qual incrementam. Quando o próximo item ficar diferente, verifique se as correspondências são maiores ou iguais a 3, chame uma função que remove os itens correspondentes e continue.

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;
        }
    }
}

Isso é apenas para o eixo x, para y, a grade [col] [i] se tornaria a grade [i] [linha], etc. Tenho certeza de que você pode descobrir isso :)

apscience
fonte
4

Apenas pensei em pesar com a nossa experiência na construção de um jogo semelhante ao Match-3.

Criamos um protótipo para um jogo de palavras baseado em Match-3, um pouco como esmagar scrabble e Bejeweled. Percebemos muito cedo que o mecanismo que fornece novas pedras preciosas / ladrilhos para preencher os espaços vazios teria que ser altamente introspectivo (executamos heurísticas híbridas e amostragem MonteCarlo) para criar oportunidades reais para um jogador amarrar letras para formar palavras através do Mecânico Match-3. É muito mais elaborado do que a descrição, mas estou sendo breve, porque teríamos que escrever um artigo.

Para responder ao OP - estamos fazendo verificações de padrões para pontuar quantas correspondências existem em uma determinada cinta, no momento atual, através de um método muito semelhante ao snippet de código "gladoscc". Embora funcione de maneira robusta, o custo computacional da execução recursiva durante o play-out da pesquisa em árvore se torna um fardo substancial, por isso estamos reescrevendo essa parte da lógica e a representação de dados com a metodologia do bit-board ( comumente implementado em jogos de outras grades, como xadrez, damas, Othello etc.) Nos testes, mostramos que ele pode ser executado 20 vezes mais rápido no ActionScript; e libera ciclos essenciais para capacidade de resposta, som, animação etc.

Wissam
fonte
3
Sua resposta deve ser uma resposta e não adicionar outra pergunta. Se você tiver alguma dúvida, crie uma nova pergunta usando o botão "PERGUNTAR PERGUNTA". Este não é um fórum de discussão.
bummzack
1
bummzack .... obrigado por isso. Minha lógica era que tínhamos uma visão a oferecer, especialmente no que se refere ao desempenho do que foi proposto anteriormente quando a pesquisa em árvore / introspecção foi adicionada ao contexto. E continuou a ser relevante, pois ainda estamos falando essencialmente da "Lógica por trás de um jogo Bejeweled". Se isso continuar mal, teremos prazer em editar / postar novamente, de acordo com seus conselhos.
Wissam 28/03
2
Isso é bom. Mas você deve remover a parte "pergunta" da sua resposta. As perguntas devem ser novas perguntas e não parte de uma resposta ...
bummzack
1
editou e postou a pergunta em outro lugar
Wissam
2

Recursão, yo. É para quando você não conhece seus limites.

   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
fonte
0

Você pode usar o algoritmo de preenchimento de inundação . É realmente útil para esse tipo de problema.

ktornai
fonte
1
Não, na verdade não tem nada a ver com a pergunta. O OP está perguntando como detectar três itens correspondentes em uma linha.
Cyclops
2
Se você iniciar o preenchimento com os elementos invertidos, o algoritmo passará pelos elementos correspondentes. Mas apenas para verificar 3 (e não mais) elemento correspondente em uma linha (e sem colunas de cruzamento), talvez seja um exagero. Usamos isso em um jogo de quebra-cabeça bolha e faz exatamente o que precisamos.
ktornai
2
Talvez você deva explicar um pouco mais do que apenas "usar o preenchimento", porque fiquei confuso por um segundo como isso é relevante para esse problema.
jhocking