配列の1の位置をplayerX、playerYとしたい、

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

配列の1の位置をplayerX、playerYとしたい、

#1

投稿記事 by Ouxiy » 3ヶ月前

コード:

#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[3][3] = {
					{0, 0, 0 },
					{0, 1, 0 },
					{0, 0, 0 }
	};

	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;                // ソフトの終了 

}
が全体のコードです。
ここから行いたいことは二つあります。
一つは題名にも書いた通りの配列idou[3][3]の1の位置をplayerX、playerYとしたいです。
二つ目は、配列の3*3という制限の中のみでキャラを移動させたいです。

コード:

例えば、
int idou[3][3] = {
					{0, 0, 0 },
					{0, 1, 0 },
					{0, 0, 0 }
	};
右に移動させたいときにplayerX+1により、
int idou[3][3] = {
					{0, 0, 0 },
					{0, 0, 1 },
					{0, 0, 0 }
	};と書くことで右への一マス移動を可能にしたいです。(すべての場合を書いて9マス移動を可能にしたいです。)

Ouxiy
記事: 166
登録日時: 4ヶ月前

Re: 配列の1の位置をplayerX、playerYとしたい、

#2

投稿記事 by Ouxiy » 3ヶ月前

質問1に関しては
配列idou[3][3]の1の位置をplayerX、playerYとしたいです。
ただ、配列の1の座標は[1][1]なので、この[1][1]とplayerXと=にできればplayerXの位置は配列の1を表せるのかなと考えていますが、入門書に詳しく書いていないため、わかりません。
どうすれば[1][1]とplayerXと=にすればいいのか詰んでいます。

Ouxiy
記事: 166
登録日時: 4ヶ月前

Re: 配列の1の位置をplayerX、playerYとしたい、

#3

投稿記事 by Ouxiy » 3ヶ月前

最初の投稿のマスに関して
例えば、真ん中の1はキャラとして周りの1は壁とします。

コード:

int idou[5][5] = {
{1,1,1,1,1 },
{1,0,0,0,1 },
{1,0,1,0,1 },
{1,0,0,0,1 },
{1,1,1,1,1 },
};
右に移動させたいときにplayerX(プレイヤーの位置(座標))+1により、

コード:

int idou[5][5] = {
{1,1,1,1,1 },
{1,0,0,0,1 },
{1,0,0,1,1 },
{1,0,0,0,1 },
{1,1,1,1,1 },
};
と書くことで右への一マス移動を可能にしたいです。(すべての場合を書いて9マス移動を可能にしたいです。)

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

Re: 配列の1の位置をplayerX、playerYとしたい、

#4

投稿記事 by みけCAT » 3ヶ月前

Ouxiy さんが書きました:
3ヶ月前
質問1に関しては
配列idou[3][3]の1の位置をplayerX、playerYとしたいです。
playerX、playerYに1の位置を入れたい、ということでしょうか?
以下のコードは、配列から1を探し、その位置をplayerXおよびplayerYに入れます。

コード:

// 探す対象の配列
int idou[3][3] = {
				{0, 0, 0 },
				{0, 1, 0 },
				{0, 0, 0 }
};

// 結果を入れる変数
int playerX = -1, playerY = -1;

// 配列から1を探し、結果を入れる (1が複数ある場合、最後に見つかったものの座標が入る)
for (int y = 0; y < static_cast<int>(sizeof(idou) / sizeof(*idou)); y++) {
	for (int x = 0; x < static_cast<int>(sizeof(*idou) / sizeof(**idou)); x++) {
		if (idou[y][x] == 1) {
			playerX = x;
			playerY = y;
		}
	}
}
もしくは、1の位置が[1][1]だとわかっているのであれば、素直に

コード:

playerX = 1;
playerY = 1;
でいいのではないでしょうか?
Ouxiy さんが書きました:
3ヶ月前

コード:

例えば、
int idou[3][3] = {
					{0, 0, 0 },
					{0, 1, 0 },
					{0, 0, 0 }
	};
右に移動させたいときにplayerX+1により、
int idou[3][3] = {
					{0, 0, 0 },
					{0, 0, 1 },
					{0, 0, 0 }
	};と書くことで右への一マス移動を可能にしたいです。(すべての場合を書いて9マス移動を可能にしたいです。)
Ouxiy さんが書きました:
3ヶ月前
最初の投稿のマスに関して
例えば、真ん中の1はキャラとして周りの1は壁とします。

コード:

int idou[5][5] = {
{1,1,1,1,1 },
{1,0,0,0,1 },
{1,0,1,0,1 },
{1,0,0,0,1 },
{1,1,1,1,1 },
};
右に移動させたいときにplayerX(プレイヤーの位置(座標))+1により、

コード:

int idou[5][5] = {
{1,1,1,1,1 },
{1,0,0,0,1 },
{1,0,0,1,1 },
{1,0,0,0,1 },
{1,1,1,1,1 },
};
と書くことで右への一マス移動を可能にしたいです。(すべての場合を書いて9マス移動を可能にしたいです。)
「すべての場合を書いて」という条件に当てはまるかはよくわかりませんが、
playerXでプレイヤーの座標を取得できるようにしつつ、
playerX+1のような書き方でプレイヤーの位置を移動できるようにしてみました。
(このコードでは前提が違うので、この回答の前半のようなplayerXやplayerYへの座標の代入はできません)

コード:

#include "DxLib.h"

// 0 : #1のコードにある3x3の配列を使用する
// 1 : #3のコードにある5x5の配列を使用する
// 2 : 配列の縦と横の要素数が違ってもきちんと動くことのテスト
#define MODE 1

template<typename T>
struct NonZeroJudger {
	bool operator()(const T& target) const {
		return target != 0;
	}
};

// 配列操作用クラス
template<typename T, int rows, int cols, class cancelCondition = NonZeroJudger<T> >
class ArrayController {
	T (*array)[cols];
	int x, y;
	cancelCondition j;
public:
	template <int x_mul, int y_mul>
	class AddSubController {
		ArrayController<T, rows, cols, cancelCondition>* controller;
	public:
		AddSubController(ArrayController<T, rows, cols, cancelCondition>* c) : controller(c) {}
		
		void operator+(int d) {
			if (controller) controller->moveTarget(d * x_mul, d * y_mul);
		}

		void operator-(int d) {
			if (controller) controller->moveTarget(-d * x_mul, -d * y_mul);
		}

		operator int() const {
			return controller->getX() * x_mul + controller->getY() * y_mul;
		}
	};
	typedef AddSubController<1, 0> xController;
	typedef AddSubController<0, 1> yController;

	ArrayController(T (*array_)[cols], int x_ = -1, int y_ = -1) : array(array_), x(x_), y(y_) {}

	// 操作対象の座標を設定する
	void setTarget(int x_, int y_) {
		if (x_ < 0 || cols <= x_ || y_ < 0 || rows <= y_) return;
		x = x_;
		y = y_;
	}

	// 操作対象を動かす (指定した量移動したマスの値と入れ替える)
	void moveTarget(int dx, int dy) {
		// 移動先を求める
		int nx = x + dx;
		int ny = y + dy;
		// 移動先が範囲外なら、キャンセルする
		if (nx < 0 || cols <= nx || ny < 0 || rows <= ny) return;
		// 移動先が移動できないマス(デフォルトでは非0)なら、キャンセルする
		if (j(array[ny][nx])) return;
		// 移動を行う
		T temp = array[y][x];
		array[y][x] = array[ny][nx];
		array[ny][nx] = temp;
		x = nx;
		y = ny;
	}

	// 座標を取得する
	int getX(void) const {
		return x;
	}
	int getY(void) const {
		return y;
	}

	// 加減算演算子で操作する用のオブジェクトを取得する
	xController getXController(void) {
		return xController(this);
	}
	yController getYController(void) {
		return yController(this);
	}
};

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

#if MODE == 0
	//1. 3x3マスの2次元配列
	int idou[3][3] = {
					{0, 0, 0 },
					{0, 1, 0 },
					{0, 0, 0 }
	};
#elif MODE == 1
	int idou[5][5] = {
		{1,1,1,1,1 },
		{1,0,0,0,1 },
		{1,0,1,0,1 },
		{1,0,0,0,1 },
		{1,1,1,1,1 },
	};
#elif MODE == 2
	int idou[7][10] = {
		{1,1,1,1,1,1,1,1,1,1},
		{1,0,0,0,0,0,0,0,0,0},
		{1,1,1,0,1,1,1,1,1,1},
		{0,0,1,0,0,1,0,0,0,1},
		{1,0,1,1,0,1,0,1,0,1},
		{1,0,0,0,0,0,0,1,0,1},
		{1,1,1,1,1,1,1,1,0,1}
	};
#else
#error invalid MODE
#endif
	// 座標操作用オブジェクト
	const int idouHeight = sizeof(idou) / sizeof(*idou);
	const int idouWidth = sizeof(*idou) / sizeof(**idou);
	ArrayController<int, idouHeight, idouWidth> controller(idou);
	ArrayController<int, idouHeight, idouWidth>::xController playerX = controller.getXController();
	ArrayController<int, idouHeight, idouWidth>::yController playerY = controller.getYController();
	// 初期座標を登録する
#if MODE == 0
	controller.setTarget(1, 1);
#elif MODE == 1
	controller.setTarget(2, 2);
#elif MODE == 2
	controller.setTarget(1, 0);
#endif

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

		if (Key[KEY_INPUT_RIGHT] == 1) {
			playerX + 1;
		}

		if (Key[KEY_INPUT_UP] == 1) {
			playerY - 1;
		}

		if (Key[KEY_INPUT_LEFT] == 1) {
			playerX - 1;
		}

		if (Key[KEY_INPUT_DOWN] == 1) {
			playerY + 1;
		}

		// 画面をクリア
		ClearDrawScreen();
		// 座標を描画
		DrawFormatString(10, 10, GetColor(255, 255, 255), "(%d, %d)",
			static_cast<int>(playerX), static_cast<int>(playerY));
		// idouの状態を描画
		for (int y = 0; y < idouHeight; y++) {
			for (int x = 0; x < idouWidth; x++) {
				DrawFormatString(10 + x * 50, 100 + y * 30, GetColor(255, 255, 255), "%d", idou[y][x]);
			}
		}
	}

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

	return 0;                // ソフトの終了 

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

Ouxiy
記事: 166
登録日時: 4ヶ月前

Re: 配列の1の位置をplayerX、playerYとしたい、

#5

投稿記事 by Ouxiy » 3ヶ月前

詳しい回答とコードありがとうございます。
やはり配列だけで書くのは難しいですね。(面倒としうか、、、)
一つお聞きしたい場合があります。
0は空のマス、1はキャラとして9マス内の制限での移動は

コード:

int idou[3][3] = {
				{0, 0, 0 },
				{0, 1, 0 },
				{0, 0, 0 }
};
として、キャラの位置は

コード:

playerX = 1;
playerY = 1;
からplayerX=(キーの右に一回入力)+1として

コード:

idou[3][3] = {
				{0, 0, 0 },
				{0, 0, 1 },
				{0, 0, 0 }
};

コード:

playerX = 2;
playerY = 1;
と書いた際に、idou[3][3]を

コード:

int idou[5][5] = {
{1,1,1,1,1 },
{1,0,0,0,1 },
{1,0,1,0,1 },
{1,0,0,0,1 },
{1,1,1,1,1 },
};
と書かなくても、

コード:

int idou[3][3] = {
				{0, 0, 0 },
				{0, 1, 0 },
				{0, 0, 0 }
};
で9マス内での移動としてキャラを動かせるのでしょうか?
int idou[5][5]のように1で空0囲まないと9マス内の移動と出来ないのでしょうか。
というもの、私個人としてはidou[3][3]は0を空のマス、1をキャラと決めたため、idou[5][5] では0を空のマス、1を壁と置いたため、idou[3][3]は0を空のマス、1をキャラとしたためidou[3][3]でも9マス内のみを動くキャラの配列にできたと思います。

Ouxiy
記事: 166
登録日時: 4ヶ月前

Re: 配列の1の位置をplayerX、playerYとしたい、

#6

投稿記事 by Ouxiy » 3ヶ月前

後、みけCATさんはどのようなCやC++の入門書を読んでいますか?

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

Re: 配列の1の位置をplayerX、playerYとしたい、

#7

投稿記事 by みけCAT » 3ヶ月前

Ouxiy さんが書きました:
3ヶ月前
idou[3][3]を

コード:

int idou[5][5] = {
{1,1,1,1,1 },
{1,0,0,0,1 },
{1,0,1,0,1 },
{1,0,0,0,1 },
{1,1,1,1,1 },
};
と書かなくても、

コード:

int idou[3][3] = {
				{0, 0, 0 },
				{0, 1, 0 },
				{0, 0, 0 }
};
で9マス内での移動としてキャラを動かせるのでしょうか?
はい。
移動先が範囲内かのチェックをして、範囲内の場合のみ動かすようにすればいいでしょう。
Ouxiy さんが書きました:
3ヶ月前
int idou[5][5]のように1で空0囲まないと9マス内の移動と出来ないのでしょうか。
いいえ。
ただし、1で囲んでおくことで範囲内かのチェックを省略することができます。
このテクニックを「番兵法」といいます。
Ouxiy さんが書きました:
3ヶ月前
後、みけCATさんはどのようなCやC++の入門書を読んでいますか?
本ではない(今は本にもなっています)が、
C言語は苦しんで覚えるC言語で学びました。
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

Ouxiy
記事: 166
登録日時: 4ヶ月前

Re: 配列の1の位置をplayerX、playerYとしたい、

#8

投稿記事 by Ouxiy » 3ヶ月前

ご親切に回答して頂きありがとうございます!

返信

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