問題の作成と、ゲームクリア

MakeProblemは、ほかの関数を変更したので若干の変更が必要である。
ただし処理内容はコンソール版と変わらない

  1. 1~15の乱数生成
  2. その番号のタイルの配列インデックスを取得
  3. そのインデックスのタイルが動かせるか確認
  4. 動かせるならループをブレイク、動かせないなら、1に戻る
  5. タイルを移動

なんか効率の悪い生成法だが、工夫できそうな人は効率の良い方法を考えてほしい。
何回シャッフルしたかで、難しさが変わってくるので、レベル設定的なのはここでできる。

Listing. 1: 問題作成関数
void MakeProblem(Board& _board)
{
	Point p;
	for (適当な回数繰り返す(繰り返しが多いほうが難しくなるはず))
	{
		while (true)
		{
			int num = 1~16の乱数を生成;
			p = numのあるタイルのインデックス{i,j}をPoint型に代入
			if (pは動かせるか?)
			{       //動かせるならループを抜ける
				break;
			}//動かせないならもう一回乱数を生成
		}
                //タイルを動かす
		SwapTile(p, _board);
	}
}

動作確認

InitGameでMakeProblemよんじゃえばいいよね。

Listing. 2: MakeProblemの動作確認
void InitGame(Board& _board)
{
	Window::Resize(WSIZE);
	state = GAME_STATE::TITLE;
	InitBoard(_board);
	問題作成関数を呼ぼう
}

動作確認

こんな感じでランダムに並び変わってれば、OKだと思う。
並べ替え繰り返しているので、基本的に解けない問題は生成されないはず

Fig. 1: caption

ゲームクリアの判定は、MakeProblemでひっかきまわす前のタイルの状態が整列状態=クリア状態なので、InitBoardでタイルを初期化した時と同じ配置にタイルが並んでいるかどうかを確認すればよい。

Listing. 3: ゲームクリアのチェック
bool CheckClear(Board& _board)
{
//よほどの確率じゃなきゃMakeProblemした後に、間違って揃っちゃったってことはないはず
	for (int j = 0; j < BOARD_HEIGHT; j++)
	{
		for (int i = 0; i < BOARD_WIDTH; i++)
		{
               //順番があってないのを発見した時点でfalse返して関数を抜ける<codeblock code_label>
 
			if (_board.tile[j][i] != j * BOARD_WIDTH + i + 1)
				return(false);
		}
	}
    //最後までたどり着いたら整列されてるってことでtrueを返す
	return(true);
}

クリアチェックの動作チェック

Listing. 4: クリアチェックの動作チェック
void PlayUpdate(Board& _board)
{
	if (MouseL.down()) {
        省略
	}
	if (クリアチェックの呼び出し)
	{
		state = GAME_STATE::CLEAR;
	}
}

これで、MakeProblemの繰り返し回数を1か2ぐらいにして、クリアしたときにおめでとう画面が描画されれば正常に動作している。

Fig. 2: クリアチェックの様子

その7 おめでとう画面→タイトルとか残務処理

  • game-engineer/classes/2023/something-else/summertime-special-cource/slidepuzle-siv3d-6.txt
  • 最終更新: 3年前
  • by root