配列を座標として障害物かどうかなぜ判断できないのかについて

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
Ouxiy
記事: 173
登録日時: 4年前

配列を座標として障害物かどうかなぜ判断できないのかについて

#1

投稿記事 by Ouxiy » 4年前

コード:

#include "DxLib.h"



int Key[256]; // キーが押されているフレーム数を格納する

// キーの入力状態を更新する
int gpUpdateKey() {
	char tmpKey[256]; // 現在のキーの入力状態を格納する
	GetHitKeyStateAll(tmpKey); // 全てのキーの入力状態を得る
	for (int i = 0; i < 256; i++) {
		if (tmpKey[i] != 0) { // i番のキーコードに対応するキーが押されていたら
			Key[i]++;     // 加算
		}
		else {              // 押されていなければ
			Key[i] = 0;   // 0にする
		}
	}
	return 0;
}

// プログラムは WinMain から始まります
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
	SetGraphMode(1600, 680, 32); // ウィンドウの大きさを指定
	ChangeWindowMode(TRUE);

	if (DxLib_Init() == -1)        // DXライブラリ初期化処理
	{
		return -1;            // エラーが起きたら直ちに終了
	}


	
	char key[256];
	//1. 3x3マスの2次元配列
	int idou[5][5] = {
					{00,10,20,30,40 },
					{01,11,21,31,41 },
					{02,12,22,32,42 },
					{03,13,23,33,43 },
					{04,14,24,34,44 },
	};

	int playerX = 300; // キャラのX座標
	int playerY = 300; // キャラのY座表
	




	//グラフィックハンドル格納用配列
	int gh[12];
	LoadDivGraph("charall.png", 12, 3, 4, 49, 66, gh);
	//DrawGraph(playerX, playerY, gh[5], FALSE);// プレイヤーの画像を描画



	while (ScreenFlip() == 0 && ProcessMessage() == 0 && gpUpdateKey() == 0) {

		int 加算 = 40;
		int b = 40;


		// カーソルキーの右が押されている
		if (Key[KEY_INPUT_RIGHT] == 1) {



			//for (int i = 0; i < 3; i++) {
			playerX = playerX + 加算;
				// 画面に出力
				ScreenFlip();
				// 画面をクリア
				ClearDrawScreen();
				// プレイヤーの画像を描画

					DrawGraph(playerX, playerY, gh[6], FALSE);//DrawGraphにより何も押されていない静止時は12分割された配列の一つである、gh[6]を描画できる関数である。
			

		}

		else { while (DrawGraph(playerX, playerY, gh[5], FALSE)); }//右を押されて加算されていく中で、もし加算されない間はキャラの描画はgh[8]にする。elseを付けることで条件を否定できる。

		if (Key[KEY_INPUT_UP] == 1) {
			playerY = playerY - b; // プレイヤーのY座標を加算

			// 画面に出力
			ScreenFlip();
			// 画面をクリア
			ClearDrawScreen();
			// プレイヤーの画像を描画
			DrawGraph(playerX, playerY, gh[8], FALSE);
		}


		if (Key[KEY_INPUT_LEFT] == 1) {
			playerX = playerX - 加算; // プレイヤーのX座標を加算


			// 画面をクリア
			ClearDrawScreen();
			// プレイヤーの画像を描画
			DrawGraph(playerX, playerY, gh[10], FALSE);

		}


		if (Key[KEY_INPUT_DOWN] == 1) {
			playerY = playerY + b; // プレイヤーのY座標を加算

			// 画面に出力
			ScreenFlip();
			// 画面をクリア
			ClearDrawScreen();
			// プレイヤーの画像を描画
			DrawGraph(playerX, playerY, gh[2], FALSE);
		}

	}

	DxLib_End();                // DXライブラリ使用の終了処理

	return 0;                // ソフトの終了 

}
について、

コード:

int idou[5][5] = {
					{00,10,20,30,40 },
					{01,11,21,31,41 },
					{02,12,22,32,42 },
					{03,13,23,33,43 },
					{04,14,24,34,44 },
	};
の配列の座標{00,10,20,30,40 },01,41,02,42,03,43,{04,14,24,34,44 },は壁として定義して、
たとえば 座標32がキャラのいる座標としてidou[y+1][x+1]により、その24から右に+1移動しすると42(壁)となり移動できませんが、前もって配列の座標42は移動できないと定義して移動できないようにすることは出来なんでしょうか?

できれば、配列の座標{00,10,20,30,40 },01,41,02,42,03,43,{04,14,24,34,44 },は壁と前もって定義して、idou[y+1][x+1]により、前もって定義した壁には移動できないとしたいのですが、iキャラ移動に使うdou[y+1][x+1]は移動できるか否かを判断できないため、使えないと言われました。しかし、移動できない座標を前もって定義すれば3*3マスの座標内でdou[y+1][x+1]を使って移動できるのではないかと未だに思っています。
どうか私の勘違いや間違いがなんなのか教えてください。
どうかよろしくお願いいたします。

Ouxiy
記事: 173
登録日時: 4年前

Re: 配列を座標として障害物かどうかなぜ判断できないのかについて

#2

投稿記事 by Ouxiy » 4年前

なぜ前もって定義してもdou[y+1][x+1]を使って移動できないのかわかりません、理由が知りたいです。

アバター
みけCAT
記事: 6734
登録日時: 13年前
住所: 千葉県
連絡を取る:

Re: 配列を座標として障害物かどうかなぜ判断できないのかについて

#3

投稿記事 by みけCAT » 4年前

Ouxiy さんが書きました:
4年前
どうか私の勘違いや間違いがなんなのか教えてください。
とりあえずわかりやすい間違いとして、
  • playerYについてのコメントに、「座標」のことだと考えられる「座表」という誤字がある
  • 「座標32がキャラのいる座標」としたはずなのに、その後にいきなり謎の数字「24」がある
    (誤字で32のことだと考えられる)
  • 「移動すると」という不自然な表現がある
    (「移動すると」を表す誤字と考えられる)
  • 「出来なんでしょうか?」という不自然な表現がある
    (「出来なんでしょうか?」を表す誤字と考えられる)
  • 配列「idou」を使うはずなのに、「dou」としている誤字がある
    (iが変な位置にあるのが1件、消えているのが#1と#2に1件ずつの2件)
というのがありますね。
Ouxiy さんが書きました:
4年前
なぜ前もって定義してもdou[y+1][x+1]を使って移動できないのかわかりません、理由が知りたいです。
dou[y+1][x+1]を使って移動するコードを書いていないからでしょう。
また、仕様書や脳内だけで「前もって定義」しても、コードから読める形にしてあげないと、
コードからその定義を利用することはできません。

以下にidou[y+1][x+1]を使って移動先が壁かを判定し、
壁でなければ移動して壁なら移動しないコードを書いてみました。

コード:

#include "DxLib.h"
#include <set>

int Key[256]; // キーが押されているフレーム数を格納する

// キーの入力状態を更新する
int gpUpdateKey() {
	char tmpKey[256]; // 現在のキーの入力状態を格納する
	GetHitKeyStateAll(tmpKey); // 全てのキーの入力状態を得る
	for (int i = 0; i < 256; i++) {
		if (tmpKey[i] != 0) { // i番のキーコードに対応するキーが押されていたら
			Key[i]++;     // 加算
		}
		else {              // 押されていなければ
			Key[i] = 0;   // 0にする
		}
	}
	return 0;
}

// プログラムは WinMain から始まります
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
	SetGraphMode(1600, 680, 32); // ウィンドウの大きさを指定
	ChangeWindowMode(TRUE);

	if (DxLib_Init() == -1)        // DXライブラリ初期化処理
	{
		return -1;            // エラーが起きたら直ちに終了
	}
	SetDrawScreen(DX_SCREEN_BACK);

	//1. 3x3マスの2次元配列
	int idou[5+1][5] = {
					{00,10,20,30,40 },
					{01,11,21,31,41 },
					{02,12,22,32,42 },
					{03,13,23,33,43 },
					{04,14,24,34,44 },
	};

	// 壁リスト
	int rawWalls[] = {/*{*/00,10,20,30,40 /*}*/,01,41,02,42,03,43,/*{*/04,14,24,34,44 /*}*/};
	// 壁かどうか判定する用のオブジェクト
	std::set<int> walls;
	// 判定用オブジェクトに壁を登録する
	for (size_t i = 0; i < sizeof(rawWalls)/sizeof(*rawWalls); i++) {
		walls.insert(rawWalls[i]);
	}

	const int zeroX = 260; // マップ上の座標0にいるときのキャラのX座標
	const int zeroY = 260; // マップ上の座標0にいるときのキャラのY座標
	const int dx = 40; // マップ上の座標を1進んだときのキャラのX座標の増分
	const int dy = 40; // マップ上の座標を1進んだときのキャラのY座標の増分

	int playerX = 300; // キャラのX座標
	int playerY = 300; // キャラのY座標

	//グラフィックハンドル格納用配列
	int gh[12];
	LoadDivGraph("charall.png", 12, 3, 4, 49, 66, gh);

	while (ScreenFlip() == 0 && ProcessMessage() == 0 && gpUpdateKey() == 0) {

		// 移動先の座標
		int nextPlayerX = playerX, nextPlayerY = playerY;

		// キーの状態に応じて、移動先の座標を更新する

		if (Key[KEY_INPUT_RIGHT] == 1) {
			nextPlayerX = playerX + dx; // プレイヤーのX座標を加算
		}

		if (Key[KEY_INPUT_UP] == 1) {
			nextPlayerY = playerY - dy; // プレイヤーのY座標を加算
		}

		if (Key[KEY_INPUT_LEFT] == 1) {
			nextPlayerX = playerX - dx; // プレイヤーのX座標を加算
		}

		if (Key[KEY_INPUT_DOWN] == 1) {
			nextPlayerY = playerY + dy; // プレイヤーのY座標を加算
		}

		// 移動先が壁でなければ、実際に移動する
		// yおよびxの値は、こだわり?のidou[y+1][x+1]で+1しているのに合わせて-1する
		int y = (nextPlayerY - zeroY) / dy - 1;
		int x = (nextPlayerX - zeroX) / dx - 1;
		if (
			// 移動先が配列の範囲内かのチェック
			0 <= y+1 && y+1 < static_cast<int>(sizeof(idou)/sizeof(*idou)) &&
			0 <= x+1 && x+1 < static_cast<int>(sizeof(*idou)/sizeof(**idou)) &&
			// 移動先が壁でないかのチェック
			walls.find(idou[y+1][x+1]) == walls.end()
		) {
			// 移動する
			playerX = nextPlayerX;
			playerY = nextPlayerY;
		}

		// 画面をクリアする
		ClearDrawScreen();
		// プレイヤーを描画する
		DrawGraph(playerX, playerY, gh[5], FALSE);
	}

	DxLib_End();                // DXライブラリ使用の終了処理

	return 0;                // ソフトの終了 

}
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

アバター
みけCAT
記事: 6734
登録日時: 13年前
住所: 千葉県
連絡を取る:

Re: 配列を座標として障害物かどうかなぜ判断できないのかについて

#4

投稿記事 by みけCAT » 4年前

申し訳ありません。
#3でidouの定義を

コード:

int idou[5+1][5]
としていますが、この+1はテストした時の消し忘れです。

コード:

int idou[5][5]
としてください。

一応修正後のコード全体を貼ります。

コード:

#include "DxLib.h"
#include <set>

int Key[256]; // キーが押されているフレーム数を格納する

// キーの入力状態を更新する
int gpUpdateKey() {
	char tmpKey[256]; // 現在のキーの入力状態を格納する
	GetHitKeyStateAll(tmpKey); // 全てのキーの入力状態を得る
	for (int i = 0; i < 256; i++) {
		if (tmpKey[i] != 0) { // i番のキーコードに対応するキーが押されていたら
			Key[i]++;     // 加算
		}
		else {              // 押されていなければ
			Key[i] = 0;   // 0にする
		}
	}
	return 0;
}

// プログラムは WinMain から始まります
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
	SetGraphMode(1600, 680, 32); // ウィンドウの大きさを指定
	ChangeWindowMode(TRUE);

	if (DxLib_Init() == -1)        // DXライブラリ初期化処理
	{
		return -1;            // エラーが起きたら直ちに終了
	}
	SetDrawScreen(DX_SCREEN_BACK);

	//1. 3x3マスの2次元配列
	int idou[5][5] = {
					{00,10,20,30,40 },
					{01,11,21,31,41 },
					{02,12,22,32,42 },
					{03,13,23,33,43 },
					{04,14,24,34,44 },
	};

	// 壁リスト
	int rawWalls[] = {/*{*/00,10,20,30,40 /*}*/,01,41,02,42,03,43,/*{*/04,14,24,34,44 /*}*/};
	// 壁かどうか判定する用のオブジェクト
	std::set<int> walls;
	// 判定用オブジェクトに壁を登録する
	for (size_t i = 0; i < sizeof(rawWalls)/sizeof(*rawWalls); i++) {
		walls.insert(rawWalls[i]);
	}

	const int zeroX = 260; // マップ上の座標0にいるときのキャラのX座標
	const int zeroY = 260; // マップ上の座標0にいるときのキャラのY座標
	const int dx = 40; // マップ上の座標を1進んだときのキャラのX座標の増分
	const int dy = 40; // マップ上の座標を1進んだときのキャラのY座標の増分

	int playerX = 300; // キャラのX座標
	int playerY = 300; // キャラのY座標

	//グラフィックハンドル格納用配列
	int gh[12];
	LoadDivGraph("charall.png", 12, 3, 4, 49, 66, gh);

	while (ScreenFlip() == 0 && ProcessMessage() == 0 && gpUpdateKey() == 0) {

		// 移動先の座標
		int nextPlayerX = playerX, nextPlayerY = playerY;

		// キーの状態に応じて、移動先の座標を更新する

		if (Key[KEY_INPUT_RIGHT] == 1) {
			nextPlayerX = playerX + dx; // プレイヤーのX座標を加算
		}

		if (Key[KEY_INPUT_UP] == 1) {
			nextPlayerY = playerY - dy; // プレイヤーのY座標を加算
		}

		if (Key[KEY_INPUT_LEFT] == 1) {
			nextPlayerX = playerX - dx; // プレイヤーのX座標を加算
		}

		if (Key[KEY_INPUT_DOWN] == 1) {
			nextPlayerY = playerY + dy; // プレイヤーのY座標を加算
		}

		// 移動先が壁でなければ、実際に移動する
		// yおよびxの値は、こだわり?のidou[y+1][x+1]で+1しているのに合わせて-1する
		int y = (nextPlayerY - zeroY) / dy - 1;
		int x = (nextPlayerX - zeroX) / dx - 1;
		if (
			// 移動先が配列の範囲内かのチェック
			0 <= y+1 && y+1 < static_cast<int>(sizeof(idou)/sizeof(*idou)) &&
			0 <= x+1 && x+1 < static_cast<int>(sizeof(*idou)/sizeof(**idou)) &&
			// 移動先が壁でないかのチェック
			walls.find(idou[y+1][x+1]) == walls.end()
		) {
			// 移動する
			playerX = nextPlayerX;
			playerY = nextPlayerY;
		}

		// 画面をクリアする
		ClearDrawScreen();
		// プレイヤーを描画する
		DrawGraph(playerX, playerY, gh[5], FALSE);
	}

	DxLib_End();                // DXライブラリ使用の終了処理

	return 0;                // ソフトの終了 

}
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

Ouxiy
記事: 173
登録日時: 4年前

Re: 配列を座標として障害物かどうかなぜ判断できないのかについて

#5

投稿記事 by Ouxiy » 4年前

いつもいつもありがとうございます
すなわち前もって定義して、その定義が反映されるように書けば配列を座標として使っても良いわけですね!
大変勉強になりました。本当にありがとうございます。

返信

“C言語何でも質問掲示板” へ戻る