// 项目名：废纸上的坦克大战
#include<iostream>
#include<easyx.h>
#include<graphics.h>
#include<ctime>
#include<conio.h>
#include <random>
#include <string>
// 导入 data_config 定义头文件
#include "data_config.h"
// #include "map.h"	// 导入预定义地图头文件
// #include "main.h"	// 导入函数声明头文件

// -------- 添加音效 --------
#include"resource.h"//导入资源之后有一个resource.h头文件 记得加上
#include<Windows.h>
#include<mmsystem.h>
#pragma comment(lib,"winmm.lib")

using namespace std;

void EnemyBulletMove();
void PlayerBulletMove();
int BulletMoveCheck(int dir, bullet bul);
void change();
void EnemiesMove();
void EnemyInit();
void EnemyShoot();
void GameView();
void GameView_ShowBullet();
void GameView_ShowLose();
void GameView_ShowMap();
void GameView_ShowTank();
void GameView_ShowWIN();
void InitMap();
// void InitMap(const int preset_map[50][50]);
bool IsWin();
void Level();
void MemberView();
void MenuView();
void Move();
void PlayerInit();
void PlayerMove();
void PlayerShoot();
int TankMoveCheck(int dir, tank tank);
void Update();

// git 测试


/*
	菜单界面：
	展示进入游戏，设置难度，退出的选项
	用户通过w和s键选择相应的按钮，回车键进入

		进入游戏：
		玩家选择后进入游戏，进入地图，并初始化地图和坦克

		设置难度：
		设置对应的难度进行游戏

		关于开发人员
		玩家点击后进入页面，展示开发人员名单

		退出游戏
		玩家选择后退出游戏

	游戏界面
		展示地图和坦克，与玩家对立方的坦克自动移动和开火
		按下wsad：进行上下左右方向的移动
		按下空格键：对自己正前方发射炮弹
		被击中：扣血
		若有一方无生存坦克，则游戏结束,回到主菜单

	暂停界面
	展示返回游戏和退出游戏按钮，同时游戏暂停
*/

/*
	界面调用
		1、菜单界面
		2、菜单界面调用游戏界面
		3、游戏界面调用暂停界面
		4、暂停界面调用菜单界面
*/

//-----------------view------------------------
/*
	负责人：
	功能：展示进入游戏，设置难度，退出的选项, 关于我们
		进入游戏：
			玩家选择进入游戏时调用游戏界面函数，直接进入游戏。
		设置难度：
			玩家选择设置难度时调用设置页面函数，敌方坦克数量和血量以及攻击力变化：改后端数据。
			设置完之后，需要esc返回主菜单，然后可进入游戏。
		退出游戏：
			玩家选择退出时调用退出函数，直接结束游戏。
		关于我们：
			展示团队信息
		// 游戏运行的最开始页面
*/
void MenuView();

/*
* 游戏界面
	负责人：under a bushel
	功能：
*/
// 每一次，地图与地图每一次状态更新
// 都在一个新地图上进行添加，根据坦克和子弹的坐标：位置和方向
void GameView()   //游戏界面视图
{
	InitMap();  //初始化地图
	// InitMap(map1);  //初始化地图
	EnemyInit();  //初始化敌方坦克的位置
	PlayerInit(); //初始化玩家坦克的位置

	GameView_ShowMap(); //显示地图
	GameView_ShowTank(); //显示坦克

	while (!IsWin())  // 游戏如果还没有胜利
	{
		if (player.hp <= 0)    //判断玩家的生命值是否小于或等于 0
		{
			GameView_ShowLose(); //调用 failView 函数显示失败视图
			/*MenuView();*/   //返回到菜单界面
			break;
		}

		if (GetAsyncKeyState(VK_ESCAPE))  //检测用户输入的键盘事件是否为 ESC 键
		{
			MenuView();  //若是则调用 menuView 函数返回到菜单界面
		}

		Move(); // 调用 Move、Shoot 和 Update 函数，这些函数需要实现坦克和子弹的移动、射击和状态更新。
		//开火
		if(GetAsyncKeyState(VK_SPACE))
			PlayerShoot();
		EnemyShoot();
		// Update();
		Update();
		GameView_ShowMap(); //显示地图的新状态
		GameView_ShowBullet(); //函数用于显示子弹的新状态
		GameView_ShowTank(); //显示坦克的新状态
	}

	if (IsWin())  //如果游戏胜利，则调用 winView 函数显示胜利视图，并返回到菜单界面。
	{
		GameView_ShowWIN();
		/*MenuView();*/
	}
}

/*
	负责人:甄子涵（口水鸡）
	开火
	首先判断玩家子弹是否达到上限，0-3，直接遍历0-3，找到一个is_live == false,break
	玩家在哪，子弹初始化就在哪
*/
void PlayerShoot()
{
	static clock_t start = clock() - 500;
	if ((clock() - start) < 500)
		return;
	start = clock();
	for (int i = 0; i < SINGLE_BULLET; i++)
	{
		if (P_bullets[i].is_live == false)
		{
			//初始化子弹
			P_bullets[i].x = player.x;
			P_bullets[i].y = player.y;
			P_bullets[i].dir = player.dir;
			P_bullets[i].damage = player.attack;
			P_bullets[i].is_live = true;
			break;
		}
	}
}

/*
	负责人:甄子涵（口水鸡）
	输入：敌人结构体数组
	敌人发射子弹，自动发射,遍历敌人坦克
	首先用随机数判断是否要发射，用随机数%2,产生0或1
	if 要发射 ，遍历子弹数组
*/
void EnemyShoot()
{
	static clock_t start = clock() - 3000;
	if ((clock() - start) < 3000)
		return;
	start = clock();
	for (int i = 0; i < ENEMIES_NUM; i++)  //遍历所有敌人坦克
	{
		if (enemies[i].hp > 0) {
			for (auto& j : E_bullets)
			{
				if (j.is_live == false) //只要有一颗子弹不存在，则发射，如果三颗都已经存在，则不发射子弹
				{
					j.x = enemies[i].x;
					j.y = enemies[i].y;
					j.dir = enemies[i].dir;
					j.damage = enemy.attack;
					j.is_live = true;
					break;
				}
			}
		}
	}
}

/*
	负责人:甄子涵（口水鸡）
	功能：
		玩家移动、子弹移动（对子弹击中目标的处理）、各种碰撞检测
*/
void Move()
{
	bool move = false;
	if (GetAsyncKeyState('W') || GetAsyncKeyState(VK_UP))
	{
		player.dir = UP;
		move = true;
	}
	else if (GetAsyncKeyState('S') || GetAsyncKeyState(VK_DOWN))
	{
		player.dir = DOWN;
		move = true;
	}
	else if (GetAsyncKeyState('A') || GetAsyncKeyState(VK_LEFT))
	{
		player.dir = LEFT;
		move = true;
	}
	else if (GetAsyncKeyState('D') || GetAsyncKeyState(VK_RIGHT))
	{
		player.dir = RIGHT;
		move = true;
	};//按键改方向



	if (move) {
		PlayerMove();   //player.dir 是全局变量，不用传参
	}
	EnemiesMove();  //敌人移动是随机的
	PlayerBulletMove();
	EnemyBulletMove();
}

///*
//* 如果玩家方向上前面的一格不是空地
//*/
//bool PlayerCollision();


/*
	负责人：小 yang
	功能：
		根据map数组生成地图
*/
void GameView_ShowMap()	// 坦克是全局的，不需要传参
//void GameView_ShowMap(tank player)
{
	// 开启双缓冲机制
	setbkmode(TRANSPARENT);     // 设置背景透明
	BeginBatchDraw();           // 开始批量绘图

	//获取并加载图片对象
	//路径得整合确定后才能确定，不唯一 ------ “ ”
	IMAGE image_WALL, image_back, image_RED_HP;
	// IMAGE image_WALL, image_back, image_RED_HP, image_BLUE_HP;
	loadimage(&image_WALL, ".//images//wall.jpg", CELL_SIZE, CELL_SIZE);
	loadimage(&image_back, ".//images//游戏主界面背景.jpg", 700, 700);
	loadimage(&image_RED_HP, ".//images//red_hp_bar.jpg", CELL_SIZE, CELL_SIZE);
	// loadimage(&image_BLUE_HP, ".//images//blue_hp.jpg", 30, 30);	// version1版本目前不画敌方的血条

	//背景渲染
	putimage(0, 0, &image_back);

	//红方坦克HP渲染
	for (int i = 0; i < player.hp; i++)
	{
		putimage(100 + i * 30 , 10, &image_RED_HP);
	}

	////蓝方坦克HP渲染
	//for (int j = 0; j < player.hp; j++)
	//{
	//	putimage(570 - j * 30, 120, &image_RED_HP);
	//}

	int dieNum = 0;
	for (auto& i : enemies) {
		if (i.hp <= 0) dieNum++;
	}
	//击败显示实时渲染
	settextcolor((157, 157, 157));
	settextstyle(30, 0, "方正舒体");
	outtextxy(110, 660, "击败：");
	outtextxy(185, 660, to_string(dieNum).data());
	outtextxy(210, 660, "/");
	outtextxy(225, 660, "10");

	outtextxy(325, 660, string("攻击力：" + to_string(player.attack)).data());


	//墙体的渲染
	for (int i = 0; i < MAP_CELL_NUM; i++)
	{
		for (int j = 0; j < MAP_CELL_NUM; j++)
		{
			if (map[i][j] == WALL)
			{
				putimage(j * CELL_SIZE + X_OFFSET, i * CELL_SIZE + Y_OFFSET, &image_WALL);
			}
		}
	}
}


/*
	负责人：
	功能：输出炮弹贴图
*/
// void GameView_ShowBullet();
// void GameView_ShowBullet(bullet b);

/*
	负责人：小 yang
	功能：输出坦克贴图

*/
void GameView_ShowTank()
// void GameView_ShowTank(tank player, tank enemies[])
{
	// 开启双缓冲机制
	setbkmode(TRANSPARENT);     // 设置背景透明
	BeginBatchDraw();           // 开始批量绘图

	//设置坦克图片对象
	IMAGE image_REDtank_UP[2], image_REDtank_DOWN[2], image_REDtank_LEFT[2], image_REDtank_RIGHT[2],

		image_BLUEtank_UP[2], image_BLUEtank_DOWN[2], image_BLUEtank_LEFT[2], image_BLUEtank_RIGHT[2],

		image_BLUE_DEADtank[2];

	//加载地图
	//路径得整合确定后才能确定，不唯一 ------ “ ”

	loadimage(&image_REDtank_DOWN[White], ".//images//red_down_w.png", CELL_SIZE, CELL_SIZE);
	loadimage(&image_REDtank_DOWN[Black], ".//images//red_down_b.png", CELL_SIZE, CELL_SIZE);

	loadimage(&image_REDtank_UP[White], ".//images//red_up_w.png", CELL_SIZE, CELL_SIZE);
	loadimage(&image_REDtank_UP[Black], ".//images//red_up_b.png", CELL_SIZE, CELL_SIZE);

	loadimage(&image_REDtank_LEFT[White], ".//images//red_left_w.png", CELL_SIZE, CELL_SIZE);
	loadimage(&image_REDtank_LEFT[Black], ".//images//red_left_b.png", CELL_SIZE, CELL_SIZE);

	loadimage(&image_REDtank_RIGHT[White], ".//images//red_right_w.png", CELL_SIZE, CELL_SIZE);
	loadimage(&image_REDtank_RIGHT[Black], ".//images//red_right_b.png", CELL_SIZE, CELL_SIZE);


	loadimage(&image_BLUEtank_UP[White], ".//images//blue_up_w.png", CELL_SIZE, CELL_SIZE);
	loadimage(&image_BLUEtank_UP[Black], ".//images//blue_up_b.png", CELL_SIZE, CELL_SIZE);

	loadimage(&image_BLUEtank_DOWN[White], ".//images//blue_down_w.png", CELL_SIZE, CELL_SIZE);
	loadimage(&image_BLUEtank_DOWN[Black], ".//images//blue_down_b.png", CELL_SIZE, CELL_SIZE);

	loadimage(&image_BLUEtank_LEFT[White], ".//images//blue_left_w.png", CELL_SIZE, CELL_SIZE);
	loadimage(&image_BLUEtank_LEFT[Black], ".//images//blue_left_b.png", CELL_SIZE, CELL_SIZE);

	loadimage(&image_BLUEtank_RIGHT[White], ".//images//blue_right_w.png", CELL_SIZE, CELL_SIZE);
	loadimage(&image_BLUEtank_RIGHT[Black], ".//images//blue_right_b.png", CELL_SIZE, CELL_SIZE);

	// loadimage(&image_RED_DEADtank, "./报废坦克.png", CELL_SIZE, CELL_SIZE); // 玩家坦克报废后即意味着游戏结束，直接弹出游戏失败页面，因此不需要显示自己的报废状态
	loadimage(&image_BLUE_DEADtank[White], ".//images//dead_tank_w.png", CELL_SIZE, CELL_SIZE);
	loadimage(&image_BLUE_DEADtank[Black], ".//images//dead_tank_b.png", CELL_SIZE, CELL_SIZE);
	//loadimage(&image_BLANK, ".//images//blank.jpg", CELL_SIZE, CELL_SIZE);




	//渲染地图元素
	for (int i = 0; i < MAP_CELL_NUM; i++)
	{
		for (int j = 0; j < MAP_CELL_NUM; j++)
		{
			//if (map[i][j] == BLANK)
			//{
			//	 putimage(j * CELL_SIZE + X_OFFSET, i * CELL_SIZE + Y_OFFSET, &image_BLANK); // 内图
			//}

			if ((map[i][j] == RED_TANK && player.dir == LEFT))
			{
				putimage(player.x * CELL_SIZE + X_OFFSET, player.y * CELL_SIZE + Y_OFFSET, &image_REDtank_LEFT[White], SRCAND);
				putimage(player.x * CELL_SIZE + X_OFFSET, player.y * CELL_SIZE + Y_OFFSET, &image_REDtank_LEFT[Black], SRCPAINT);
			}

			if (map[i][j] == RED_TANK && player.dir == RIGHT)
			{
				putimage(player.x * CELL_SIZE + X_OFFSET, player.y * CELL_SIZE + Y_OFFSET, &image_REDtank_RIGHT[White], SRCAND);
				putimage(player.x * CELL_SIZE + X_OFFSET, player.y * CELL_SIZE + Y_OFFSET, &image_REDtank_RIGHT[Black], SRCPAINT);
			}

			if (map[i][j] == RED_TANK && player.dir == DOWN)
			{
				putimage(player.x * CELL_SIZE + X_OFFSET, player.y * CELL_SIZE + Y_OFFSET, &image_REDtank_DOWN[White], SRCAND);
				putimage(player.x * CELL_SIZE + X_OFFSET, player.y * CELL_SIZE + Y_OFFSET, &image_REDtank_DOWN[Black], SRCPAINT);
			}

			if (map[i][j] == RED_TANK && player.dir == UP)
			{
				putimage(player.x * CELL_SIZE + X_OFFSET, player.y * CELL_SIZE + Y_OFFSET, &image_REDtank_UP[White], SRCAND);
				putimage(player.x * CELL_SIZE + X_OFFSET, player.y * CELL_SIZE + Y_OFFSET, &image_REDtank_UP[Black], SRCPAINT);
			}

			//if (map[i][j] == RED_DEAD_TANK)
			//{

			//	putimage(j * CELL_SIZE + X_OFFSET, i * CELL_SIZE + Y_OFFSET, &image_RED_DEADtank);
			//}
		}
	}

	//渲染蓝方坦克
	for (int i = 0; i < ENEMIES_NUM; i++)
	{
		if (enemies[i].is_taken)
			continue;
		if (enemies[i].hp > 0) {
			switch (enemies[i].dir)
			{
			case UP:
				putimage(enemies[i].x * CELL_SIZE + X_OFFSET, enemies[i].y * CELL_SIZE + Y_OFFSET, &image_BLUEtank_UP[White], SRCAND);
				putimage(enemies[i].x * CELL_SIZE + X_OFFSET, enemies[i].y * CELL_SIZE + Y_OFFSET, &image_BLUEtank_UP[Black], SRCPAINT);
				break;
			case DOWN:
				putimage(enemies[i].x * CELL_SIZE + X_OFFSET, enemies[i].y * CELL_SIZE + Y_OFFSET, &image_BLUEtank_DOWN[White], SRCAND);
				putimage(enemies[i].x * CELL_SIZE + X_OFFSET, enemies[i].y * CELL_SIZE + Y_OFFSET, &image_BLUEtank_DOWN[Black], SRCPAINT);
				break;
			case LEFT:
				putimage(enemies[i].x * CELL_SIZE + X_OFFSET, enemies[i].y * CELL_SIZE + Y_OFFSET, &image_BLUEtank_LEFT[White], SRCAND);
				putimage(enemies[i].x * CELL_SIZE + X_OFFSET, enemies[i].y * CELL_SIZE + Y_OFFSET, &image_BLUEtank_LEFT[Black], SRCPAINT);
				break;
			case RIGHT:
				putimage(enemies[i].x * CELL_SIZE + X_OFFSET, enemies[i].y * CELL_SIZE + Y_OFFSET, &image_BLUEtank_RIGHT[White], SRCAND);
				putimage(enemies[i].x * CELL_SIZE + X_OFFSET, enemies[i].y * CELL_SIZE + Y_OFFSET, &image_BLUEtank_RIGHT[Black], SRCPAINT);
				break;
			default:
				break;
			}
		}
		else {
			putimage(enemies[i].x * CELL_SIZE + X_OFFSET, enemies[i].y * CELL_SIZE + Y_OFFSET, &image_BLUE_DEADtank[White], SRCAND);
			putimage(enemies[i].x * CELL_SIZE + X_OFFSET, enemies[i].y * CELL_SIZE + Y_OFFSET, &image_BLUE_DEADtank[Black], SRCPAINT);
		}
	}

	  // 结束批量绘图并显示图像
    EndBatchDraw();             // 结束批量绘图
}


IMAGE image_BULLET[4][2];

void GameView_ShowBullet()
{
	bool b = true;
	if (b) {
		b = false;
		loadimage(&image_BULLET[UP][White], ".//images//B_UP_w.png", CELL_SIZE / 2 / 2, CELL_SIZE / 2);
		loadimage(&image_BULLET[UP][Black], ".//images//B_UP_b.png", CELL_SIZE / 2 / 2, CELL_SIZE / 2);
		loadimage(&image_BULLET[DOWN][White], ".//images//B_DOWN_w.png", CELL_SIZE / 2 / 2, CELL_SIZE / 2);
		loadimage(&image_BULLET[DOWN][Black], ".//images//B_DOWN_b.png", CELL_SIZE / 2 / 2, CELL_SIZE / 2);
		loadimage(&image_BULLET[LEFT][White], ".//images//B_LEFT_w.png", CELL_SIZE / 2, CELL_SIZE / 2 / 2);
		loadimage(&image_BULLET[LEFT][Black], ".//images//B_LEFT_b.png", CELL_SIZE / 2, CELL_SIZE / 2 / 2);
		loadimage(&image_BULLET[RIGHT][White], ".//images//B_RIGHT_w.png", CELL_SIZE / 2, CELL_SIZE / 2 / 2);
		loadimage(&image_BULLET[RIGHT][Black], ".//images//B_RIGHT_b.png", CELL_SIZE / 2, CELL_SIZE / 2 / 2);
	}
	for (int i = 0; i < BULLET_NUM; i++) {  //绘制玩家子弹
		if (P_bullets[i].is_live) {
			int x = P_bullets[i].x * CELL_SIZE + X_OFFSET;
			int y = P_bullets[i].y * CELL_SIZE + Y_OFFSET;
			putimage((P_bullets[i].dir > DOWN ? x : x + 10.5), (P_bullets[i].dir > DOWN ? y + 10.5 : y), &image_BULLET[P_bullets[i].dir][White], SRCAND);
			putimage((P_bullets[i].dir > DOWN ? x : x + 10.5), (P_bullets[i].dir > DOWN ? y + 10.5 : y), &image_BULLET[P_bullets[i].dir][Black], SRCPAINT);
		}
	}
	for (int i = 0; i < BULLET_NUM * ENEMIES_NUM; i++) {  //绘制敌方子弹
		if (E_bullets[i].is_live) {
			int x = E_bullets[i].x * CELL_SIZE + X_OFFSET;
			int y = E_bullets[i].y * CELL_SIZE + Y_OFFSET;
			putimage((E_bullets[i].dir > DOWN ? x : x + 10.5), (E_bullets[i].dir > DOWN ? y + 10.5 : y), &image_BULLET[E_bullets[i].dir][White], SRCAND);
			putimage((E_bullets[i].dir > DOWN ? x : x + 10.5), (E_bullets[i].dir > DOWN ? y + 10.5 : y), &image_BULLET[E_bullets[i].dir][Black], SRCPAINT);
		}
	}

	/*for (int i = 0; i < 50; i++)
	{
		for (int j = 0; j < 50; j++)
		{
			if (map[i][j] == BULLET && bullets[i].dir == UP)
			{
				putimage(j * PIEXL1 + X + (PIEXL1 - PIEXL2) / 2, i * PIEXL1 + (PIEXL1 - PIEXL2) / 2, &image_BULLET_UP);
			}
			if (map[i][j] == BULLET && BULLET.dir == DOWN)
			{
				putimage(j * PIEXL1 + X + (PIEXL1 - PIEXL2) / 2, i * PIEXL1 + (PIEXL1 - PIEXL2) / 2, &image_BULLET_DOWN);
			}
			if (map[i][j] == BULLET && BULLET.dir == RIGHT)
			{
				putimage(j * PIEXL1 + X + (PIEXL1 - PIEXL2) / 2, i * PIEXL1 + (PIEXL1 - PIEXL2) / 2, &image_BULLET_RIGHT);
			}
			if (map[i][j] == BULLET && BULLET.dir == LEFT)
			{
				putimage(j * PIEXL1 + X + (PIEXL1 - PIEXL2) / 2, i * PIEXL1 + (PIEXL1 - PIEXL2) / 2, &image_BULLET_LEFT);
			}
		}
	}*/
}

/*
	负责人：布泣
	功能：输出胜利界面
*/
void GameView_ShowWIN()
{
	cleardevice();
	setbkmode(TRANSPARENT);
	IMAGE img;
	loadimage(&img, ".//images//胜利.png", 700, 700);
	putimage(0, 0, &img);
	IMAGE img_back;
	loadimage(&img_back, ".//images//返回按钮.jpg", 150, 50);
	putimage(30, 550, &img_back);
	//键盘鼠标操作
	ExMessage msg;
	while (true)
	{
		//键盘操作
		if (_kbhit())
		{
			char key = _getch();//阻塞函数，不输入一直等
			//printf("%d,%c\n", key, key);
			switch (key)
			{
			case 27://上键
				//返回菜单界面
				MenuView();
				//printf("返回菜单界面/n");
				return;
				break;
			}
		}

		//鼠标操作
		if (peekmessage(&msg, WH_MOUSE))
		{
			switch (msg.message)
			{
			case WM_LBUTTONDOWN:

				//返回到菜单界面
				if (msg.x >= 30 && msg.x <= 180 && msg.y >= 550 && msg.y <= 600)
				{
					MenuView();
					return;
					//printf("返回到菜单界面\n");
					//跳转到设置难度界面
				}
				break;
			default:
				break;
			}
		}
	}
	//char s[] = "按任意键返回主菜单";
	//outtextxy(250, 400, s);
	//_getch();
}

/*
	负责人：布泣
	功能：输出失败界面

*/

void GameView_ShowLose()
{
	cleardevice();
	setbkmode(TRANSPARENT);
	IMAGE img;
	loadimage(&img, ".//images//失败.png", 700, 700);
	putimage(0, 0, &img);
	IMAGE img_back;
	loadimage(&img_back, ".//images//返回按钮.jpg", 150, 50);
	putimage(30, 550, &img_back);
	//键盘鼠标操作
	ExMessage msg;
	while (true)
	{
		//键盘操作
		if (_kbhit())
		{
			char key = _getch();//阻塞函数，不输入一直等
			//printf("%d,%c\n", key, key);
			switch (key)
			{
			case 27://上键
				//返回菜单界面
				MenuView();
				//printf("返回菜单界面/n");
				return;
				break;
			}
		}

		//鼠标操作
		if (peekmessage(&msg, WH_MOUSE))
		{
			switch (msg.message)
			{
			case WM_LBUTTONDOWN:

				//返回到菜单界面
				if (msg.x >= 30 && msg.x <= 180 && msg.y >= 550 && msg.y <= 600)
				{
					MenuView();
					return;
					//printf("返回到菜单界面\n");
					//跳转到设置难度界面
				}
				break;
			default:
				break;
			}
		}
	}
	//char s[] = "按任意键返回主菜单";
	//outtextxy(250, 400, s);
	//_getch();
}

//------------------view-------------------

//-------------------service---------------

/*
* 刷新地图
*/
 void Update()
{
	 InitMap();		//用原有的地图数据覆盖一遍map

	 map[player.x][player.y] = RED_TANK;	//遍历玩家、敌人、子弹数组，根据位置信息写入到地图
	 
	 for (int i = 0; i < ENEMIES_NUM; i++) {  
		 if (enemies[i].hp > 0) {
			 map[enemies[i].x][enemies[i].y] = BLUE_TANK;
		 }
		 else if (enemies[i].hp <= 0 && enemies[i].is_taken == false) {
			 map[enemies[i].x][enemies[i].y] = BLUE_DEAD_TANK;
		 }
	 }

	 //for (int j = 0; j < BULLET_NUM; j++) {       //玩家子弹
		// if (P_bullets[j].is_live == true) {
		//	 map[enemies[j].x][enemies[j].y] = BULLET;
		// }
	 //}

	 //for (int k = 0; k < BULLET_NUM * ENEMIES_NUM; k++) {       //敌方子弹
		// if (E_bullets[k].is_live == true) {
		//	 map[enemies[k].x][enemies[k].y] = BULLET;
		// }
	 //}
}

/*
	负责人：刘博
	功能：初始化为仅四周有墙的空白地图
*/
void InitMap()
{
	// 初始化地图
	for (int i = 0; i < MAP_CELL_NUM; i++) {
		for (int j = 0; j < MAP_CELL_NUM; j++) {
			// 如果是四周的位置，设定为 WALL
			if (i == 0 || i == MAP_CELL_NUM - 1 || j == 0 || j == MAP_CELL_NUM - 1) {
				map[i][j] = WALL;
			}
			// 其他位置设定为 BLANK
			else {
				map[i][j] = BLANK;
			}
		}
	}
}

/*
	负责人：刘博
	功能：拓展版的地图初始化，调用map.h文件传入地图数组
*/
//void InitMap(const int preset_map[MAP_CELL_NUM][MAP_CELL_NUM]) {
//	for (int i = 0; i < MAP_CELL_NUM; i++) {
//		for (int j = 0; j < MAP_CELL_NUM; j++) {
//			map[i][j] = preset_map[i][j];
//		}
//	}
//}

/*
	负责人：丧丧超人
	功能：
		接收方向参数，判断坦克移动的可行性
		实现坦克移动
*/
void PlayerMove() {
	static clock_t start = clock() - 100;
	if ((clock() - start) < 100)
		return;
	start = clock();
	if (player.dir == UP) {
		switch (TankMoveCheck(player.dir, player)) {	//空地,敌方坦克,子弹,敌方报废坦克,墙
		case BLANK:
			player.y--;
			break;
		case BULLET:
			player.y--;
			player.hp--;
			for (int i = 0; i <= BULLET_NUM * ENEMIES_NUM; i++) {		//找出哪颗子弹让其报销
				if (E_bullets[i].x == player.x && E_bullets[i].y == player.y) {
					E_bullets[i].is_live = false;
				}
			}
			break;
		case BLUE_DEAD_TANK:
			player.y--;
			player.attack++;
			if(player.hp < 5) player.hp++;
			for (int i = 0; i < ENEMIES_NUM; i++) {			//循环遍历坦克数组
				if (player.x == enemies[i].x && player.y == enemies[i].y) //找该位置是哪辆坦克
					enemies[i].is_taken = true;
			}
			break;
		default:
			break;
		}
		
			
	}
	else if (player.dir == DOWN) {
		switch (TankMoveCheck(player.dir, player)) {	//空地,敌方坦克,子弹,敌方报废坦克,墙
		case BLANK:
			player.y++;
			break;
		case BULLET:
			player.y++;
			player.hp--;
			for (int i = 0; i <= BULLET_NUM * ENEMIES_NUM; i++) {		//找出哪颗子弹让其报销
				if (E_bullets[i].x == player.x && E_bullets[i].y == player.y) {
					E_bullets[i].is_live = false;
				}
			}
			break;
		case BLUE_DEAD_TANK:
			player.y++;
			player.attack++;
			if (player.hp < 5) player.hp++;
			for (int i = 0; i < ENEMIES_NUM; i++) {			//循环遍历坦克数组
				if (player.x == enemies[i].x && player.y == enemies[i].y) //找该位置是哪辆坦克
					enemies[i].is_taken = true;
			}
			break;
		default:
			break;
		}
	}
	else if (player.dir == LEFT) {
		switch (TankMoveCheck(player.dir, player)) {	//空地,敌方坦克,子弹,敌方报废坦克,墙
		case BLANK:
			player.x--;
			break;
		case BULLET:
			player.x--;
			player.hp--;
			for (int i = 0; i <= BULLET_NUM * ENEMIES_NUM; i++) {		//找出哪颗子弹让其报销
				if (E_bullets[i].x == player.x && E_bullets[i].y == player.y) {
					E_bullets[i].is_live = false;
				}
			}
			break;
		case BLUE_DEAD_TANK:
			player.x--;
			player.attack++;
			if (player.hp < 5) player.hp++;
			for (int i = 0; i < ENEMIES_NUM; i++) {			//循环遍历坦克数组
				if (player.x == enemies[i].x && player.y == enemies[i].y) //找该位置是哪辆坦克
					enemies[i].is_taken = true;
			}
			break;
		default:
			break;
		}
	}
	else if (player.dir == RIGHT) {
		switch (TankMoveCheck(player.dir, player)) {	//空地,敌方坦克,子弹,敌方报废坦克,墙
		case BLANK:
			player.x++;
			break;
		case BULLET:
			player.x++;
			player.hp--;
			for (int i = 0; i <= BULLET_NUM * ENEMIES_NUM; i++) {		//找出哪颗子弹让其报销
				if (E_bullets[i].x == player.x && E_bullets[i].y == player.y) {
					E_bullets[i].is_live = false;
				}
			}
			break;
		case BLUE_DEAD_TANK:
			player.x++;
			player.attack++;
			if (player.hp < 5) player.hp++;
			for (int i = 0; i < ENEMIES_NUM; i++) {			//循环遍历坦克数组
				if (player.x == enemies[i].x && player.y == enemies[i].y) //找该位置是哪辆坦克
					enemies[i].is_taken = true;
			}
			break;
		default:
			break;
		}
	}
}//撞到墙和敌方坦克坦克不会移动，不做修改

/*
	负责人：丧丧超人
	功能：坦克碰撞检测：检测是否碰到墙、敌方报废坦克、敌方坦克、空地
	针对不同的情况进行不同的处理
	0->空地、1->表示墙、2->玩家坦克、3->敌人坦克、4->报废坦克
	根据下一步位置的坐标（根据player.dir可算），检测该坐标上是什么情况
*/
int TankMoveCheck(int dir, tank tank) {	//坦克能否移动检测,返回检测位置存储的枚举值
	int ret = 0; // 默认返回值为 0
	switch (dir) {
	case UP:
		return map[tank.x][tank.y - 1];
		break;
	case DOWN:
		return map[tank.x][tank.y + 1];
		break;
	case LEFT:
		return map[tank.x - 1][tank.y];
		break;
	case RIGHT:
		return map[tank.x + 1][tank.y];
		break;
	default: // 添加默认分支
		break;
	}
	return ret;
}

/*
	负责人：康宝
	功能：接受子弹数组，对每一个子弹进行处理
	首先肯定得计算它的末状态位置，（1，2）-》（1，5）：（1，2）、（1，3）、（1，4）、（1，5）
	子弹碰撞检测：检测是否碰到墙、敌方报废坦克、敌方坦克、玩家子弹、敌方子弹、空地、玩家坦克。
*/

/*
	负责人：康宝
*/
int BulletMoveCheck(int dir, bullet bul) //返回当前目标区域的map数组值
{
	int ret = 0; // 默认返回值为 0
	switch (dir) {
	case UP:
		return map[bul.x][bul.y - 1];
		break;
	case DOWN:
		return map[bul.x][bul.y + 1];
		break;
	case LEFT:
		return map[bul.x - 1][bul.y];
		break;
	case RIGHT:
		return map[bul.x + 1][bul.y];
		break;
	default: // 添加默认分支
		return ret;
		break;
	}
}

/*
	负责人：丧丧超人
	功能：
		随机移动，wasd，随机生成数，对4进行取模0123
		方向定了之后-》先判断下一个位置的状态，然后进行相应操作
		延时移动，改变方向，判断敌人移动的可行性实现敌人移动
*/
void EnemiesMove() { //传入关卡敌人数量
	static clock_t start = clock() - 1000;
	if((clock() - start) < 1000)
		return;
	start = clock();
	for (int i = 0; i < ENEMIES_NUM; ++i) {	//n辆敌方坦克移动
		if (enemies[i].hp <= 0)
			continue;
		int dir = rand() % 4;		//随机生成敌方坦克的移动方向
		if (dir == UP) {		//0向上
			enemies[i].dir = UP;	// 将当前 enemies[i] 的方向存下来
			switch (TankMoveCheck(dir, enemies[i])) {	//空地,敌方坦克,子弹,墙
			case BLANK:
				enemies[i].y--;
				break;
			case BULLET:
				enemies[i].y--;
				for (int i = 0; i < BULLET_NUM; i++) {			//遍历玩家子弹部分
					if (P_bullets[i].x == enemies[i].x && P_bullets[i].y == enemies[i].y) {
						P_bullets[i].is_live = false;
						enemies[i].hp--;
					}
				}
				break;
			}
		}
		else if (dir == DOWN) {		//1向下
			enemies[i].dir = DOWN;
			switch (TankMoveCheck(dir, enemies[i])) {	//空地,敌方坦克,子弹,墙
			case BLANK:
				enemies[i].y++;
				break;
			case BULLET:
				enemies[i].y++;
				for (int i = 0; i < BULLET_NUM; i++) {			//遍历玩家子弹部分
					if (P_bullets[i].x == enemies[i].x && P_bullets[i].y == enemies[i].y) {
						P_bullets[i].is_live = false;
						enemies[i].hp--;
					}
				}
				break;
			}
		}
		else if (dir == LEFT) {		//2向左
			enemies[i].dir = LEFT;
			switch (TankMoveCheck(dir, enemies[i])) {	//空地,敌方坦克,子弹，墙
			case BLANK:
				enemies[i].x--;
				break;
			case BULLET:
				enemies[i].x--;
				for (int i = 0; i < BULLET_NUM; i++) {			//遍历玩家子弹部分
					if (P_bullets[i].x == enemies[i].x && P_bullets[i].y == enemies[i].y) {
						P_bullets[i].is_live = false;
						enemies[i].hp--;
					}
				}
				break;
			}
		}
		else if (dir == RIGHT) {		//3向右
			enemies[i].dir = RIGHT;
			switch (TankMoveCheck(dir, enemies[i])) {	//空地,敌方坦克,子弹,墙
			case BLANK:
				enemies[i].x++;
				break;
			case BULLET:
				enemies[i].x++;
				for (int i = 0; i < BULLET_NUM; i++) {			//遍历玩家子弹部分
					if (P_bullets[i].x == enemies[i].x && P_bullets[i].y == enemies[i].y) {
						P_bullets[i].is_live = false;
						enemies[i].hp--;
					}
				}
				break;
			}
		}
	}
}

/*
	负责人：康宝
	功能：
		接收方向参数，根据BulletMoveCheck()
函数的返回值判断子弹移动的情况
		实现子弹移动
*/

void PlayerBulletMove() {
	static clock_t start = clock() - 100;
	if ((clock() - start) < 100)
		return;
	start = clock();

	int arr[4][2] = {
		{0, -1},
		{0, 1},
		{-1, 0},
		{1, 0},
	};
	for (int i = 0; i < BULLET_NUM; i++)  // 玩家子弹
	{
		if (P_bullets[i].is_live == false)
		{
			continue;
		}
		else
		{
			// 子弹碰撞检测：检测是否碰到空地、墙、玩家坦克、敌方坦克、敌方报废坦克、玩家子弹、敌方子弹。
				// 0->空地、1->表示墙、2->玩家坦克、3->敌人坦克、4->报废坦克、5->我方子弹、6->敌方子弹
				// 0 空地 1 墙 3 敌方坦克 6 敌方子弹
			int type = BulletMoveCheck(P_bullets[i].dir, P_bullets[i]);
			if (type == BLANK)
			{
				P_bullets[i].x += arr[P_bullets[i].dir][0];
				P_bullets[i].y += arr[P_bullets[i].dir][1];
			}
			else if (type == WALL)
			{
				P_bullets[i].is_live = false;
			}
			else if (type == BLUE_TANK)    //敌方坦克
			{
				P_bullets[i].is_live = false;				//子弹销毁
				for (int k = 0; k < ENEMIES_NUM; k++)	//坦克遍历
				{
					switch (P_bullets[i].dir) {
					case UP:
						if (enemies[k].x == P_bullets[i].x && enemies[k].y == P_bullets[i].y - 1)	//检测上方敌方坦克是哪辆
						{
							enemies[k].hp -= P_bullets[i].damage;
						}
						break;
					case DOWN:
						if (enemies[k].x == P_bullets[i].x && enemies[k].y == P_bullets[i].y + 1)	//检测上方敌方坦克是哪辆
						{
							enemies[k].hp -= P_bullets[i].damage;
						}
						break;
					case LEFT:
						if (enemies[k].x == P_bullets[i].x - 1 && enemies[k].y == P_bullets[i].y)	//检测上方敌方坦克是哪辆
						{
							enemies[k].hp -= P_bullets[i].damage;
						}
						break;
					case RIGHT:
						if (enemies[k].x == P_bullets[i].x + 1 && enemies[k].y == P_bullets[i].y)	//检测上方敌方坦克是哪辆
						{
							enemies[k].hp -= P_bullets[i].damage;
						}
						break;
					default: // 添加默认分支
						break;
					}

				}
			}
			else
			{
				P_bullets[i].is_live = false;
				if (BULLET_NUM == 2)
				{
					for (int k = 3; k <= 8; k++)
					{
						if (P_bullets[k].x == P_bullets[i].x && P_bullets[k].y == P_bullets[i].y)
						{
							P_bullets[k].is_live = false;
							break;
						}
					}
				}
				else
				{
					for (int k = 3; k <= 12; k++)
					{
						if (P_bullets[k].x == P_bullets[i].x && P_bullets[k].y == P_bullets[i].y)
						{
							P_bullets[k].is_live = false;
							break;
						}
					}
				}
				break;
			}
		}
	}
}

void EnemyBulletMove() {
	static clock_t start = clock() - 500;
	if ((clock() - start) < 500)
		return;
	start = clock();

	int arr[4][2] = {
		{0, -1},
		{0, 1},
		{-1, 0},
		{1, 0},
	};
	for (auto& i : E_bullets) {
		if (i.is_live) {
			int type = BulletMoveCheck(i.dir, i);
			if (type == BLANK)
			{
				i.x += arr[i.dir][0];
				i.y += arr[i.dir][1];
			}
			else if (type == WALL)
			{
				i.is_live = false;
			}
			else if (type == RED_TANK)
			{
				i.is_live = false;
				player.hp -= i.damage;
			}
			else {
				i.x += arr[i.dir][0];
				i.y += arr[i.dir][1];
			}
			/*else
			{
				i.is_live = false;
				if (BULLET_NUM == 2)
				{
					for (int k = 3; k <= 8; k++)
					{
						if (P_bullets[k].x == i.x && P_bullets[k].y == i.y)
						{
							P_bullets[k].is_live = false;
							break;
						}
					}
				}
				else
				{
					for (int k = 3; k <= 12; k++)
					{
						if (P_bullets[k].x == i.x && P_bullets[k].y == i.y)
						{
							P_bullets[k].is_live = false;
							break;
						}
					}
				}
				break;
			}*/
		}
	}
}
/*
	负责人：刘博
	功能：生成玩家坦克
*/
void PlayerInit()
{
	player.x = MAP_CELL_NUM / 2;	// 玩家坐标初始化
	player.y = MAP_CELL_NUM / 2;
	player.hp = 5;	// 玩家血量初始化
	player.dir = UP;	// 初始化玩家方向朝右
	player.attack = 5;	// 初始化玩家攻击力为 5
	kill = 0;			// 玩家初始击杀数为 0
	map[player.x][player.y] = RED_TANK;	// 在地图上标记玩家坦克的位置
}

/*
	负责人：刘博
	功能：生成敌方坦克
*/
void EnemyInit()
{
	srand((unsigned int)time(NULL));	 //生成随机数种子
	// 使用 <random> 库创建随机数生成器
	//default_random_engine generator;
	//uniform_int_distribution<int> distribution(0, 49); // 创建一个均匀分布的随机数生成器，生成的随机数范围在1-48

	// 初始化敌人坦克
	for (int i = 0; i < ENEMIES_NUM; i++) {
		enemies[i].x = rand() % (MAP_CELL_NUM - 2) + 1 ; // 使用生成器生成随机坐标
		enemies[i].y = rand() % (MAP_CELL_NUM - 2) + 1;

		// 如果生成的位置上已经有坦克或者墙，那么重新生成
		while (map[enemies[i].x][enemies[i].y] != BLANK) {
			enemies[i].x = rand() % (MAP_CELL_NUM - 2) + 1;
			enemies[i].y = rand() % (MAP_CELL_NUM - 2) + 1;
		}

		enemies[i].hp = enemy.hp; // 假设敌人初始血量为5
		enemies[i].attack = enemy.attack; // 假设敌人初始攻击力为1
		enemies[i].dir = LEFT; // 假设敌人初始面朝左
		map[enemies[i].x][enemies[i].y] = BLUE_TANK; // 在地图上标记敌人位置
	}
}

/*
	负责人：布泣
	功能：
		返回值为假:说明失败：玩家坦克hp<=0，或者还没结束，正在玩：玩家坦克hp>0,敌方坦克数量>0
		返回值为真：说明赢了 玩家坦克hp==0,敌方坦克数量==0
*/
bool IsWin() {
	bool all_die = true;
	for (auto& i : enemies) {
		if (i.hp > 0)
			all_die = false;
	}
	if (player.hp > 0 && all_die) {
		return true;	// 胜利
	}
	else return false;	// 没胜利（“失败” 或者 “还在游戏中”）
}

// 汪禹良
void Level()
{
	cleardevice();
	IMAGE img_memberview;
	loadimage(&img_memberview, ".//images//游戏主界面背景.jpg", 700, 700);
	putimage(0, 0, &img_memberview);

	IMAGE img_easy;
	loadimage(&img_easy, ".//images//简单难度.jpg", 150, 100);
	putimage(275, 150, &img_easy);

	IMAGE img_middle;
	loadimage(&img_middle, ".//images//中等难度.jpg", 150, 100);
	putimage(275, 300, &img_middle);

	IMAGE img_difficult;
	loadimage(&img_difficult, ".//images//困难难度.jpg", 150, 100);
	putimage(275, 450, &img_difficult);

	//鼠标键盘操作
	ExMessage msg;
	while (true)
	{
		//键盘操作
		if (_kbhit())
		{
			char key = _getch();//阻塞函数，不输入一直等
			//printf("%d,%c\n", key, key);
			switch (key)
			{
			case 27://上键
				//返回菜单界面
				MenuView();
				//printf("返回菜单界面/n");
				return;
				break;
			}
		}

		//鼠标操作
		if (peekmessage(&msg, WH_MOUSE))
		{
			switch (msg.message)
			{
			case WM_LBUTTONDOWN:

				//选择简单难度
				if (msg.x >= 275 && msg.x <= 425 && msg.y >= 150 && msg.y <= 250)
				{
					enemy.hp = 5;
					enemy.attack = 1;
					//printf("简单难度\n");
					MenuView();
					//printf("返回菜单界面/n");
					return;
				}
				//选择中等难度
				if (msg.x >= 275 && msg.x <= 425 && msg.y >= 300 && msg.y <= 400)
				{
					enemy.hp = 10;
					enemy.attack = 2;
					//printf("中等难度\n");
					MenuView();
					//printf("返回菜单界面/n");
					return;
				}
				//选择困难难度
				if (msg.x >= 275 && msg.x <= 425 && msg.y >= 450 && msg.y <= 550)
				{
					enemy.hp = 15;
					enemy.attack = 3;
					//printf("困难难度\n");
					MenuView();
					//printf("返回菜单界面/n");
					return;
				}
				break;
			default:
				break;
			}
		}
	}
}

// 汪禹良
void MemberView()
{
	cleardevice();
	IMAGE img_memberview;
	loadimage(&img_memberview, ".//images//相关人员界面.jpg", 700, 700);
	putimage(0, 0, &img_memberview);

	IMAGE img_back;
	loadimage(&img_back, ".//images//返回按钮.jpg", 150, 50);
	putimage(30, 550, &img_back);
	//键盘鼠标操作
	ExMessage msg;
	while (true)
	{
		//键盘操作
		if (_kbhit())
		{
			char key = _getch();//阻塞函数，不输入一直等
			//printf("%d,%c\n", key, key);
			switch (key)
			{
			case 27://上键
				//返回菜单界面
				MenuView();
				//printf("返回菜单界面/n");
				return;
				break;
			}
		}

		//鼠标操作
		if (peekmessage(&msg, WH_MOUSE))
		{
			switch (msg.message)
			{
			case WM_LBUTTONDOWN:

				//返回到菜单界面
				if (msg.x >= 30 && msg.x <= 180 && msg.y >= 550 && msg.y <= 600)
				{
					MenuView();
					return;
					//printf("返回到菜单界面\n");
					//跳转到设置难度界面
				}
				break;
			default:
				break;
			}
		}
	}
}

// 汪禹良
void MenuView()
{
	InitMap();
	cleardevice();
	//输出图片
	setbkmode(TRANSPARENT);
	IMAGE img_menuview;
	loadimage(&img_menuview, ".//images//菜单界面.jpg", 700, 700);
	putimage(0, 0, &img_menuview);

	IMAGE img_start;
	loadimage(&img_start, ".//images//开始游戏按键.jpg", 150, 50);
	putimage(50, 250, &img_start);

	IMAGE img_level;
	loadimage(&img_level, ".//images//难度设置按键.jpg", 150, 50);
	putimage(50, 330, &img_level);

	IMAGE img_member;
	loadimage(&img_member, ".//images//相关人员按键.jpg", 150, 50);
	putimage(50, 410, &img_member);

	IMAGE img_quit;
	loadimage(&img_quit, ".//images//退出游戏按键.jpg", 150, 50);
	putimage(50, 490, &img_quit);
	//键盘鼠标操作
	ExMessage msg;
	while (true)
	{

		//鼠标操作
		if (peekmessage(&msg, WH_MOUSE))
		{
			switch (msg.message)
			{
			case WM_LBUTTONDOWN:

				//跳转到游戏界面
				if (msg.x >= 50 && msg.x <= 200 && msg.y >= 250 && msg.y <= 300)
				{
					GameView();
					//printf("开始游戏\n");
				}
				//跳转到设置难度界面
				if (msg.x >= 50 && msg.x <= 200 && msg.y >= 330 && msg.y <= 380)
				{
					Level();
					return;
					//printf("难度设置\n");
				}
				//跳转到相关人员界面
				if (msg.x >= 50 && msg.x <= 200 && msg.y >= 410 && msg.y <= 460)
				{
					MemberView();
					return;
					//printf("相关人员\n");
				}
				//结束游戏
				if (msg.x >= 50 && msg.x <= 200 && msg.y >= 490 && msg.y <= 540)
				{
					exit(0);
				}
				break;
			default:
				break;
			}
		}
	}
}

void change()
{
	//获取窗口句柄
	HWND hnd = GetHWnd();
	//设置窗口标题
	SetWindowText(hnd, "纸上坦克");
}


//-------------------service---------------

/*
	负责人：丧丧超人
*/
int main() {
	// bgm 播放
	//PlaySound(LPWSTR(IDR_WAVE1), GetModuleHandle(NULL), SND_RESOURCE | SND_ASYNC | SND_LOOP);
	PlaySound(MAKEINTRESOURCE(IDR_WAVE1), GetModuleHandle(NULL), SND_RESOURCE | SND_ASYNC | SND_LOOP);

	// ----------汪禹良------------
	//创建窗口
	initgraph(700, 700);
	change();

	MenuView();

	getchar();
	//关闭窗口
	closegraph();

	return 0;
}