Logik hinter einem bejeweled ähnlichen Spiel


12

In einem Prototyp, den ich gerade mache, gibt es ein Minispiel, das bejeweled ähnelt. int[,]Wie kann ich mithilfe eines Rasters, das ein 2d-Array ( ) ist, feststellen, wann der Benutzer eine Übereinstimmung gebildet hat? Mir geht es nur um horizontal und vertikal.

Von oben dachte ich, ich würde einfach in jede Richtung schauen. Etwas wie:

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)
    //...

Es scheint, als gäbe es einen besseren Weg. Gibt es?


Ich erinnerte mich, dass ich mühsam eine for-Schleife schrieb, um dies zu tun (für ein connect-n)
Ming-Tang

Antworten:


6

Durchlaufen Sie alle Elemente auf derselben Achse (x oder y), sofern sie mit denen des vorherigen Elements identisch sind. Wenn das nächste Element anders wird, prüfen Sie, ob Übereinstimmungen größer als 3 sind, rufen Sie eine Funktion auf, mit der übereinstimmende Elemente entfernt werden, und fahren Sie fort.

AS3-Code:

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

Dies ist nur für die x-Achse, für y würde grid [col] [i] zu grid [i] [row] usw. Ich bin sicher, dass Sie das herausfinden können :)


4

Ich dachte nur, ich würde mit unserer Erfahrung beim Aufbau eines Match-3-ähnlichen Spiels abwägen.

Wir haben einen Prototyp für ein Match-3-basiertes Wortspiel gebaut, ähnlich wie Scrabble und Bejeweled. Wir haben sehr früh erkannt, dass die Engine, die neue Edelsteine ​​/ Kacheln liefert, um leere Räume zu füllen, sehr introspektiv sein muss (wir führen hybride Heuristiken und MonteCarlo-Stichproben durch), um einem Spieler die Möglichkeit zu geben, Buchstaben zu reihen, um Wörter zu bilden 3-Gewinnt-Mechaniker. Es ist weitaus ausführlicher als die Beschreibung, aber ich fasse mich kurz, weil wir eine Arbeit schreiben müssten.

Zur Beantwortung des OP führen wir Musterprüfungen durch, um zu ermitteln, wie viele Übereinstimmungen zu einem bestimmten Gurt derzeit vorhanden sind, und zwar mit einer Methode, die dem Code-Snippet "gladoscc" sehr ähnlich ist. Obwohl es robust arbeitet, wird der Rechenaufwand für die Ausführung dieses rekursiven Vorgangs während des Abspielens der Baumsuche zu einer erheblichen Belastung. Wir sind also dabei, diesen Teil der Logik und die Datendarstellung mit der Bitboard-Methodik neu zu schreiben ( Wird häufig in Spielen mit anderen Rastern wie Schach, Dame, Othello usw. implementiert. In Tests haben wir gezeigt, dass es in ActionScript über 20-mal schneller laufen kann. und befreit wesentliche Zyklen für Reaktionsfähigkeit, Klang, Animation usw.


3
Ihre Antwort sollte eine Antwort sein und keine weitere Frage hinzufügen. Wenn Sie eine Frage haben, erstellen Sie bitte eine neue Frage über die Schaltfläche "FRAGE STELLEN". Dies ist kein Diskussionsforum.
Mistzack

1
Blödmann ... danke dafür. Mein Grundgedanke war, dass wir einen Einblick zu bieten hatten, insbesondere in Bezug auf die Leistung dessen, was früher vorgeschlagen wurde, als Baumsuche / Introspektion zum Kontext hinzugefügt wurde. Und es war weiterhin relevant, da wir immer noch im Wesentlichen über die "Logik hinter einem Bejeweled-Spiel" sprechen. Wenn dies weiterhin eine schlechte Form ist, bearbeite / poste ich sie gerne nach Ihren Wünschen.
Wissam

2
Das ist gut. Sie sollten jedoch den Teil "Frage" aus Ihrer Antwort entfernen. Fragen sollten neue Fragen sein und nicht Teil einer Antwort ...
Bummzack

1
Bearbeitet und veröffentlicht die Frage an anderer Stelle
Wissam

2

Rekursion, yo. Es ist für den Fall, dass Sie Ihre Grenzen nicht kennen.

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

0

Sie können den Flood-Fill- Algorithmus verwenden. Es ist wirklich brauchbar für diese Art von Problem.


1
Nein, eigentlich hat es nichts mit der Frage zu tun. Das OP fragt, wie drei übereinstimmende Elemente in einer Reihe erkannt werden sollen.
Cyclops

2
Wenn Sie die Füllung mit dem oder den gespiegelten Elementen beginnen, durchläuft der Algorithmus die übereinstimmenden Elemente. Aber nur um 3 (und nicht mehr) passende Elemente in einer Reihe (und keine sich kreuzenden Spalten) zu überprüfen, ist es vielleicht ein Overkill. Wir verwenden dies in einem Bubble-Puzzle-ähnlichen Spiel und tun genau das, was wir brauchen.
ktornai

2
Sie sollten vielleicht ein bisschen mehr als nur "Verwenden der Überflutungsfüllung" erklären, da ich eine Sekunde verwirrt war, wie dies für dieses Problem relevant ist.
jhocking
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.