[前へ]   [目次へ]   [次へ]

CUIミニゲーム(高低当て)Ver.2(C/C++)

今回は、 第47回 の高低当てミニゲームを以下の仕様に改造していきます。

●「前回と同じ」選択肢の削除
●同じ数字は一度しか出ない
●10個の数字全て出し切ればクリア

まず、47回のプログラムを再掲載します。
<  1>
<  2>
<  3>
<  4>
<  5>
<  6>
<  7>
<  8>
<  9>
< 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>
< 41>
< 42>
< 43>
< 44>
< 45>
< 46>
< 47>
< 48>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>

int main(void){
   
int now;//現在値
   
int sel=0;//プレイヤーの選択(選択結果)
   
int next;//次回値
   
int loopcnt;//成功回数
   
char buf[256]="";//入力バッファ
   
int cmpres=0;//現在値と次回値の比較結果
   //randを初期化
   
srand(time(NULL));
   
//初期値を生成
   
now=rand()%10;
   
//ループ
   
for(loopcnt=0;sel==cmpres;loopcnt++){
      printf(
"現在の値:%d\n"
         "1:現在値<次回値 2:現在値==次回値 3:現在値>次回値\n"
         "次回はどうなると思いますか?:"
,now);
      fgets(buf,255,stdin);
      
if((buf[0]>='1')&&(buf[0]<='3')){
         sel=buf[0]-
'0';
      }
      next=rand()%10;
      
if(now<next){
         cmpres=1;
      }
      
else if(now==next){
         cmpres=2;
      }
      
else{
         cmpres=3;
      }
      now=next;
      
if(sel==cmpres){
         printf(
"成功!%dでした。\n\n",now);
      }
   }
   
//辻褄あわせ
   
loopcnt--;
   
//成功数表示
   
printf("失敗!%dでした。\n"
      "%d回成功しました。\n"
,now,loopcnt);
   
//終了待ち
   
getchar();
   
return 0;

それでは改造をしていきます。
まず、「前回と同じ」選択肢を削除します。
<  1>
<  2>
<  3>
<  4>
<  5>
<  6>
<  7>
<  8>
<  9>
< 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>
< 41>
< 42>
< 43>
< 44>
< 45>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>

int main(void){
   
int now;//現在値
   
int sel=0;//プレイヤーの選択(選択結果)
   
int next;//次回値
   
int loopcnt;//成功回数
   
char buf[256]="";//入力バッファ
   
int cmpres=0;//現在値と次回値の比較結果
   //randを初期化
   
srand(time(NULL));
   
//初期値を生成
   
now=rand()%10;
   
//ループ
   
for(loopcnt=0;sel==cmpres;loopcnt++){
      printf(
"現在の値:%d\n"
         "1:現在値<次回値 2:現在値>次回値\n"
         "次回はどうなると思いますか?:"
,now);//表示文字列を変更
      
fgets(buf,255,stdin);
      
if((buf[0]>='1')&&(buf[0]<='2')){//選択肢判定を修正
         
sel=buf[0]-'0';
      }
      next=rand()%10;
      
if(now<next){
         cmpres=1;
      }
//「同じ」判定を削除
      
else{//「同じ」は出なくなるのでここはこのままでも問題ない
         
cmpres=2;//現在値>次回値の番号を修正
      }
      now=next;
      
if(sel==cmpres){
         printf(
"成功!%dでした。\n\n",now);
      }
   }
   
//辻褄あわせ
   
loopcnt--;
   
//成功数表示
   
printf("失敗!%dでした。\n"
      "%d回成功しました。\n"
,now,loopcnt);
   
//終了待ち
   
getchar();
   
return 0;

次に、出現させる数字の順番を生成するようにします。
<  1>
<  2>
<  3>
<  4>
<  5>
<  6>
<  7>
<  8>
<  9>
< 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>
< 41>
< 42>
< 43>
< 44>
< 45>
< 46>
< 47>
< 48>
< 49>
< 50>
< 51>
< 52>
< 53>
< 54>
< 55>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>

int main(void){
   
int now;//現在値
   
int sel=0;//プレイヤーの選択(選択結果)
   
int next;//次回値
   
int loopcnt;//成功回数
   
char buf[256]="";//入力バッファ
   
int cmpres=0;//現在値と次回値の比較結果
   
   
int numbers[10]={0,1,2,3,4,5,6,7,8,9};//出現させる数字配列
   
int i,n,n2;
   
//randを初期化
   
srand(time(NULL));
   
//(1)前回の方法で数字配列をシャッフル
   
for(i=10;i;i--){
      n=rand()%i;
      n2=numbers[i-1];
      numbers[i-1]=numbers[n];
      numbers[n]=n2;
   }
   
//初期値を代入
   
now=numbers[0];//(2)
   //ループ
   
for(loopcnt=0;sel==cmpres;loopcnt++){
      printf(
"現在の値:%d\n"
         "1:現在値<次回値 2:現在値>次回値\n"
         "次回はどうなると思いますか?:"
,now);
      fgets(buf,255,stdin);
      
if((buf[0]>='1')&&(buf[0]<='2')){
         sel=buf[0]-
'0';
      }
      next=numbers[loopcnt+1];
//(3)次回値を代入
      
if(now<next){
         cmpres=1;
      }
      
else{
         cmpres=2;
      }
      now=next;
      
if(sel==cmpres){
         printf(
"成功!%dでした。\n\n",now);
      }
   }
   
//辻褄あわせ
   
loopcnt--;
   
//成功数表示
   
printf("失敗!%dでした。\n"
      "%d回成功しました。\n"
,now,loopcnt);
   
//終了待ち
   
getchar();
   
return 0;
(1)17〜23行目で numbers 配列の数列をシャッフルして、出現順番を決めます。
(2)25行目は numbers 配列をシャッフルして決めた出現順番の最初の番号を初回値とするようにします。
(3)35行目も同様に、 numbers 配列の出現順番を元に次回値を設定するようにします。

とりあえずこれで動作の方は改造できましたが、まだ配列を使い果たした時にクリアになりません。
次はその部分を改造してみましょう。

今回は、メインループの継続条件は「まだ出現していない数字が残っている」に変更します。
配列の使用数は loopcnt を使って判断できるので、 loopcnt<10 でよさそうです。
次に、ループの最後での成否判定に失敗時の処理も割り当てます。
最後に成功数表示をクリア判定に置き換えれば完成ですね。

<  1>
<  2>
<  3>
<  4>
<  5>
<  6>
<  7>
<  8>
<  9>
< 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>
< 41>
< 42>
< 43>
< 44>
< 45>
< 46>
< 47>
< 48>
< 49>
< 50>
< 51>
< 52>
< 53>
< 54>
< 55>
< 56>
< 57>
< 58>
< 59>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>

int main(void){
   
int now;//現在値
   
int sel=0;//プレイヤーの選択(選択結果)
   
int next;//次回値
   
int loopcnt;//成功回数
   
char buf[256]="";//入力バッファ
   
int cmpres=0;//現在値と次回値の比較結果
   
   
int numbers[10]={0,1,2,3,4,5,6,7,8,9};//出現させる数字配列
   
int i,n,n2;
   
//randを初期化
   
srand(time(NULL));
   
//前回の方法で数字配列をシャッフル
   
for(i=10;i;i--){
      n=rand()%i;
      n2=numbers[i-1];
      numbers[i-1]=numbers[n];
      numbers[n]=n2;
   }
   
//初期値を代入
   
now=numbers[0];
   
//ループ
   
for(loopcnt=0;loopcnt<10;loopcnt++){
      printf(
"現在の値:%d\n"
         "1:現在値<次回値 2:現在値>次回値\n"
         "次回はどうなると思いますか?:"
,now);
      fgets(buf,255,stdin);
      
if((buf[0]>='1')&&(buf[0]<='2')){
         sel=buf[0]-
'0';
      }
      next=numbers[loopcnt+1];
//次回値を代入
      
if(now<next){
         cmpres=1;
      }
      
else{
         cmpres=2;
      }
      now=next;
      
if(sel==cmpres){
         printf(
"成功!%dでした。\n\n",now);
      }
      
else{
         
//成功数表示
         
printf("失敗!%dでした。\n"
            "%d回成功しました。\n"
,now,loopcnt);
         
break;//ゲーム終了
      }
   }
   
if(loopcnt==10){//失敗してなければloopcntは10になるはず
      
puts("ゲームクリア!");
   }
   
//終了待ち
   
getchar();
   
return 0;
えーやってみるとクリアするのは結構難しいんですけど(笑)
一応仕様通り・・・に見えます。

しかし、やっぱり今回もバグ混入状態です。
しっかりじっくりやってれば「アレ?」って部分に気付くと思います。
バグ数は1、割と致命的ですが地味なので気付きにくいタイプです。
何度も遭遇していると何故かコードから感覚的に分かるようになる(バグ臭がするというか(笑))ので、
がんばって探してください。

次回は、今回のデバッグ編です。

[前へ]   [目次へ]   [次へ]

プログラミング講座 総合目次

最終更新 2008/10/17