メモ帳からカンマ付き文字列のデータの読み込みが出来ません。

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

メモ帳からカンマ付き文字列のデータの読み込みが出来ません。

#1

投稿記事 by プログラマ見習い » 1ヶ月前

 プログラマ見習いです。
 DXライブラリとVisalStudio2017communityを利用しています。

 次のマップデータを読み込みたいのですが出来ません。
 次のマップデータは、ご覧の通り、カンマで区切っている2桁で一組の文字列で出来ています。
 次のマップデータを読み込むには、次の課題をクリアしなければなりません。
  1.カンマを読み込まないで読み込みたい文字列だけを読み込む。
  2.00,11,AAなど、一組の文字列として読み込む。

コード:

 
 
00,00,00,00,00,00,00,00,00,00,11,11,11,11,11,11,11,11,11,11,00,00,00,00,00,00,00,00,00,00,11,11,11,11,11,11,11,11,11,11
00,00,00,00,00,00,00,00,00,00,00,00,AA,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00
00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00
00,00,00,00,00,00,00,00,00,00,AA,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00
00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00
00,00,00,00,00,00,00,00,00,00,00,AA,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00
00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00
00,00,00,00,00,00,00,00,00,00,AA,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00
00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00
00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00
00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00


  


 以上のマップデータを読み込むために、書籍やネットなどの情報を参考に、考えられる方法を試しました。
 しかし、すべて失敗してフリーズしてしまいました。

 ソースコードは、「配列とfor文を使っているのに画像が一つしか表示されない。」に体裁されたものに、
ファイル読み込み用関数void MapLoad();を追加したものです。
 画像は、以前、みけCATさんが投稿してくれたものそのまま利用するのはいかがなものかと思ったので、
参考にして自分で描いたものを投稿します。

 ファイル読み込みのソースコードはvoid MapLoad(){}の中に書いています。

 一つは、以下のようにsscanf_s();関数で分割する方法です。
 しかし、失敗してフリーズしてしまいました。

 方法1

コード:

 
 
#include <DxLib.h>



#define MAPSIZE 32 //マップサイズを決めます。

#define HEIGHT 15 //Y座標の最大値を決めます
#define WIDTH 40 //X座標の最大値を決めます

 //キャラクターの数の最大値を決めます。念のために多めにします。今回はマップデータの数に合わせます。
#define CHARA HEIGHT*WIDTH



 //画像データの構造体を作ります。
 //画像データは無理に配列やポインタで整理しようとすると、エラーやフリーズの原因になります。
struct ImageData{

 int kabe01; //
 int teki0A[2]; //

};

struct ImageData im; //



 //各キャラクターのデータの構造体を作ります。
struct CharaData{

 //int *ghandle; //アニメーションさせるために画像データハンドル。
 //ポインタ設定をしたが、これが原因の一つでした。

 char kind; //キャラクターの種類を格納。
 int anime_pattern; //アニメパーン数
 float x; //座標はfloatにします。
 float y;
 int body; //体力

};

struct CharaData charadata[CHARA]; //今回はcharadataと名づけます。
 //キャラクターは複数出現させるので、配列内に各キャラクターの最大値CHMAXを格納します。

//struct CharaData im[2]; //画像を描画するための変数。
//or//struct CharaData im[CHARA]; //画像を描画するための変数。



 //アニメーションカウンター用の変数を作ります。
unsigned int g_anime_counter=0;



 //マップデータを作ります。
char mapdata[HEIGHT][WIDTH];



  //メモ帳からマップデータを読み込み
void MapLoad(){

  //各キャラクターのデータを初期化します。
 ZeroMemory(charadata,sizeof(charadata));

 char buf[1024];
 sprintf_s(buf,1024,"media/map%d",1); //ファイル名を用意する
 int fp; //ファイルハンドル
 fp==FileRead_open(buf); //ファイルを開く

  //ファイル読み込みエラー処理
 if(fp=NULL){
  printfDx("ファイル読み込みエラー");
  return;
 }



/////////////////////////////ここから////////////////////////////


 int x=0;
 for(int y=0;y<HEIGHT;y++){
  for(int x=0;x<WIDTH;x++){

  //1024が1023に減っているのは、NULL文字対策
 FileRead_gets(buf,1023,fp); //ファイルを一行読み込む

 char c[WIDTH];
             //01,02,03,04,05,06,07,08,09,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40
 sscanf_s(buf,"%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s",
"&c[0]","&c[1]","&c[2]","&c[3]","&c[4]","&c[5]","&c[6]","&c[7]","&c[8]","&c[9]",
"&c[10]","&c[11]","&c[12]","&c[13]","&c[14]","&c[15]","&c[16]","&c[17]","&c[18]","&c[19]",
"&c[20]","&c[21]","&c[22]","&c[23]","&c[24]","&c[25]","&c[26]","&c[27]","&c[28]","&c[29]",
"&c[30]","&c[31]","&c[32]","&c[33]","&c[34]","&c[35]","&c[36]","&c[37]","&c[38]","&c[39]");


 mapdata[y][x] = c[x];
 //FileRead_gets(mapdata[y], c[x], fp);
 //FileRead_gets(mapdata[y], buf[x], fp);
 //FileRead_gets(mapdata[y], buf[WIDTH], fp);

 x++;

 } //for(int x=0;x<WIDTH;x++)
} //for(int y=0;y<HEIGHT;y++)の最後

/////////////////////////////ここまで////////////////////////////

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

} //void MapLoad();の最後



 //画像をロードする関数を作ります。
void Load(){

 im.kabe01=LoadGraph("media/kabe01.bmp");

 LoadDivGraph("media/teki0A.bmp",2,2,1,32,32,im.teki0A);

}



 //初期化用の関数を作ります。
void Init(){

  //キャラクターをカウントする変数を作ります。必要な変数の一つです。
  //キャラクターをカウントする変数はローカル変数でも問題ありませんでした。
 int counter=0;

 for(int y=0;y<HEIGHT;y++){
  for(int x=0;x<WIDTH;x++){

  char c=mapdata[y][x];

   //初期化してマップデータから、キャラクターのデータを取り出します。

   //kindにマップデータを代入します。
   //これも必要な変数の一つです。
  charadata[counter].kind=c;

  charadata[counter].x=(float)x*MAPSIZE;
  charadata[counter].y=(float)y*MAPSIZE;

  int charaValid=0;
   //この変数を利用しないと初期化関数Init();をwhile文に入れた場合に適切に描画されません。
   //Validは英語で「有効、根拠の確実な、確かな、正当な」などの意味です。

   //キャラクターごとに異なるものはswicth文を使います。
  switch(c){ //なお、ここにcounterを入れてしまうと、フリーズしてしまいました。
   case '11':
    charadata[counter].body=1;
    charaValid=1; //case毎にcv=1;と代入します。
    break;

   case 'AA':
    charadata[counter].anime_pattern=2; //アニメーションさせる場合はここで代入します。
    charadata[counter].body=1;
    charaValid=1; //
    break;

  }

    //このif文がないと初期化関数Init();をwhile文に入れた場合に適切に描画されません。
   if(charaValid){
   mapdata[y][x]='0'; //マップデータを'0'にする事で、データの取り出しは終わりです。
    //ここでキャラクターの数を一つずつ増やしていきます。
   counter++;
   }

  }
 }

}


 //描画と移動処理用の関数を作ります
void Move(){

 for(int i=0;i<CHARA;i++){

  char c=charadata[i].kind;

  switch(c){
   //ここにcharadata[i].kindではなくiを入れると、一つしか描画されませんでした。
   //また、フリーズしてまった場合もあります。

   case '11':
    DrawGraph(charadata[i].x,charadata[i].y,im.kabe01,TRUE);
  
    break;

   case 'AA':
    int a=g_anime_counter/20%charadata[i].anime_pattern;
    DrawGraph(charadata[i].x,charadata[i].y,im.teki0A[a],TRUE);

    break;

  }

   //キャラクター単位で動かす方法でマップスクロールを行います。
  charadata[i].x=charadata[i].x-1;

 }

}



 //WinMain関数の中に、先ほど作った関数を入れます。//Move();だけwhile内に入れます。
int WINAPI WinMain(HINSTANCE hI,HINSTANCE hP,LPSTR lpC,int nC){

 if(ChangeWindowMode(TRUE)!=0) return -1; //ウィンドウモードの変更
 if(DxLib_Init()!=0) return -1; //DXライブラリ初期化処理
 if(SetDrawScreen(DX_SCREEN_BACK)!=0) return -1; //描画先を裏画面に設定


 //ロードの関数は、ここではここに入れます。


 MapLoad(); //マップデータのロード

 Load(); //画像のロード 

 Init(); //初期化。//if(charaValid)に関するコードを書いていない時は、ここに置かないで、while文の中に置くと、適切に描画されません。



 while(ProcessMessage()==0&&CheckHitKey(KEY_INPUT_ESCAPE)==0){
  //メッセージ処理(XキーかAlt+F4キーが押されたら終了)
  //ESCキーが押されたら終了
 if(ClearDrawScreen()!=0) return -1; //裏画面を消す


  //Init(); //初期化。//if(charaValid)に関するコードを書いていないでwhile文の中に初期化関数Init();置くと、適切に描画されません。
   //この関数をそのままwhile文の中に入れてしまうと、一番最初の画像が消えてしまう。

  Move(); //画像の描画と移動用の関数をここに置きます。

  g_anime_counter++; //



  if(ScreenFlip()!=0) return -1; //裏画面を表画面に反映

 }

 if(DxLib_End()!=0) return -1; //DXライブラリの終了処理
 return 0; //ソフトの終了

}

 



 以下はvoid MapLoad(){}の中身だけを投稿します。

 次に、カンマや改行を調べて、それをヌル文字に変換する方法も試してみました。



 方法2

コード:

 

 //メモ帳からマップデータを読み込み
void MapLoad(){

  //各キャラクターのデータを初期化します。
 ZeroMemory(charadata,sizeof(charadata));

 char buf[1024];
 sprintf_s(buf,1024,"media/map%d",1); //ファイル名を用意する
 int fp; //ファイルハンドル
 fp==FileRead_open(buf); //ファイルを開く

  //ファイル読み込みエラー処理
 if(fp=NULL){
  printfDx("ファイル読み込みエラー");
  return;
 }


/////////////////////////////ここから////////////////////////////


 char c=0; //文字を読み込む
 int i=0; //文字列のデータのカウント

  //1024が1023に減っているのは、NULL文字対策
 while(FileRead_gets(buf,1023,fp)!='\n'); //改行に来たら読み込みを辞める



 for(int y=0;y<HEIGHT;y++){
  for(int x=0;x<WIDTH;x++){

   //1024が1023に減っているのは、NULL文字対策
 c=FileRead_gets(buf,1023,fp);
 buf[i]=c;

 if(buf[i]==','||buf[i]=='\n'||buf[i]==EOF){
  buf[i]='\0'; //ヌル文字を代入
  i=-1; //カウントをリセットする。
  } //if(buf[i]==','||buf[i]=='\n'||buf[i]==EOF)の最後


 //いずれもフリーズしました。
 //mapdata[y][x]=buf[i];
 //FileRead_gets(mapdata[y],buf[i],fp);

 if(c==EOF) break;

  i++;


  } //for(int x=0;x<WIDTH;x++)の最後
 } //for(int y=0;y<HEIGHT;y++)の最後



/////////////////////////////ここまで////////////////////////////

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

} //void MapLoad();の最後

 



方法3

コード:

 
 
  //メモ帳からマップデータを読み込み
void MapLoad(){

  //各キャラクターのデータを初期化します。
 ZeroMemory(charadata,sizeof(charadata));

 char buf[1024];
 sprintf_s(buf,1024,"media/map%d",1); //ファイル名を用意する
 int fp; //ファイルハンドル
 fp==FileRead_open(buf); //ファイルを開く

  //ファイル読み込みエラー処理
 if(fp=NULL){
  printfDx("ファイル読み込みエラー");
  return;
 }


/////////////////////////////ここから////////////////////////////


 int i=0; //文字列データのカウント

 for(int y=0;y<HEIGHT;y++){

   //1024が1023に減っているのは、NULL文字対策
  FileRead_gets(buf,1023,fp);

  //for(int x=0;x<WIDTH;x++){

 if(buf[i]==','||buf[i]=='\n'||buf[i]==EOF){
  buf[i]='\0'; //ヌル文字を代入
  i=-1; //カウントをリセットする。
  } //if(buf[i]==','||buf[i]=='\n'||buf[i]==EOF)の最後

 
 //mapdata[y][x]=buf[x];
 FileRead_gets(mapdata[y],buf[i],fp);

  i++;


  //} //for(int x=0;x<WIDTH;x++)の最後


 } //for(int y=0;y<HEIGHT;y++)の最後



/////////////////////////////ここまで////////////////////////////

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

} //void MapLoad();の最後

  



 mapdataを二次元配列から一次元配列にする方法も試しました。

コード:

 

 //メモ帳からマップデータを読み込み
void MapLoad(){

  //各キャラクターのデータを初期化します。
 ZeroMemory(charadata,sizeof(charadata));

 char buf[1024];
 sprintf_s(buf,1024,"media/map%d",1); //ファイル名を用意する
 int fp; //ファイルハンドル
 fp==FileRead_open(buf); //ファイルを開く

  //ファイル読み込みエラー処理
 if(fp=NULL){
  printfDx("ファイル読み込みエラー");
  return;
 }


/////////////////////////////ここから////////////////////////////

  //1024が1023に減っているのは、NULL文字対策
 while(FileRead_gets(buf,1023,fp)!='\n'); //改行に来たら読み込みを辞める


 int x=0;
 for(int y=0;y<HEIGHT;y++){

   //1024が1023に減っているのはヌル文字対策
  fp=FileRead_gets(buf,1023,fp);

 //for(int x=0;x<WIDTH;x++){

 if(buf[x]==','||buf[x]=='\n'||buf[x]==EOF){
  buf[x]='\0'; //ヌル文字を代入
  x=-1; //カウントをリセットする。
  } //if(buf[x]==','||buf[x]=='\n'||buf[x]==EOF)の最後


  mapdata[y*WIDTH+x]=buf[x];

   x++;

  //} //for(int x=0;x<WIDTH;x++)の最後
 } //for(int y=0;y<HEIGHT;y++)の最後



/////////////////////////////ここまで////////////////////////////

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

} //void MapLoad();の最後

 


 しかし、どれも失敗してフリーズしてしまいました。

 さらに、読み込んだデータをmapdataの中に変換や代入する方法も、分かりません。

 お手上げです。

 どのソースコードをどのように直せば、カンマ付き文字列のデータの読み込みが出来るようになるでしょうか。


 
添付ファイル
teki0A.jpg.jpg
teki0A.jpg.jpg (1.59 KiB) 閲覧数: 1680 回

プログラマ見習い
記事: 44
登録日時: 3ヶ月前

Re: メモ帳からカンマ付き文字列のデータの読み込みが出来ません。

#2

投稿記事 by プログラマ見習い » 1ヶ月前

添付ファイルの投稿に失敗したので、あらためて投稿します。
添付ファイル
teki0A.jpg.jpg
敵AA
teki0A.jpg.jpg (1.59 KiB) 閲覧数: 1679 回
kabe01.jpg.jpg
壁11
kabe01.jpg.jpg (1.08 KiB) 閲覧数: 1679 回

アバター
usao
記事: 1550
登録日時: 6年前

Re: メモ帳からカンマ付き文字列のデータの読み込みが出来ません。

#3

投稿記事 by usao » 1ヶ月前

=と==の違い,わかってますかね?

FileRead_gets()の戻り値はググった感じだと「長さ」らしいですが,
だとしたら,↓って何の判定なのかわからないですよね.

コード:

FileRead_gets(buf,1023,fp)!='\n'
#方法論がどうの以前に最低限のことはしようぜ

プログラマ見習い
記事: 44
登録日時: 3ヶ月前

Re: メモ帳からカンマ付き文字列のデータの読み込みが出来ません。

#4

投稿記事 by プログラマ見習い » 1ヶ月前

usaoさん。分かっています。ソースコードを書き直す際に書き間違えただけです。手書きでソースコードを書けば、誰にでも失敗があって、見落としてしまう事はありますよ。

アバター
usao
記事: 1550
登録日時: 6年前

Re: メモ帳からカンマ付き文字列のデータの読み込みが出来ません。

#5

投稿記事 by usao » 1ヶ月前

OK.他者に期待.
オフトピック
ソースをどう直したらいいか? という話をする際には,私なら,コードをコピー&ペーストする.

「ここに提示したコードは実際のものとは異なっていて,そりゃあ書き写しのミスもありますよ」とか言われても,
じゃあどれがそのミスで,どれは違うのか?
一体何に注目してどの問題について論じれば良いのか?
第三者には判断材料がないわけだから,正常なやりとり自体が不可能ですな.
(それでも大丈夫なエスパーな人もいるかもだが,私には無理)

Math

Re: メモ帳からカンマ付き文字列のデータの読み込みが出来ません。

#6

投稿記事 by Math » 1ヶ月前

>以上のマップデータを読み込むために、書籍やネットなどの情報を参考に、考えられる方法を試しました
本当に(^^

相当頭が混乱して様ですね。

まず char型 のデータに 2文字の文字列がはいるわけないじゃん!

--------------------------------------------------------
switch(c){ //なお、ここにcounterを入れてしまうと、フリーズしてしまいました。
case '11':
charadata[counter].body=1;
charaValid=1; //case毎にcv=1;と代入します。
break;

case 'AA':
charadata
--------------------------------------------------------

の'11'  と 'AA' はVS2019 では ワーニングがでて  '1' と 'A' に切り詰められますよ。


当然ながらデータ読み込みのところは大間違い!

かずま

Re: メモ帳からカンマ付き文字列のデータの読み込みが出来ません。

#7

投稿記事 by かずま » 1ヶ月前

media/map1 ですが、提示されたものは、空行 2行、データ 11行、空行 3行
になっていますよ。いいんですか?

media/map1 は CSVファイルである必要はありませんよね。
次のように変更してみました。読み込みが楽になります。

コード:

0000000000000000000000000000000000000000
0000000000111111111100000000001111111111
000000000000A000000000000000000000000000
0000000000000000000000000000000000000000
0000000000A00000000000000000000000000000
0000000000000000000000000000000000000000
00000000000A0000000000000000000000000000
0000000000000000000000000000000000000000
0000000000A00000000000000000000000000000
0000000000000000000000000000000000000000
0000000000000000000000000000000000000000
0000000000000000000000000000000000000000
0000000000000000000000000000000000000000
0000000000000000000000000000000000000000
0000000000000000000000000000000000000000
char の変数に入らない '11' や 'AA' などのデータを使わず、
'0'、'1'、'A' にしました。

media/kabe01.bmp と media/teki0A.bmp を適当に作ったら、
次のプログラムで動きました。

コード:

#include <DxLib.h>

#define MAPSIZE 32

#define HEIGHT 15
#define WIDTH  40

#define CHARA (HEIGHT * WIDTH)

struct ImageData {
	int kabe01;
	int teki0A[2];
};

struct ImageData im;

struct CharaData {
	char kind;
	int anime_pattern;
	int x, y;
	int body;
};
int counter;  // ★

struct CharaData charadata[CHARA];
unsigned int g_anime_counter = 0;
char mapdata[HEIGHT][WIDTH];

void MapLoad()
{
	ZeroMemory(charadata, sizeof(charadata));

	char buf[1024];
	strcpy(buf, "media/map1");
	int fh = FileRead_open(buf);
	if (fh == NULL) { printfDx("ファイル読み込みエラー"); return; }

	for (int y = 0; y < HEIGHT; y++) {
		if (FileRead_gets(buf, 1024, fh) == -1) break;
		memcpy(mapdata[y], buf, WIDTH);
	}
	FileRead_close(fh);
}

void Load()
{
	im.kabe01 = LoadGraph("media/kabe01.bmp");
	LoadDivGraph("media/teki0A.bmp", 2, 2, 1, 32, 32, im.teki0A);
}

void Init()
{
	counter = 0;
	for (int y = 0; y < HEIGHT; y++) {
		for (int x = 0; x < WIDTH; x++) {
			char c = mapdata[y][x];
			charadata[counter].kind = c;
			charadata[counter].x = x * MAPSIZE;
			charadata[counter].y = y * MAPSIZE;
			switch (c) {
			case '1':
				charadata[counter].body = 1;
				mapdata[y][x] = '0';
				counter++;
				break;
			case 'A':
				charadata[counter].anime_pattern = 2;
				charadata[counter].body = 1;
				mapdata[y][x] = '0';
				counter++;
				break;
			}
		}
	}
}

void Move()
{
	for (int i = 0; i < counter; i++) {  // ★
		char c = charadata[i].kind;
		switch (c) {
		case '1':
			DrawGraph(charadata[i].x, charadata[i].y, im.kabe01, TRUE);
			break;

		case 'A':
			int a = g_anime_counter / 20 % charadata[i].anime_pattern;
			DrawGraph(charadata[i].x, charadata[i].y, im.teki0A[a], TRUE);
			break;
		}
		charadata[i].x = charadata[i].x - 1;
	}
}

int WINAPI WinMain(HINSTANCE hI, HINSTANCE hP, LPSTR lpC, int nC)
{
	if (ChangeWindowMode(TRUE) != 0) return -1;
	if (DxLib_Init() != 0) return -1;
	if (SetDrawScreen(DX_SCREEN_BACK) != 0) return -1;

	MapLoad();
	Load();
	Init();

	while (ProcessMessage() == 0 && CheckHitKey(KEY_INPUT_ESCAPE) == 0) {
		if (ClearDrawScreen() != 0) return -1;
		Move();
		g_anime_counter++;
		if (ScreenFlip() != 0) return -1;
	}

	if (DxLib_End() != 0) return -1;
	return 0;
}

Math

Re: メモ帳からカンマ付き文字列のデータの読み込みが出来ません。

#8

投稿記事 by Math » 1ヶ月前

14歳からはじめるC言語わくわくゲームプログラミング教室 (DXライブラリー使用)
https://www.rutles.net/products/detail. ... uct_id=591

コード:

#include "gamemain.h"

int g_mapdata[MAP_HEIGHT][MAP_WIDTH] = {
	//0  1  2  3  4  5  6  7  8  9  0  1  2  3  4  5
	{ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 },	//0
	{ 1, 7, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 4 },	//1
	{ 1, 0, 1, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 9 },	//2
	{ 1, 0, 0, 0, 0, 2, 0, 0, 1, 0, 0, 1, 1, 1, 1, 1 },	//3
	{ 1, 0, 1, 1, 1, 1, 0, 0, 1, 0, 3, 1, 0, 0, 0, 1 },	//4
	{ 1, 0, 1, 0, 0, 1, 0, 8, 1, 0, 0, 1, 0, 1, 0, 1 },	//5
	{ 1, 0, 1, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0, 1 },	//6
	{ 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1 },	//7
	{ 1, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1 },	//8
	{ 1, 0, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 0, 1 },	//9
	{ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 1 },	//10
	{ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }	//11
};

StageData g_stagedata;	//ゲーム本編のデータ

//ステージ初期化
void InitStage(){


DXライブラリーのサンプルも
https://dxlib.xsrv.jp/dxprogram.html#N3

コード:

// マップ表示基本
#include "DxLib.h"

#define MAP_SIZE	64			// マップチップ一つのドットサイズ

#define MAP_WIDTH	10			// マップの幅
#define MAP_HEIGHT	8			// マップの縦長さ

// マップのデータ
int MapData[ MAP_HEIGHT ][ MAP_WIDTH ] =
{
	{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } ,
	{ 0, 1, 0, 0, 0, 0, 0, 0, 0, 0 } ,
	{ 0, 1, 0, 1, 1, 1, 1, 1, 1, 0 } ,
	{ 0, 1, 0, 1, 1, 0, 0, 0, 1, 0 } ,
	{ 0, 1, 1, 1, 1, 0, 0, 0, 1, 0 } ,
	{ 0, 1, 0, 1, 0, 0, 0, 0, 1, 0 } ,
	{ 0, 1, 1, 1, 1, 1, 1, 1, 1, 0 } ,
	{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } 
} ;

int コンマ・セパレートですね
ここにあるいろいろなサンプルを触ってみるのがいいでしょうね。

プログラマ見習い
記事: 44
登録日時: 3ヶ月前

Re: メモ帳からカンマ付き文字列のデータの読み込みが出来ません。

#9

投稿記事 by プログラマ見習い » 1ヶ月前

Mathさん。かずまさん。貴重なアドバイスありがとうごさいます。
「相当頭が混乱して様ですね。」
はい。おっしゃる通り、試行錯誤を続けているうちに、頭が疲労してしまいました。ソースコードに初歩的なミスがあるのも、そのためです。修正を繰り返しているうちに、気づかないうちにミスを犯した部分があります。
疲れに気を付けながら、またじっくり試行錯誤をするつもりです。

 私は当サイトの規約の趣旨を考慮しながら、どう説明すればいいか考えた上で慎重に言葉を選んで投稿したつもりでしたが、説明が不十分で、ソースコードに初歩的なミスがあるなど、不適切な部分がありました。お詫び申し上げます。


11、AAなど、2行になっているのは、扱うデータの種類が多くなった場合に備えての事です。

根本的な質問ですが、以下のようなメモ帳に書かれた00,00,11,11,11,00,11,AAなどのカンマで区切られた2行以上の文字列は、読み込んでマップデータに変換する事は,
そもそも技術的に可能なのでしょうか?

00,00,11,11,11,00,11,AA
00,AA,11,11,11,00,11,00
11,00,00,11,11,00,11,AA

もしも可能なのであれば、引き続き試行錯誤するつもりですが、不可能であれば、諦めます。

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

Re: メモ帳からカンマ付き文字列のデータの読み込みが出来ません。

#10

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

どう直せばいいかを考えるのは難しそうだったので、
とりあえず、コンマで区切ってデータを読み込む部分を作ってみました。
変換の方法は、何がしたいのかがわからないのでわかりません。
やりたいことやその実装に応じて適宜行ってください。
ただし、少なくとも、指摘されている通りchar型に複数の文字は
(使う文字の集合を決めて自分でエンコードするなどの工夫をしない限り)入りません。

コード:

#include <DxLib.h>
#include <cstdio>
#include <vector>
#include <string>

// 対応していない環境用
//#define sprintf_s snprintf

// データを読み込んで返す
std::vector<std::vector<std::string> > loadMapData(void) {
	std::vector<std::vector<std::string> > result;
	std::vector<std::string> rowBuffer;
	std::string cellBuffer;
	int fp;
	char fileName[1024];
	// ファイル名を用意する (拡張子が無いが、いいのかな?)
	sprintf_s(fileName, sizeof(fileName), "media/map%d", 1);
	// ファイルを開く
	fp = FileRead_open(fileName);
	if (fp == 0) {
		printfDx("ファイル読み込みエラー");
		return result;
	}
	// データを読み込む
	bool prevIsCr = false; // CRLFを二重にカウントするのを防ぐ用
	for (;;) {
		int c = FileRead_getc(fp);
		if (c < 0) break;
		if (c == '\r' || c == '\n') {
			if (!(prevIsCr && c == '\n')) { // CRLFを二重にカウントするのを防ぐ
				// セルのデータを行に反映させる
				rowBuffer.push_back(cellBuffer);
				// 行のデータを全体に反映させる
				result.push_back(rowBuffer);
				// データバッファを初期化する
				rowBuffer.clear();
				cellBuffer.clear();
			}
		} else if (c == ',') {
			// セルのデータを行に反映させる
			rowBuffer.push_back(cellBuffer);
			// データバッファを初期化する
			cellBuffer.clear();
		} else {
			// セルのデータに加える 
			cellBuffer.push_back(c);
		}
		// 改行の状態を更新する
		prevIsCr = (c == '\r');
	}
	// 最後の改行の後にデータがあったら反映させる
	if (!cellBuffer.empty() || !rowBuffer.empty()) {
		// セルのデータを行に反映させる
		rowBuffer.push_back(cellBuffer);
		// 行のデータを全体に反映させる
		result.push_back(rowBuffer);
	}
	// ファイルを閉じる
	FileRead_close(fp);
	// 読み込んだデータを返す
	return result;
}

int WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int) {
	if (ChangeWindowMode(TRUE) != DX_CHANGESCREEN_OK || DxLib_Init() != 0) return -1;
	SetDrawScreen(DX_SCREEN_BACK);

	// マップデータを読み込む
	std::vector<std::vector<std::string> > mapData = loadMapData();
	// 読み込んだデータを出力する
	for (size_t i = 0; i < mapData.size(); i++) {
		printfDx("%2d:", i);
		for (size_t j = 0; j < mapData[i].size(); j++) {
			if (j > 0) {
				if (j % 20 == 0) printfDx("\n  ");
				printfDx(" ");
			}
			printfDx("%s", mapData[i][j].c_str());
		}
		printfDx("\n");
	}

	while (ProcessMessage() == 0 && ClearDrawScreen() == 0) {
		ScreenFlip();
	}

	DxLib_End();
	return 0;
}
実行結果
ss20190723.png
実行結果
ss20190723.png (23.26 KiB) 閲覧数: 1562 回
プログラマ見習い さんが書きました:
1ヶ月前
根本的な質問ですが、以下のようなメモ帳に書かれた00,00,11,11,11,00,11,AAなどのカンマで区切られた2行以上の文字列は、読み込んでマップデータに変換する事は,
そもそも技術的に可能なのでしょうか?
可能と考えられます。
まず、変換先の「マップデータ」を定義するところから始めましょう。
添付ファイル
media.zip
マップデータ
(350 バイト) ダウンロード数: 9 回
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

かずま

Re: メモ帳からカンマ付き文字列のデータの読み込みが出来ません。

#11

投稿記事 by かずま » 1ヶ月前

プログラマ見習い さんが書きました:
1ヶ月前
11、AAなど、2行になっているのは、扱うデータの種類が多くなった場合に備えての事です。
何種類のデータが必要ですか?
必ず答えてください。
プログラマ見習い さんが書きました:
1ヶ月前
根本的な質問ですが、以下のようなメモ帳に書かれた00,00,11,11,11,00,11,AAなどのカンマで区切られた2行以上の文字列は、読み込んでマップデータに変換する事は,
そもそも技術的に可能なのでしょうか?
可能です。
00,01,02,...,0A,0B,0C,0D,0E,0F,10,11,12,...,FD,FE,FF
のように 16進で書けば、256種類のデータを扱えます。

media/map1

コード:

00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00
00,00,00,00,00,00,00,00,00,00,11,11,11,11,11,11,11,11,11,11,00,00,00,00,00,00,00,00,00,00,11,11,11,11,11,11,11,11,11,11
00,00,00,00,00,00,00,00,00,00,00,00,AA,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00
00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00
00,00,00,00,00,00,00,00,00,00,AA,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00
00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00
00,00,00,00,00,00,00,00,00,00,00,AA,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00
00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00
00,00,00,00,00,00,00,00,00,00,AA,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00
00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00
00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00
00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00
00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00
00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00
00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00
strtol を使い、0x11 や 0xAA として読み込みます。

コード:

#include <DxLib.h>

#define MAPSIZE 32

#define HEIGHT 15
#define WIDTH  40

#define CHARA (HEIGHT * WIDTH)

struct ImageData {
	int kabe01;
	int teki0A[2];
};

struct ImageData im;

struct CharaData {
	char kind;
	int anime_pattern;
	int x, y;
	int body;
};
int counter;

struct CharaData charadata[CHARA];
unsigned int g_anime_counter = 0;
char mapdata[HEIGHT][WIDTH];

void MapLoad()
{
	ZeroMemory(charadata, sizeof(charadata));

	char buf[1024];
	strcpy(buf, "media/map1");
	int fh = FileRead_open(buf);
	if (fh == NULL) { printfDx("ファイル読み込みエラー"); return; }

	for (int y = 0; y < HEIGHT; y++) {
		if (FileRead_gets(buf, 1024, fh) == -1) break;
		char *p = buf;                          // ★
		for (int x = 0; x < WIDTH; x++) {       // ★
			mapdata[y][x] = strtol(p, &p, 16);  // ★
			p++; // skip ','                    // ★
		}                                       // ★
	}
	FileRead_close(fh);
}

void Load()
{
	im.kabe01 = LoadGraph("media/kabe01.bmp");
	LoadDivGraph("media/teki0A.bmp", 2, 2, 1, 32, 32, im.teki0A);
}

void Init()
{
	counter = 0;
	for (int y = 0; y < HEIGHT; y++) {
		for (int x = 0; x < WIDTH; x++) {
			unsigned char c = mapdata[y][x];  // ★
			charadata[counter].kind = c;
			charadata[counter].x = x * MAPSIZE;
			charadata[counter].y = y * MAPSIZE;
			switch (c) {
			case 0x11:  // ★
				charadata[counter].body = 1;
				mapdata[y][x] = '0';
				counter++;
				break;
			case 0xAA:  // ★
				charadata[counter].anime_pattern = 2;
				charadata[counter].body = 1;
				mapdata[y][x] = '0';
				counter++;
				break;
			}
		}
	}
}

void Move()
{
	for (int i = 0; i < counter; i++) {
		unsigned char c = charadata[i].kind;  // ★
		switch (c) {
		case 0x11:  // ★
			DrawGraph(charadata[i].x, charadata[i].y, im.kabe01, TRUE);
			break;

		case 0xAA:  // ★
			int a = g_anime_counter / 20 % charadata[i].anime_pattern;
			DrawGraph(charadata[i].x, charadata[i].y, im.teki0A[a], TRUE);
			break;
		}
		charadata[i].x = charadata[i].x - 1;
	}
}

int WINAPI WinMain(HINSTANCE hI, HINSTANCE hP, LPSTR lpC, int nC)
{
	if (ChangeWindowMode(TRUE) != 0) return -1;
	if (DxLib_Init() != 0) return -1;
	if (SetDrawScreen(DX_SCREEN_BACK) != 0) return -1;

	MapLoad();
	Load();
	Init();

	while (ProcessMessage() == 0 && CheckHitKey(KEY_INPUT_ESCAPE) == 0) {
		if (ClearDrawScreen() != 0) return -1;
		Move();
		g_anime_counter++;
		if (ScreenFlip() != 0) return -1;
	}

	if (DxLib_End() != 0) return -1;
	return 0;
}
このプログラムを実行した結果を報告してください。
また、プログラム上の疑問点を質問してください。

box
記事: 1737
登録日時: 8年前

Re: メモ帳からカンマ付き文字列のデータの読み込みが出来ません。

#12

投稿記事 by box » 1ヶ月前

ソースコードを書き直す際に書き間違えただけです。手書きでソースコードを書けば
投稿のためにわざわざ入力し直したんですか?うわ~そりゃ大変だ。
それは大変な手間がかかり、今回のように打ち間違えたコードを
アップしてしまうことになりかねませんので、コピペといういちばん楽と思われる
方法を使いましょう。
ソースコードが1万行くらいあっても手で打ち直しますか?ということです。
そんなことしたくありませんよね。
バグのないプログラムはない。
プログラムは思ったとおりには動かない。書いたとおりに動く。

アバター
usao
記事: 1550
登録日時: 6年前

Re: メモ帳からカンマ付き文字列のデータの読み込みが出来ません。

#13

投稿記事 by usao » 1ヶ月前

オフトピック
こんな単純データだったら,stringstream様のお力で解決してもらえば楽なのでは.

プログラマ見習い
記事: 44
登録日時: 3ヶ月前

Re: メモ帳からカンマ付き文字列のデータの読み込みが出来ません。

#14

投稿記事 by プログラマ見習い » 1ヶ月前

皆さん。貴重なアドバイスありがとうございます。

まずはみけCATさん。みけCATさんが投稿してくれたソースコードをこちらでコンパイルしたら、正常に作動しました。

次にかずまさん。かずまさんが投稿してくれたソースコードををこちらでコンパイルしたら、エラー警告C4996が出て、strcpyに問題があると言う事でしたので、strcpyをsprintf_sに修正してコンパイルした所、真黒な画面が出ました。

次にboxさん。多分ソースコードの見直しのつもりで書き直しなんてしたんだと思いますが、かえって仇となりました。気をつけます。

次にusaoさん。stringstream様のお力を使いこなせれるように、試行錯誤中です。

現在皆様のアドバイスを参考に、試行錯誤中ですが、今の自分の実力では一筋縄ではいかない事が分かりました。

ただ、第一に、質問者である自分が何をしたいのか分からない、第二に、他人に期待しすぎていると言うご指摘があったので、それについて述べさせてもらいます。

第一については、もう一度分かりやすいように整理してから報告します。
第二については、客観的に見れば、おっしゃる通りだったと答えます。ただ、他の人にとっては簡単なプログラムでも、今の自分にとっては難しい事であることは確かです。

アバター
usao
記事: 1550
登録日時: 6年前

Re: メモ帳からカンマ付き文字列のデータの読み込みが出来ません。

#15

投稿記事 by usao » 1ヶ月前

オフトピック
カンマ区切りな内容のファイルを用意するとしたら,それを読込むプログラムの側ではカンマの存在に対処する必要がある.
その処理が自分自身に厳しいかどうかは,やる前にわかるハズ.

にも関わらず,何故カンマ区切りなフォーマットのデータファイルを用いようと思うのか.
わざわざ問題の難易度を自分自身で大きく引き上げて困っているという構図.
「自分が余裕で扱える形でデータを用意しちゃいけない縛り」みたいな営みなのか? 行き詰るのが好きなのか?

アバター
usao
記事: 1550
登録日時: 6年前

Re: メモ帳からカンマ付き文字列のデータの読み込みが出来ません。

#16

投稿記事 by usao » 1ヶ月前

オフトピック
> mapdataを二次元配列から一次元配列にする方法も試しました

こういうことしている時点で,何かが根本的にズレている気がする.

あるロジックがあるデータ構造を用いて動く状態が存在していて,
→当該データ構造のデータを用意する手段として「ファイルから読む」

じゃないのか?
データ構造側をファイル読込処理の都合によって変えちゃうの?

プログラマ見習い
記事: 44
登録日時: 3ヶ月前

Re: メモ帳からカンマ付き文字列のデータの読み込みが出来ません。

#17

投稿記事 by プログラマ見習い » 1ヶ月前

 質問者である自分が何をしたいについて改めて説明しなおします。
 まずはmap0.txtの中身と、ソースコードを投稿します。
 今回はちゃんとコピペしたので、画面が正常に表示されるはずです。

 map0.txt

コード:

 
0000000000111111111100000000001111111111
0000000000000000000000000000000000000000
0000000000000000000000000000000000000000
0000000000000000000000000000000000000000
0000000000AAA000000000000000000000000000
0000000000000000000000000000000000000000
0000000000000000000000000000000000000000
0000000000000000000000000000000000000000
0000000000000000000000000000000000000000
0000000000000000000000000000000000000000
0000000000AAA000000000000000000000000000
0000000000000000000000000000000000000000
0000000000000000000000000000000000000000
0000000000000000000000000000000000000000
0000000000111111111100000000001111111111
 


 map0.txtを読み込んだもの

コード:

 

#include <DxLib.h>

#define MAPSIZE 32 //マップサイズを決めます。

#define HEIGHT 15 //Y座標の最大値を決めます
#define WIDTH 40 //X座標の最大値を決めます

 //キャラクターの数の最大値を決めます。念のために多めにします。今回はマップデータの数に合わせます。
#define CHARA HEIGHT*WIDTH



 //画像データの構造体を作ります。
 //画像データは無理に配列やポインタで整理しようとすると、エラーやフリーズの原因になります。
struct ImageData{

 int kabe01; //
 int teki0A[2]; //

};

struct ImageData im; //



 //各キャラクターのデータの構造体を作ります。
struct CharaData{

 //int *ghandle; //アニメーションさせるために画像データハンドル。
 //ポインタ設定をしたが、これが原因の一つでした。

 char kind; //キャラクターの種類を格納。
 int anime_pattern; //アニメパーン数
 float x; //座標はfloatにします。
 float y;
 int body; //体力

};

struct CharaData charadata[CHARA]; //今回はcharadataと名づけます。
 //キャラクターは複数出現させるので、配列内に各キャラクターの最大値CHMAXを格納します。

//struct CharaData im[2]; //画像を描画するための変数。
//or//struct CharaData im[CHARA]; //画像を描画するための変数。



 //アニメーションカウンター用の変数を作ります。
unsigned int g_anime_counter=0;



 //マップデータを作ります。
char mapdata[HEIGHT][WIDTH];



  //メモ帳からマップデータを読み込み
void MapLoad(){

  //各キャラクターのデータを初期化します。
 ZeroMemory(charadata,sizeof(charadata));

 char buf[1024];
 sprintf_s(buf,1024,"media/map%d.txt",1); //ファイル名を用意する
 int fp; //ファイルハンドル
 fp=FileRead_open(buf); //ファイルを開く

  //ファイル読み込みエラー処理
 if(fp==NULL){
  printfDx("ファイル読み込みエラー");
  return;
 }



/////////////////////////////ここから////////////////////////////



 for(int y=0;y<HEIGHT;y++){
  for(int x=0;x<WIDTH;x++){



  FileRead_scanf(fp,"%s",mapdata[y][x]);



 } //for(int x=0;x<WIDTH;x++)の最後

} //for(int y=0;y<HEIGHT;y++)の最後

/////////////////////////////ここまで////////////////////////////

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

} //void MapLoad();の最後



 //画像をロードする関数を作ります。
void Load(){

 im.kabe01=LoadGraph("media/kabe01.jpg");

 LoadDivGraph("media/teki0A.jpg",2,2,1,32,32,im.teki0A);

}



 //初期化用の関数を作ります。
void Init(){

  //キャラクターをカウントする変数を作ります。必要な変数の一つです。
  //キャラクターをカウントする変数はローカル変数でも問題ありませんでした。
 int counter=0;

 for(int y=0;y<HEIGHT;y++){
  for(int x=0;x<WIDTH;x++){

  char c=mapdata[y][x];

   //初期化してマップデータから、キャラクターのデータを取り出します。

   //kindにマップデータを代入します。
   //これも必要な変数の一つです。
  charadata[counter].kind=c;

  charadata[counter].x=(float)x*MAPSIZE;
  charadata[counter].y=(float)y*MAPSIZE;

  int charaValid=0;
   //この変数を利用しないと初期化関数Init();をwhile文に入れた場合に適切に描画されません。
   //Validは英語で「有効、根拠の確実な、確かな、正当な」などの意味です。

   //キャラクターごとに異なるものはswicth文を使います。
  switch(c){ //なお、ここにcounterを入れてしまうと、フリーズしてしまいました。
   case '1':
    charadata[counter].body=1;
    charaValid=1; //case毎にcv=1;と代入します。
    break;

   case 'A':
    charadata[counter].anime_pattern=2; //アニメーションさせる場合はここで代入します。
    charadata[counter].body=1;
    charaValid=1; //
    break;

  }

    //このif文がないと初期化関数Init();をwhile文に入れた場合に適切に描画されません。
   if(charaValid){
   mapdata[y][x]='0'; //マップデータを'0'にする事で、データの取り出しは終わりです。
    //ここでキャラクターの数を一つずつ増やしていきます。
   counter++;
   }

  }
 }

}


 //描画と移動処理用の関数を作ります
void Move(){

 for(int i=0;i<CHARA;i++){

  char c=charadata[i].kind;

  switch(c){
   //ここにcharadata[i].kindではなくiを入れると、一つしか描画されませんでした。
   //また、フリーズしてまった場合もあります。

   case '1':
    DrawGraph(charadata[i].x,charadata[i].y,im.kabe01,TRUE);
  
    break;

   case 'A':
    int a=g_anime_counter/20%charadata[i].anime_pattern;
    DrawGraph(charadata[i].x,charadata[i].y,im.teki0A[a],TRUE);

    break;

  }

   //キャラクター単位で動かす方法でマップスクロールを行います。
  charadata[i].x=charadata[i].x-1;

 }

}



 //WinMain関数の中に、先ほど作った関数を入れます。//Move();だけwhile内に入れます。
int WINAPI WinMain(HINSTANCE hI,HINSTANCE hP,LPSTR lpC,int nC){

 if(ChangeWindowMode(TRUE)!=0) return -1; //ウィンドウモードの変更
 if(DxLib_Init()!=0) return -1; //DXライブラリ初期化処理
 if(SetDrawScreen(DX_SCREEN_BACK)!=0) return -1; //描画先を裏画面に設定


 //ロードの関数は、ここではここに入れます。


 MapLoad(); //マップデータのロード

 Load(); //画像のロード 

 Init(); //初期化。//if(charaValid)に関するコードを書いていない時は、ここに置かないで、while文の中に置くと、適切に描画されません。



 while(ProcessMessage()==0&&CheckHitKey(KEY_INPUT_ESCAPE)==0){
  //メッセージ処理(XキーかAlt+F4キーが押されたら終了)
  //ESCキーが押されたら終了
 if(ClearDrawScreen()!=0) return -1; //裏画面を消す


  //Init(); //初期化。//if(charaValid)に関するコードを書いていないでwhile文の中に初期化関数Init();置くと、適切に描画されません。
   //この関数をそのままwhile文の中に入れてしまうと、一番最初の画像が消えてしまう。

  Move(); //画像の描画と移動用の関数をここに置きます。

  g_anime_counter++; //



  if(ScreenFlip()!=0) return -1; //裏画面を表画面に反映

 }

 if(DxLib_End()!=0) return -1; //DXライブラリの終了処理
 return 0; //ソフトの終了

}

 


 次にvoid MapLoad(){}の中身をご覧ください。
 以上のソースコードは、map0.txtからデータを読み込んで、マップデータに変換しているのですが、map0.txtは、ご覧の通り、カンマや空白などで区切られておらず、1ケタずつ読み込まれます。

 以上の方法には、二つ問題があります。
 第一に、以上のような1ケタずつ読み込んでいく方法だと、整数10個、アルファベット大文字26文字、小文字26文字で、合計62種類までのデータを読み込む事が出来ます。
 しかし、もしも62種類よりも多くのデータを読み込みたい場合、2ケタの整数や文字を用意する必要があります。例えば100種類、200種類のデータを読み込みたい場合、00、01、AAなどのような整数や文字が必要であります、

 第二に、カンマや空白などで区切られていないと、何行目の何列目かが分かり辛い、目で見ると目が痛くなってしまうと言う問題があります。そこで、カンマや空白などでデータを区切る事で、見えやすくする必要があります。

 以上の理由から、私はカンマ区切りの文字を読み込む事と、2ケタの文字を読み込む事がしたいのです。



 次に、2ケタずつカンマで区切って読み込んだソースコードを投稿します。
 但し、ここではmap0.txtをmap1.txtに、void Init(){}とvoid Move(){}関数の中身の1とAを、それぞれ1とAに変更しただけです。

 map1.txt

コード:

 
00,00,00,00,00,00,00,00,00,00,11,11,11,11,11,11,11,11,11,11,00,00,00,00,00,00,00,00,00,00,11,11,11,11,11,11,11,11,11,11
00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00
00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00
00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00
00,00,00,00,00,00,00,00,00,00,AA,AA,AA,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00
00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00
00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00
00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00
00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00
00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00
00,00,00,00,00,00,00,00,00,00,AA,AA,AA,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00
00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00
00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00
00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00
00,00,00,00,00,00,00,00,00,00,11,11,11,11,11,11,11,11,11,11,00,00,00,00,00,00,00,00,00,00,11,11,11,11,11,11,11,11,11,11
 


 map1.txtを読み込んだもの

コード:

 
#include <DxLib.h>

#define MAPSIZE 32 //マップサイズを決めます。

#define HEIGHT 15 //Y座標の最大値を決めます
#define WIDTH 40 //X座標の最大値を決めます

 //キャラクターの数の最大値を決めます。念のために多めにします。今回はマップデータの数に合わせます。
#define CHARA HEIGHT*WIDTH



 //画像データの構造体を作ります。
 //画像データは無理に配列やポインタで整理しようとすると、エラーやフリーズの原因になります。
struct ImageData{

 int kabe01; //
 int teki0A[2]; //

};

struct ImageData im; //



 //各キャラクターのデータの構造体を作ります。
struct CharaData{

 //int *ghandle; //アニメーションさせるために画像データハンドル。
 //ポインタ設定をしたが、これが原因の一つでした。

 char kind; //キャラクターの種類を格納。
 int anime_pattern; //アニメパーン数
 float x; //座標はfloatにします。
 float y;
 int body; //体力

};

struct CharaData charadata[CHARA]; //今回はcharadataと名づけます。
 //キャラクターは複数出現させるので、配列内に各キャラクターの最大値CHMAXを格納します。

//struct CharaData im[2]; //画像を描画するための変数。
//or//struct CharaData im[CHARA]; //画像を描画するための変数。



 //アニメーションカウンター用の変数を作ります。
unsigned int g_anime_counter=0;



 //マップデータを作ります。
char mapdata[HEIGHT][WIDTH];



  //メモ帳からマップデータを読み込み
void MapLoad(){

  //各キャラクターのデータを初期化します。
 ZeroMemory(charadata,sizeof(charadata));

 char buf[1024];
 sprintf_s(buf,1024,"media/map%d.txt",1); //ファイル名を用意する
 int fp; //ファイルハンドル
 fp=FileRead_open(buf); //ファイルを開く

  //ファイル読み込みエラー処理
 if(fp==NULL){
  printfDx("ファイル読み込みエラー");
  return;
 }



/////////////////////////////ここから////////////////////////////



 for(int y=0;y<HEIGHT;y++){
  for(int x=0;x<WIDTH;x++){



  FileRead_scanf(fp,"%s",mapdata[y][x]);



 } //for(int x=0;x<WIDTH;x++)の最後

} //for(int y=0;y<HEIGHT;y++)の最後

/////////////////////////////ここまで////////////////////////////

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

} //void MapLoad();の最後



 //画像をロードする関数を作ります。
void Load(){

 im.kabe01=LoadGraph("media/kabe01.jpg");

 LoadDivGraph("media/teki0A.jpg",2,2,1,32,32,im.teki0A);

}



 //初期化用の関数を作ります。
void Init(){

  //キャラクターをカウントする変数を作ります。必要な変数の一つです。
  //キャラクターをカウントする変数はローカル変数でも問題ありませんでした。
 int counter=0;

 for(int y=0;y<HEIGHT;y++){
  for(int x=0;x<WIDTH;x++){

  char c=mapdata[y][x];

   //初期化してマップデータから、キャラクターのデータを取り出します。

   //kindにマップデータを代入します。
   //これも必要な変数の一つです。
  charadata[counter].kind=c;

  charadata[counter].x=(float)x*MAPSIZE;
  charadata[counter].y=(float)y*MAPSIZE;

  int charaValid=0;
   //この変数を利用しないと初期化関数Init();をwhile文に入れた場合に適切に描画されません。
   //Validは英語で「有効、根拠の確実な、確かな、正当な」などの意味です。

   //キャラクターごとに異なるものはswicth文を使います。
  switch(c){ //なお、ここにcounterを入れてしまうと、フリーズしてしまいました。
   case '11':
    charadata[counter].body=1;
    charaValid=1; //case毎にcv=1;と代入します。
    break;

   case 'AA':
    charadata[counter].anime_pattern=2; //アニメーションさせる場合はここで代入します。
    charadata[counter].body=1;
    charaValid=1; //
    break;

  }

    //このif文がないと初期化関数Init();をwhile文に入れた場合に適切に描画されません。
   if(charaValid){
   mapdata[y][x]='0'; //マップデータを'0'にする事で、データの取り出しは終わりです。
    //ここでキャラクターの数を一つずつ増やしていきます。
   counter++;
   }

  }
 }

}


 //描画と移動処理用の関数を作ります
void Move(){

 for(int i=0;i<CHARA;i++){

  char c=charadata[i].kind;

  switch(c){
   //ここにcharadata[i].kindではなくiを入れると、一つしか描画されませんでした。
   //また、フリーズしてまった場合もあります。

   case '11':
    DrawGraph(charadata[i].x,charadata[i].y,im.kabe01,TRUE);
  
    break;

   case 'AA':
    int a=g_anime_counter/20%charadata[i].anime_pattern;
    DrawGraph(charadata[i].x,charadata[i].y,im.teki0A[a],TRUE);

    break;

  }

   //キャラクター単位で動かす方法でマップスクロールを行います。
  charadata[i].x=charadata[i].x-1;

 }

}



 //WinMain関数の中に、先ほど作った関数を入れます。//Move();だけwhile内に入れます。
int WINAPI WinMain(HINSTANCE hI,HINSTANCE hP,LPSTR lpC,int nC){

 if(ChangeWindowMode(TRUE)!=0) return -1; //ウィンドウモードの変更
 if(DxLib_Init()!=0) return -1; //DXライブラリ初期化処理
 if(SetDrawScreen(DX_SCREEN_BACK)!=0) return -1; //描画先を裏画面に設定


 //ロードの関数は、ここではここに入れます。


 MapLoad(); //マップデータのロード

 Load(); //画像のロード 

 Init(); //初期化。//if(charaValid)に関するコードを書いていない時は、ここに置かないで、while文の中に置くと、適切に描画されません。



 while(ProcessMessage()==0&&CheckHitKey(KEY_INPUT_ESCAPE)==0){
  //メッセージ処理(XキーかAlt+F4キーが押されたら終了)
  //ESCキーが押されたら終了
 if(ClearDrawScreen()!=0) return -1; //裏画面を消す


  //Init(); //初期化。//if(charaValid)に関するコードを書いていないでwhile文の中に初期化関数Init();置くと、適切に描画されません。
   //この関数をそのままwhile文の中に入れてしまうと、一番最初の画像が消えてしまう。

  Move(); //画像の描画と移動用の関数をここに置きます。

  g_anime_counter++; //



  if(ScreenFlip()!=0) return -1; //裏画面を表画面に反映

 }

 if(DxLib_End()!=0) return -1; //DXライブラリの終了処理
 return 0; //ソフトの終了

}
 


 以上のソースコードをコンパイルすると、真黒な画面が表示されるだけです。

 修正するべき箇所は、void MapLoad(){}関数内の//ここから//、//ここまで//の間に囲まれている部分である事までは分かっているのですが、どのように修正すればよいかが解決出来ていないと言うのが現状です。

以下にvoid MapLoad{}を抜粋します。

コード:

 
  //メモ帳からマップデータを読み込み
void MapLoad(){

  //各キャラクターのデータを初期化します。
 ZeroMemory(charadata,sizeof(charadata));

 char buf[1024];
 sprintf_s(buf,1024,"media/map%d.txt",1); //ファイル名を用意する
 int fp; //ファイルハンドル
 fp=FileRead_open(buf); //ファイルを開く

  //ファイル読み込みエラー処理
 if(fp==NULL){
  printfDx("ファイル読み込みエラー");
  return;
 }



/////////////////////////////ここから////////////////////////////



 for(int y=0;y<HEIGHT;y++){
  for(int x=0;x<WIDTH;x++){



  FileRead_scanf(fp,"%s",mapdata[y][x]);



 } //for(int x=0;x<WIDTH;x++)の最後

} //for(int y=0;y<HEIGHT;y++)の最後

/////////////////////////////ここまで////////////////////////////

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

} //void MapLoad();の最後


 

プログラマ見習い
記事: 44
登録日時: 3ヶ月前

Re: メモ帳からカンマ付き文字列のデータの読み込みが出来ません。

#18

投稿記事 by プログラマ見習い » 1ヶ月前

コピペする投稿するソースコードを間違えました。上記のソースコードは忘れて下さい。
改めて説明しなおします。

 質問者である自分が何をしたいについて改めて説明しなおします。

 まずはmap0.txtの中身と、ソースコードを投稿します。
 今回はちゃんとコピペしたので、今度こそ画面が正常に表示されるはずです。

 map0.txt

コード:

 
0000000000111111111100000000001111111111
0000000000000000000000000000000000000000
0000000000000000000000000000000000000000
0000000000000000000000000000000000000000
0000000000AAA000000000000000000000000000
0000000000000000000000000000000000000000
0000000000000000000000000000000000000000
0000000000000000000000000000000000000000
0000000000000000000000000000000000000000
0000000000000000000000000000000000000000
0000000000AAA000000000000000000000000000
0000000000000000000000000000000000000000
0000000000000000000000000000000000000000
0000000000000000000000000000000000000000
0000000000111111111100000000001111111111
 

 map1.txtを読み込んだもの

コード:

  
#include <DxLib.h>



#define MAPSIZE 32 //マップサイズを決めます。

#define HEIGHT 15 //Y座標の最大値を決めます
#define WIDTH 40 //X座標の最大値を決めます

 //キャラクターの数の最大値を決めます。念のために多めにします。今回はマップデータの数に合わせます。
#define CHARA HEIGHT*WIDTH



 //画像データの構造体を作ります。
 //画像データは無理に配列やポインタで整理しようとすると、エラーやフリーズの原因になります。
struct ImageData{

 int kabe01; //
 int teki0A[2]; //

};

struct ImageData im; //



 //各キャラクターのデータの構造体を作ります。
struct CharaData{

 //int *ghandle; //アニメーションさせるために画像データハンドル。
 //ポインタ設定をしたが、これが原因の一つでした。

 char kind; //キャラクターの種類を格納。
 int anime_pattern; //アニメパーン数
 float x; //座標はfloatにします。
 float y;
 int body; //体力

};

struct CharaData charadata[CHARA]; //今回はcharadataと名づけます。
 //キャラクターは複数出現させるので、配列内に各キャラクターの最大値CHMAXを格納します。

//struct CharaData im[2]; //画像を描画するための変数。
//or//struct CharaData im[CHARA]; //画像を描画するための変数。



 //アニメーションカウンター用の変数を作ります。
unsigned int g_anime_counter=0;



 //マップデータを作ります。
char mapdata[HEIGHT][WIDTH];



  //メモ帳からマップデータを読み込み
void MapLoad(){

  //各キャラクターのデータを初期化します。
 ZeroMemory(charadata,sizeof(charadata));

 char buf[1024];
 sprintf_s(buf,1024,"media/map%d.txt",0); //ファイル名を用意する
 int fp; //ファイルハンドル
 fp=FileRead_open(buf); //ファイルを開く

  //ファイル読み込みエラー処理
 if(fp==NULL){
  printfDx("ファイル読み込みエラー");
  return;
 }



/////////////////////////////ここから////////////////////////////


 for(int y=0;y<HEIGHT;y++){

  //1024が1023に減っているのは、NULL文字対策
 FileRead_gets(buf,1023,fp); //ファイルを一行読み込む



  for(int x=0;x<WIDTH;x++){

   mapdata[y][x]=buf[x];

 } //for(int x=0;x<WIDTH;x++)の最後

} //for(int y=0;y<HEIGHT;y++)の最後

/////////////////////////////ここまで////////////////////////////

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

} //void MapLoad();の最後



 //画像をロードする関数を作ります。
void Load(){

 im.kabe01=LoadGraph("media/kabe01.jpg");

 LoadDivGraph("media/teki0A.jpg",2,2,1,32,32,im.teki0A);

}



 //初期化用の関数を作ります。
void Init(){

  //キャラクターをカウントする変数を作ります。必要な変数の一つです。
  //キャラクターをカウントする変数はローカル変数でも問題ありませんでした。
 int counter=0;

 for(int y=0;y<HEIGHT;y++){
  for(int x=0;x<WIDTH;x++){

  char c=mapdata[y][x];

   //初期化してマップデータから、キャラクターのデータを取り出します。

   //kindにマップデータを代入します。
   //これも必要な変数の一つです。
  charadata[counter].kind=c;

  charadata[counter].x=(float)x*MAPSIZE;
  charadata[counter].y=(float)y*MAPSIZE;

  int charaValid=0;
   //この変数を利用しないと初期化関数Init();をwhile文に入れた場合に適切に描画されません。
   //Validは英語で「有効、根拠の確実な、確かな、正当な」などの意味です。

   //キャラクターごとに異なるものはswicth文を使います。
  switch(c){ //なお、ここにcounterを入れてしまうと、フリーズしてしまいました。
   case '1':
    charadata[counter].body=1;
    charaValid=1; //case毎にcv=1;と代入します。
    break;

   case 'A':
    charadata[counter].anime_pattern=2; //アニメーションさせる場合はここで代入します。
    charadata[counter].body=1;
    charaValid=1; //
    break;

  }

    //このif文がないと初期化関数Init();をwhile文に入れた場合に適切に描画されません。
   if(charaValid){
   mapdata[y][x]='0'; //マップデータを'0'にする事で、データの取り出しは終わりです。
    //ここでキャラクターの数を一つずつ増やしていきます。
   counter++;
   }

  }
 }

}


 //描画と移動処理用の関数を作ります
void Move(){

 for(int i=0;i<CHARA;i++){

  char c=charadata[i].kind;

  switch(c){
   //ここにcharadata[i].kindではなくiを入れると、一つしか描画されませんでした。
   //また、フリーズしてまった場合もあります。

   case '1':
    DrawGraph(charadata[i].x,charadata[i].y,im.kabe01,TRUE);
  
    break;

   case 'A':
    int a=g_anime_counter/20%charadata[i].anime_pattern;
    DrawGraph(charadata[i].x,charadata[i].y,im.teki0A[a],TRUE);

    break;

  }

   //キャラクター単位で動かす方法でマップスクロールを行います。
  charadata[i].x=charadata[i].x-1;

 }

}



 //WinMain関数の中に、先ほど作った関数を入れます。//Move();だけwhile内に入れます。
int WINAPI WinMain(HINSTANCE hI,HINSTANCE hP,LPSTR lpC,int nC){

 if(ChangeWindowMode(TRUE)!=0) return -1; //ウィンドウモードの変更
 if(DxLib_Init()!=0) return -1; //DXライブラリ初期化処理
 if(SetDrawScreen(DX_SCREEN_BACK)!=0) return -1; //描画先を裏画面に設定


 //ロードの関数は、ここではここに入れます。


 MapLoad(); //マップデータのロード

 Load(); //画像のロード 

 Init(); //初期化。//if(charaValid)に関するコードを書いていない時は、ここに置かないで、while文の中に置くと、適切に描画されません。



 while(ProcessMessage()==0&&CheckHitKey(KEY_INPUT_ESCAPE)==0){
  //メッセージ処理(XキーかAlt+F4キーが押されたら終了)
  //ESCキーが押されたら終了
 if(ClearDrawScreen()!=0) return -1; //裏画面を消す


  //Init(); //初期化。//if(charaValid)に関するコードを書いていないでwhile文の中に初期化関数Init();置くと、適切に描画されません。
   //この関数をそのままwhile文の中に入れてしまうと、一番最初の画像が消えてしまう。

  Move(); //画像の描画と移動用の関数をここに置きます。

  g_anime_counter++; //



  if(ScreenFlip()!=0) return -1; //裏画面を表画面に反映

 }

 if(DxLib_End()!=0) return -1; //DXライブラリの終了処理
 return 0; //ソフトの終了

}
 次にvoid MapLoad(){}の中身をご覧ください。
 以上のソースコードは、map0.txtからデータを読み込んで、マップデータに変換しているのですが、map0.txtは、ご覧の通り、カンマや空白などで区切られておらず、1ケタずつ読み込まれます。

 以上の方法には、二つ問題があります。
 第一に、以上のような1ケタずつ読み込んでいく方法だと、整数10個、アルファベット大文字26文字、小文字26文字で、合計62種類までのデータを読み込む事が出来ます。
 しかし、もしも62種類よりも多くのデータを読み込みたい場合、2ケタの整数や文字を用意する必要があります。例えば100種類、200種類のデータを読み込みたい場合、00、01、AAなどのような整数や文字が必要であります、

 第二に、カンマや空白などで区切られていないと、何行目の何列目かが分かり辛い、目で見ると目が痛くなってしまうと言う問題があります。そこで、カンマや空白などでデータを区切る事で、見えやすくする必要があります。

 以上の理由から、私はカンマ区切りの文字を読み込む事と、2ケタの文字を読み込む事がしたいのです。



 次に、2ケタずつカンマで区切って読み込んだソースコードを投稿します。
 但し、ここではmap0.txtをmap1.txtに、void Init(){}とvoid Move(){}関数の中身の1とAを、それぞれ1とAに変更しただけです。
 map1.txt

コード:

 

00,00,00,00,00,00,00,00,00,00,11,11,11,11,11,11,11,11,11,11,00,00,00,00,00,00,00,00,00,00,11,11,11,11,11,11,11,11,11,11
00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00
00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00
00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00
00,00,00,00,00,00,00,00,00,00,AA,AA,AA,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00
00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00
00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00
00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00
00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00
00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00
00,00,00,00,00,00,00,00,00,00,AA,AA,AA,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00
00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00
00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00
00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00
00,00,00,00,00,00,00,00,00,00,11,11,11,11,11,11,11,11,11,11,00,00,00,00,00,00,00,00,00,00,11,11,11,11,11,11,11,11,11,11
 




 map1.txtを読み込んだもの

コード:

 

#include <DxLib.h>



#define MAPSIZE 32 //マップサイズを決めます。

#define HEIGHT 15 //Y座標の最大値を決めます
#define WIDTH 40 //X座標の最大値を決めます

 //キャラクターの数の最大値を決めます。念のために多めにします。今回はマップデータの数に合わせます。
#define CHARA HEIGHT*WIDTH



 //画像データの構造体を作ります。
 //画像データは無理に配列やポインタで整理しようとすると、エラーやフリーズの原因になります。
struct ImageData{

 int kabe01; //
 int teki0A[2]; //

};

struct ImageData im; //



 //各キャラクターのデータの構造体を作ります。
struct CharaData{

 //int *ghandle; //アニメーションさせるために画像データハンドル。
 //ポインタ設定をしたが、これが原因の一つでした。

 char kind; //キャラクターの種類を格納。
 int anime_pattern; //アニメパーン数
 float x; //座標はfloatにします。
 float y;
 int body; //体力

};

struct CharaData charadata[CHARA]; //今回はcharadataと名づけます。
 //キャラクターは複数出現させるので、配列内に各キャラクターの最大値CHMAXを格納します。

//struct CharaData im[2]; //画像を描画するための変数。
//or//struct CharaData im[CHARA]; //画像を描画するための変数。



 //アニメーションカウンター用の変数を作ります。
unsigned int g_anime_counter=0;



 //マップデータを作ります。
char mapdata[HEIGHT][WIDTH];



  //メモ帳からマップデータを読み込み
void MapLoad(){

  //各キャラクターのデータを初期化します。
 ZeroMemory(charadata,sizeof(charadata));

 char buf[1024];
 sprintf_s(buf,1024,"media/map%d.txt",1); //ファイル名を用意する
 int fp; //ファイルハンドル
 fp=FileRead_open(buf); //ファイルを開く

  //ファイル読み込みエラー処理
 if(fp==NULL){
  printfDx("ファイル読み込みエラー");
  return;
 }



/////////////////////////////ここから////////////////////////////


 for(int y=0;y<HEIGHT;y++){

  //1024が1023に減っているのは、NULL文字対策
 FileRead_gets(buf,1023,fp); //ファイルを一行読み込む



  for(int x=0;x<WIDTH;x++){

   mapdata[y][x]=buf[x];

 } //for(int x=0;x<WIDTH;x++)の最後

} //for(int y=0;y<HEIGHT;y++)の最後

/////////////////////////////ここまで////////////////////////////

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

} //void MapLoad();の最後



 //画像をロードする関数を作ります。
void Load(){

 im.kabe01=LoadGraph("media/kabe01.jpg");

 LoadDivGraph("media/teki0A.jpg",2,2,1,32,32,im.teki0A);

}



 //初期化用の関数を作ります。
void Init(){

  //キャラクターをカウントする変数を作ります。必要な変数の一つです。
  //キャラクターをカウントする変数はローカル変数でも問題ありませんでした。
 int counter=0;

 for(int y=0;y<HEIGHT;y++){
  for(int x=0;x<WIDTH;x++){

  char c=mapdata[y][x];

   //初期化してマップデータから、キャラクターのデータを取り出します。

   //kindにマップデータを代入します。
   //これも必要な変数の一つです。
  charadata[counter].kind=c;

  charadata[counter].x=(float)x*MAPSIZE;
  charadata[counter].y=(float)y*MAPSIZE;

  int charaValid=0;
   //この変数を利用しないと初期化関数Init();をwhile文に入れた場合に適切に描画されません。
   //Validは英語で「有効、根拠の確実な、確かな、正当な」などの意味です。

   //キャラクターごとに異なるものはswicth文を使います。
  switch(c){ //なお、ここにcounterを入れてしまうと、フリーズしてしまいました。
   case '11':
    charadata[counter].body=1;
    charaValid=1; //case毎にcv=1;と代入します。
    break;

   case 'AA':
    charadata[counter].anime_pattern=2; //アニメーションさせる場合はここで代入します。
    charadata[counter].body=1;
    charaValid=1; //
    break;

  }

    //このif文がないと初期化関数Init();をwhile文に入れた場合に適切に描画されません。
   if(charaValid){
   mapdata[y][x]='0'; //マップデータを'0'にする事で、データの取り出しは終わりです。
    //ここでキャラクターの数を一つずつ増やしていきます。
   counter++;
   }

  }
 }

}


 //描画と移動処理用の関数を作ります
void Move(){

 for(int i=0;i<CHARA;i++){

  char c=charadata[i].kind;

  switch(c){
   //ここにcharadata[i].kindではなくiを入れると、一つしか描画されませんでした。
   //また、フリーズしてまった場合もあります。

   case '11':
    DrawGraph(charadata[i].x,charadata[i].y,im.kabe01,TRUE);
  
    break;

   case 'AA':
    int a=g_anime_counter/20%charadata[i].anime_pattern;
    DrawGraph(charadata[i].x,charadata[i].y,im.teki0A[a],TRUE);

    break;

  }

   //キャラクター単位で動かす方法でマップスクロールを行います。
  charadata[i].x=charadata[i].x-1;

 }

}



 //WinMain関数の中に、先ほど作った関数を入れます。//Move();だけwhile内に入れます。
int WINAPI WinMain(HINSTANCE hI,HINSTANCE hP,LPSTR lpC,int nC){

 if(ChangeWindowMode(TRUE)!=0) return -1; //ウィンドウモードの変更
 if(DxLib_Init()!=0) return -1; //DXライブラリ初期化処理
 if(SetDrawScreen(DX_SCREEN_BACK)!=0) return -1; //描画先を裏画面に設定


 //ロードの関数は、ここではここに入れます。


 MapLoad(); //マップデータのロード

 Load(); //画像のロード 

 Init(); //初期化。//if(charaValid)に関するコードを書いていない時は、ここに置かないで、while文の中に置くと、適切に描画されません。



 while(ProcessMessage()==0&&CheckHitKey(KEY_INPUT_ESCAPE)==0){
  //メッセージ処理(XキーかAlt+F4キーが押されたら終了)
  //ESCキーが押されたら終了
 if(ClearDrawScreen()!=0) return -1; //裏画面を消す


  //Init(); //初期化。//if(charaValid)に関するコードを書いていないでwhile文の中に初期化関数Init();置くと、適切に描画されません。
   //この関数をそのままwhile文の中に入れてしまうと、一番最初の画像が消えてしまう。

  Move(); //画像の描画と移動用の関数をここに置きます。

  g_anime_counter++; //



  if(ScreenFlip()!=0) return -1; //裏画面を表画面に反映

 }

 if(DxLib_End()!=0) return -1; //DXライブラリの終了処理
 return 0; //ソフトの終了

}
 


 以上のソースコードをコンパイルすると、真黒な画面が表示されるだけです。

 修正するべき箇所は、void MapLoad(){}関数内の//ここから//、//ここまで//の間に囲まれている部分である事までは分かっているのですが、どのように修正すればよいかが解決出来ていないと言うのが現状です。

かずま

Re: メモ帳からカンマ付き文字列のデータの読み込みが出来ません。

#19

投稿記事 by かずま » 1ヶ月前

プログラマ見習い さんが書きました:
1ヶ月前
 修正するべき箇所は、void MapLoad(){}関数内の//ここから//、//ここまで//の間に囲まれている部分である事までは分かっているのですが、どのように修正すればよいかが解決出来ていないと言うのが現状です。
#11 のプログラムは読んでいないのですね。
strcpy を sprintf_s に修正したら真黒な画面が出ました、で終わりですか?
真黒になったのは、そのプログラムが #1 の最初のプログラムにあったように
.jpg ではなく .bmp の画像ファイルになっていたからだと思います。
真黒の画面になったら、それで終わりですか?
プログラムを読もうとしないのですか?
// ★ を付けて目立つようにしたのに。

もう一度、修正個所を示します。

コード:

/////////////////////////////ここから////////////////////////////
	for (int y = 0; y < HEIGHT; y++) {
		if (FileRead_gets(buf, 1024, fp) == -1) break;
		char *p = buf;
		for (int x = 0; x < WIDTH; x++) {
			mapdata[y][x] = strtol(p, &p, 16);
			p++; // skip ','
		}
	}
/////////////////////////////ここまで////////////////////////////
さらに次の変更が必要です。

コード:

char c=mapdata[y][x]; を unsigned char c = mapdata[y][x]; に変更

char c=charadata[i].kind; を unsigned char c = charadata[i].kind; に変更

case '11': を case 0x11: に変更(2個所)

case 'AA': を case 0xAA: に変更(2個所)
疑問点があれば、具体的に質問してください

かめのこのこのこ
記事: 12
登録日時: 2年前

Re: メモ帳からカンマ付き文字列のデータの読み込みが出来ません。

#20

投稿記事 by かめのこのこのこ » 1ヶ月前

いまいちやりたいことをうまく把握できないので、こちらからお尋ねしますが..

マップテキスト map1.txt がありましたとさ

コード:

 

00,00,00,00,00,00,00,00,00,00,11,11,11,11,11,11,11,11,11,11,00,00,00,00,00,00,00,00,00,00,11,11,11,11,11,11,11,11,11,11
00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00
00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00
00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00
00,00,00,00,00,00,00,00,00,00,AA,AA,AA,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00
00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00
00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00
00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00
00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00
00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00
00,00,00,00,00,00,00,00,00,00,AA,AA,AA,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00
00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00
00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00
00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00
00,00,00,00,00,00,00,00,00,00,11,11,11,11,11,11,11,11,11,11,00,00,00,00,00,00,00,00,00,00,11,11,11,11,11,11,11,11,11,11
 
その(データのある)1行目に注目しましたとさ

コード:

00,00,00,00,00,00,00,00,00,00,11,11,11,11,11,11,11,11,11,11,00,00,00,00,00,00,00,00,00,00,11,11,11,11,11,11,11,11,11,11
それのコンマを無視して読み込みたいのさ (1: カンマ区切りの文字を読み込む事 or カンマを読み込まないで読み込みたい文字列だけを読み込む)

コード:

00000000000000000000111111111111111111110000000000000000000011111111111111111111
最後にこれを2文字(2桁)ずつ区切ってマップデータを入れる変数に保存したいのさ (2: 2ケタの文字を読み込む事 or 00,11,AAなど、一組の文字列として読み込む)

mapdata[0][0]mapdata[0][1]mapdata[0][2]...
'00''00''00'...
という把握でよろしいでしょうか。

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

Re: メモ帳からカンマ付き文字列のデータの読み込みが出来ません。

#21

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

このようなコードを書いてみました。
strchrおよびstrcmpを使うために、

コード:

#include <DxLib.h>
の後ろに

コード:

#include <cstring>
を追加してください。

コード:

  //メモ帳からマップデータを読み込み
void MapLoad(){

  //各キャラクターのデータを初期化します。
 ZeroMemory(charadata,sizeof(charadata));

 char buf[1024];
 sprintf_s(buf,1024,"media/map%d.txt",1); //ファイル名を用意する
 int fp; //ファイルハンドル
 fp=FileRead_open(buf); //ファイルを開く

  //ファイル読み込みエラー処理
 if(fp==NULL){
  printfDx("ファイル読み込みエラー");
  return;
 }



/////////////////////////////ここから////////////////////////////



 for(int y=0;y<HEIGHT;y++){
  for(int x=0;x<WIDTH;x++){



  // これは文字列の読み込み先として無効な可能性が高いポインタを指定することになるのでダメ
  //FileRead_scanf(fp,"%s",mapdata[y][x]);
  // 1セル分のデータを読み込む場所を作る
  char input[1024], *cr;
  // 1セル分のデータを読み込む
  FileRead_scanf(fp,"%1023[^\n,]%*c",input);
  // ゴミが付いている場合があるので、外す
  if ((cr = strchr(input, '\r')) != NULL) *cr = '\0';
  // データを変換する
  if (strcmp(input, "00") == 0) mapdata[y][x] = 0;
  else if (strcmp(input, "11") == 0) mapdata[y][x] = '11';
  else if (strcmp(input, "AA") == 0) mapdata[y][x] = 'AA';
  else x--; // 変換できなかった場合、なかったことにする



 } //for(int x=0;x<WIDTH;x++)の最後

} //for(int y=0;y<HEIGHT;y++)の最後

/////////////////////////////ここまで////////////////////////////

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

} //void MapLoad();の最後
複数文字の文字定数がどのような値になるかは、処理系定義です。
GCC 4.8.1では動きませんでしたが、MathさんのいうVS2019なら動くかもしれません。
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

プログラマ見習い
記事: 44
登録日時: 3ヶ月前

Re: メモ帳からカンマ付き文字列のデータの読み込みが出来ません。

#22

投稿記事 by プログラマ見習い » 1ヶ月前

まずはかずまさん。
申し訳ございません。
報告して下さいと書かれていたので、皆さんに急いで報告しなければならないと思い、結果としてあのような報告となってしまいました。
ソースコードは読んでいたのですが、画像ファイル形式を完全に見落としてしまいました。後で読み返して間違いに気づいたので、修正したら正常に描画されました。
不快な思いをさせて申し訳ございませんでした。

そして皆さん。
皆さんのアドバイスを読んで、書籍やネットで調べて、考えている所です。
次の返答までに時間がかかりますが、どうかご容赦下さい。

プログラマ見習い
記事: 44
登録日時: 3ヶ月前

Re: メモ帳からカンマ付き文字列のデータの読み込みが出来ません。

#23

投稿記事 by プログラマ見習い » 1ヶ月前

かめのこのこのこさん。
はい。その通りです。
mapdata[0][0]="00";
mapdata[0][1]="00";
mapdata[0][2]="00";
mapdata[0][?]="11"
~~~~~~省略
mapdata[?][?]="AA";
~~~~~~省略
この把握で宜しいです。

かずま

Re: メモ帳からカンマ付き文字列のデータの読み込みが出来ません。

#24

投稿記事 by かずま » 1ヶ月前

プログラマ見習い さんが書きました:
1ヶ月前
不快な思いをさせて申し訳ございませんでした。
不快には思いませんが、
#7 さんが書きました: media/map1 ですが、提示されたものは、空行 2行、データ 11行、空行 3行
になっていますよ。いいんですか?
なぜ、この質問にすぐ答えてくれないのですか?
未だに、先頭に空行を含むデータを提示していますよね。
空行があると正しく読めません。
#7 さんが書きました:char の変数に入らない '11' や 'AA' などのデータを使わず、
'0'、'1'、'A' にしました。
char の変数に入らないと言っているのに、まだ '11' を使おうとしていますね。
なぜ入らないのか調べて分からなければ、それを質問してください。
#11 さんが書きました:何種類のデータが必要ですか? 必ず答えてください。
すぐに答えてもらうと、100 の場合、200の場合、300の場合などについて
それに対応できるコードやデータ構造をアドバイスできたのに。

char mapdate[HEIGHT][WIDTH]; を
int mapdate[HEIGHT][WIDTH]; や
char mapdate[HEIGHT][WIDTH][2]; や
std::string mapdate[HEIGHT][WIDTH]; などにするやり方があります。

char mapdate[HEIGHT][WIDTH]; のままで stringstream を使うとすれば
次のようなコードになるでしょう。

コード:

#include <sstream>   // istringstream

/////////////////////////////ここまで////////////////////////////
	for (int y = 0; y < HEIGHT; y++) {
		if (FileRead_gets(buf, 1024, fp) == -1) break;
		std::istringstream iss(buf);
		iss >> std::hex;
		for (int x = 0; x < WIDTH; x++) {
			int v; iss >> v;
			mapdata[y][x] = v;
			char c; iss >> c;   // skip ','
		}
	}
/////////////////////////////ここまで////////////////////////////

unsigned char, 0x11, 0xAA の修正も必要

プログラマ見習い
記事: 44
登録日時: 3ヶ月前

Re: メモ帳からカンマ付き文字列のデータの読み込みが出来ません。

#25

投稿記事 by プログラマ見習い » 1ヶ月前

かずまさん。すみません。
まずは三つの質問に一つずつ質問に答えます。


●「media/map1 ですが、提示されたものは、空行 2行、データ 11行、空行 3行
になっていますよ。いいんですか?」

 自分では15行40列のものをアップロードしたつもりだったものが、間違いを指摘されて見直して修正した後、再びアップロードつもりだったのですけど、直っていませんでしたか?
 一応、新しいのをアップロードします。間違っている部分をもう少し詳しく教えてください。

map0.txt

コード:

 

0000000000111111111100000000001111111111
0000000000000000000000000000000000000000
0000000000000000000000000000000000000000
0000000000000000000000000000000000000000
0000000000AAA000000000000000000000000000
0000000000000000000000000000000000000000
0000000000000000000000000000000000000000
0000000000000000000000000000000000000000
0000000000000000000000000000000000000000
0000000000000000000000000000000000000000
0000000000AAA000000000000000000000000000
0000000000000000000000000000000000000000
0000000000000000000000000000000000000000
0000000000000000000000000000000000000000
0000000000111111111100000000001111111111

 
map1.txt

コード:

 
00,00,00,00,00,00,00,00,00,00,11,11,11,11,11,11,11,11,11,11,00,00,00,00,00,00,00,00,00,00,11,11,11,11,11,11,11,11,11,11
00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00
00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00
00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00
00,00,00,00,00,00,00,00,00,00,AA,AA,AA,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00
00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00
00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00
00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00
00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00
00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00
00,00,00,00,00,00,00,00,00,00,AA,AA,AA,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00
00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00
00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00
00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00
00,00,00,00,00,00,00,00,00,00,11,11,11,11,11,11,11,11,11,11,00,00,00,00,00,00,00,00,00,00,11,11,11,11,11,11,11,11,11,11

 

●「charの変数に入らない '11' や 'AA' などのデータを使わず、'0'、'1'、'A' にしました。」

 これについては、必要なデータの種類が62を超えた場合どうするんだと言う焦りがありました。それと、Aやaなど、文字列を使うのはcharを使うのが良いと書籍やネットにか書いてあったので、そのままcharを使い続けてしまいました。
 charでは1ケタでないと都合が悪い理由は、charが2進数で256個しか表現出来ない事が理由であると理解しても良いのでしょうか?



●「何種類のデータが必要ですか? 必ず答えてください。」

 具体的な数字をいくつ出せばいいのか迷っていました。控えめな数字の方が良いのか、欲を張っても良いのか。現状では100もあれば安心ですが、将来の事を考えて、欲を張って1000と答えます。
 必要な種類のデータ数によって、プログラムを組む考え方も、大きく、根本的に変わってくるのでしょうか?

 かずまさんが投稿して下さったソースコードについての回答は、後ほどします。

かめのこのこのこ
記事: 12
登録日時: 2年前

Re: メモ帳からカンマ付き文字列のデータの読み込みが出来ません。

#26

投稿記事 by かめのこのこのこ » 1ヶ月前

プログラマ見習い さんが書きました:
1ヶ月前
かめのこのこのこさん。
はい。その通りです。
mapdata[0][0]="00";
mapdata[0][1]="00";
mapdata[0][2]="00";
mapdata[0][?]="11"
~~~~~~省略
mapdata[?][?]="AA";
~~~~~~省略
この把握で宜しいです。
了解なのです
  • カンマ区切りの文字を読み込む事 or カンマを読み込まないで読み込みたい文字列だけを読み込む
  • 2ケタの文字を読み込む事 or 00,11,AAなど、一組の文字列として読み込む
の(私の考えている)実装を明日以降返信します
(ある程度頭の中で固まってきてはいますが、プログラマ見習いさんにどのように伝えればわかりやすいかというところ考えきれてないので、もうしばらく時間が欲しいです)

---------------------------------------------------------------------------------

そしてプログラマ見習いさんとかずまさんのやりとりに横槍を刺すとして..
プログラマ見習い さんが書きました:
1ヶ月前
●「charの変数に入らない '11' や 'AA' などのデータを使わず、'0'、'1'、'A' にしました。」

 これについては、必要なデータの種類が62を超えた場合どうするんだと言う焦りがありました。それと、Aやaなど、文字列を使うのはcharを使うのが良いと書籍やネットにか書いてあったので、そのままcharを使い続けてしまいました。
 charでは1ケタでないと都合が悪い理由は、charが2進数で256個しか表現出来ない事が理由であると理解しても良いのでしょうか?
プログラマ見習いさん、以下の3点に目を通して欲しいです
  • プログラミングにおいて、文字」と「文字列」は区別されます。「文字」は A や a などの文字1つを表し、「文字列」は「文字」を複数並べたものです。
  • C言語のソースコード上では、「文字」を 'A' や 'a' のように ' (シングルクォーテーション)で囲って表現し、「文字列」を "Hello, world!" のように " (ダブルクォーテーション) で囲って表現します。
    ( 'a' と "a" が別物であることのややこしさだったり..)
  • C言語の変数では、charが「文字」を保存できる型であり、「文字列」は往往にして charの配列 を使って保存します。(C++もOKならば stringも「文字列」を保存できます。)

    コード:

    char moji = 'A'; // 文字 A をcharの変数 moji に保存
    char mojiretsu[5] = "Hei!"; // 文字列 Hei! をcharの配列の変数 mojiretsu に保存
    
    ここで、配列の変数 mojiretsu の中身は
    mojiretsu[0]mojiretsu[1]mojiretsu[2]mojiretsu[3]mojiretsu[4]
    'H''e''i''!''\0'
以上の3点のこと、もしくは別のことで、もしわからないことがあれば、気軽に質問してくださいなのです。

プログラマ見習い
記事: 44
登録日時: 3ヶ月前

Re: メモ帳からカンマ付き文字列のデータの読み込みが出来ません。

#27

投稿記事 by プログラマ見習い » 1ヶ月前

 かめのこのこのさん。
 ありがとうございます。
 文字と文字列。文字が''で、文字列が""。気を取られていて初歩的な事を意識するのを忘れていました。



 かずまさん。
 かずまさんが投稿して下さったソースコードを読んで、コメント文に自分なりに理解した所をまとめました。

コード:

 

#include <DxLib.h>

#define MAPSIZE 32

#define HEIGHT 15
#define WIDTH  40

#define CHARA (HEIGHT * WIDTH)

struct ImageData {
	int kabe01;
	int teki0A[2];
};

struct ImageData im;

struct CharaData {
	char kind;
	int anime_pattern;
	int x, y;
	int body;
};
int counter;

struct CharaData charadata[CHARA];
unsigned int g_anime_counter = 0;
char mapdata[HEIGHT][WIDTH];

void MapLoad()
{
	ZeroMemory(charadata, sizeof(charadata));

	char buf[1024];
	//strcpy_s(buf, "media/map1.txt"); //☆strcpyのままではエラー警告C4996が出たので、strcpy_sに修正しました。また、sprintf_sに修正しても、描画自体は出来ました。
        sprintf_s(buf, "media/map1.txt"); //
	int fh = FileRead_open(buf);
	if (fh == NULL) { printfDx("ファイル読み込みエラー"); return; }

	for (int y = 0; y < HEIGHT; y++) {
		if (FileRead_gets(buf, 1024, fh) == -1) break;
		char *p = buf;                          // ★
		for (int x = 0; x < WIDTH; x++) {       // ★
			mapdata[y][x] = strtol(p, &p, 16);  //★strol関数は、第一引数をlong型に変換する関数。
			p++; // skip ','                    // ★
		}                                       // ★
	}
	FileRead_close(fh);
}
 //strol関数(const char *nptr,char **endptr,int base);
 //strol関数は、第一引数(const char *nptr)をlong型に変換する関数。
 //第三引数(int base)は基数。16進数や2進数など、指定した進数に変換。

void Load()
{
	im.kabe01 = LoadGraph("media/kabe01.png"); //☆画像形式をpngに修正しました。
	LoadDivGraph("media/teki0A.png", 2, 2, 1, 32, 32, im.teki0A);
}

void Init()
{
	counter = 0;
	for (int y = 0; y < HEIGHT; y++) {
		for (int x = 0; x < WIDTH; x++) {
			unsigned char c = mapdata[y][x];  // ★こことInit関数内のunsigned charをunsigned intにすると、0x11の画像が表示されなくなりました。
                        unsigned int c = mapdata[y][x];  // ★
                        //char c= mapdata[y][x]; //☆こことMove関数内のunsignedを取ってしまうと、0x11が表示されなくなりました。
			charadata[counter].kind = c;
			charadata[counter].x = x * MAPSIZE;
			charadata[counter].y = y * MAPSIZE;
			switch (c) {
			case 0x11:  // ★16進数の整数に変換されたので、文字列''では駄目。
				charadata[counter].body = 1;
				mapdata[y][x] = '0';
				counter++;
				break;
			case 0xAA:  // ★
				charadata[counter].anime_pattern = 2;
				charadata[counter].body = 1;
				mapdata[y][x] = '0';
				counter++;
				break;
			}
		}
	}
}

void Move()
{
	for (int i = 0; i < counter; i++) {
		unsigned char c = charadata[i].kind;  // ★
                //unsigned int c = charadata[i].kind;  //
                //char c = charadata[i].kind;  ////☆
		switch (c) {
		case 0x11:  // ★
			DrawGraph(charadata[i].x, charadata[i].y, im.kabe01, TRUE);
			break;

		case 0xAA:  // ★
			int a = g_anime_counter / 20 % charadata[i].anime_pattern;
			DrawGraph(charadata[i].x, charadata[i].y, im.teki0A[a], TRUE);
			break;
		}
		charadata[i].x = charadata[i].x - 1;
	}
}

int WINAPI WinMain(HINSTANCE hI, HINSTANCE hP, LPSTR lpC, int nC)
{
	if (ChangeWindowMode(TRUE) != 0) return -1;
	if (DxLib_Init() != 0) return -1;
	if (SetDrawScreen(DX_SCREEN_BACK) != 0) return -1;

	MapLoad();
	Load();
	Init();

	while (ProcessMessage() == 0 && CheckHitKey(KEY_INPUT_ESCAPE) == 0) {
		if (ClearDrawScreen() != 0) return -1;
		Move();
		g_anime_counter++;
		if (ScreenFlip() != 0) return -1;
	}

	if (DxLib_End() != 0) return -1;
	return 0;
}

 
 気になる所があったので質問します。
 「16進数で書けば256種類のデータを扱える」点について、256種類が限界である理由をchar型の限界が256にあると理解していたので、では256種類を超えるにはunsigned char型をunsigned int型にすれば良いのではと思い、、unsigned int型にしてコンパイルした所、0x11の部分が表示されなくなりました。
 0x11の10進数の17で、0xAAは10進数の170なので、unsignedのないchar型だと0x11がマイナスの部分に入ってしまう事が原因だと理解していたので、unsigned int型0x11でも表示されない事にびっくりしました。

 改めて調べてみると、コンピュータが2進数を基礎としているので、256種類がコンピュータの限界だと理解してもいいのでしょうか?ゲームでも255の数字が良く使われているそうです。
 もしも256種類を超える種類のデータが必要な場合、上記のソースコードにどのような変更が必要なのでしょうか?
 ただ、コンピュータの性質上、よほどの事がない限り256種類を超えるデータはお勧めしないと指摘されたら、深入りしないで、256種類にとどめておきます。

プログラマ見習い
記事: 44
登録日時: 3ヶ月前

Re: メモ帳からカンマ付き文字列のデータの読み込みが出来ません。

#28

投稿記事 by プログラマ見習い » 1ヶ月前

みけCTAさん。

 みけCATさんが投稿してくれた、strchrとstrcmpのソースコードについての返答が遅れてすみませんでした。
 貴重なアドバイスをありがとうございます。

 コンパイルすると、残念ながら、画面は描画されませんでした。
 ソースコードを入れておきます。

コード:

#include <DxLib.h>
#include <cstring>

#define MAPSIZE 32 //マップサイズを決めます。

#define HEIGHT 15 //Y座標の最大値を決めます
#define WIDTH 40 //X座標の最大値を決めます

 //キャラクターの数の最大値を決めます。念のために多めにします。今回はマップデータの数に合わせます。
#define CHARA HEIGHT*WIDTH



 //画像データの構造体を作ります。
 //画像データは無理に配列やポインタで整理しようとすると、エラーやフリーズの原因になります。
struct ImageData{

 int kabe01; //
 int teki0A[2]; //

};

struct ImageData im; //



 //各キャラクターのデータの構造体を作ります。
struct CharaData{

 //int *ghandle; //アニメーションさせるために画像データハンドル。
 //ポインタ設定をしたが、これが原因の一つでした。

 char kind; //キャラクターの種類を格納。
 int anime_pattern; //アニメパーン数
 float x; //座標はfloatにします。
 float y;
 int body; //体力

};

struct CharaData charadata[CHARA]; //今回はcharadataと名づけます。
 //キャラクターは複数出現させるので、配列内に各キャラクターの最大値CHMAXを格納します。

//struct CharaData im[2]; //画像を描画するための変数。
//or//struct CharaData im[CHARA]; //画像を描画するための変数。



 //アニメーションカウンター用の変数を作ります。
unsigned int g_anime_counter=0;



 //マップデータを作ります。
char mapdata[HEIGHT][WIDTH];



  //メモ帳からマップデータを読み込み
void MapLoad(){

  //各キャラクターのデータを初期化します。
 ZeroMemory(charadata,sizeof(charadata));

 char buf[1024];
 sprintf_s(buf,1024,"media/map%d.txt",1); //ファイル名を用意する
 int fp; //ファイルハンドル
 fp=FileRead_open(buf); //ファイルを開く

  //ファイル読み込みエラー処理
 if(fp==NULL){
  printfDx("ファイル読み込みエラー");
  return;
 }



/////////////////////////////ここから////////////////////////////



 for(int y=0;y<HEIGHT;y++){
  for(int x=0;x<WIDTH;x++){

  //★これは文字列の読み込み先として無効な可能性が高いポインタを指定することになるのでダメ
  //FileRead_scanf(fp,"%s",mapdata[y][x]);



   //★1セル分のデータを読み込む場所を作る
  char input[1024], *cr; //☆ポインタ指定を忘れずに。

   //★1セル分のデータを読み込む
  FileRead_scanf(fp,"%1023[^\n,]%*c",input);

   //★ゴミが付いている場合があるので、外す
  if ((cr = strchr(input, '\r')) != NULL) *cr = '\0';
 //☆strchr関数。文字列の中の文字を検索する関数。

   //★データを変換する
  if (strcmp(input, "00") == 0) mapdata[y][x] ='00'; //☆0を'00'に修正しました。0のままで修正しなくても、結果は同じでした。
  else if (strcmp(input, "11") == 0) mapdata[y][x] = '11';
  else if (strcmp(input, "AA") == 0) mapdata[y][x] = 'AA';
  else x--; // 変換できなかった場合、なかったことにする
    //else{x--;continue;}にしてもダメ。
   //☆strcmp関数。文字列を比較する関数。



  } //for(int x=0;x<WIDTH;x++)の最後
 } //for(int y=0;y<HEIGHT;y++)の最後

/////////////////////////////ここまで////////////////////////////

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

} //void MapLoad();の最後



 //画像をロードする関数を作ります。
void Load(){

 im.kabe01=LoadGraph("media/kabe01.png");//画像形式をpngにする。

 LoadDivGraph("media/teki0A.png",2,2,1,32,32,im.teki0A);

}



 //初期化用の関数を作ります。
void Init(){

  //キャラクターをカウントする変数を作ります。必要な変数の一つです。
  //キャラクターをカウントする変数はローカル変数でも問題ありませんでした。
 int counter=0;

 for(int y=0;y<HEIGHT;y++){
  for(int x=0;x<WIDTH;x++){

  char c=mapdata[y][x];

   //初期化してマップデータから、キャラクターのデータを取り出します。

   //kindにマップデータを代入します。
   //これも必要な変数の一つです。
  charadata[counter].kind=c;

  charadata[counter].x=(float)x*MAPSIZE;
  charadata[counter].y=(float)y*MAPSIZE;

  int charaValid=0;
   //この変数を利用しないと初期化関数Init();をwhile文に入れた場合に適切に描画されません。
   //Validは英語で「有効、根拠の確実な、確かな、正当な」などの意味です。

   //キャラクターごとに異なるものはswicth文を使います。
  switch(c){ //なお、ここにcounterを入れてしまうと、フリーズしてしまいました。
   case '11':
    charadata[counter].body=1;
    charaValid=1; //case毎にcv=1;と代入します。
    break;

   case 'AA':
    charadata[counter].anime_pattern=2; //アニメーションさせる場合はここで代入します。
    charadata[counter].body=1;
    charaValid=1; //
    break;

  }

    //このif文がないと初期化関数Init();をwhile文に入れた場合に適切に描画されません。
   if(charaValid){
   mapdata[y][x]='0'; //マップデータを'0'にする事で、データの取り出しは終わりです。
    //ここでキャラクターの数を一つずつ増やしていきます。
   counter++;
   }

  }
 }

}


 //描画と移動処理用の関数を作ります
void Move(){

 for(int i=0;i<CHARA;i++){

  char c=charadata[i].kind;

  switch(c){
   //ここにcharadata[i].kindではなくiを入れると、一つしか描画されませんでした。
   //また、フリーズしてまった場合もあります。

   case '11':
    DrawGraph(charadata[i].x,charadata[i].y,im.kabe01,TRUE);
  
    break;

   case 'AA':
    int a=g_anime_counter/20%charadata[i].anime_pattern;
    DrawGraph(charadata[i].x,charadata[i].y,im.teki0A[a],TRUE);

    break;

  }

   //キャラクター単位で動かす方法でマップスクロールを行います。
  charadata[i].x=charadata[i].x-1;

 }

}



 //WinMain関数の中に、先ほど作った関数を入れます。//Move();だけwhile内に入れます。
int WINAPI WinMain(HINSTANCE hI,HINSTANCE hP,LPSTR lpC,int nC){

 if(ChangeWindowMode(TRUE)!=0) return -1; //ウィンドウモードの変更
 if(DxLib_Init()!=0) return -1; //DXライブラリ初期化処理
 if(SetDrawScreen(DX_SCREEN_BACK)!=0) return -1; //描画先を裏画面に設定


 //ロードの関数は、ここではここに入れます。


 MapLoad(); //マップデータのロード

 Load(); //画像のロード 

 Init(); //初期化。//if(charaValid)に関するコードを書いていない時は、ここに置かないで、while文の中に置くと、適切に描画されません。



 while(ProcessMessage()==0&&CheckHitKey(KEY_INPUT_ESCAPE)==0){
  //メッセージ処理(XキーかAlt+F4キーが押されたら終了)
  //ESCキーが押されたら終了
 if(ClearDrawScreen()!=0) return -1; //裏画面を消す


  //Init(); //初期化。//if(charaValid)に関するコードを書いていないでwhile文の中に初期化関数Init();置くと、適切に描画されません。
   //この関数をそのままwhile文の中に入れてしまうと、一番最初の画像が消えてしまう。

  Move(); //画像の描画と移動用の関数をここに置きます。

  g_anime_counter++; //



  if(ScreenFlip()!=0) return -1; //裏画面を表画面に反映

 }

 if(DxLib_End()!=0) return -1; //DXライブラリの終了処理
 return 0; //ソフトの終了

}



「複数文字の文字定数がどのような値になるかは、処理系定義です。
GCC 4.8.1では動きませんでしたが、MathさんのいうVS2019なら動くかもしれません。」と言う事でしたので、vs2017communityには対応していないのかもしれません。それともまた私の記述ミス?上記のソースコードはコピペです。

アバター
usao
記事: 1550
登録日時: 6年前

Re: メモ帳からカンマ付き文字列のデータの読み込みが出来ません。

#29

投稿記事 by usao » 1ヶ月前

オフトピック
> 第一に、以上のような1ケタずつ読み込んでいく方法だと、整数10個、アルファベット大文字26文字、小文字26文字で、合計62種類までのデータを読み込む事が出来ます。

この話だと,1データを「数字とアルファベットからなる2文字」にすることで62*62=3844パターンを表現するという世界を目指していることになる.
ファイルに書かれている"11"だの"AA"だのいうのは16進文字列ではないのだろうから,
strtol(p, &p, 16)
だと目指す仕様と違うんじゃないの?

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

Re: メモ帳からカンマ付き文字列のデータの読み込みが出来ません。

#30

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

プログラマ見習い さんが書きました:
1ヶ月前
 気になる所があったので質問します。
 「16進数で書けば256種類のデータを扱える」点について、256種類が限界である理由をchar型の限界が256にあると理解していたので、では256種類を超えるにはunsigned char型をunsigned int型にすれば良いのではと思い、、unsigned int型にしてコンパイルした所、0x11の部分が表示されなくなりました。
 0x11の10進数の17で、0xAAは10進数の170なので、unsignedのないchar型だと0x11がマイナスの部分に入ってしまう事が原因だと理解していたので、unsigned int型0x11でも表示されない事にびっくりしました。
手元で試したところ、unsigned int型の場合、
逆に0x11のキャラクターは表示されるが、0xAAのキャラクターは表示されない現象を観測できました。
これは、char型が符号(2の補数)付き8ビット、unsigned int型が32ビットであると仮定すると、
char型の変数に入れられた0xAAは負の数-86となり、
これをunsigned int型に変換すると0xFFFFFFAAとなるため、
caseの0xAAとは一致しなくなるからであると考えられます。
(0xFFFFFFAAとなるのは負の数を変換先の符号なし整数の最大値+1を足して範囲内に変換するため、
もしくは符号拡張(もとの数を最上位ビットをコピーして拡張)するため)

プログラマ見習いさんの環境では、本当に0x11の部分が表示されなくなったのですか?
プログラマ見習い さんが書きました:
1ヶ月前
改めて調べてみると、コンピュータが2進数を基礎としているので、256種類がコンピュータの限界だと理解してもいいのでしょうか?ゲームでも255の数字が良く使われているそうです。
いいえ。
もし2進数を基礎としているからというなら、2種類がコンピュータの限界となるでしょう。
現代のコンピュータでは8個のビット(0か1かの情報)をまとめて単位(バイト、またはオクテット)として扱い、
この1バイトで表せるのが256種類です。
そして、複数のバイトを組み合わせることで、
単純計算で256の(組み合わせるバイト数)乗種類のデータを表すことができます。
2バイトなら65,536種類、4バイトなら4,294,967,296(約43億)種類、
8バイトなら18,446,744,073,709,551,616(約2千京)種類となります。
(現実では、コマンドとして解釈される、誤りの検出や訂正を行う、
などの理由で禁止されるバイトの組み合わせがあり、データの種類数が少なくなる場合もあります)
プログラマ見習い さんが書きました:
1ヶ月前
もしも256種類を超える種類のデータが必要な場合、上記のソースコードにどのような変更が必要なのでしょうか?
やりたいことを実現するようにする変更が必要でしょう。
これまでの回答者の方々のアドバイスが参考になることを期待します。
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

返信

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