セーブやロードをする範囲を変化させたい

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

セーブやロードをする範囲を変化させたい

#1

投稿記事 by bonbo » 13年前

Map[5][200][200]とIntNum[5][200][200]の
セーブ、ロードを行う関数を作ったのですが

コード:

			//データのセーブ
		void Save( int (*Map)[200][200],int(*IntNum)[200][200])
		{
			FILE *fp ;

			fp = fopen( "Map.dat" , "wb" ) ;
			if( fp == NULL ) return ;
			// データの書き出し
			for(int i=0;i<200;i++)                                                                     //これだと200*200*2*5=40万も保存しなければいけない
				for(int j=0;j<200;j++)
					for(int k=0;k<5;k++){
						fwrite( &Map[k][j][i] , sizeof(Map[k][j][i] ) , 1 , fp ) ;           //このMapと
						fwrite( &IntNum[k][j][i] , sizeof(IntNum[k][j][i] ) , 1 , fp ) ;   //Intnumを保存したい
					}
			// ファイルを閉じる
			fclose( fp ) ;
		}

		// ロード
		void Load(int (*Map)[200][200],int (*IntNum)[200][200])
		{
			FILE *fp ;
			fp = fopen( "Map.dat" , "rb" ) ;
			if( fp == NULL )
			{
			for(int i=0;i<200;i++)
				for(int j=0;j<200;j++)
					for(int k=0;k<5;k++){
						Map[k][j][i];
						IntNum[k][j][i];
					}
			}
			else
			{

				// データの読み込み
				for(int i=0;i<200;i++)
					for(int j=0;j<200;j++)
						for(int k=0;k<5;k++){
							fread( &Map[k][j][i] , sizeof( Map[k][j][i] ) , 1 , fp ) ;
							fread( &IntNum[k][j][i] , sizeof( IntNum[k][j][i] ) , 1 , fp ) ;
						}
			fwrite( &boxXmax , sizeof( boxXmax ) , 1 , fp ) ;
			fwrite( &boxYmax , sizeof( boxYmax ) , 1 , fp ) ;

				// ファイルを閉じる
				fclose( fp ) ;
			}
		}




上記のはうまくいったのですが、これだとファイルサイズがばかでかくなってしまうので改良しようと思い以下のように変えました。

コード:

			//データのセーブ
		void Save( int (*Map)[200][200],int(*IntNum)[200][200],int boxXmax,int boxYmax )//boxXmax,boxYmaxは横幅、縦幅それぞれの最大値です
		{
			FILE *fp ;

			fp = fopen( "Map.dat" , "wb" ) ;
			if( fp == NULL ) return ;
			// データの書き出し
			for(int i=0;i<boxXmax;i++)
				for(int j=0;j<boxYmax;j++)
					for(int k=0;k<5;k++){
						fwrite( &Map[k][j][i] , sizeof(Map[k][j][i] ) , 1 , fp ) ;           //このMapと
						fwrite( &IntNum[k][j][i] , sizeof(IntNum[k][j][i] ) , 1 , fp ) ;   //Intnumと
					}
			fwrite( &boxXmax , sizeof( boxXmax ) , 1 , fp ) ;                              //boxXmaxと
			fwrite( &boxYmax , sizeof( boxYmax ) , 1 , fp ) ;                              //boxYmaxを保存したい
			// ファイルを閉じる
			fclose( fp ) ;
		}

		// ロード
		void Load(int (*Map)[200][200],int (*IntNum)[200][200],int *boxXmax,int *boxYmax)
		{
			FILE *fp ;
			fp = fopen( "Map.dat" , "rb" ) ;
			if( fp == NULL )
			{
			for(int i=0;i<200;i++)
				for(int j=0;j<200;j++)
					for(int k=0;k<5;k++){
						Map[k][j][i];
						IntNum[k][j][i];
					}
			}
			else
			{

				// データの読み込み
				for(int i=0;i<200;i++)
					for(int j=0;j<200;j++)
						for(int k=0;k<5;k++){
							fread( &Map[k][j][i] , sizeof( Map[k][j][i] ) , 1 , fp ) ;
							fread( &IntNum[k][j][i] , sizeof( IntNum[k][j][i] ) , 1 , fp ) ;
						}
			fwrite( &boxXmax , sizeof( boxXmax ) , 1 , fp ) ;
			fwrite( &boxYmax , sizeof( boxYmax ) , 1 , fp ) ;

				// ファイルを閉じる
				fclose( fp ) ;
			}
		}


すると、ファイルのサイズは小さくなったのですが今度はうまく読み込んでくれなくなってしましました。

配列のサイズが違うのがおかしいのかも..?とかいろいろ考えてみたのですが、なかなか解決できなかったので質問させていただきました。
わかりにくくて申し訳ないのですが、よろしくおねがいします。

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 15年前
住所: 東海地方
連絡を取る:

Re: セーブやロードをする範囲を変化させたい

#2

投稿記事 by softya(ソフト屋) » 13年前

書き出しファイルにboxXmax * boxYmax * 5個しか書いていないにもかかわらず、読み込みで200x200x5個ある前提で読み込んでいるからでしょう。
サイズをファイルの最後に書いていますがファイルの先頭に書いて、読み込む時に先にサイズを読み取ってサイズ分読み込む様にして下さい。
書き出し時に
fwrite( &boxXmax , sizeof( boxXmax ) , 1 , fp ) ; //boxXmaxと
fwrite( &boxYmax , sizeof( boxYmax ) , 1 , fp ) ; //boxYmaxを保存したい。
これをファイル先頭にします。

あとLoadでfwriteしているのはバグですよ。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

bonbo

セーブやロードをする範囲を変化させたい

#3

投稿記事 by bonbo » 13年前

>>softyaさん
ありがとうございます。Saveの中でfwiteを前に持ってきて、Loadの中でboxXmax*boxYmax*5個読み込むように変えました。
ただ、まだエラーで動きません…ほかにおかしい点があれば指摘してもらえないでしょうか…

コード:

		//セーブ
		void Save( int (*Map)[200][200],int(*IntNum)[200][200],int boxXmax,int boxYmax )
		{
			FILE *fp ;
			fp = fopen( "Map.dat" , "wb" ) ;
			if( fp == NULL ) return ;

			//データの書き出し
			fwrite( &boxXmax , sizeof( boxXmax ) , 1 , fp ) ;
			fwrite( &boxYmax , sizeof( boxYmax ) , 1 , fp ) ;
			for(int i=0;i<boxXmax;i++)
				for(int j=0;j<boxYmax;j++)
					for(int k=0;k<5;k++){
						fwrite( &Map[k][j][i] , sizeof(Map[k][j][i] ) , 1 , fp ) ;
						fwrite( &IntNum[k][j][i] , sizeof(IntNum[k][j][i] ) , 1 , fp ) ;
					}

			// ファイルを閉じる
			fclose( fp ) ;
		}

		//ロード
		void Load(int (*Map)[200][200],int (*IntNum)[200][200],int *boxXmax,int *boxYmax)
		{
			FILE *fp ;
			fp = fopen( "Map.dat" , "rb" ) ;
			if( fp == NULL )
			{
			for(int i=0;i<200;i++)
				for(int j=0;j<200;j++)
					for(int k=0;k<5;k++){
						Map[k][j][i];
						IntNum[k][j][i];

					}
			}
			else
			{

				//データの読み込み
				fread( &boxYmax , sizeof( boxYmax ) , 1 , fp ) ;
				fread( &boxXmax , sizeof( boxXmax ) , 1 , fp ) ;
				for(int i=0;i<*boxXmax;i++)
					for(int j=0;j<*boxYmax;j++)
						for(int k=0;k<5;k++){
							fread( &Map[k][j][i] , sizeof( Map[k][j][i] ) , 1 , fp ) ;
							fread( &IntNum[k][j][i] , sizeof( IntNum[k][j][i] ) , 1 , fp ) ;
						}

				// ファイルを閉じる
				fclose( fp ) ;
			}
		}

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 15年前
住所: 東海地方
連絡を取る:

Re: セーブやロードをする範囲を変化させたい

#4

投稿記事 by softya(ソフト屋) » 13年前

エラーの内容をもっと正確に伝えて下さい。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

bonbo

Re: セーブやロードをする範囲を変化させたい

#5

投稿記事 by bonbo » 13年前

>>softyaさん
すみません…
内容は、Load関数を呼び出したときに、

「map.exeは動作を停止しました
この問題の解決策を検索しています…」

と出てそこでエラーで終了してしまうというものです。

コード:

int a=1;
scanf("%d",&a);
if(a==0)
       Load(map,InterNumber,&boxXmax,&boxYmax);
のような形でLoad関数を呼び出しているだけなので外部には問題はないはずなのですが…

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 15年前
住所: 東海地方
連絡を取る:

Re: セーブやロードをする範囲を変化させたい

#6

投稿記事 by softya(ソフト屋) » 13年前

Loadで引数のint *boxXmax,int *boxYmaxは元々ポインタなので、fread( &boxYmax , sizeof( boxYmax ) , 1 , fp ) ;の&boxYmaxだとダブルポインタになってしまいますので、この場合何処に読み込まれるかは神ののみぞ知るです。たいていは読み込んではいけない領域に読み込みます。
デバッガで動作させれば、その実行エラー行を示してくれるはずですが?

こういうミスを避けるために引数ではポインタならboxYmax_ptrなど変数名を変えることをおすすめします。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

bonbo

Re: セーブやロードをする範囲を変化させたい

#7

投稿記事 by bonbo » 13年前

一応読み込みはできるようになったのですが、今度は正しく読み込めない状態に逆戻りしてしまいました…
Saveで正しく書き込みができていないのでしょうか…

コード:

		//セーブ
		void Save( int (*Map)[200][200],int(*IntNum)[200][200],int boxXmax,int boxYmax )
		{
			FILE *fp ;
			fp = fopen( "Map.dat" , "wb" ) ;
			if( fp == NULL ) return ;

			//データの書き出し
			fwrite( &boxXmax , sizeof( boxXmax ) , 1 , fp ) ;
			fwrite( &boxYmax , sizeof( boxYmax ) , 1 , fp ) ;
			for(int i=0;i<boxXmax;i++)
				for(int j=0;j<boxYmax;j++)
					for(int k=0;k<5;k++){
						fwrite( &Map[k][j][i] , sizeof(Map[k][j][i] ) , 1 , fp ) ;
						fwrite( &IntNum[k][j][i] , sizeof(IntNum[k][j][i] ) , 1 , fp ) ;
					}

			// ファイルを閉じる
			fclose( fp ) ;
		}

		//ロード
		void Load(int (*Map)[200][200],int (*IntNum)[200][200],int boxXmax,int boxYmax)
		{
			FILE *fp ;
			fp = fopen( "Map.dat" , "rb" ) ;
			if( fp == NULL )
			{
			for(int i=0;i<200;i++)
				for(int j=0;j<200;j++)
					for(int k=0;k<5;k++){
						Map[k][j][i];
						IntNum[k][j][i];

					}
			}
			else
			{

				//データの読み込み
				fread( &boxYmax , sizeof( boxYmax ) , 1 , fp ) ;
				fread( &boxXmax , sizeof( boxXmax ) , 1 , fp ) ;
				for(int i=0;i<boxXmax;i++)
					for(int j=0;j<boxYmax;j++)
						for(int k=0;k<5;k++){
							fread( &Map[k][j][i] , sizeof( Map[k][j][i] ) , 1 , fp ) ;
							fread( &IntNum[k][j][i] , sizeof( IntNum[k][j][i] ) , 1 , fp ) ;
						}

				// ファイルを閉じる
				fclose( fp ) ;
			}
		}

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 15年前
住所: 東海地方
連絡を取る:

Re: セーブやロードをする範囲を変化させたい

#8

投稿記事 by softya(ソフト屋) » 13年前

bonbo さんが書きました:一応読み込みはできるようになったのですが、今度は正しく読み込めない状態に逆戻りしてしまいました…
Saveで正しく書き込みができていないのでしょうか…
デバッグ方法について説明します。
(1)バイナリエディタで出来上がったファイル内容を必ず確認する。
(2)読み込み時にデバッガで指定行でブレークさせて、ちゃんと読み込まれているか変数を確認する。
(3)Loadの呼び出し元に、ちゃんと値を返せているか確認する。
以上を実践してみて下さい。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

bonbo

Re: セーブやロードをする範囲を変化させたい

#9

投稿記事 by bonbo » 13年前

バイナリエディタでバイナリファイルを開いてみたのですが、0と1のられつばかりでよくわかりません…
どうやって中身を確認するのでしょうか…

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 15年前
住所: 東海地方
連絡を取る:

Re: セーブやロードをする範囲を変化させたい

#10

投稿記事 by softya(ソフト屋) » 13年前

バイナリデータがどの様な形で格納されているか分かりますか?
キーワード: 16進数、リトルエンディアン、int型のバイト数
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

bonbo

Re: セーブやロードをする範囲を変化させたい

#11

投稿記事 by bonbo » 13年前

つまり、あの文字列は16進数で、バイト数をリトルエンディアン方式で並べたものなのでしょうか。

しかしそれでは配列がどうなっているかどうかまではわからないのでは…

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 15年前
住所: 東海地方
連絡を取る:

Re: セーブやロードをする範囲を変化させたい

#12

投稿記事 by softya(ソフト屋) » 13年前

bonbo さんが書きました:つまり、あの文字列は16進数で、バイト数をリトルエンディアン方式で並べたものなのでしょうか。

しかしそれでは配列がどうなっているかどうかまではわからないのでは…
バイト数ではなくint型の4バイトの数値がリトルエンディアン方式で並んでいます。
自分でfwriteしたのですから、intの配列の並びは分かっているはずです(分かっているべきです)。
なので、特定のバイト毎に自分で区切れるはずです。それでイメージ通りかイメージと実体を付きあわせてみて下さい。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

bonbo

Re: セーブやロードをする範囲を変化させたい

#13

投稿記事 by bonbo » 13年前

>>softyaさん
なるほど…高等な技術ですね…
できるようにがんばってみます…

sq

Re: セーブやロードをする範囲を変化させたい

#14

投稿記事 by sq » 13年前

コード:

void Load(int (*Map)[200][200],int (*IntNum)[200][200],int boxXmax,int boxYmax)
Load関数のboxXmaxとboxYmaxの二つの引数はポインタでなくていいんですか?
呼び出し元にサイズを返すことができていないようですが。

bonbo

Re: セーブやロードをする範囲を変化させたい

#15

投稿記事 by bonbo » 13年前

>Load関数のboxXmaxとboxYmaxの二つの引数はポインタでなくていいんですか?
呼び出し元にサイズを返すことができていないようですが

ありがとうございます
それだとダブルポインタになっちゃいます

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 15年前
住所: 東海地方
連絡を取る:

Re: セーブやロードをする範囲を変化させたい

#16

投稿記事 by softya(ソフト屋) » 13年前

bonbo さんが書きました:>Load関数のboxXmaxとboxYmaxの二つの引数はポインタでなくていいんですか?
呼び出し元にサイズを返すことができていないようですが

ありがとうございます
それだとダブルポインタになっちゃいます
まぁ、それは本末転倒なんですけどね。
問題を無くすために別の機能を無効にしてしまっています。
実はシングルポインタに出来るのです(余分なことをしなければ)。

それはそれとしても、今後のためにもバイナリファイルの見方は覚えてほしですね。
(1)(2)(3)の工程が確認できて初めて、ちゃんとセーブ/ロードが出来たと言えるわけですから。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

bonbo

Re: セーブやロードをする範囲を変化させたい

#17

投稿記事 by bonbo » 13年前

>>softyaさん
何度もありがとうございます
バイナリファイル見てみましたけど[5][200][200] (ここは200じゃないかもしれないが)
の数字の表れ方の規則性を予測するのは難しいです…テキストファイルに出力するとかできないですかね。
ブレークポイントはさっき友達に教えてもらったのですがなぜかストップしてくれない…
Loadの呼び出し元に返ってくる値は…返ってくるにはくるんですけどそれがどこで変な値になっているのかよくわからないので手詰まりです…
せめてバイナリファイルの中に正しい値が入っているか分かればどこが原因かわかるのですが…

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 15年前
住所: 東海地方
連絡を取る:

Re: セーブやロードをする範囲を変化させたい

#18

投稿記事 by softya(ソフト屋) » 13年前

バイナリエディタは4バイトまとめて更にリトルエンディアンを分りやすい形に並べ直して表示とか出来るはずです。
あと、それをテキストコピーできたりしませんか?
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

bonbo

Re: セーブやロードをする範囲を変化させたい

#19

投稿記事 by bonbo » 13年前

"4バイトまとめて"というのがどうやるのかわからないです…
stiringというソフトをダウンロードしてきて使っているのですが、
ゲームの改造やらのページしか出てこないので困っています…

(ちなみに実験しているうちにバイナリエディタの動き方がちょっとわかってきました。で、1か所バグが見つかりました。
boxXmax,boxYmaxは0のときがあるけど、for文を動かすため実際には1以上になるはずだったので、

for(int i=0;i<boxXmax;i++)

for(int i=0;i<boxXmax+1;i++) //boxYmaxも同様

としてそれに関しては解決しました。
しかし、まだうまく動いていないみたいで、

どうやら "Save→Load→Save→Load" と2回繰り返すことでうまくいくみたいです。
このまま2回繰り返す関数を作れば一応それで解決なのですが…)
以下現在の状態

コード:

MapLoad(map,InterNumber,boxXmax,boxYmax);
MapSave(map,InterNumber,boxXmax,boxYmax);

コード:

		//セーブ
		void MapSave( int (*Map)[200][200],int(*IntNum)[200][200],int boxXmax,int boxYmax )
		{
			FILE *fp ;
			fp = fopen( "Map.dat" , "wb" ) ;
			if( fp == NULL ) return ;

			//データの書き出し
			fwrite( &boxXmax , sizeof( boxXmax ) , 1 , fp ) ;
			fwrite( &boxYmax , sizeof( boxYmax ) , 1 , fp ) ;
			for(int i=0;i<boxXmax+1;i++)
				for(int j=0;j<boxYmax+1;j++)
					for(int k=0;k<rayermax;k++){
						fwrite( &Map[k][j][i] , sizeof(Map[k][j][i] ) , 1 , fp ) ;
						fwrite( &IntNum[k][j][i] , sizeof(IntNum[k][j][i] ) , 1 , fp ) ;
					}
			fclose( fp ) ;
		}

		//ロード
		void MapLoad(int (*Map)[200][200],int (*IntNum)[200][200],int boxXmax,int boxYmax)
		{
			FILE *fp ;
			fp = fopen( "Map.dat" , "rb" ) ;
			if( fp == NULL )
			{
			for(int i=0;i<boxXmax+1;i++)
				for(int j=0;j<boxYmax+1;j++)
					for(int k=0;k<rayermax;k++){
						Map[k][j][i];
						IntNum[k][j][i];

					}
			}
			else
			{

				//データの読み込み
				fread( &boxYmax , sizeof( boxYmax ) , 1 , fp ) ;
				fread( &boxXmax , sizeof( boxXmax ) , 1 , fp ) ;

				for(int i=0;i<boxXmax+1;i++)
					for(int j=0;j<boxYmax+1;j++)
						for(int k=0;k<rayermax;k++){
							fread( &Map[k][j][i] , sizeof( Map[k][j][i] ) , 1 , fp ) ;
							fread( &IntNum[k][j][i] , sizeof( IntNum[k][j][i] ) , 1 , fp ) ;
						}

				// ファイルを閉じる
				fclose( fp ) ;
			}
		}

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 15年前
住所: 東海地方
連絡を取る:

Re: セーブやロードをする範囲を変化させたい

#20

投稿記事 by softya(ソフト屋) » 13年前

LoadでboxXmaxとboxYmaxを返せないとうまく動くはずがありません。
なので
>どうやら "Save→Load→Save→Load" と2回繰り返すことでうまくいくみたいです。
>このまま2回繰り返す関数を作れば一応それで解決なのですが…)
は解決策ではありません。

ところで放置してあったんですが、このコードはまったく意味が無いので消したほうが良いと思います。

コード:

            for(int i=0;i<boxXmax+1;i++)
                for(int j=0;j<boxYmax+1;j++)
                    for(int k=0;k<rayermax;k++){
                        Map[k][j][i];
                        IntNum[k][j][i];
 
                    }
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 15年前
住所: 東海地方
連絡を取る:

Re: セーブやロードをする範囲を変化させたい

#21

投稿記事 by softya(ソフト屋) » 13年前

それとboxXmaxが0の場合があるとの事ですがサイズではないのでしょうか?
x値の最大値って事でしょうか?

string関しては調べてみます。
私の使っているTSXBINなら出来るんですけどね。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

bonbo

Re: セーブやロードをする範囲を変化させたい

#22

投稿記事 by bonbo » 13年前

>>softyaさん
ありがとうございます、
>>LoadでboxXmaxとboxYmaxを返せないとうまく動くはずがありません。
おっしゃる通りできるときとできないときがあってまったく解決策にはなっていませんでした…
>>それとboxXmaxが0の場合があるとの事ですがサイズではないのでしょうか?
boxXmax*boxYmax=2*1のマップがあるとして記録したいのは(0,0)(1,0)(2,0)(0,1)(1,1)(2,1)であるが、
これだと(2*1)=2しか保存されないので(3*2)=6こ保存するようにした。ということです。わかりにくくてすみません…
>>ところで放置してあったんですが、このコードはまったく意味が無いので消したほうが良いと思います。
ここは開けなかったときに初期化するコードだったのですが肝心の初期化処理をしていませんでした…

コード:


           for(int i=0;i<boxXmax+1;i++)
                for(int j=0;j<boxYmax+1;j++)
                    for(int k=0;k<rayermax;k++){
                        Map[k][j][i]=0;                           //書き忘れていました
                        IntNum[k][j][i]=0;
 
                    } 
すみません…
>>TSXBIN
TSXBINをダウンロードしてきました。いろいろ実験してみようと思います。

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 15年前
住所: 東海地方
連絡を取る:

Re: セーブやロードをする範囲を変化させたい

#23

投稿記事 by softya(ソフト屋) » 13年前

調べみてみましたがstiringはできませんね。TEXBINは下にあるボタンで表示バイト数の単位を変更できます。10進表示もできます。

ちなにみダブルポインタに成っている原因はポインタを&演算しているからでポインタはポインタのまま扱えば良いのです。
分かり辛ければ、int tmpboxXmaxとかに一度freadしてから*boxXmax = tmpboxXmax;としてコピーしても良いですよ。

>boxXmax*boxYmax=2*1のマップがあるとして記録したいのは(0,0)(1,0)(2,0)(0,1)(1,1)(2,1)であるが、
>これだと(2*1)=2しか保存されないので(3*2)=6こ保存するようにした。ということです。わかりにくくてすみません…

やはり、xとyの上限値だったんですね。
boxXmax*boxYmax=2*1だと要素は3*2って事ですね。
まぁ、あまり上限値をマップファイルの情報として書き込む事はないので要素数の方が一般的だと思います。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

bonbo

Re: セーブやロードをする範囲を変化させたい

#24

投稿記事 by bonbo » 13年前

>>softyaさん
ありがとうございます。長いですがもう少しだけおつきあいください。
boxXmax,boxYmaxは外に値を渡すことができるようになりました。
次に
Save→Load→Save→Loadと繰り返すのところですが、
Save→(初期化)→Load→Saveだと100%セーブが成功するみたいです(全然根本的な解決策ではありませんが…)。
どうやらboxXmax,boxYmaxが変化するときに異常が発生するようです
LoadはboxXmax→boxXmax+1にしたことで問題が解決したみたいです(今のところおかしな動作はありません)
問題はSaveですが、今TSXBINでいろいろ見てますがやはりSave関数がおかしい気がします。
freadやfwriteの仕様をあまり理解してないので確かなことは言えないですが…
一応もう一度張っておきます

コード:

			//データのセーブ
		void MapSave( int (*Map)[200][200],int(*IntNum)[200][200],int boxXmax,int boxYmax )
		{
			FILE *fp ;
			fp = fopen( "Map.dat" , "wb" ) ;
			// オープンできなかったらここで終了
			if( fp == NULL ) return ;
			//データの書き出し
			fwrite( &boxXmax , sizeof( boxXmax ) , 1 , fp ) ;
			fwrite( &boxYmax , sizeof( boxYmax ) , 1 , fp ) ;
			for(int i=0;i<boxXmax+1;i++)
				for(int j=0;j<boxYmax+1;j++)
					for(int k=0;k<5;k++){
						fwrite( &Map[k][j][i] , sizeof(Map[k][j][i] ) , 1 , fp ) ;
						fwrite( &IntNum[k][j][i] , sizeof(IntNum[k][j][i] ) , 1 , fp ) ;
					}
			// ファイルを閉じる
			fclose( fp ) ;
		}

bonbo

Re: セーブやロードをする範囲を変化させたい

#25

投稿記事 by bonbo » 13年前

>>100%成功
全然そんなことなかったです…

bonbo

Re: セーブやロードをする範囲を変化させたい

#26

投稿記事 by bonbo » 13年前

一応使える状態までは復帰したみたいなので(不具合があるような気もしますが)解決ということで。
これからバイナリエディタの使い方を学びつつ改善していこうと思います。
今回は本当にありがとうございました。またなにかあったらよろしくお願いします。

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 15年前
住所: 東海地方
連絡を取る:

Re: セーブやロードをする範囲を変化させたい

#27

投稿記事 by softya(ソフト屋) » 13年前

bonbo さんが書きました:一応使える状態までは復帰したみたいなので(不具合があるような気もしますが)解決ということで。
これからバイナリエディタの使い方を学びつつ改善していこうと思います。
今回は本当にありがとうございました。またなにかあったらよろしくお願いします。
ここのルールなのですがセーブとロードの最終コードは貼り付けるようにお願いします。
※ よく問題が残っていることが発見されますので、ご自身のためにもお願いします。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

bonbo

Re: セーブやロードをする範囲を変化させたい

#28

投稿記事 by bonbo » 13年前

すみません忘れていました…
以下コードです
------------------------------------------------------------------------------------
Map,InterNumberはそれぞれ[5][200][200]の3次配列です

コード:

//セーブの一通りの流れ(Save関数に異常があると考えられるため擬似的にセーブをしている)
//セーブ→初期化→ロード→セーブ→初期化→ロード
{
			Save(map,InterNumber,boxXmax,boxYmax);	//Save関数を呼び出す
			for(int i=0;i<boxXmax+1;i++)		//初期化する
				for(int j=0;j<boxYmax+1;j++)
					for(int k=0;k<5;k++){
						map[k][j][i]=0;
						InterNumber[k][j][i]=0;
					}
			boxXmax=0;				//boxXmax,boxYmaxを再び決定
			boxYmax=0;
			for(int i=0;i<200;i++)
				for(int j=0;j<200;j++)
					for(int k=0;k<5;k++){
						if(map[k][j][i]!=0){
							if(j>boxYmax)
								boxYmax=j;
							if(i>boxXmax)
								boxXmax=i;
						}
					}			//初期化終了
			Load(map,InterNumber,boxXmax,boxYmax,&boxXmax,&boxYmax);//Load関数を呼び出す
			boxXmax=0;				//boxXmax,boxYmaxを再び決定
			boxYmax=0;
			for(int i=0;i<200;i++)//マップの幅、高さの特定
				for(int j=0;j<200;j++)
					for(int k=0;k<5;k++){
						if(map[k][j][i]!=0){
							if(j>boxYmax)
								boxYmax=j;
							if(i>boxXmax)
								boxXmax=i;
						}
					}
			Save(map,InterNumber,boxXmax,boxYmax);	//Save関数を呼び出す(2度呼び出すことによって成功するらしい)
			for(int i=0;i<boxXmax+1;i++)		//初期化
				for(int j=0;j<boxYmax+1;j++)
					for(int k=0;k<5;k++){
						map[k][j][i]=0;
						InterNumber[k][j][i]=0;
					}
			boxXmax=0;				//boxXmax,boxYmaxを再び決定
			boxYmax=0;
			for(int i=0;i<200;i++)
				for(int j=0;j<200;j++)
					for(int k=0;k<5;k++){
						if(map[k][j][i]!=0){
							if(j>boxYmax)
								boxYmax=j;
							if(i>boxXmax)
								boxXmax=i;
						}
					}			//初期化終了
			Load(map,InterNumber,boxXmax,boxYmax,&boxXmax,&boxYmax);//ロードして元の状態に戻して終了
}//一応これで範囲を変えるセーブは可能であるが…汚い…

								//ロードに関しては
Load(map,InterNumber,boxXmax,boxYmax,&boxXmax,&boxYmax);	//ロード関数を呼び出すだけでOKです
Save,Loadの各関数は下のようになっています

コード:

			//データのセーブ
		void Save( int (*Map)[200][200],int(*IntNum)[200][200],int boxXmax,int boxYmax )
		{
			FILE *fp ;
			fp = fopen( "Map.dat" , "wb" ) ;

			// オープンできなかったらここで終了
			if( fp == NULL ) return ;

			//データの書き出し
			fwrite( &boxXmax , sizeof( boxXmax ) , 1 , fp ) ;
			fwrite( &boxYmax , sizeof( boxYmax ) , 1 , fp ) ;
			for(int i=0;i<boxXmax+1;i++)
				for(int j=0;j<boxYmax+1;j++)
					for(int k=0;k<5;k++){
						fwrite( &Map[k][j][i] , sizeof(Map[k][j][i] ) , 1 , fp ) ;
						fwrite( &IntNum[k][j][i] , sizeof(IntNum[k][j][i] ) , 1 , fp ) ;
					}

			// ファイルを閉じる
			fclose( fp ) ;
		}

		//ロード
		void Load(int (*Map)[200][200],int (*IntNum)[200][200],int boxXmax,int boxYmax,int *tempX,int *tempY)
		{
			FILE *fp ;
			fp = fopen( "Map.dat" , "rb" ) ;

			// オープンできなかったらファイルが無いとみなし
			//消す
			if( fp == NULL )
			{
			for(int i=0;i<200;i++)
				for(int j=0;j<200;j++)
					for(int k=0;k<5;k++){
						Map[k][j][i]=0;
						IntNum[k][j][i]=0;

					}
			}
			else
			{

				//データの読み込み
				fread( &boxYmax , sizeof( boxYmax ) , 1 , fp ) ;
				fread( &boxXmax , sizeof( boxXmax ) , 1 , fp ) ;
				*tempX=boxXmax;
				*tempY=boxYmax;
				for(int i=0;i<boxXmax+1;i++)
					for(int j=0;j<boxYmax+1;j++)
						for(int k=0;k<5;k++){
							fread( &Map[k][j][i] , sizeof( Map[k][j][i] ) , 1 , fp ) ;
							fread( &IntNum[k][j][i] , sizeof( IntNum[k][j][i] ) , 1 , fp ) ;
						}

				// ファイルを閉じる
				fclose( fp ) ;
			}
		}

----------------------------------------------------------------------------------------------------
みなさんありがとうございました

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 15年前
住所: 東海地方
連絡を取る:

Re: セーブやロードをする範囲を変化させたい

#29

投稿記事 by softya(ソフト屋) » 13年前

幾つか問題点を指摘しておきます。
[呼び出し元]
(1) 5~10行目。最大値(200)までクリアしないとゴミが残っているかも知れません。同じ処理をあちこちに書くのは無駄とバグの元なので関数化して下さい。
(2) 13~22行目。意味がありません。
(3) 24~35行目。せっかくロードしたboxXmax,boxYmax値を使って下さい。あとmapの値は有効な場合かならず0以外なのでしょうか?
(4) 36~55行目。バグをごまかしているだけですので、ぜひ止めて下さい。根本的な原因を探りましょう。

[呼び出されるLoad/Save]
(1) int boxXmax,int boxYmaxはローカル変数にすべきです。引数にしてある意味がありません。
というか、tempXとboxXmaxは名前と役割が逆では?
(2) 34~40行目。fp==NULLだけで無くfopen前に無条件に実行すべきです。上の[呼び出し元](1)で関数化したものを使って下さい。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

bonbo

Re: セーブやロードをする範囲を変化させたい

#30

投稿記事 by bonbo » 13年前

わざわざありがとうございます…
呼び出し元(4)を何とか解決できるようにしていきます…
SaveのboxXmaxは後々使うことになるのでグローバル変数にしてます。
名前逆でしたか…お恥ずかしい..
それ以外はなんとかなりそうです

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 15年前
住所: 東海地方
連絡を取る:

Re: セーブやロードをする範囲を変化させたい

#31

投稿記事 by softya(ソフト屋) » 13年前

>SaveのboxXmaxは後々使うことになるのでグローバル変数にしてます。

Load()関数内における引数のboxXmax,boxYmaxはグローバル変数ではありませんよ。
一種のローカル変数で元のboxXmax,boxYmaxから値だけを引き継いだ別の変数です。
名前(識別名)が同じだからといって同じ変数だと思うのは誤りです。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

bonbo

Re: セーブやロードをする範囲を変化させたい

#32

投稿記事 by bonbo » 13年前

>>softyaさん
ああなるほど!確かにその通りですね。また変な理解をしてたみたいです…
なおしておきます

ISLe
記事: 2650
登録日時: 15年前
連絡を取る:

Re: セーブやロードをする範囲を変化させたい

#33

投稿記事 by ISLe » 13年前

『マップの幅、高さの特定』という処理で、boxXmaxやboxYmaxにインデックス値をセットしているのがそもそもの問題かと。
そのせいでループ時に余計な+1が必要になっているのでは?

boxXmaxやboxYmaxが表しているのは、サイズなのか、最大インデックス値なのかはっきりさせましょう。

bonbo

Re: セーブやロードをする範囲を変化させたい

#34

投稿記事 by bonbo » 13年前

>>ISLeさん
ありがとうございます。
そこが原因の可能性もありますね…もっときれいに書き換えてみます

閉鎖

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