////////////////////////////////////////////////////////
// 程序名称：合成立方体 (Cube)
// 编译环境：VS2019		EasyX_2021-7-30
// 作　　者：Margoo <1683691371@qq.com>
// 最后修改：2021-9-4
//

#include "cube.random.h"

#include <string>
#include <conio.h>

// 分数
int score = 0;

// 棋盘
int map[10][10] = { 0 };

// 绘制棋盘
void draw_graphics()
{
	int x = 20;
	int y = 20;

	IMAGE fillrect(80, 80);
	IMAGE fillrect_60px(60, 80);

	for (int map_x = 0; map_x < 10; x += 60, ++map_x)
	{
		for (int map_y = 0; map_y < 10; y += 60, ++map_y)
		{
			if (map[map_x][map_y] == 0)
			{
				rectangle(x, y, x + 60, y + 60);
			}
			else
			{
				fillrectangle(x, y, x + 60, y + 60);
			}
		}

		y = 20;
	}
}

// 绘制方块候选栏
void draw_blank(image_object blank[3], image_object candidate_blocks[3])
{
	int x = 21;

	for (int count = 0; count < 3; ++count)
	{
		if (blank[count].y == 0 &&
			blank[count].x == 0)
		{
			blank[count].y = 670;

			blank[count].x = x;
			blank[count].init();
		}

		SetWorkingImage(&blank[count].image);

		setbkcolor(RGB(120, 120, 120));
		cleardevice();

		candidate_blocks[count].x = 0;
		candidate_blocks[count].y = 0;
		candidate_blocks[count].draw(&blank[count].image);

		SetWorkingImage();

		blank[count].draw();

		x += 60 * 3 + 20;
	}
}

// 绘制分数
void draw_score()
{
	outtextxy(0, 0, std::to_wstring(score).c_str());
}

// 判断鼠标是否在候选栏上
bool on_blank(int mx, int my,int& blank)
{
	int x = 21;

	for (int count = 0; count < 3; ++count)
	{
		if (my >= 640 && my <= 820 &&
			mx >= x && mx <= x + 180)
		{
			blank = count;

			return true;
		}

		x += 60 * 3 + 20;
	}

	return false;
}

// 清除整行整列
void clear_block()
{
	bool flag = true;

	for (int x = 0; x < 10; ++x)
	{
		flag = true;

		for (int y = 0; y < 10; ++y)
		{
			if (map[x][y] == 0)
			{
				flag = false;
			}
		}

		if (flag == true)
		{
			for (int y = 0; y < 10; ++y)
			{
				score += 20;
				map[x][y] = 0;
			}
		}
	}

	for (int x = 0; x < 10; ++x)
	{
		flag = true;

		for (int y = 0; y < 10; ++y)
		{
			if (map[y][x] == 0)
			{
				flag = false;
			}
		}

		if (flag == true)
		{
			for (int y = 0; y < 10; ++y)
			{
				score += 20;
				map[y][x] = 0;
			}
		}
	}

	draw_graphics();
}

// 添加方块
bool update_map(int mx, int my, image_object select_object)
{
	int block_x = mx / 60;
	int block_y = my / 60;

	if (block_x < 10 && block_y < 10)
	{
		if (select_object.object_type == ONE_BLOCK)
		{
			if (map[block_x][block_y] != 1)
			{
				map[block_x][block_y] = 1;

				return true;
			}
			else
			{
				return false;
			}
		}
	}
	else
	{
		return false;
	}

	if (block_x < 10 + 1 && block_y < 10)
	{
		if (select_object.object_type == TWO_BLOCK_LANDSCAPE)
		{
			if (map[block_x][block_y] != 1 && map[block_x + 1][block_y] != 1)
			{
				map[block_x][block_y] = 1;
				map[block_x + 1][block_y] = 1;

				return true;
			}
			else
			{
				return false;
			}
		}
	}
	else if (!(block_x < 10 && block_y + 1 < 10))
	{
		return false;
	}

	if (block_x < 10 && block_y + 1 < 10)
	{
		if (select_object.object_type == TWO_BLOCK_PORTRAIT)
		{
			if (map[block_x][block_y + 1] != 1 && map[block_x][block_y] != 1)
			{
				map[block_x][block_y] = 1;
				map[block_x][block_y + 1] = 1;

				return true;
			}
			else
			{
				return false;
			}
		}
	}
	else
	{
		return false;
	}
	if (block_x + 2 < 10 && block_y + 1 < 10)
	{
		if (select_object.object_type == THREE_BLOCK_MIDDLE)
		{
			if (map[block_x][block_y + 1] != 1 && map[block_x + 1][block_y + 1] != 1 &&
				map[block_x + 1][block_y] != 1)
			{
				map[block_x][block_y + 1] = 1;
				map[block_x + 1][block_y + 1] = 1;
				map[block_x + 2][block_y + 1] = 1;
				map[block_x + 1][block_y] = 1;

				return true;
			}
			else
			{
				return false;
			}
		}
	}
	else if (!(block_x + 1 < 10 && block_y + 1 < 10))
	{
		return false;
	}

	if (block_x + 1 < 10 && block_y + 1 < 10)
	{
		if (select_object.object_type == THREE_BLOCK_LEFT)
		{
			if (map[block_x][block_y] != 1 && map[block_x + 1][block_y + 1] != 1 &&
				map[block_x][block_y + 1] != 1)
			{
				map[block_x][block_y + 1] = 1;
				map[block_x + 1][block_y + 1] = 1;
				map[block_x][block_y] = 1;

				return true;
			}
			else
			{
				return false;
			}
		}
	}
	else
	{
		return false;
	}

	return false;
}

// 检查该方块是否能够放置
bool check_map(int mx, int my, image_object select_object)
{
	int block_x = mx / 60;
	int block_y = my / 60;

	if (block_x < 10 && block_y < 10)
	{
		if (select_object.object_type == ONE_BLOCK)
		{
			if (map[block_x][block_y] != 1)
			{
				return true;
			}
			else
			{
				return false;
			}
		}
	}
	else
	{
		return false;
	}

	if (block_x < 10 + 1 && block_y < 10)
	{
		if (select_object.object_type == TWO_BLOCK_LANDSCAPE)
		{
			if (map[block_x][block_y] != 1 && map[block_x + 1][block_y] != 1)
			{
				return true;
			}
			else
			{
				return false;
			}
		}
	}
	else if (!(block_x < 10 && block_y + 1 < 10))
	{
		return false;
	}

	if (block_x < 10 && block_y + 1 < 10)
	{
		if (select_object.object_type == TWO_BLOCK_PORTRAIT)
		{
			if (map[block_x][block_y + 1] != 1 && map[block_x][block_y] != 1)
			{
				return true;
			}
			else
			{
				return false;
			}
		}
	}
	else
	{
		return false;
	}
	if (block_x + 2 < 10 && block_y + 1 < 10)
	{
		if (select_object.object_type == THREE_BLOCK_MIDDLE)
		{
			if (map[block_x][block_y + 1] != 1 && map[block_x + 1][block_y + 1] != 1 &&
				map[block_x + 1][block_y] != 1 && map[block_x + 2][block_y + 1] != 1)
			{
				return true;
			}
			else
			{
				return false;
			}
		}
	}
	else if (!(block_x + 1 < 10 && block_y + 1 < 10))
	{
		return false;
	}

	if (block_x + 1 < 10 && block_y + 1 < 10)
	{
		if (select_object.object_type == THREE_BLOCK_LEFT)
		{
			if (map[block_x][block_y + 1] != 1 && map[block_x + 1][block_y + 1] != 1 &&
				map[block_x][block_y] != 1)
			{
				return true;
			}
			else
			{
				return false;
			}
		}
	}
	else
	{
		return false;
	}

	return false;
}

// 精确延时
void dealy(ULONG time)
{
	clock_t old_clock = clock();

	old_clock += time * CLOCKS_PER_SEC / 1000;

	if (clock() > old_clock)
	{
		old_clock = clock();
	}
	else
	{
		while (clock() < old_clock)
		{
			Sleep(1);
		}
	}
}

// 检测游戏是否结束
bool is_game_over(image_object candiate_blocks[3])
{
	std::vector<bool> result;
	short			  temp = 0;

	for (int count = 0; count < 3; ++count)
	{
		for (int x = 0; x < 10; ++x)
		{
			for (int y = 0; y < 10; ++y)
			{
				result.push_back(check_map(x * 60, y * 60, candiate_blocks[count]));
			}
		}
	}

	for (auto item : result)
	{
		if (item == false)
		{
			++temp;
		}
	}

	if (temp == result.size())
	{
		return true;
	}

	return false;
}

int main()
{
	rand_init();

	initgraph(640, 900);

	SetWindowText(GetHWnd(), L"Cube");

	// 初始化候选栏对象和候选方块对象
	image_object candidate_blocks[3];
	image_object blank_blocks[3];

	blank_blocks[0].width  = 60 * 3;
	blank_blocks[0].height = 60 * 3;
	blank_blocks[1].width  = 60 * 3;
	blank_blocks[1].height = 60 * 3;
	blank_blocks[2].width  = 60 * 3;
	blank_blocks[2].height = 60 * 3;

	// 设置窗口背景色
	setbkcolor(RGB(51, 195, 206));
	cleardevice();

	// 随机匹配方块
	candidate_blocks[0] = random_rect();
	candidate_blocks[1] = random_rect();
	candidate_blocks[2] = random_rect();

	BeginBatchDraw();

	// 绘制界面
	draw_score();
	draw_graphics();
	
	draw_blank(blank_blocks, candidate_blocks);

	FlushBatchDraw();

	ExMessage message;

	// 主循环
	while (true)
	{
		while (peekmessage(&message))
		{
			if (message.message == WM_LBUTTONDOWN)
			{
				int blank = -1;

				if (on_blank(message.x, message.y, blank) == true)
				{
					int offset_x = message.x - blank_blocks[blank].x;
					int offset_y = message.y - blank_blocks[blank].y;

					bool flag = false;

					while (true)
					{
						while (peekmessage(&message))
						{
							// 鼠标拖动
							if (message.message == WM_LBUTTONUP)
							{
								cleardevice();

								blank_blocks[blank].x = 0;
								blank_blocks[blank].y = 0;

								switch (candidate_blocks[blank].object_type)
								{
								case THREE_BLOCK_LEFT: case THREE_BLOCK_MIDDLE:
								{
									if (update_map(message.x - offset_x, message.y - offset_y, candidate_blocks[blank]) == true)
									{
										SetWorkingImage(&candidate_blocks[blank].image);

										cleardevice();
										
										candidate_blocks[blank].object_type = -1;

										SetWorkingImage();
									}

									break;
								}
								case ONE_BLOCK:
								{
									if (update_map(message.x - offset_x + 60, message.y - offset_y + 60, candidate_blocks[blank]) == true)
									{
										SetWorkingImage(&candidate_blocks[blank].image);

										cleardevice();

										candidate_blocks[blank].object_type = -1;

										SetWorkingImage();
									}

									break;
								}
								case TWO_BLOCK_LANDSCAPE:
								{
									if (update_map(message.x - offset_x, message.y - offset_y + 60, candidate_blocks[blank]) == true)
									{
										SetWorkingImage(&candidate_blocks[blank].image);

										cleardevice();

										candidate_blocks[blank].object_type = -1;

										SetWorkingImage();
									}

									break;
								}
								case TWO_BLOCK_PORTRAIT:
								{
									if (update_map(message.x - offset_x + 60, message.y - offset_y, candidate_blocks[blank]) == true)
									{
										SetWorkingImage(&candidate_blocks[blank].image);

										cleardevice();

										candidate_blocks[blank].object_type = -1;

										SetWorkingImage();
									}

									break;
								}
								}

								clear_block();
								draw_score();

								if (candidate_blocks[0].object_type == candidate_blocks[1].object_type &&
									candidate_blocks[1].object_type == candidate_blocks[2].object_type &&
									candidate_blocks[0].object_type == -1)
								{
									
									candidate_blocks[0] = random_rect();
									candidate_blocks[1] = random_rect();
									candidate_blocks[2] = random_rect();
								}

								draw_blank(blank_blocks, candidate_blocks);

								FlushBatchDraw();

								// 判断是否能继续游玩
								if (is_game_over(candidate_blocks) == true)
								{
									cleardevice();

									outtextxy(640 / 2 - textwidth(L"Game Over") / 2,
										900 / 2 - textheight(L"Game Over") / 2, L"Game Over");

									FlushBatchDraw();

									if (_getch() != NULL) {}

									return 0;
								}

								flag = true;

								break;
							}
							else
							{
								blank_blocks[blank].x = message.x - offset_x;
								blank_blocks[blank].y = message.y - offset_y;

								cleardevice();

								draw_score();
								draw_graphics();
								draw_blank(blank_blocks, candidate_blocks);

								FlushBatchDraw();
							}
						}

						if (flag == true)
						{
							break;
						}

						dealy(30);
					}
				}
			}
		}

		// 休息一会儿 zzzz
		dealy(30);
	}

	EndBatchDraw();

	return 0;
}
