宝石をちりばめたようなゲームの背後にあるロジック


12

私がやっているプロトタイプには、宝石をちりばめたようなミニゲームがあります。2D配列のグリッド(int[,])を使用すると、ユーザーがいつマッチを形成したかを知ることができますか?私は水平方向と垂直方向のみを気にします。

私は頭のてっぺんから、それぞれの方向を見るだけだと思っていました。何かのようなもの:

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

もっと良い方法があるはずです。ある?


それを行うために退屈なforループを書いたことを思い出しました(connect-nの場合)
Ming-Tang

回答:


6

同じ軸(xまたはy)内の各アイテムをループします。それらが前のアイテムと同じである場合、それらは一致をインクリメントします。次のアイテムが異なる場合、matchesが3以上かどうかを確認し、一致するアイテムを削除する関数を呼び出して続行します。

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

これはx軸専用です。yの場合、grid [col] [i]はgrid [i] [row]などになります。


4

マッチ3のようなゲームを作成した経験に私は圧倒されると思っただけです。

マッチ3ベースのワードゲームのプロトタイプを作成しました。これは、スクラブルとビジュエルドをマッシュアップするようなものです。空のスペースを埋めるために新しい宝石/タイルを供給するエンジンは、プレイヤーが文字列を作成して単語を形成する実際の機会を作成するために、非常に内省的である必要があることを非常に早い段階で認識しました(ハイブリッドヒューリスティックとモンテカルロサンプリングを実行します)マッチ3メカニック。説明よりもずっと複雑ですが、論文を書かなければならないので簡潔にしています。

OPに答えるために、「gladoscc」コードスニペットに非常によく似た方法で、現在、指定されたグリッドに存在する一致数をスコアリングするパターンチェックを行っています。堅牢に機能しますが、ツリー検索のプレイアウト中に再帰的に実行するための計算コストは​​かなりの負担になるため、ビットボード手法を使用してロジックとデータ表現のこの部分を書き換えています(チェス、チェッカー、オセロなどのゲームのような他のグリッドに一般的に実装されています。)テストでは、ActionScriptで20倍以上高速に実行できることが示されました。応答性、サウンド、アニメーションなどに不可欠なサイクルを解放します。


3
あなたの答えは答えであり、別の質問を追加するべきではありません。質問がある場合は、「質問をする」ボタンを使用して新しい質問を作成してください。これはディスカッションフォーラムではありません。
-bummzack

1
bummzack ....ありがとうございます。私の理論的根拠は、特にツリー検索/イントロスペクションがコンテキストに追加されたときに以前に提案されたもののパフォーマンスに関連するため、提供する洞察があったことです。そして、「宝石をちりばめたゲームの背後にある論理」について本質的に話しているので、それは関連し続けました。これが引き続き悪い形である場合、私はあなたのアドバイスに従って編集/再投稿させていただきます。
ウィサム

2
それはいいです。ただし、回答から「質問」の部分を削除する必要があります。質問は新しい質問であり、回答の一部ではありません
...-bummzack

1
編集し、他の場所に質問を投稿しました
ウィッサム

2

再帰、よ。境界がわからないときのためです。

   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

フラッドフィルアルゴリズムを使用できます。このタイプの問題には本当に役立ちます。


1
いいえ、実際には質問とは何の関係もありません。OPは、3つの一致するアイテムを連続して検出する方法を尋ねています。
サイクロプス

2
反転した要素で塗りつぶしを開始すると、アルゴリズムは一致する要素を通過します。しかし、行の3つ(およびそれ以上)の一致する要素(および交差する列)をチェックするだけでは、多すぎるかもしれません。これをゲームのようなバブルパズルで使用し、必要なことを正確に行います。
ktornai

2
この問題にどのように関連するのか、もう少し混乱していたので、「塗りつぶしを使用する」だけでなく、もう少し説明する必要があります。
ジョッキング
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.