パソコン活用研究シリコンバレー(C、C++、の活用研究)

Short Program (モグラたたき)

ゲームを作ったことのある人なら、おそらく誰もが一度は作ったことがあると思いますが、
往年の由緒あるゲーム「もぐらたたき」を作制してみます。今回のソースはLSIC用です。

1 ゲームの内容

まずは、シンプルなゲームにするために、アルファベットをモグラに見立てることにします。
'A' が表示されたら、A のキーを押すことによりモグラをたたいたことにします。
モグラたたきというよりは、キー打ちの練習のようなものですが、まあ、勘弁してください。

少しゲームらしくするために、制限時間を設け、たたいたモグラの数をカウントすることにします。
モグラは、ランダムに出現しますが、最大同時に出現する数は20とします。

モグラの出現は乱数により決定します。
モグラの出現から消えるまではターン制とし出現時間は20ターンとします。(20ターン後に消える)
また、それだけではつまらないので、11ターン以降は無敵モグラに変身(文字色を変化させる)する
こととし、無敵モグラになると、たたいてもやられないということにします。

たたかれたモグラは * 表示し、ターンを17ターン目にします(すなわち3ターン * 表示されている)

まとめると以下の様です。

モグラ出現−−−−−>11ターン−−−−−−−−−−−−−−−−>20ターン
         |     無敵モグラ                        モグラ消える
         |
         たたく−−−−−−−−−−−−−−−−>17ターン−−>20ターン
                                       * 表示   消える

実行画面は下のような感じです。赤で表示されているのが無敵モグラです。
(LSICでコンパイルしたDOS/V用のバージョンは無敵モグラは反転表示で表示されます。
TurboC でコンパイルした PC98用、DOS/V 用は無敵モグラは赤色で表示されます)


****アルファベットもぐらたたき ver 0.01*****
coded by Tsuyoshi Kasai for LSIC-86
らんだむに表示するアルファベットのもぐら(A−Z)と同じキーを押して下さい
時間がたつともぐらは反転文字になります。この反転文字もぐらは無敵になります
キーは大文字にして下さい 制限時間 40
マシンウェイト(1000−3000が標準) 2000
残り時間 : 0
COUNT : 31
   *      *    M    X      K

THE END!!

C:\C>


2 プログラム

プログラムはLSIC用です。LSICでコンパイルされた実行ファイルは DOS/V, PC-98両方で動きます。
(1) 初期化
まずは、初期化の関数です。

void init() /*初期化*/
{long nowt;
long t;

/* window(1,1,80,24); */
printf("\x01b[2J"); /*画面クリア*/  
printf("\x01b[>5h");
t= time(&nowt);
srand(nowt%3600);
}




Window関数はTurboC用なのでLSIC用ではコメント         
画面クリアのエスケープシーケンス
カーソル消去のエスケープシーケンス
t に現在時刻取得
乱数発生系列の初期化

LSICには画面制御関連の関数がない(おじさんが知らないだけ?)ので、画面クリア、カーソル消去は
エスケープシーケンスで行っています。
srand で乱数のシードはもとめた現在時刻(システムクロック)を3600で割った余りをあてています。
              

(2) 画面上の表示位置
TurboC では文字の画面表示位置の指定には、 gotoxy という便利な関数がありますが、LSICには
見当たらないので、これも
エスケープシーケンスで実現しています。
(BASICでいうところの Locate)
locate 関数にx,y 座標を引数として渡します。

void locate (tx,ty)
int tx,ty;
{ printf("\x1b[%d;%dH" ,ty,tx);   
}


(3) 文字色の設定
テキスト文字色の設定には、TurboCでは textcolor という関数がありますが、LSICにはこれも見当たらない
ので、エスケープシーケンスで実現しています。
color 関数に 表示文字の属性を引数として渡します。7をわたすと反転表示になります。

void color(col)
int col;
{printf("\x01b[%dm",col);}         


(4) モグラの出現

void appear(n)
int n;
{int r,d;
d=32767/26;
if (rand()<2000) {
r=rand()/d; m[n][0]=r+65;
st[n]=1;
locate(n*2,10);putch(m[n][0]);}}         




rand()<2000 ならモグラ出現  確率 2000/32767 = 約6%
rは0〜25まで。アルファベットのアスキーコード(大文字)の決定
モグラの状態 st=1 出現 

LSICでは 乱数発生の関数' rand() は32767までの整数を発生します。
必要な乱数を得るため、適宜加工します。

変数 st はモグラの状態を現わす変数です。実際は各モグラのターンを入れます。
0は消えている状態
1で出現
10以降無敵モグラ状態
20で再び消える
というわけです。

(5) メインルーチン
まずは初期化の部分です

main(){
int i,j,k,t,wait;
time_t start,interval;

for (i=1; i<=num; i++){ /*変数初期化*/
st[i]=0;m[i][1]='\n';}
init();
printf("\n****アルファベットもぐらたたき ver 0.01*****\n coded by Tsuyoshi Kasai for LSIC-86");
printf("\nらんだむに表示するアルファベットのもぐら(A−Z)と同じキーを押して下さい\n");
printf("時間がたつともぐらは反転文字になります。この反転文字もぐらは無敵になります\n");
printf("キーは大文字にして下さい 制限時間 %d",timelimit);
printf("\nマシンウェイト(1000−3000が標準) ");scanf("%d",&wait);

以下はゲームの骨格部分です

time(&start);
for (;;){
for (i=1; i<=num; i++){
if (st[i]==0) {appear(i);continue;}
st[i]++;
if (st[i]==10) {color(7);
locate(i*2,10);putch(m[i][0]);
color(0);
continue;}
if (st[i]==20) {locate(i*2,10);putch(' ');  
st[i]=0;}
}

/*キー入力(モグラをたたく)の処理*/
while(kbhit())
{int c;
int n;
c=getch();
for (n=1;n<=num;n++){
if (c==m[n][0] && st[n]<10 && st[n]>0) {   
count++;
locate(1,9);printf("COUNT : %d",count);
locate(n*2,10);putch('*');
putch('\x07');
st[n]=17;}
}}


/*終了判定 */

for (j=0;j<8000;j++){for (k=0;k<wait;k++);}
time(&interval);
t=(unsigned int)difftime(interval,start);
locate(1,8);printf("残り時間 : %3d",timelimit-t);
if (t>=timelimit) break;}

locate(1,12);printf("THE END!!\n");
printf("\x01b[>5l");
}
&start にゲームスタート時間を入れる  
この for (;;) は ・・・(a) までが範囲
各モグラ(num=20まで)の処理
出現関数をコールし、continueで次のモグラの処理に移る 
ターンを一つ増加
ターン10になったら 表示反転(−−>無敵モグラ)
表示
表示属性を元にもどしておく

ターン20ならモグラ消える




キー入力チェック   


キーコードの取得
各モグラに対して処理      
キーが一致しており、普通の状態のモグラなら−−>たたいた
countを増加

* たたいた印の表示
Beep音
ターンを17に





ウェイトをかけている

関数difftimeで経過時間とスタート時間の差をとる
残り時間の表示
タイムリミットなら終了 ・・・・(a)



main 終わり


短いプログラムなので全リストつけておきます

/*アルファベット(A−Z)モグラたたき ver 0.01−−coded by Tsuyoshi Kasai for LSIC*/

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define timelimit 40
#define num 20
void locate (int,int);
void init();
void appear(int);
void color(int);
char m[num][2];
int st[num],count;

main(){
    int i,j,k,t,wait;
    time_t start,interval;
   
 for (i=1; i<=num; i++){                  /*変数初期化*/
  st[i]=0;m[i][1]='\n';}
init();
printf("\n****アルファベットもぐらたたき  ver 0.01*****\n coded by Tsuyoshi Kasai for LSIC-86");   
printf("\nらんだむに表示するアルファベットのもぐら(A−Z)と同じキーを押して下さい\n");
printf("時間がたつともぐらは反転文字になります。この反転文字もぐらは無敵になります\n");
printf("キーは大文字にして下さい  制限時間 %d",timelimit);
printf("\nマシンウェイト(1000−3000が標準) ");scanf("%d",&wait);
time(&start);
for (;;){
for (i=1; i<=num; i++){
if (st[i]==0) {appear(i);continue;}
st[i]++;
if (st[i]==10) {color(7);
                locate(i*2,10);putch(m[i][0]);
                color(0);
                continue;}
if (st[i]==20) {locate(i*2,10);putch(' ');
                st[i]=0;}
                        }
while(kbhit())
{int c;
int n;
c=getch();
for (n=1;n<=num;n++){
if (c==m[n][0] && st[n]<10 && st[n]>0) {
         count++;
         locate(1,9);printf("COUNT : %d",count);
         locate(n*2,10);putch('*');
         putch('\x07');
         st[n]=17;}
 }}
for (j=0;j<8000;j++){for (k=0;k<wait;k++);}
time(&interval);
t=(unsigned int)difftime(interval,start);
locate(1,8);printf("残り時間 : %3d",timelimit-t);
if (t>=timelimit) break;}

locate(1,12);printf("THE END!!\n");
 printf("\x01b[>5l");
}



void init()          /*初期化*/
{long nowt;
long t;

/* window(1,1,80,24); */
 printf("\x01b[2J");   /*画面クリア*/
 printf("\x01b[>5h");
t= time(&nowt);
srand(nowt%3600);
}

void locate (tx,ty)
int tx,ty;
{  printf("\x1b[%d;%dH" ,ty,tx);
  }

void color(col)
int col;
{printf("\x01b[%dm",col);}

void appear(n)
int n;
{int r,d;
 d=32767/26;
if (rand()<2000) {
       r=rand()/d; m[n][0]=r+65;
       st[n]=1;
      locate(n*2,10);putch(m[n][0]);}}


ソースファイルと実行ファイルは、ショートプログラム集に置いて有ります。
また、エスケープシーケンスについては、関連サイト(!)ラピュタへの道/エスケープシケンスを参照して下さい


TopPage