
#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
#include <time.h>

#define	LIM_left 5				//　左枠の x 座標値 
#define LIM_right 46				//　右枠の x 座標値
						//  プレイヤーは x = 6 〜 44 まで移動可能
						//   y 座標値は 5 〜 35(x -> 60)

int player_x = 24;				//  プレイヤーの初期 x 座標値
int player_y = 30;				//  プレイヤーの初期 y 座標値
int e_pos_x = 0;				//  敵球の x 座標値
int e_pos_y = 0;				//  敵球の y 座標値
int judg_val = 1;
int score = 0;
double score_count = 0.0; 

void set_state(void);				//  初期カーソル位置にカーソルを移動
void set_frame(void);				//　横枠を画面に表示する
void output_howto(void);			//  説明の表示
void start_play(void);				//　ゲームのスタート
 void move_judg(int);				//  どこに動くか判定
  int con_move(int);				//  上下左右の枠内のみで動くよう制御
void make_enemy_ball(void);			//  上から降ってくる球を生成する
 int judg_pos(void);				//  敵との当たり判定
 int rand_val(void);				//  ランダムな 0 〜 38 までの値を生成
void judg_score(void);				// SCORE の表示と判定


int main()
{
	COORD coset;
	HANDLE hOut;
	char ch = 'e';

	hOut = GetStdHandle(STD_OUTPUT_HANDLE);
	
	set_frame();
	output_howto();

	srand((unsigned)time(NULL));

	coset.X = player_x;			//  プレイヤーの初期位置　↓
	coset.Y = player_y;			//			　⇔
	SetConsoleCursorPosition(hOut, coset);	
	puts("●");
	start_play();

	while(1) {
		ch = getch();
		if(ch == 0xd)
			break;
	}
	

	return 0;
}

void set_state(void)
{
	COORD coset;
	HANDLE hOut;

	hOut = GetStdHandle(STD_OUTPUT_HANDLE);
	coset.X = 60;					//  初期カーソル位置の座標	↓
	coset.Y = 20;					//  兼 プレイヤー入力位置の座標	⇔
	SetConsoleCursorPosition(hOut, coset);
}

void set_frame(void)
{
	COORD coset;
	HANDLE hOut;
	int i;

	hOut = GetStdHandle(STD_OUTPUT_HANDLE);

	for (i = 5; i < 36; i++) {
		coset.X = LIM_left;
		coset.Y = i;
		SetConsoleCursorPosition(hOut, coset);
		putchar('|');
	}
	for (i = 5; i < 36; i++) {
		coset.X = LIM_right;
		coset.Y = i;
		SetConsoleCursorPosition(hOut, coset);
		putchar('|');
	}

	set_state();
}

void output_howto(void)
{
	COORD coset;
	HANDLE hOut;
	int i;

	hOut = GetStdHandle(STD_OUTPUT_HANDLE);
	set_state();

	for (i = 10; i < 13; i++) {
		coset.X = 60;
		coset.Y = i;
		SetConsoleCursorPosition(hOut, coset);
		switch (i) {
			case 10: printf("ｽﾍﾟｰｽｷｰホールドで");	break;
			case 11: printf("球が降ってきます。"); break;
			case 12: printf("矢印キーで移動。");	break;
		}
	}
}

void start_play(void)
{
	while (1) {
		set_state();

		make_enemy_ball();
		judg_score();
		if (judg_val == 0)
			return;
	}
}

void move_judg(int a_val)
{
	COORD coset;
	HANDLE hOut;

	hOut = GetStdHandle(STD_OUTPUT_HANDLE);

	switch (a_val) {
		case 0x48:			//  ↑ は16進数値で 48 という値を返す
			if (con_move(a_val) == 1)
				return;
			coset.X = player_x;
			coset.Y = player_y;
			SetConsoleCursorPosition(hOut, coset);
			puts("  ");
			player_y -= 1;
			coset.X = player_x;
			coset.Y = player_y;

			if(judg_pos() == 0) {
			coset.X = e_pos_x - 4;
			coset.Y = e_pos_y;
			SetConsoleCursorPosition(hOut, coset);
			printf("GAME OVER");
			return;
			}

			SetConsoleCursorPosition(hOut, coset);
			puts("●");
			return;
		case 0x50:			//  ↓ は16進数値で 50 という値を返す
			if (con_move(a_val) == 2)
				return;
			coset.X = player_x;
			coset.Y = player_y;
			SetConsoleCursorPosition(hOut, coset);
			puts("  ");
			player_y += 1;
			coset.X = player_x;
			coset.Y = player_y;

			if(judg_pos() == 0) {
			coset.X = e_pos_x - 4;
			coset.Y = e_pos_y;
			SetConsoleCursorPosition(hOut, coset);
			printf("GAME OVER");
			return;
			}

			SetConsoleCursorPosition(hOut, coset);
			puts("●");
			return;
		case 0x4B:			//  ← は16進数値で 4B という値を返す
			if (con_move(a_val) == 3)
				return;
			coset.X = player_x;
			coset.Y = player_y;
			SetConsoleCursorPosition(hOut, coset);
			puts("  ");
			player_x -= 2;
			coset.X = player_x;
			coset.Y = player_y;

			if(judg_pos() == 0) {
			coset.X = e_pos_x - 4;
			coset.Y = e_pos_y;
			SetConsoleCursorPosition(hOut, coset);
			printf("GAME OVER");
			return;
			}

			SetConsoleCursorPosition(hOut, coset);
			puts("●");
			return;
		case 0x4D:			//  → は16進数値で 4D という値を返す
			if (con_move(a_val) == 4)
				return;
			coset.X = player_x;
			coset.Y = player_y;
			SetConsoleCursorPosition(hOut, coset);
			puts("  ");
			player_x += 2;
			coset.X = player_x;
			coset.Y = player_y;

			if(judg_pos() == 0) {
			coset.X = e_pos_x - 4;
			coset.Y = e_pos_y;
			SetConsoleCursorPosition(hOut, coset);
			printf("GAME OVER");
			return;
			}
	
			SetConsoleCursorPosition(hOut, coset);
			puts("●");
			return;
	}
}

int con_move(int a_val)
{
	switch (player_x + player_y) {			//角４隅の動作制御
		case 12:
			if (player_x == 6 && player_y == 6) {
				if (a_val == 0x4B)
					return 3;
				if (a_val == 0x48)
					return 1;
			}
			break;
		case 50:
			if (player_x == 44 && player_y == 6) {
				if (a_val == 0x4D)
					return 4;
				if (a_val == 0x48)
					return 1;
			}
			break;
		case 40:
			if (player_x == 6 && player_y == 34) {
				if (a_val == 0x4B)
					return 3;
				if (a_val == 0x50)
					return 2;
			}
			break;
		case 78:
			if (player_x == 44 && player_y == 34) {
				if (a_val == 0x4D)
					return 4;
				if (a_val == 0x50)
					return 2;
			}
			break;
	}
			
	if (player_y <= 6)				//角４隅以外の上下左右の動作制御
		return 1;
	if (player_y >= 34)
		return 2;
	if (player_x <= LIM_left + 1)
		return 3;
	if (player_x >= LIM_right - 2)
		return 4;

	return 0;
}

void make_enemy_ball(void)
{
	COORD coset;
	HANDLE hOut;
	int move;

	e_pos_y = 5;

	hOut = GetStdHandle(STD_OUTPUT_HANDLE);
	e_pos_x = rand_val();

	for (; e_pos_y < 36; e_pos_y++) {
		set_state();
		if(judg_pos() == 0) {
			coset.X = e_pos_x - 4;
			coset.Y = e_pos_y;
			SetConsoleCursorPosition(hOut, coset);
			printf("GAME OVER");
			return;
		}
		if(kbhit())
			move = getch();
		
		judg_score();
		coset.X = e_pos_x;
		coset.Y = e_pos_y - 2;
		SetConsoleCursorPosition(hOut, coset);
		puts("　");
		coset.X = e_pos_x;
		coset.Y = e_pos_y - 1;
		SetConsoleCursorPosition(hOut, coset);
		puts("  ");		
		coset.X = e_pos_x;
		coset.Y = e_pos_y;
		SetConsoleCursorPosition(hOut, coset);
		puts("○");
		set_state();
		Sleep(30);
		
		if (move == 0x48 || move == 0x50 || move == 0x4B || move == 0x4D) {
			move_judg(move);
			judg_score();
			if (judg_pos() == 0)
				return;
		}
		if (judg_pos() == 0)
		return;

	}
}

int judg_pos(void)
{
	if (e_pos_y == player_y) {					//上から下への衝突判定
		if (e_pos_x == player_x || e_pos_x == player_x - 1 || e_pos_x == player_x + 1)
			return judg_val = 0;
	}
	if (e_pos_x == player_x + 1 || e_pos_x == player_x - 1) {	//左右から右・左への衝突判定
		if (e_pos_y == player_y)
			return judg_val = 0;
	}

	return judg_val;
}

void judg_score(void)
{
	COORD coset;
	HANDLE hOut;

	hOut = GetStdHandle(STD_OUTPUT_HANDLE);
	coset.X = 60;
	coset.Y = 25;
	SetConsoleCursorPosition(hOut, coset);

	printf("SCORE : %d", score);

	score_count += 0.1;
	score += (score_count * 10) / player_y;
}

int rand_val(void)
{
	int r_val, r;

	while(1) {
		if (r = rand()) {
			if(r > 36);
				break;
		}
	}

	r_val = r % 39 + 6;

	return r_val;
}

	
 