• 締切済み

私のCプログラムの悪いところを教えてください。

デバッグではじめるCプログラミングって言う本を見ながらやっているのですが、マップが崩れるし、キャラは飛びまくるし、うまく動作しないのです。 どこが悪いのか、見ていただけないでしょうか? マップは2階までと、プレイヤーキャラ、モンスターそれぞれ一体の表示と移動まで。(本当なら・・・) 情けない話ですがよろしくお願いします。

みんなの回答

  • Wr5
  • ベストアンサー率53% (2173/4061)
回答No.5

結局、switch~caseは使用しなくなってしまったようですが…念のため。 # if文を列挙するよりはswitchの方が効率的なのですが……。 # 今時のコンパイラなら最適化してくれるとは思いますが。 >case 119: //Wキー > if((PC.y >= 1) && (dungeon[PC.Level][PC.x][PC.y-1] != 1)){ >  PC.y--; >  break; > } >case 120: //xキー > if((PC.y <= 18) && (dungeon[PC.Level][PC.x][PC.y+1] != 1)){ >  PC.y++; >  break; > } >  : ちゃんとbreak入れましょう。 wキーを押したとき、(PC.y >= 1) && (dungeon[PC.Level][PC.x][PC.y-1] != 1)の条件が成立せずに、 (PC.y <= 18) && (dungeon[PC.Level][PC.x][PC.y+1] != 1)の条件が成立した場合にどうなるでしょうか? さらに、case 119とかcase 120とかのマジックナンバーを使用するのではなく、case 'w'とかcase 'x'などの文字定数を使用して可読性をあげるようにしましょう。 # こういうところも「デバッグ」では必要です。

ForceFeed
質問者

補足

がんばって、switch文に直しました。 あと、ランダムで動くようなモンスターも入れてみました。 スライム一匹だけですけど^_^; プログラムは面白いですけど、奥が深いです。 ここの部分直すだけで、朝になってしまいました>< これでどうでしょうか? while(1){ if(kbhit()){ PC.key=getch(); switch(PC.key){ case 'w'://Wキー ↑ if((PC.x>=1)&&(dungeon[PC.level][PC.x-1][PC.y]!=1)) PC.x--; break; case 's'://sキー ↓ if((PC.x<=18)&&(dungeon[PC.level][PC.x+1][PC.y]!=1)) PC.x++; break; case 'd'://dキー → if((PC.y<=18)&&(dungeon[PC.level][PC.x][PC.y+1]!=1)) PC.y++; break; case 'a'://aキー ← if((PC.y>=1)&&(dungeon[PC.level][PC.x][PC.y-1]!=1)) PC.y--; break; default: printf("想定外の値です: %d",PC.key); break; } dMonster=rand()%4; switch(dMonster){ case 0: if((slime.x>=1)&&(dungeon[slime.level][slime.x-1][slime.y]!=1)) slime.x--;//↑ break; case 2: if((slime.x<=18)&&(dungeon[slime.level][slime.x+1][slime.y]!=1)) slime.x++;//↓ break; case 3: if((slime.x<=18)&&(dungeon[slime.level][slime.x][slime.y+1]!=1)) slime.y++;//→ break; case 1: if((slime.x>=1)&&(dungeon[slime.level][slime.x][slime.y-1]!=1)) slime.y--;//← break; default: printf("想定外の値です: %d",dMonster); break; } show_dungeon(); } switch(dungeon[PC.level][PC.x][PC.y]){ case 2: if((dungeon[PC.level][PC.x][PC.y]==2)&&(PC.level<1)) printf("%s:おっ、こんな所に下り階段がある…\n",PC.name); PC.level++; break; case 3: if((dungeon[PC.level][PC.x][PC.y]==3)&&(PC.level>0)) printf("%s:おっ、こんな所に上がり階段がある…\n",PC.name); PC.level--; break; } }

すると、全ての回答が全文表示されます。
  • zwi
  • ベストアンサー率56% (730/1282)
回答No.4

>プログラムをテストするつもりで短くしたのですが、こちらはキャラクターの'@’が動かないです。 >本の通りにやっていて途中までは動いていたのですが、理由がわかりません。 プログラムを身に付ける&デバッグの基本として、 (1)試したい機能だけを取り出して別プログラムにしてみる。 (2)途中までは動いていたであれば、動いてたものとの違いを比べてみる。 (3)1行毎に何をしているかコメントを付ける。分らない機能が有れば徹底的に調べる。 (4)本を最初から見直して、見落としがないか調べてみる。分らなくなったら基本に返りましょう。 を実践すればやがて分ってくると思います。 >どのあたりを貼り付ければいいのかもわからないのです。 これもどの部分がどんな役目をしているか分らない事から来ています。1行ごとの動作、そして数行から数十行の機能単位分けてごとにコメントしてみましょう。今の部分で難しいのであれば、理解していたと思っているTrainingの前の章から始めてみます。本当に全てを理解してましたか?

ForceFeed
質問者

補足

ご指摘ありがとうございます。 最初に遡って学習しなおしてみます。(そういう本でした) あと、ZWiさんの4か条をしっかりと身に付けるように努力してみます。 また、わからなくなったら、その時は皆さんよろしくお願いします。 ちなみに、動くようになりました。 まだ、壁とか素通りしちゃいますけど(^^ゞ #include <conio.h> #include <stdlib.h> #include <stdio.h> void show_title(void);//タイトル表示関数 char make_character(void);//今の所名前入力とYes/Noだけの関数  void show_dungeon(int,int,int);//ダンジョン&キャラ表示関数 char name[20];//名前の変数をグローバルにしました int level=0,xpc=1,ypc=0;//キャラクターの位置情報をグローバルにしました char dungeon[2][20][20]={ここ省略}//ダンジョンマップをグローバルにしました int main(void) { char result='n'; int key; int directiion; show_title(); while(result!='y'){ result=make_character(); } system("cls"); show_dungeon(level,xpc,ypc); while(1){ if(kbhit()){ key=getch(); //printf("%d\n",key); キーコード確認用 if(key==119){ ypc--; } if(key==115){ ypc++; } if(key==100){ xpc++; } if(key==97){ xpc--; } show_dungeon(level,xpc,ypc); if((dungeon[level][xpc][ypc]==2)&&(level<1)){ printf("%s:おっ、こんな所に下り階段がある…",name); while(1){ if(kbhit()){ level++; break; }    }   }  }     } scanf("%*c%c",&directiion); return 0; } void show_dungeon(int z,int x,int y) { int i,j; system("cls"); for(i=0;i<20;i++){ for(j=0;j<20;j++){ if((j==x) && (i==y))printf("@"); else if(dungeon[z][i][j]==0)printf("+"); else if(dungeon[z][i][j]==2)printf(">"); else printf("#"); } printf("\n"); } } void show_title(void) { system("cls"); printf("見習い魔道師の受難\n\n\n"); } char make_character(void) { char confirmation; printf("見習い魔道師の最初の受難\n\n"); printf("名前の入力をしてください:"); scanf("%s",name); printf("%sでよろしいですか?Y/N :",name); scanf("%*c%c",&confirmation); if(confirmation=='y')printf("確定しました"); return confirmation; }

すると、全ての回答が全文表示されます。
noname#227064
noname#227064
回答No.3

No.1の補足にかかれたソースだけでは、アドバイスは難しいので、No.2の方のみ。 こちらは、マップを表示するのが最初だけしか行っていないので、@が動かないのです。 マップが崩れるのは、ひょっとして改行がずれているだけでしょうか?

ForceFeed
質問者

補足

いろいろ、やり直してみました。ご指摘の部分を考えて本見直しながら、変数の位置と関数の位置をmain()の外や中に入れたり出したりしてみました。 おかげでようやく動くようになりました。 プログラムって動くと面白いですね^^ また、トラぶったときにはよろしくお願いします。

すると、全ての回答が全文表示されます。
  • zwi
  • ベストアンサー率56% (730/1282)
回答No.2

「デバッグではじめるCプログラミング」を読んだことは無いですが、どうやらわざとバグのあるプログラムプログラムが本に載っているみたいですね。なのでうまく動かなくて当然と言うか当たり前だと思います。 最初から順番に進めていけば、問題なくバグは取れるんだと思いますが。 少なくとも本を読んだことがある人を期待するのは無理だと思いますので、最初から順番どおりやっているのかと理解して進んでいるのか聞きたいですね。

ForceFeed
質問者

補足

プログラムをテストするつもりで短くしたのですが、こちらはキャラクターの'@’が動かないです。 本の通りにやっていて途中までは動いていたのですが、理由がわかりません。 どのようなプログラムか載せるのが遅くなってもうしわけないです。 #include <conio.h> #include <stdlib.h> #include <stdio.h> int main(void) { int i,j; int xpc=0,ypc=0; int key; char dungeon[5][5]={{0,0,0,1,1}, {1,1,0,1,1}, {1,0,0,0,1}, {1,1,0,1,1}, {1,1,0,0,0}}; for(i=0;i<5;i++){ for(j=0;j<5;j++){ if(j==xpc && i==ypc)printf("@"); else if(dungeon[i][j]==0)printf("+"); else printf("#"); } printf("\n"); } while(1){ if(_kbhit()){ key=_getch(); if(key==119) ypc--; if(key==120) ypc++; if(key==97) xpc--; if(key==100) xpc++; } } //system("cls"); return 0; }

すると、全ての回答が全文表示されます。
noname#227064
noname#227064
回答No.1

> どこが悪いのか、見ていただけないでしょうか? どこを見ればいいのでしょうか? 補足に記載してください。

ForceFeed
質問者

補足

プログラムを貼り付けたいのですが、文字数のせいで貼り付けられません。どのあたりを貼り付ければいいのかもわからないのです。 一応、このあたりがおかしいかなと思うところを貼り付けさせてもらいます。 while(result != 'y'){ result = make_character(); } system("cls"); show_dungeon(); while(1){ if(kbhit()){ key=getch(); //マップの配列要素が1なら移動できない。 switch(key){ case 119: //Wキー if((PC.y >= 1) && (dungeon[PC.Level][PC.x][PC.y-1] != 1)){ PC.y--; break; } case 120: //xキー if((PC.y <= 18) && (dungeon[PC.Level][PC.x][PC.y+1] != 1)){ PC.y++; break; } case 97: //aキー if((PC.x >= 1) && (dungeon[PC.Level][PC.x-1][PC.y] != 1)){ PC.x--; break; } case 100: //dキー if((PC.x <= 18) && (dungeon[PC.Level][PC.x+1][PC.y] != 1)){ PC.x++; break; } default: printf("W,X A D以外のキーが入力されました。!:%d",key); continue; break; }

すると、全ての回答が全文表示されます。