C++での乱射ショットについて教えてください。

このQ&Aのポイント
  • C++での乱射ショットについての質問です。乱射ショットのコードについて説明してください。
  • 現在、乱射ショットの実装について困っています。コードを追加しても乱射にならず、乱射する方法がわかりません。
  • 乱射ショットの部分のコードを提供してください。また、ENEMY::Shot()の全体のコードも教えてください。
回答を見る
  • ベストアンサー

C++での乱射ショットについて教えてください。

お疲れ様です。 今回もお世話になります。 シューティングゲームのサンプルで勉強しています。 サンプルの乱射ショットの実行画面では弾が20発くらい 一度に乱射した状態で発射します。 自分の実行画面は1~2発、画面から後退するときに もう1~2発発射するだけです。 自分なりにコードを足してみたりしたのですが 2くらい増えただけで乱射になりません。 まだ理解不足で出来ませんでした。 何が足りないか教えてください。 以下は乱射部分だけのコードです。 その下にENEMY::Shot()の全体のコードを載せます。 失礼します。 //乱射ショット case 3: //1ループ毎に1発発射 for(int i=0;i<ENEMY_SNUM;++i){ //フラグが立ってない弾を探して、座標セット if(shot[i].flag==false){ shot[i].flag=true; shot[i].x=x; shot[i].y=y; //初回だけ乱数初期化 if(num==0){ srand((unsigned int)time(NULL)); shot[i].rad=atan2(py-y,px-x)-(60*PI/180)+((rand()%120)*PI/180); ++num; break; } } } break; 以下はENEMY::Shot()の全体のコードです。 void ENEMY::Shot() { //CONTROLクラスの参照 CONTROL &control = CONTROL::GetInstance(); double px,py; //発射タイミングになったら、フラグを立てる if(shot_time==g_count){ sflag=true; } //フラグを立てるときだけ if(sflag){ //プレイヤーの一取得 control.GetPlayerPosition(&px,&py); //敵とプレイヤーとの座標の差から逆正接を求める。 //初回だけ実行 if(scount==0) rad=atan2(py-y,px-x); switch(s_pattern){ //前方にショット case 0: //5回に一回発射。20までなので5発発射。 if(scount%5==0 && scount<=20){ for(int i=0;i<ENEMY_SNUM;++i){ //フラグが立ってない弾を探して、座標をセット f(shot[i].flag==false){ shot[i].flag=true; shot[i].x=x; shot[i].y=y; shot[i].rad=rad; break; } } } break; //プレイヤーに向かって直線ショット case 1: //6ループに一回発射。54までなので10発発射。 if(scount%6==0 && scount<=54){ for(int i=0;i<ENEMY_SNUM;++i){ //フラグが立っていない弾を探して、座標をセット if(shot[i].flag==false){ shot[i].flag=true; shot[i].x=x; shot[i].y=y; shot[i].rad=rad; break; } } } break; //3直線ショット case 2: //10ループに一回発射。1ループに3発なので5ループさせると15発発射 if(scount%10==0 && scount<=40){ for(int i=0;i<ENEMY_SNUM;++i){ //フラグが立っていない弾を探して、座標等をセット if(shot[i].flag==false){ shot[i].flag=true; shot[i].x=x; shot[i].y=y; //0の時は左より if(num==0){ //敵とプレイヤーとの逆正接から10度引いたラジアンを代入 shot[i].rad=rad-(10*3.14/180); //1の時はプレイヤー一直線 }else if(num==1){ //敵とプレイヤーとの逆正接を代入 shot[i].rad=rad; //2の時は右より }else if(num==2){ //敵とプレイヤーとの逆正接から10度足したラジアンを代入 shot[i].rad=rad+(10*PI/180); } ++num; //3発発射したら,numを0にしてループを抜ける。 if(num==3){ num=0; break; } } } } break; //乱射ショット case 3: //1ループ毎に1発発射 for(int i=0;i<ENEMY_SNUM;++i){ //フラグが立ってない弾を探して、座標セット if(shot[i].flag==false){ shot[i].flag=true; shot[i].x=x; shot[i].y=y; //初回だけ乱数初期化 if(num==0){ srand((unsigned int)time(NULL)); shot[i].rad=atan2(py-y,px-x)-(60*PI/180)+((rand()%120)*PI/180); ++num; break; } } } break; } //フラグが立ってる弾の数 int s=0; //フラグが立ってる弾だけ、弾の移動を行う for(int i=0;i<ENEMY_SNUM;++i){ if(shot[i].flag){ switch(shot[i].pattern){ //単純に下に発射 case0: shot[i].y+=shot[i].speed; break; case 1: shot[i].x+=shot[i].speed*cos(shot[i].rad); shot[i].y+=shot[i].speed*sin(shot[i].rad); break; case 2: shot[i].x+=shot[i].speed*cos(shot[i].rad); shot[i].y+=shot[i].speed*sin(shot[i].rad); break; case 3: shot[i].x+=shot[i].speed*cos(shot[i].rad); shot[i].y+=shot[i].speed*sin(shot[i].rad); break; } //弾が画面をはみ出たらフラグを戻す。 if(ShotOutCheck(i)){ shot[i].flag=false; continue; } ++s; } } //sがゼロということは発射中の弾がない。 //かつdeadflagがTRUEということはこの敵のクラスは消滅させてよい if(s==0 && deadflag){ //敵クラス消滅フラグをTRUEにする endflag=true; } ++scount; } }

質問者が選んだベストアンサー

  • ベストアンサー
  • kmee
  • ベストアンサー率55% (1857/3366)
回答No.2

細かく全体を見てはいません。 //初回だけ乱数初期化 if(num==0){ srand((unsigned int)time(NULL)); shot[i].rad=atan2(py-y,px-x)-(60*PI/180)+((rand()%120)*PI/180); ++num; break; } 提示された部分で、rand が使われているのはここだけです。 これだと、 「num==0 のとき、必ず srand してからrand」となります。 ・numがどうなっているのか、コードからはわかりません。 最初の1回だけ角度がランダムに決定され、それ以降はnum!=0となり、shot[i].radが過去に設定されたもののまま、ということは無いですか? ・乱数の発生原理を理解しましょう。 randは「疑似乱数」と呼ばれるもので、「乱数のように見えるけど、実際には一定の法則に従った数列」です。 srand (seed,種と呼ばれます)は、その初期値を決めるものです。種が同じなら、発生する乱数列も同じになります。 例えば srand(10) 後、 rand()を繰り返したら 5,3,7,2 .... と乱数が求められたとします。 この場合、srand(10)とすれば、その後のrand()は、必ず 5,3,7,2 .... となります。 通常は、最初にsrandして、後はrandを繰り返す、という使い方をします。 srandは、プログラム実行時に初期値が設定されます。そのため、プログラム実行の度に同じ乱数列が発生します。 # いわゆる「電源パターン」です。 それを防ぐテクニックに一つが、「現在時刻を元に種を作る」です。 srand((unsigned int)time(NULL)); はそのためのものです。 ですが、これには「同じ時刻だと同じ乱数になる」という欠点があります。 time()は1秒単位です。よって、現在のプログラムだと、1秒間に撃たれた「乱射弾」は、全部同じ方向へ飛びます。

bari-kinki
質問者

お礼

お疲れ様です。 いろいろ復習になった部分もあったのでよかったです。 解決出来ました。 ありがとうございます。 失礼します。

その他の回答 (1)

  • honor
  • ベストアンサー率35% (25/71)
回答No.1

他のショットはサンプルのように上手くできているのでしょうか? shot[i].flagやshot[i].radの値をデバッガで確認してみるとか。 乱数の初期化が出来ていないせいで全ての弾が重なってるなんてことはないですよね。

bari-kinki
質問者

お礼

お疲れ様です。 言葉をヒントに試していたら解決出来ました。 ありがとうございます。 失礼します。

関連するQ&A

  • C++デバックエラーについて詳しく教えてください。

    Microsoft Visual C++ Debug Library と言うエラーが発生しました。 Visual C++ 2008 Express Edition を使っています。 状況は以下になります。 Program:C:\DxLib_VC\サンプルプログラム実行用フォルダ \Debug\DxLib_VC2008用.exe Module:C:\DxLib_VC\サンプルプログラム実行用フォルダ \Debug\DxLib_VC2008用.exe File: Run-Time Check Failure #3 - The variable 'temp' is being used without being initialized (Press Retry to debug the application) Run-Timeの部分から自分なりに調べてみたのですが ランタイム・チェック失敗#3-変数'temp'は初期化されずに使用されています と書いてあると思います。 それで いろいろみなさんに意見をいただいたのですが stype!=0のときの処理が書けません。 初期化は出来たのですが、複数の敵が弾をだすはずが プレイヤーしかでなくなりました。 またいろいろ意見お願いします。 tempの部分のコードは以下です。 (define.h) struct E_SHOT{ bool flag;//弾が発射中かどうか double x;//x座標 double y;//y座標 int gh;//グラフィックハンドル int width,height;//画像の幅と高さ int pattern;//ショットパターン int speed;//弾スピード }; #define ENEMY_SNUM 50//敵の弾の上限 (enemy.cpp) #include "pch.h" #include "enemy.h" ENEMY::ENEMY( int type,//敵タイプ、 int stype,//弾種類 int m_pattern,//移動パターン、 int s_pattern,//発射パターン int in_time,//出現時間、 int stop_time,//停止時間、 int shot_time,//弾発射時間、 int out_time,//帰還時間、 int x,//x座標、 int y,//Y座標、 int speed,//弾スピード int hp,//HP int item//アイテム) { //サイズ width=27; height=25;      //敵の種類 this->type=type; //弾の種類 this->stype=stype; //移動パターンとショットパターン this->m_pattern=m_pattern; this->s_pattern=s_pattern;      this->speed=speed; //座標セット this->x=x; this->y=y; //出現、停止、発射、帰還セット this->in_time=in_time; this->stop_time=stop_time; this->shot_time=shot_time; this->out_time=out_time; //hpとアイテム代入 this->hp=hp; this->item=item; //弾初期化 memset(shot,0,sizeof(shot)); //敵画像読み込み if(type==0){ LoadDivGraph("enemy.png",3,1,3,27,25,gh); } int temp; //弾画像読み込み if(stype==0){ temp=LoadGraph("enemyshot1.png"); } //サイズ取得 int w,h; GetGraphSize(temp,&w,&h); //弾の初期化 for(int i=0;i<ENEMY_SNUM;++i){ shot[i].flag=false; shot[i].gh=temp; shot[i].width=w; shot[i].height=h; shot[i].pattern=s_pattern; shot[i].speed=speed; shot[i].x=x; shot[i].y=y; } count=0; scount=0; deadflag=false; endflag=false; sflag=false; } void ENEMY::Move() { //出てきてから止まる時間までの間なら下に移動 if(in_time<g_count && g_count<stop_time){   y+=2;      //帰還時間を過ぎたら戻る。 }else if(g_count>out_time){    y-=2;    if(y<-40){    deadflag=true;  }    } } void ENEMY::Draw() { int temp; //弾から最初に描画 for(int i=0;i<ENEMY_SNUM;++i){ if(shot[i].flag){ DrawGraph(shot[i].x,shot[i].y,shot[i].gh,true); } } if(!deadflag){ temp= count%40/10; if(temp==3) temp=1; DrawGraph(x,y,gh[temp],TRUE); } } bool ENEMY::All() { Move(); Shot(); Draw(); ++count; return endflag; } void ENEMY::Shot() { //発射タイミングになったら、フラグを立てる if(shot_time==g_count){    sflag=true;    } //フラグを立てるときだけ if(sflag){   switch(s_pattern){ case 0: //10回に一回発射。40までなので5発発射。 if(scount%10==0 && scount<=40){ for(int i=0;i<ENEMY_SNUM;++i){ //フラグが立ってない弾を探して、座標をセット if(shot[i].flag==false){   shot[i].flag=true; shot[i].x=x; shot[i].y=y; break; } } } break; } //フラグが立ってる弾の数 int s=0; //フラグが立ってる弾だけ、弾の移動を行う for(int i=0;i<ENEMY_SNUM;++i){ if(shot[i].flag){ shot[i].y+=shot[i].speed; //弾が画面をはみ出たらフラグを戻す。 if(shot[i].x<-20 || shot[i].x>420 || shot[i].y<-20 || shot[i].y>500){ shot[i].flag=false; continue; } ++s; } } //sがゼロということは発射中の弾がない。 //かつdeadflagがTRUEということはこの敵のクラスは消滅させてよい if(s==0 && deadflag){ //敵クラス消滅フラグをTRUEにする endflag=true; } ++scount; } }

  • C++デバックエラーについて詳しく教えてください。

    Picosoftさんまだ未熟で解消できませんでした。 また見てたらお願いします。 他の人もお願いします。 Microsoft Visual C++ Debug Library と言うエラーが発生しました。 Visual C++ 2008 Express Edition を使っています。 状況は以下になります。 Program:C:\DxLib_VC\サンプルプログラム実行用フォルダ \Debug\DxLib_VC2008用.exe Module:C:\DxLib_VC\サンプルプログラム実行用フォルダ \Debug\DxLib_VC2008用.exe File: Run-Time Check Failure #3 - The variable 'temp' is being used without being initialized (Press Retry to debug the application) Run-Timeの部分から自分なりに調べてみたのですが ランタイム・チェック失敗#3-変数'temp'は初期化されずに使用されています と書いてあると思うのですが、tempの部分のコードは以下です。 (define.h) struct E_SHOT{ bool flag;//弾が発射中かどうか double x;//x座標 double y;//y座標 int gh;//グラフィックハンドル int width,height;//画像の幅と高さ int pattern;//ショットパターン int speed;//弾スピード }; #define ENEMY_SNUM 50//敵の弾の上限 (enemy.cpp) #include "pch.h" #include "enemy.h" ENEMY::ENEMY( int type,//敵タイプ、 int stype,//弾種類 int m_pattern,//移動パターン、 int s_pattern,//発射パターン int in_time,//出現時間、 int stop_time,//停止時間、 int shot_time,//弾発射時間、 int out_time,//帰還時間、 int x,//x座標、 int y,//Y座標、 int speed,//弾スピード int hp,//HP int item//アイテム) { //サイズ width=27; height=25;      //敵の種類 this->type=type; //弾の種類 this->stype=stype; //移動パターンとショットパターン this->m_pattern=m_pattern; this->s_pattern=s_pattern;      this->speed=speed; //座標セット this->x=x; this->y=y; //出現、停止、発射、帰還セット this->in_time=in_time; this->stop_time=stop_time; this->shot_time=shot_time; this->out_time=out_time; //hpとアイテム代入 this->hp=hp; this->item=item; //弾初期化 memset(shot,0,sizeof(shot)); //敵画像読み込み if(type==0){ LoadDivGraph("enemy.png",3,1,3,27,25,gh); } int temp; //弾画像読み込み if(stype==0){ temp=LoadGraph("enemyshot1.png"); } //サイズ取得 int w,h; GetGraphSize(temp,&w,&h); //弾の初期化 for(int i=0;i<ENEMY_SNUM;++i){ shot[i].flag=false; shot[i].gh=temp; shot[i].width=w; shot[i].height=h; shot[i].pattern=s_pattern; shot[i].speed=speed; shot[i].x=x; shot[i].y=y; } count=0; scount=0; deadflag=false; endflag=false; sflag=false; } void ENEMY::Move() { //出てきてから止まる時間までの間なら下に移動 if(in_time<g_count && g_count<stop_time){   y+=2;      //帰還時間を過ぎたら戻る。 }else if(g_count>out_time){    y-=2;    if(y<-40){    deadflag=true;  }    } } void ENEMY::Draw() { int temp; //弾から最初に描画 for(int i=0;i<ENEMY_SNUM;++i){ if(shot[i].flag){ DrawGraph(shot[i].x,shot[i].y,shot[i].gh,true); } } if(!deadflag){ temp= count%40/10; if(temp==3) temp=1; DrawGraph(x,y,gh[temp],TRUE); } } bool ENEMY::All() { Move(); Shot(); Draw(); ++count; return endflag; } void ENEMY::Shot() { //発射タイミングになったら、フラグを立てる if(shot_time==g_count){    sflag=true;    } //フラグを立てるときだけ if(sflag){   switch(s_pattern){ case 0: //10回に一回発射。40までなので5発発射。 if(scount%10==0 && scount<=40){ for(int i=0;i<ENEMY_SNUM;++i){ //フラグが立ってない弾を探して、座標をセット if(shot[i].flag==false){   shot[i].flag=true; shot[i].x=x; shot[i].y=y; break; } } } break; } //フラグが立ってる弾の数 int s=0; //フラグが立ってる弾だけ、弾の移動を行う for(int i=0;i<ENEMY_SNUM;++i){ if(shot[i].flag){ shot[i].y+=shot[i].speed; //弾が画面をはみ出たらフラグを戻す。 if(shot[i].x<-20 || shot[i].x>420 || shot[i].y<-20 || shot[i].y>500){ shot[i].flag=false; continue; } ++s; } } //sがゼロということは発射中の弾がない。 //かつdeadflagがTRUEということはこの敵のクラスは消滅させてよい if(s==0 && deadflag){ //敵クラス消滅フラグをTRUEにする endflag=true; } ++scount; } } になります。 ビルドの正常終了後になぜエラーがでるかと 内容を詳しく説明いただけるとありがたいです。 よろしくお願いします。

  • C++ Debug Errorについて教えて

    Visual C++ 2008 Express Edition を使っています。 シューティングゲームのサンプルで勉強しています。 すべで正常終了したあとダイヤログボックスが 出てくる時にMicrosoft Visual C++ Debug Library と言うエラーが発生しました。 状況は以下のとおりです。 Program:C:\DxLib_VC\サンプルプログラム実行用フォルダ\Debug\DxLib_VC2008用.exe Module:C:\DxLib_VC\サンプルプログラム実行用フォルダ\Debug\DxLib_VC2008用.exe File: Run-Time Check Failure #3 - The variable 'temp' is being used without being initialized (Press Retry to debug the application) Run-Timeの部分から自分なりに調べてみたのですが ランタイム・チェック失敗#3-変数'temp'は初期化されずに使用されています。 と書いてあると思うのですが、tempの部分のコードは以下です。 (define.h) struct E_SHOT{ bool flag;//弾が発射中かどうか double x;//x座標 double y;//y座標 int gh;//グラフィックハンドル int width,height;//画像の幅と高さ int pattern;//ショットパターン int speed;//弾スピード }; #define ENEMY_SNUM 50//敵の弾の上限 (enemy.cpp) int temp; //弾画像読み込み if(stype==0){ temp=LoadGraph("enemyshot1.png"); } //サイズ取得 int w,h; GetGraphSize(temp,&w,&h); //弾の初期化 for(int i=0;i<ENEMY_SNUM;++i){ shot[i].flag=false; shot[i].gh=temp; shot[i].width=w; shot[i].height=h; shot[i].pattern=s_pattern; shot[i].speed=speed; shot[i].x=x; shot[i].y=y; } 正常終了後のエラーがなぜでるのかについてと、 その内容の部分について教えてください。 お願いします。

  • switch文を教えてください。

    以下のスイッチ文はcounterが特定の時にある値を代入する文ですが、 マッチした時全部同じ処理をしてしまいますよね。 case 50: の時だけ enemy[i].pattern=2; ではなく、 enemy[i].pattern=0; にしたいんです。 どうすればいいでしょうか。 やはりif文を使うしかないのでしょうか? これだけが実現できるとりあえずの処理ではなくて、これからドンドンcase文が増えていくものとして汎用性の高い書き方にしたいです。 switch(counter){   case 50:   case 350:   case 650:   case 950:   case 1250:   case 1550:   case 1850:   case 2150:     enemy[i].pattern=2; //どういう軌道を描くか     enemy[i].flag=1; //出現フラグを立てる     enemy[i].counter=0;//カウンター初期化         enemy[i].size=0.5f;//敵の大きさ     enemy[i].range=10.0f//範囲     enemy[i].x=210.0; //xの初期座標     enemy[i].y=-10.0; //yの初期座標     break;   default:     break; } どなたかよろしくお願いします><

  • シューティングゲームの当たり判定

    現在directxを用いた(DXライブラリは使わない)インベーダーゲームを作っているのですが、当たり判定の部分がなぜかうまくいきません。自機と敵の弾の当たり判定部分のコードを載せるのでどなたかご享受ください。 //============敵の攻撃======================== if(enemy[rand_atk].tamaflag == 0 && shot_save % 100 == 0 ){ __enemy[rand_atk].tamaflag = 1; __enemy_atk[rand_atk].x = enemy[rand_atk].x+17; __enemy_atk[rand_atk].y = enemy[rand_atk].y+17; } for(i = 0; i < 11; i++){ __if(enemy[i].tamaflag == 1){ ____enemy_atk[i].y+=1; ____if(enemy_atk[i].y >= 480){ ______enemy[i].tamaflag = 0; ______enemy_atk[i].y = -20; //画面外へ ____} ____if( ( move.x - 7 < enemy_atk[i].x && move.x + 32 > enemy_atk[i].x ) && ________( move.y - 13 < enemy_atk[i].y && move.y + 24 > enemy_atk[i].y ) ){ ______move.zanki--; ______enemy[i].tamaflag = 0; ______enemy_atk[i].y = -20; //画面外へ ____} __} } move.x,move.yは自機のx,y座標で横32縦24 敵の弾の大きさは横7縦13 rand_atkはrand_atk = timeGetTime() % 11;でランダムに攻撃させようとしています。

  • C++のファイルの読み込みの部分で質問があります。

    fp = fopen("enemydata.csv","r");の部分のコードで "enemydata.csv"のファイルを読み込むのですが "r"の部分が何を意味しているのがわかりません。 以下のコードの他にも enemy.cpp enemy.h がありますが関連するものが見あたりません。 "r"の部分のコードは以下に表示します。 よろしくお願いします。 control.cpp #include "pch.h" #include "control.h" CONTROL::CONTROL() { player = new PLAYER; back = new BACK; FILE *fp; ENEMYDATA data[ENEMY_NUM]; char buf[100]; int c; int col=1; int row=0; memset(buf,0,sizeof(buf)); ここの部分→fp = fopen("enemydata.csv","r"); //ヘッダ読み飛ばし while(fgetc(fp)!='\n'); while(1){ while(1){ c=fgetc(fp); //末尾ならループを抜ける。 if(c==EOF) goto out; //カンマか改行でなければ、文字としてつなげる if(c!=','&& c!='\n') strcat(buf,(const char*)&c); //カンマか改行ならループ抜ける。 else break; } //ここにきたということは、1セル分の文字列が出来上がったということ switch(col){ //1列目は敵種類を表す。atoi関数で数値として代入。 case 1: data[row].type=atoi(buf); break; //2列目は弾種類。以降省略。 case 2: data[row].stype=atoi(buf); break; case 3: data[row].m_pattern=atoi(buf); break; case 4: data[row].s_pattern=atoi(buf); break; case 5: data[row].in_time=atoi(buf); break; case 6: data[row].stop_time=atoi(buf); break; case 7: data[row].shot_time=atoi(buf); break; case 8: data[row].out_time=atoi(buf); break; case 9: data[row].x=atoi(buf); break; case 10: data[row].y=atoi(buf); break; case 11: data[row].speed=atoi(buf); break; case 12: data[row].hp=atoi(buf); break; case 13: data[row].item=atoi(buf); break; } //バッファを初期化 memset(buf,0,sizeof(buf)); //列数を足す ++col; //もし読み込んだ文字が改行だったら列数を初期化して行数を増やす if(c=='\n'){ col=1; ++row; } } out: //敵クラス生成 for(int i=0;i<ENEMY_NUM;++i){ enemy[i]=new ENEMY( data[i].type, data[i].stype, data[i].m_pattern, data[i].s_pattern, data[i].in_time, data[i].stop_time, data[i].shot_time, data[i].out_time, data[i].x, data[i].y, data[i].speed, data[i].hp, data[i].item); } } void CONTROL::All() { //int count = 0; //描画領域を指定 SetDrawArea(MARGIN,MARGIN,MARGIN+380,MARGIN+460); back->All(); //プレイヤークラスのAll関数実行 player->All(); for(int i=0;i<ENEMY_NUM;++i){ if(enemy[i]!=NULL){ if(enemy[i]->All()){ delete enemy[i]; enemy[i]=NULL; } } } ++g_count; } CONTROL::~CONTROL() { //プレイヤークラスの解放 delete player; delete back; for(int i=0;i<ENEMY_NUM;++i){ if(enemy[i]!=NULL){ delete enemy[i]; } } }

  • ちょっとした記述に関する疑問

    どちらでもいいような内容かもしれませんが、よろしくお願いします。 ---------------------------------- flag = false; if(num < 0) { num *= -1; flag = true; } //numを使って何かの処理 ~~ if(flag) { //処理 num *= -1; } ---------------------------------- 例として、変数numが負だったらフラグをtrueにして、 最後にそのフラグをもとに処理を行うという一連の動作があった場合に、 if(num < 0) { num *= -1; flag = true; } というふうにフラグを後に記述するのか if(num < 0) { flag = true; num *= -1; } というふうにフラグを先に記述するのか がふと気になったのですが、みなさんはどちらでやっているのでしょうか?

  • C言語による簡易電卓の作成

    四則演算に加えてべき乗、階乗を使えるような電卓を作りたいのです。 四則演算は #include <stdio.h> #include <ctype.h> void Factor( int *x ); void MulDiv( int *x ); void AddSub( int *x ); int expression( void ); int main( void ) { printf( "%d\n", expression() ); return 0; } void Factor( int *x ) { int num = 0, flag = 1, c = 0; c = fgetc( stdin ); if( c == '-' || c == '+' ){ c = fgetc( stdin ); flag = (c == '+' ) ? 1 : -1; } if( isdigit(c) ){ int n = 0; while( isdigit(c) ){ n = n * 10 + ( c - '0' ); c = fgetc( stdin ); } num = n * flag; }else{ if( c == '(' ){ num = expression(); if( fgetc( stdin ) != ')' ){ exit(-1); } c = 0x0100; } } if( c != 0x0100 ) ungetc( c, stdin ); (*x) = num; } void MulDiv( int *x ) { int num = 0, c = 0; Factor( x ); num = (*x); c = fgetc( stdin ); while( c == '*' || c == '/' || c == '%' ){ switch( c ) { case '*': Factor( x ); num = num * (*x); break; case '/': Factor( x ); num = num / (*x); break; case '%': Factor( x ); num = num % (*x); break; } c = fgetc( stdin ); } ungetc( c, stdin ); (*x) = num; } void AddSub( int *x ) { int num = 0, c = 0; MulDiv( x ); num = (*x); c = fgetc( stdin ); while( c == '+' || c == '-' ){ switch( c ) { case '+': MulDiv( x ); num = num + (*x); break; case '-': MulDiv( x ); num = num - (*x); break; } c = fgetc( stdin ); } ungetc( c, stdin ); (*x) = num; } int expression( void ) { int x = 0; AddSub( &x ); return x; } これで正しく動くことを確認できたのですが、階乗、べき乗の書き方が全くわかりません。どなたか、詳しい方いらっしゃいましたら、ご教授願います。

  • c言語

    c言語で写真の課題を出されたのですが自分のプログラムでは上手くいきません。どこが間違っているのか教えて欲しいです。 自分のプログラム #include<stdio.h> #include<math.h> int main(){ int i,j; double c,d,x,y,z; for(i=0;i<=360;i++){ c=10*cos(i*M_PI/180); d=10*sin(i*M_PI/180); if(c>=0 && d>=0){ for(j=0;j<=1000;j++){ x=0.001*j; y =x*d/c; z=1-x*x-(sqrt(x)+y)*(sqrt(x)+y); if(z<=0.0){break;} } } if(c<=0 && d>=0){ for(j=0;j<=1000;j++){ x=-0.001*j; y=x*d/c; z=1-x*x-(sqrt(-x)+y)*(sqrt(-x)+y); if(z<=0.0){break;} } } if(c<=0 && d<=0){ for(j=0;j<=1000;j++){ x=-0.001*j; y=x*d/c; z=1-x*x-(sqrt(-x)+y)*(sqrt(-x)+y); if(z<=0.0){break;} } } if(c>=0 && d<=0){ for(j=0;j<=1000;j++){ x=0.001*j; y=x*d/c; z=1-x*x-(sqrt(x)+y)*(sqrt(x)+y); if(z<=0.0){break;} } } printf("x=%lf y=%lf z=%lf\n",x,y,z); } return(0); }

  • c言語 

    答えを0にするこまち算のプログラムを組んでみたのですが、ここからどうしても進まなくなってしまいました。 自分ではいけるかなと思ったのですが、9-8-7+65-4321=9など答えがありえない数になってしまいます。 どこがいけないか教えてください。むしろ最初から組み直した方がよいのでしょうか… #include <stdio.h> int cul(); int num[9] ={9,8,7,6,5,4,3,2,1}; int total;/**/ int kigou[8]={0,0,0,0,0,0,0,0}; int main(){ for(kigou[0]=0;kigou[0]<3;kigou[0]++){ for(kigou[1]=0;kigou[1]<3;kigou[1]++){ for(kigou[2]=0;kigou[2]<3;kigou[2]++){ for(kigou[3]=0;kigou[3]<3;kigou[3]++){ for(kigou[4]=0;kigou[4]<3;kigou[4]++){ for(kigou[5]=0;kigou[5]<3;kigou[5]++){ for(kigou[6]=0;kigou[6]<3;kigou[6]++){ for(kigou[7]=0;kigou[7]<3;kigou[7]++){ keisan(); } } } } } } } } return 0; } int keisan(){ int n =0; int flag = 0; int t = 0; int i = 0; total = num[0]; /* for (n=0;n<9;n++) printf("kigou[%d] == %d",n,kigou[n]);確かめ*/ for(;n<8;n++){ if(kigou[n] == 0 && n == 0){ total = total * 10 + num[n+1]; for(flag=1;kigou[n+flag]==0 && (n+flag)<9 ;flag++){ total = total * 10 + num[n+flag+1]; } n = n + flag; } flag=0; if(kigou[n]!= 0){ for(flag=1;kigou[n+flag]==0 && (n+flag)<9 ;flag++){ t = num[n+1] * 10 + num[n+flag+1]; } n = n+ flag; total = total + t; } } /*0になる計算式の表示*/ kigou[8]=2;/*表示しないために空白を入れる*/ if(total==0){ for(i=0;i<9;i++){ printf("%d",num[i]); if(kigou[i]==0) printf("+"); if(kigou[i]==1) printf("-"); if(kigou[i]==2) printf(""); } printf("=%d\n",total); } return 0; }

専門家に質問してみよう