ページ 1 / 1
セーブやロードをする範囲を変化させたい
Posted: 2012年7月15日(日) 15:44
by bonbo
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 ) ;
}
}
すると、ファイルのサイズは小さくなったのですが今度はうまく読み込んでくれなくなってしましました。
配列のサイズが違うのがおかしいのかも..?とかいろいろ考えてみたのですが、なかなか解決できなかったので質問させていただきました。
わかりにくくて申し訳ないのですが、よろしくおねがいします。
Re: セーブやロードをする範囲を変化させたい
Posted: 2012年7月15日(日) 16:43
by softya(ソフト屋)
書き出しファイルにboxXmax * boxYmax * 5個しか書いていないにもかかわらず、読み込みで200x200x5個ある前提で読み込んでいるからでしょう。
サイズをファイルの最後に書いていますがファイルの先頭に書いて、読み込む時に先にサイズを読み取ってサイズ分読み込む様にして下さい。
書き出し時に
fwrite( &boxXmax , sizeof( boxXmax ) , 1 , fp ) ; //boxXmaxと
fwrite( &boxYmax , sizeof( boxYmax ) , 1 , fp ) ; //boxYmaxを保存したい。
これをファイル先頭にします。
あとLoadでfwriteしているのはバグですよ。
セーブやロードをする範囲を変化させたい
Posted: 2012年7月15日(日) 17:31
by bonbo
>>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 ) ;
}
}
Re: セーブやロードをする範囲を変化させたい
Posted: 2012年7月15日(日) 17:35
by softya(ソフト屋)
エラーの内容をもっと正確に伝えて下さい。
Re: セーブやロードをする範囲を変化させたい
Posted: 2012年7月15日(日) 17:46
by bonbo
>>softyaさん
すみません…
内容は、Load関数を呼び出したときに、
「map.exeは動作を停止しました
この問題の解決策を検索しています…」
と出てそこでエラーで終了してしまうというものです。
コード:
int a=1;
scanf("%d",&a);
if(a==0)
Load(map,InterNumber,&boxXmax,&boxYmax);
のような形でLoad関数を呼び出しているだけなので外部には問題はないはずなのですが…
Re: セーブやロードをする範囲を変化させたい
Posted: 2012年7月15日(日) 17:58
by softya(ソフト屋)
Loadで引数のint *boxXmax,int *boxYmaxは元々ポインタなので、fread( &boxYmax , sizeof( boxYmax ) , 1 , fp ) ;の&boxYmaxだとダブルポインタになってしまいますので、この場合何処に読み込まれるかは神ののみぞ知るです。たいていは読み込んではいけない領域に読み込みます。
デバッガで動作させれば、その実行エラー行を示してくれるはずですが?
こういうミスを避けるために引数ではポインタならboxYmax_ptrなど変数名を変えることをおすすめします。
Re: セーブやロードをする範囲を変化させたい
Posted: 2012年7月15日(日) 18:12
by bonbo
一応読み込みはできるようになったのですが、今度は正しく読み込めない状態に逆戻りしてしまいました…
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 ) ;
}
}
Re: セーブやロードをする範囲を変化させたい
Posted: 2012年7月15日(日) 18:16
by softya(ソフト屋)
bonbo さんが書きました:一応読み込みはできるようになったのですが、今度は正しく読み込めない状態に逆戻りしてしまいました…
Saveで正しく書き込みができていないのでしょうか…
デバッグ方法について説明します。
(1)バイナリエディタで出来上がったファイル内容を必ず確認する。
(2)読み込み時にデバッガで指定行でブレークさせて、ちゃんと読み込まれているか変数を確認する。
(3)Loadの呼び出し元に、ちゃんと値を返せているか確認する。
以上を実践してみて下さい。
Re: セーブやロードをする範囲を変化させたい
Posted: 2012年7月15日(日) 19:34
by bonbo
バイナリエディタでバイナリファイルを開いてみたのですが、0と1のられつばかりでよくわかりません…
どうやって中身を確認するのでしょうか…
Re: セーブやロードをする範囲を変化させたい
Posted: 2012年7月15日(日) 19:39
by softya(ソフト屋)
バイナリデータがどの様な形で格納されているか分かりますか?
キーワード: 16進数、リトルエンディアン、int型のバイト数
Re: セーブやロードをする範囲を変化させたい
Posted: 2012年7月15日(日) 20:43
by bonbo
つまり、あの文字列は16進数で、バイト数をリトルエンディアン方式で並べたものなのでしょうか。
しかしそれでは配列がどうなっているかどうかまではわからないのでは…
Re: セーブやロードをする範囲を変化させたい
Posted: 2012年7月15日(日) 21:16
by softya(ソフト屋)
bonbo さんが書きました:つまり、あの文字列は16進数で、バイト数をリトルエンディアン方式で並べたものなのでしょうか。
しかしそれでは配列がどうなっているかどうかまではわからないのでは…
バイト数ではなくint型の4バイトの数値がリトルエンディアン方式で並んでいます。
自分でfwriteしたのですから、intの配列の並びは分かっているはずです(分かっているべきです)。
なので、特定のバイト毎に自分で区切れるはずです。それでイメージ通りかイメージと実体を付きあわせてみて下さい。
Re: セーブやロードをする範囲を変化させたい
Posted: 2012年7月15日(日) 23:13
by bonbo
>>softyaさん
なるほど…高等な技術ですね…
できるようにがんばってみます…
Re: セーブやロードをする範囲を変化させたい
Posted: 2012年7月15日(日) 23:28
by sq
コード:
void Load(int (*Map)[200][200],int (*IntNum)[200][200],int boxXmax,int boxYmax)
Load関数のboxXmaxとboxYmaxの二つの引数はポインタでなくていいんですか?
呼び出し元にサイズを返すことができていないようですが。
Re: セーブやロードをする範囲を変化させたい
Posted: 2012年7月15日(日) 23:55
by bonbo
>Load関数のboxXmaxとboxYmaxの二つの引数はポインタでなくていいんですか?
呼び出し元にサイズを返すことができていないようですが
ありがとうございます
それだとダブルポインタになっちゃいます
Re: セーブやロードをする範囲を変化させたい
Posted: 2012年7月16日(月) 00:16
by softya(ソフト屋)
bonbo さんが書きました:>Load関数のboxXmaxとboxYmaxの二つの引数はポインタでなくていいんですか?
呼び出し元にサイズを返すことができていないようですが
ありがとうございます
それだとダブルポインタになっちゃいます
まぁ、それは本末転倒なんですけどね。
問題を無くすために別の機能を無効にしてしまっています。
実はシングルポインタに出来るのです(余分なことをしなければ)。
それはそれとしても、今後のためにもバイナリファイルの見方は覚えてほしですね。
(1)(2)(3)の工程が確認できて初めて、ちゃんとセーブ/ロードが出来たと言えるわけですから。
Re: セーブやロードをする範囲を変化させたい
Posted: 2012年7月16日(月) 00:42
by bonbo
>>softyaさん
何度もありがとうございます
バイナリファイル見てみましたけど[5][200][200] (ここは200じゃないかもしれないが)
の数字の表れ方の規則性を予測するのは難しいです…テキストファイルに出力するとかできないですかね。
ブレークポイントはさっき友達に教えてもらったのですがなぜかストップしてくれない…
Loadの呼び出し元に返ってくる値は…返ってくるにはくるんですけどそれがどこで変な値になっているのかよくわからないので手詰まりです…
せめてバイナリファイルの中に正しい値が入っているか分かればどこが原因かわかるのですが…
Re: セーブやロードをする範囲を変化させたい
Posted: 2012年7月16日(月) 00:44
by softya(ソフト屋)
バイナリエディタは4バイトまとめて更にリトルエンディアンを分りやすい形に並べ直して表示とか出来るはずです。
あと、それをテキストコピーできたりしませんか?
Re: セーブやロードをする範囲を変化させたい
Posted: 2012年7月16日(月) 01:37
by bonbo
"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 ) ;
}
}
Re: セーブやロードをする範囲を変化させたい
Posted: 2012年7月16日(月) 11:36
by softya(ソフト屋)
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];
}
Re: セーブやロードをする範囲を変化させたい
Posted: 2012年7月16日(月) 11:39
by softya(ソフト屋)
それとboxXmaxが0の場合があるとの事ですがサイズではないのでしょうか?
x値の最大値って事でしょうか?
string関しては調べてみます。
私の使っているTSXBINなら出来るんですけどね。
Re: セーブやロードをする範囲を変化させたい
Posted: 2012年7月16日(月) 12:47
by bonbo
>>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をダウンロードしてきました。いろいろ実験してみようと思います。
Re: セーブやロードをする範囲を変化させたい
Posted: 2012年7月16日(月) 13:11
by softya(ソフト屋)
調べみてみましたが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って事ですね。
まぁ、あまり上限値をマップファイルの情報として書き込む事はないので要素数の方が一般的だと思います。
Re: セーブやロードをする範囲を変化させたい
Posted: 2012年7月16日(月) 13:55
by bonbo
>>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 ) ;
}
Re: セーブやロードをする範囲を変化させたい
Posted: 2012年7月16日(月) 14:52
by bonbo
>>100%成功
全然そんなことなかったです…
Re: セーブやロードをする範囲を変化させたい
Posted: 2012年7月16日(月) 15:05
by bonbo
一応使える状態までは復帰したみたいなので(不具合があるような気もしますが)解決ということで。
これからバイナリエディタの使い方を学びつつ改善していこうと思います。
今回は本当にありがとうございました。またなにかあったらよろしくお願いします。
Re: セーブやロードをする範囲を変化させたい
Posted: 2012年7月16日(月) 15:08
by softya(ソフト屋)
bonbo さんが書きました:一応使える状態までは復帰したみたいなので(不具合があるような気もしますが)解決ということで。
これからバイナリエディタの使い方を学びつつ改善していこうと思います。
今回は本当にありがとうございました。またなにかあったらよろしくお願いします。
ここのルールなのですがセーブとロードの最終コードは貼り付けるようにお願いします。
※ よく問題が残っていることが発見されますので、ご自身のためにもお願いします。
Re: セーブやロードをする範囲を変化させたい
Posted: 2012年7月16日(月) 15:50
by bonbo
すみません忘れていました…
以下コードです
------------------------------------------------------------------------------------
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 ) ;
}
}
----------------------------------------------------------------------------------------------------
みなさんありがとうございました
Re: セーブやロードをする範囲を変化させたい
Posted: 2012年7月16日(月) 16:18
by softya(ソフト屋)
幾つか問題点を指摘しておきます。
[呼び出し元]
(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)で関数化したものを使って下さい。
Re: セーブやロードをする範囲を変化させたい
Posted: 2012年7月16日(月) 17:07
by bonbo
わざわざありがとうございます…
呼び出し元(4)を何とか解決できるようにしていきます…
SaveのboxXmaxは後々使うことになるのでグローバル変数にしてます。
名前逆でしたか…お恥ずかしい..
それ以外はなんとかなりそうです
Re: セーブやロードをする範囲を変化させたい
Posted: 2012年7月16日(月) 17:17
by softya(ソフト屋)
>SaveのboxXmaxは後々使うことになるのでグローバル変数にしてます。
Load()関数内における引数のboxXmax,boxYmaxはグローバル変数ではありませんよ。
一種のローカル変数で元のboxXmax,boxYmaxから値だけを引き継いだ別の変数です。
名前(識別名)が同じだからといって同じ変数だと思うのは誤りです。
Re: セーブやロードをする範囲を変化させたい
Posted: 2012年7月16日(月) 17:46
by bonbo
>>softyaさん
ああなるほど!確かにその通りですね。また変な理解をしてたみたいです…
なおしておきます
Re: セーブやロードをする範囲を変化させたい
Posted: 2012年7月17日(火) 00:03
by ISLe
『マップの幅、高さの特定』という処理で、boxXmaxやboxYmaxにインデックス値をセットしているのがそもそもの問題かと。
そのせいでループ時に余計な+1が必要になっているのでは?
boxXmaxやboxYmaxが表しているのは、サイズなのか、最大インデックス値なのかはっきりさせましょう。
Re: セーブやロードをする範囲を変化させたい
Posted: 2012年7月17日(火) 03:21
by bonbo
>>ISLeさん
ありがとうございます。
そこが原因の可能性もありますね…もっときれいに書き換えてみます