2015/07/12

繋がり判定(2)

突然旅に出て、ようやく今日(もう日付が変わっているので昨日ですが…)帰ってきました。

どこまで書いたのかを覚えていなかったので、前々回の投稿を参照して…
つながり判定の部分でした。

再帰処理での判定方法ですが、そんなに難しくありません。
今現在の時点が呼び出し元と同じ色かを判定し、違う場合には処理(現在の呼び出し処理)を終了します。
すると、呼び出し元の処理へ戻るわけですね。

同じ色だった場合には、上下と斜めに隣接する部分を判定するように呼び出す感じです。

まぁ、こんな感じ…

 1:    private void check(int x , int y , int color)
 2:    {
 3:        if ((y >= 0) && (y < GAME_SCREEN_Y) && (x >= 0) && (x < GAME_SCREEN_X) &&
 4:            (screen_data[y][x] == color))
 5:        {
 6:            check(x , y + 1 , color);   // 下方向のチェック
 7:            check(x , y - 1 , color);   // 上方向のチェック
 8:
 9:            check(x + 1 , y , color);   // 右方向のチェック
10:            check(x - 1 , y , color);   // 左方向のチェック
11:            if (x % 2 == 1)
12:            {
13:                check(x - 1 , y + 1 , color);   // 左下のチェック
14:                check(x + 1 , y + 1 , color);   // 右下のチェック
15:            }
16:            else
17:            {
18:                check(x - 1 , y - 1 , color);   // 左上のチェック
19:                check(x + 1 , y - 1 , color);   // 右上のチェック
20:            }
21:        }
22:    }

前回の図と説明を参照してください。
(0,0)の場合にチェックする部分は、(0,1)→下方向、(1,0)→右方向です。

範囲のチェックは呼び出された側で行うようにしておくと、呼び出す側は座標を渡すだけで良くなります。
範囲チェックは3行目で行っています。
同じ色かの判定は4行目で行っており、異なる色の場合には再帰処理も終了しています。

下方向への呼び出しは6行目で実行されており、ここからまた1行目が呼び出されますが、1つ下の石に対しての判定となっています。
上方向への呼び出しは下方向へのチェックが終了後に呼び出されますが、この時は(0,-1)に対しての判定となりますが、呼び出された先の範囲チェックにより、すぐに呼び出し元へ帰ることになります。

11行目からの部分では、 (0,1)と(1,1)の横方向へのチェックを考えてみるとわかります。

(0,1)の場合にチェックするのは、 (-1,0)、(-1,1)、(1,0)、(1,1)が対象です。
これは、相対位置で考えると(-1,-1)、(-1,0)、(1,-1)、(1,0)となります。
(-1,0)、(1,0)の座標は9行目および10行目でチェックしていますので、(-1,-1)、(1,-1)のチェックを行うために、18行目および19行目を処理します。

今度は(1,1)ですね…(う~ん、長いなぁ)
(1,1)の場合にチェックするのは、 (0,1)、(0,2)、(2,1)、(2,2)が対象です。
これは、相対位置で考えると(-1,0)、(-1,1)、(1,0)、(1,1)となります。
(-1,0)、(1,0)の座標は9行目および10行目でチェックしていますので、(-1,1)、(1,1)のチェックを行うために、13行目および14行目を処理します。

11行目は、X座標の位置が偶数か奇数かを判定しています。
偶数の場合には18行目、19行目を処理し、奇数の場合には13行目、14行目を処理しています。

このようにして、繋がりの判定を行っています。

0 件のコメント:

コメントを投稿