#include "stdio.h"
#include <conio.h>
#include <time.h>
#include "Console.h"
#define	MAX_ST	10		// 爆弾の最大数
#define	MAX_GR	20		// 地面の最大数
struct Stone_Data{		// 爆弾の構造体
	bool Ex;			// 爆弾があるかどうか
	int	x, y;			// xy座標
};
// キーコード  位置     得点     最高点
int	keyCode ,  Xp= 18, Score= 0, MaxSc=  0 ;
Stone_Data	Stone[MAX_ST];	// 爆弾
bool		GRND[MAX_GR] ;	// true : 地面あり
HANDLE g_h;					// 出力用スクリーンハンドル
static long s_Time;	    	// 時間
// 関数プロトタイプ宣言
void eraseBase(); void  moveBase() ; void drawBase();
void moveStone(); void  drawScore(); void initGame();
//-----------------------------------------------------------------------------
int main(int argc, char* argv[]){// ■メインプログラム
	initGame();	while(true){moveBase(); moveStone(); ::Sleep(60);}
}
void prXY(short X, short Y, WORD fColor, WORD bColor, char *str){//■文字列表示
	setCursorPosition(g_h, X, Y); setColor(g_h, fColor, bColor); printf(str);
}
void initGame(){				// ■ゲーム開始
	srand((unsigned) time(NULL));g_h=getOutConsole();
	setCursorInfo(g_h,25,false); clearConsole(g_h); Score=0;
	prXY( 0, 0,L_WHITE, L_BLACK,"攻撃を防御せよ!! \n左移動:Z 右移動:X");
	s_Time = 0;	drawScore();					// 得点描画
	for(int i = 0; i < MAX_GR; i++){GRND[i] = true;	Stone[i].Ex = false;	}
	prXY(0, MAX_GR,L_WHITE, L_YELLOW, "                                        ");
	drawBase();									// 台描画
	prXY(15,10, L_WHITE, L_BLACK,"         ");	// ゲームオーバ消去
}
void moveBase0(int m){			// ■台移動。m: 正のとき右移動, 負のとき左移動
	eraseBase(); Xp += m; drawBase();
}
void moveBase(){				// ■受け止める台の移動。
	if(kbhit()){
		keyCode = getch();		// キーコード取得
	    if     (keyCode == 'z' || keyCode == 'Z'){ if(Xp >  0) moveBase0(-2);}
	    else if(keyCode == 'x' || keyCode == 'X'){ if(Xp < 36) moveBase0(2);}
	}
}
void eraseBase(){				// ■受け止める台消去
	prXY(Xp, 19,L_WHITE, L_BLACK,"    ");
}
void drawBase(){				// ■受け止める台を描画
	prXY(Xp    , 19, L_WHITE, H_WHITE,"    ");
	prXY(Xp + 1, 19, H_WHITE, L_BLACK,"__");
}
void drawScore(){				// ■得点描画
	char str[100]; sprintf(str,"得点:%02d 最高点:%02d", Score, MaxSc);
	prXY(20, 1, H_YELLOW, L_BLACK, str);
}
void endGame(){					// ■ゲーム終了
	prXY(15, 10, H_RED, L_BLACK,"GAME OVER");	// "GAME OVER" 描画
	if(MaxSc < Score) MaxSc = Score;			// 最高点を保存
	getch(); initGame();						// 初期化する
}
void deleteStone(int i){		// ■i番目の爆弾を非表示
	if(Stone[i].y > 1) prXY(Stone[i].x, Stone[i].y, H_CYAN, L_BLACK,"  ");
	Stone[i].y++;
}
void genStone(int i){			// ■i番目の爆弾生成
	Stone[i].Ex = true; Stone[i].x = (rand() % MAX_GR) * 2; Stone[i].y = 1;
}
void genStone(){				// ■爆弾の生成
	for(int i = 0; i < MAX_ST; i++)
		if(!Stone[i].Ex)	if(rand()<RAND_MAX/3){ genStone(i);	break;}
}
void JadgeCatchStone(int i){	//■爆弾をキャッチしたかどうかの判定
	if(Stone[i].y == 19 && (Stone[i].x == Xp || Stone[i].x == Xp + 2)){
		Stone[i].Ex = false; Score++;	// 爆弾を受け止めたときの処理
		::Beep(5000, 30); drawScore();		// 得点描画
	}
	else{// 爆弾描画と一番下に到達したかどうかの判定
		prXY(Stone[i].x, Stone[i].y, L_RED, L_BLACK,"●");
		if(Stone[i].y == 20){ // 一番下に到達したかどうか
			::Beep(50, 500); Stone[i].Ex = false;
			if(GRND[Stone[i].x >>1]) GRND[Stone[i].x >>1] = false;
			else  endGame(); 
		}
	}
}
void moveStone(){				// ■爆弾の移動
	if(++s_Time == 5){
		s_Time = 0; if(rand() % 4 == 0) genStone();
		for(int i = 0; i < MAX_ST; i++)
			if(Stone[i].Ex){	deleteStone(i);JadgeCatchStone(i);}
	}
}