C++での迷路生成プログラムについて

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
迷路くん

C++での迷路生成プログラムについて

#1

投稿記事 by 迷路くん » 3年前

C++にて迷路を生成するプログラムを作っているのですが、以下のコードではうまく動作しません。
プログラム内で、successかfailureと表示される部分があるのですが、failureと出るべきところもsuccessと表示されてしまいます。
恐らくisInsideというメンバ関数に問題があるのだと考えていますが、何が間違ているのかがわからないので教えていただければと思います。
以下、ソースコードです。

コード:

#ifndef MAZEMAP_H
#define MAZEMAP_H
#include <iostream>
class MazeMap {
public:
/** 「壁」の表示 */
static const char wall = 'O';
/** 「通路」の表示 */
static const char passage = ' ';
/** 「スタート地点」の表示 */
static const char start = 'S';
/** 「ゴール地点」の表示 */
static const char goal = 'G';

/**
* コンストラクタ
* @param w 迷路幅の基底
* @param h 迷路高の基底
* @attention 実際の迷路幅は2w+1,迷路高は2h+1
*/
MazeMap(int w, int h);

/**
* デストラクタ
*/
virtual ~MazeMap();

/**
* 迷路幅用ゲッタ
* @return 迷路幅
*/
int getWidth();

/**
* 迷路高用ゲッタ
* @return 迷路高
*/
int getHeight();

/**
* 指定座標が迷路の範囲内に存在するかをチェック
* @param x x座標
* @param y y座標
* @retval true 迷路の範囲内
* @retval false 迷路の範囲外
*/
bool isInside(int x, int y);

/**
* 指定座標が壁かどうかをチェック
* @param x x座標
* @param y y座標
* @retval true 壁
* @retval false 壁でない
* @attention 指定座標が迷路範囲外であればfalse
*/
bool isWall(int x, int y);

/**
* 指定座標のマップ情報のセッタ
* @param x x座標
* @param y y座標
* @param c 要素
* @retval true 指定座標が迷路の範囲内
* @retval false 指定座標が迷路の範囲外
* @attention 要素を指定しない場合,通路とする
*/
bool set(int x, int y, char c = passage);

/**
* 指定座標のマップ情報のゲッタ
* @param x x座標
* @param y y座標
* @return マップ情報
* @attention 迷路範囲外の座標を指定した場合,'\0'を返す
*/
char get(int x, int y);

/**
* マップ情報の初期化
* @attention 全ての要素を「壁」にする
*/
void clear();
private:
/** 迷路幅 */
int width;
/** 迷路高 */
int height;
/** 迷路情報 */
char** data;
};

#endif /* MAZEMAP_H */

MazeMap::MazeMap(int w, int h) {
width = 2 * w + 1;
height = 2 * h + 1;
data = new char* [width];
for (int i = 0; i < width; ++i) {
data = new char[height];
}
}

MazeMap::~MazeMap() {
for (int i = 0; i < width; ++i) {
delete[] data;
}
delete[] data;
}


int MazeMap::getWidth() {
return width;
}

int MazeMap::getHeight() {
return height;
}

bool MazeMap::isInside(int x, int y) {
if ((0 <= x < width) && (0 <= y < height)) {
std::cout << "Inside true" << std::endl;
return true;
}
else {
std::cout << "Inside false" << std::endl;
return false;
}
}

bool MazeMap::isWall(int x, int y) {
if (isInside(x, y) == false) {
return false;
}
if (**data == wall) {
return true;
}
else {
return false;
}
}

bool MazeMap::set(int x, int y, char c) {
if (isInside(x, y) == true) {
std::cout << "Set true" << std::endl;
**data = c;
return true;
}
else {
std::cout << "Set false" << std::endl;
return false;
}
}

char MazeMap::get(int x, int y) {
return data[x][y];
}

void MazeMap::clear() {
for (int i = 0; i < width; i++) {
for (int j = 0; j < height; j++)
data[j] = wall;
}
}

/**
* 迷路の表示
* @param mazeMap mazeMapインスタンスの参照
*/
void printMap(MazeMap& mazeMap) {
for (int y = 0; y < mazeMap.getHeight(); ++y) {
for (int x = 0; x < mazeMap.getWidth(); ++x) {
std::cout << mazeMap.get(x, y); // get()を使って表示
}
std::cout << std::endl;
}
std::cout << std::endl;
}

/**
* 指定座標を通路に設定
* @param mazeMap MazeMapインスタンスの参照
* @param x x座標
* @param y y座標
*/
void testSet(MazeMap& mazeMap, int x, int y) {
std::cout << "set(" << x << ", " << y << ") = " << (mazeMap.set(x, y) ? "success" : "failure") << std::endl;
}

/**
* 指定座標が迷路範囲内かどうかをチェックし,結果を出力
* @param mazeMap mazeMapインスタンスの参照
* @param x x座標
* @param y y座標
*/
void testIsInside(MazeMap& mazeMap, int x, int y) {
std::cout << "(" << x << ", " << y << ") = " << (mazeMap.isInside(x, y) ? "inside" : "outside") << std::endl;
}

/**
* 指定座標が壁かどうかをチェックし,結果を出力
* @param mazeMap mazeMapインスタンスの参照
* @param x x座標
* @param y y座標
*/
void testIsWall(MazeMap& mazeMap, int x, int y) {
std::cout << "(" << x << ", " << y << ") " << (mazeMap.isWall(x, y) ? "= " : "!= ") << "wall" << std::endl;
}

int main() {
MazeMap mazeMap(2, 1);

// マップのサイズを表示
// (マップのサイズはコンストラクタに渡した値を 2倍して1足した値)
std::cout << "width=" << mazeMap.getWidth() << std::endl;
std::cout << "height=" << mazeMap.getHeight() << std::endl;

// 迷路データクリア 全て壁 'O'になる
mazeMap.clear();

// set()の動作チェック
std::cout << "##### Test for set #####" << std::endl;
testSet(mazeMap, 0, 1); // success
testSet(mazeMap, 1, 1); // success 
testSet(mazeMap, 2, 1); // success 
testSet(mazeMap, 2, 2); // success 
testSet(mazeMap, 6, 4); // failure 
testSet(mazeMap, -1, 0); // failure 

// 中身を表示 (意図した通りにセットされているかをチェック)
std::cout << "##### Print Map #####" << std::endl;
printMap(mazeMap);

// isInside()の動作チェック
std::cout << "##### Test for isInside #####" << std::endl;
testIsInside(mazeMap, 0, 0); // inside
testIsInside(mazeMap, mazeMap.getWidth() - 1, 0); // inside
testIsInside(mazeMap, 0, mazeMap.getHeight() - 1); // inside
testIsInside(mazeMap, -1, -1); // outside
testIsInside(mazeMap, mazeMap.getWidth() + 1, 0); // outside
testIsInside(mazeMap, 0, mazeMap.getHeight() + 1); // outside
testIsInside(mazeMap, mazeMap.getWidth(), 0); // outside
testIsInside(mazeMap, 0, mazeMap.getHeight()); // outside

// isWall()の動作チェック
std::cout << "##### Test for isWall #####" << std::endl;
testIsWall(mazeMap, 0, 0); // wall
testIsWall(mazeMap, 1, 0); // wall
testIsWall(mazeMap, -1, -1); // not wall 範囲外は壁ではない
testIsWall(mazeMap, 1, 1); // not wall
testIsWall(mazeMap, 2, 1); // not wall
std::cout << std::endl;

// 再び迷路データクリア 全て壁
mazeMap.clear();

std::cout << "##### Print Map #####" << std::endl;
printMap(mazeMap);
return 0;
}

アバター
あたっしゅ
記事: 664
登録日時: 13年前
住所: 東京23区
連絡を取る:

Re: C++での迷路生成プログラムについて

#2

投稿記事 by あたっしゅ » 3年前

 インデント(字下げ)のとれちゃったものを

コード:

で囲っても意味がないんですが。
とりあえず、Visual Studio 2019 にペーストしてみたところ、オート・インデントしてくれましたが。
 で、ビルドしてみたんですが、エラーでます。ソースコードの UP ミスでしょうか ?
それとも、このままでビルドできるコンパイラがあるのでしょうか ?

1.

コード:

MazeMap::MazeMap(int w, int h) {
	width = 2 * w + 1;
	height = 2 * h + 1;
	data = new char* [width];
	for (int i = 0; i < width; ++i) {
		data = new char[height];
	}
}
MazeMap::~MazeMap() {
	for (int i = 0; i < width; ++i) {
		delete[] data;
	}
	delete[] data;
}

コード:

MazeMap::MazeMap(int w, int h) {
	width = 2 * w + 1;
	height = 2 * h + 1;
	data = new char* [width];
	for (int i = 0; i < width; ++i) {
		data[i] = new char[height];
	}
}
MazeMap::~MazeMap() {
	for (int i = 0; i < width; ++i) {
		delete data[i];
	}
	delete data;
}
の間違いですかね。

2.

コード:

bool MazeMap::isInside(int x, int y) {
	if ((0 <= x < width) && (0 <= y < height)) {
		std::cout << "Inside true" << std::endl;
		return true;
	}
	else {
		std::cout << "Inside false" << std::endl;
		return false;
	}
}
C/C++ では、「0 <= x < width」とか「0 <= y < height」できません。
「(0 <= x)&&(x < width )」や「(0 <= y)&&(y< height)」と書きましょう。

コード:

bool MazeMap::isInside(int x, int y) {
	if ((0 <= x)&&(x < width )&&(0 <= y)&&(y< height)) {
		std::cout << "Inside true" << std::endl;
		return true;
	}
	else {
		std::cout << "Inside false" << std::endl;
		return false;
	}
}
3.

コード:

void MazeMap::clear() {
	for (int i = 0; i < width; i++) {
		for (int j = 0; j < height; j++)
			data[j] = wall;
	}
}

コード:

void MazeMap::clear() {
	for (int i = 0; i < width; i++) {
		for (int j = 0; j < height; j++)
			data[i][j] = wall;
	}
}
ですかね。

 で、
>プログラム内で、successかfailureと表示される部分があるのですが、
>failureと出るべきところもsuccessと表示されてしまいます。
>恐らくisInsideというメンバ関数に問題があるのだと考えていますが、
>何が間違ているのかがわからないので教えていただければと思います。

コード:

bool MazeMap::isWall(int x, int y) {
	if (isInside(x, y) == false) {
		return false;
	}
	if (**data == wall)
	{
		return true;
	}
	else {
		return false;
	}
}

bool MazeMap::set(int x, int y, char c) {
	if (isInside(x, y) == true) {
		std::cout << "Set true" << std::endl;
		**data = c;
		return true;
	}
	else {
		std::cout << "Set false" << std::endl;
		return false;
	}
}

コード:

bool MazeMap::isWall(int x, int y) {
	if (isInside(x, y) == false) {
		return false;
	}
	if (data[x][y] == wall)// by Atassyu
	{
		return true;
	}
	else {
		return false;
	}
}

bool MazeMap::set(int x, int y, char c) {
	if (isInside(x, y) == true) {
		std::cout << "Set true" << std::endl;
		data[x][y] = c; // by Atassyu 
		return true;
	}
	else {
		std::cout << "Set false" << std::endl;
		return false;
	}
}
ではないでしょうか ?
VTuber:
東上☆海美☆(とうじょう・うみみ)
http://atassyu.php.xdomain.jp/vtuber/index.html
レスがついていないものを優先して、レスするみみ。時々、見当外れなレスしみみ。

中の人:
手提鞄あたッしュ、[MrAtassyu] 手提鞄屋魚有店
http://ameblo.jp/mratassyu/
Pixiv: 666303
Windows, Mac, Linux, Haiku, Raspbery Pi, Jetson Nano, 電子ブロック 持ち。

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

Re: C++での迷路生成プログラムについて

#3

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

あたっしゅ さんが書きました:
3年前
1.

コード:

MazeMap::MazeMap(int w, int h) {
	width = 2 * w + 1;
	height = 2 * h + 1;
	data = new char* [width];
	for (int i = 0; i < width; ++i) {
		data = new char[height];
	}
}
MazeMap::~MazeMap() {
	for (int i = 0; i < width; ++i) {
		delete[] data;
	}
	delete[] data;
}

コード:

MazeMap::MazeMap(int w, int h) {
	width = 2 * w + 1;
	height = 2 * h + 1;
	data = new char* [width];
	for (int i = 0; i < width; ++i) {
		data[i] = new char[height];
	}
}
MazeMap::~MazeMap() {
	for (int i = 0; i < width; ++i) {
		delete data[i];
	}
	delete data;
}
の間違いですかね。
new[]で確保したメモリの開放にはdelete[]を使わなければならず、
この後者のコードのようにdeleteで開放してはいけません。
実際に、new[]で確保したメモリをdeleteで開放してしまうと、
実行時エラーになる例を確認できました。
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

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

Re: C++での迷路生成プログラムについて

#4

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

オフトピック
やはり[​/i]がなくても[​i]が斜体タグと認識される仕様は実害が発生する悪い仕様だ。
早く撤廃されてほしいなあ。
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

アバター
あたっしゅ
記事: 664
登録日時: 13年前
住所: 東京23区
連絡を取る:

Re: C++での迷路生成プログラムについて

#5

投稿記事 by あたっしゅ » 3年前

コード:

MazeMap::~MazeMap() {
	for (int i = 0; i < width; ++i) {
		delete[] data[i];
	}
	delete[] data;
}
ですかね。

https://ja.stackoverflow.com/questions/ ... 9%E3%81%8B
c++ - delete[] a; どうしてdelete[]←ここに値がないのに配列を廃棄できるのですか - スタック・オーバーフロー(ja)

とか読んでて、delete[n]じゃなくて、delete[] 自体がいらなくなったと勘違いしてしまいした。
Visual Studio 2019 で、コンパイルエラーも、実行時エラーもでなくなったんで。


http://superactionshootinggame4.hatenab ... /26/135038
deleteとdelete[ ]の違い - Super Action Shooting Game4(ja)


http://qwertyfk.blog16.fc2.com/blog-entry-101.html
プログラミングメモ日記 C++ の delete と delete[] の違い(ja)
VTuber:
東上☆海美☆(とうじょう・うみみ)
http://atassyu.php.xdomain.jp/vtuber/index.html
レスがついていないものを優先して、レスするみみ。時々、見当外れなレスしみみ。

中の人:
手提鞄あたッしュ、[MrAtassyu] 手提鞄屋魚有店
http://ameblo.jp/mratassyu/
Pixiv: 666303
Windows, Mac, Linux, Haiku, Raspbery Pi, Jetson Nano, 電子ブロック 持ち。

返信

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