Skip to main content

第3回 そのタイル動く?

タイルを探して動かせるか調べよう

このページでは、指定したタイルが動かせるかどうかを調べます。

スライドパズルでは、空白の上下左右にあるタイルだけを動かせます。

そのためには、まず、

空白はSearchTile()どこにある?
動かしたいタイルはどこにある?

を調べる必要があります。

そこで、最初に**指定したタイルの位置を探しすSearchTile()**を作ってみよう!

タイルと空白の位置が分かったら、次にその2つが隣り合っているかを調べる**CanMoveTile()で空白の隣にあるか調べ**を作ります。


1.指定したタイルの位置を探そう

例えば、次の盤面を考えます。

  1   2   3   4
  5   6   7   8
  9  10      12
 13  14  11  15

このとき、

空白 → x = 2, y = 2
11   → x = 2, y = 3

です。

タイルと空白の位置

見つけた位置はPositionで返そう! 関数の形はこうなります。

Position SearchTile(Board* board, int number)

numberには探したいタイル番号が入ります。盤面を左上から順番に調べて、同じ番号を見つけたら、その位置を返そう!

最初のresultを{-1, -1}にしておけば、見つからなかったときは「盤面の外の位置」を返せます。

穴埋め

Position SearchTile(Board* board, int number)
{
    Position result = { -1, -1 };

    for (int y = 0; y < BOARD_HEIGHT; y++)
    {
        for (int x = 0; x < BOARD_WIDTH; x++)
        {
            // xとyから1次元配列の添字を求める
            int index = ______________________________;

            // このマスが探しているタイル番号か調べる
            if (______________________________________)
            {
                // 見つけた横位置を保存する
                result.x = ______;

                // 見つけた縦位置を保存する
                result.y = ______;

                return result;
            }
        }
    }

    return result;
}

模範解答

模範解答を見る
Position SearchTile(Board* board, int number)
{
    Position result = { -1, -1 };

    for (int y = 0; y < BOARD_HEIGHT; y++)
    {
        for (int x = 0; x < BOARD_WIDTH; x++)
        {
            int index = y * BOARD_WIDTH + x;

            if (board->tile[index] == number)
            {
                result.x = x;
                result.y = y;
                return result;
            }
        }
    }

    return result;
}

2.そのタイルは動かせる?

スライドパズルでは、空白の上下左右にあるタイルだけを動かせます。

空白の上下左右にある動かせるタイル

まず、空白と指定タイルの位置を調べます。

ここでは、今作ったSearchTile()をそのまま使います。

Position blank = SearchTile(board, BLANK_TILE);
Position tile = SearchTile(board, number);

位置が分かったら、2つの位置の差を求めてみよう!

int dx = blank.x - tile.x;
int dy = blank.y - tile.y;

上下左右に隣り合っているとき、dxとdyは、

( 1,  0)
(-1,  0)
( 0,  1)
( 0, -1)

のどれかになります。

そこで、

dx × dx + dy × dy

を計算すると、どの場合でも1になります。

穴埋め

int CanMoveTile(Board* board, int number)
{
    Position blank = SearchTile(board, BLANK_TILE);
    Position tile = SearchTile(board, number);

    int dx = blank.x - tile.x;
    int dy = blank.y - tile.y;

    // 空白とタイルが上下左右に1マスだけ離れているか調べる
    if (________________________________)
    {
        return 1;
    }

    return 0;
}

模範解答

模範解答を見る
int CanMoveTile(Board* board, int number)
{
    Position blank = SearchTile(board, BLANK_TILE);
    Position tile = SearchTile(board, number);

    int dx = blank.x - tile.x;
    int dy = blank.y - tile.y;

    if (dx * dx + dy * dy == 1)
    {
        return 1;
    }

    return 0;
}

3.関数動かせるタイルを組み合わせてい判定できるようになった!

CanMoveTile()この中ページでは、SearchTile()を2回使っています。

つまり、

① SearchTile()で空白とタイルの位置を探す処理
② CanMoveTile()で2つの位置を比べる
③ 空白の上下左右にあれば動かせると判定する

という処理をもう一度書いたわけではあ作りませんした。

これで、

SearchTile(if (CanMoveTile(&board, 11))に探索を任
{
    // 11番のタイルは動かせることで
}

のように、CanMoveTile()では位置関係の指定したタイルを動かしてよいか判定に集中断できるようになりますした。

SearchTile()とCanMoveTile()次は、この判定を使えば、って実際にタイルを空白へ移動する処理を作れます。ってみよう!