妙妙小豆子

胆子大一点,想开一点。长风破浪会有时,直挂云帆济沧海

泡泡龙 银牌收录

程序简介

泡泡龙,游戏玩法是玩家从下方中央的弹珠发射台射出彩珠,多于 3 个同色珠相连则会消失,悬空彩珠也会跟随消失。

通过点线距离判断发射路线中经过的区域,然后从附着点开始检测消除区域,最后从顶层点开始检测悬空区域。使用镜像减小反弹造成的误差。通过初始化中的命名规则,规避奇偶层分类讨论。增加了作弊路径,指哪打哪。不能全 180 度是镜像不够。可以增加像是万能球,炸弹球的功能,或者一次发射两颗球的模式。下沉函数中确定了发射 6 次下沉,可以修改,还保证新生成发射颜色必须是场上剩有的颜色。

右键可以交换发射点。将动画和发射分开,现在无间隔发射十次,然后需要等待下沉。十次间隔可以增加,需要同步多个地方。

程序运行展示

完整源代码

////////////////////////////////////////
// 程序:泡泡龙
// 作者:Gary
// 编译环境:Visual C++ 2010,EasyX_20211109
// 编写日期:2023.2.15

# include <math.h>
# include <graphics.h>
# include <time.h>

static HWND hOut;						// 画布

// 定义一个结构体,格子
struct Node1
{
	int posx[9], posy;					// 物理坐标
	double d[9];						// 与发射点距离
	int num_type;						// 格子类型
};

// 定义一个结构体,临时存放格子
struct Node2
{
	int boxnum;							// 存放格子编号
	double d;							// 存放距离
};

// 定义一个结构体,动画
struct Node3
{
	double flash_x0, flash_y0;			// 路径向量
	int num_type;						// 颜色
	int boxnum_attachable;				// 目的点编号
	int boxnum_eliminate[3000];			// 消除点编号
	int num_eliminate;					// 消除点数量
	int boxnum_airborne[3000];			// 悬空点编号
	int num_airborne;					// 悬空点数量
	int time_airborne;					// 悬空时间
	int flag;							// 动画帧编号
	int lifenum;						// 激活状态
};

// 定义一个结构体,格子
struct Node4
{
	int num_type;						// 格子类型
};

Node1 box[3000];						// 格子,预制 2000 个
Node2 eat[3000];						// 临时存储格子
Node3 flash[10];						// 动画结构体
Node4 box1[3000];						// 格子

// 定义一个类
class Gary
{
public:
	void carry();						// 主进程
	void initialization();				// 初始化
	void move();						// 窗口主视角函数
	void draw_scene();					// 绘制界面函数
	void attachable_area_check();		// 可触区域检测
	void eliminate_check(int boxnum);	// 消除区域检测
	void airborne_check();				// 悬空区域检测
	void sink();						// 下沉函数
	void cheat();						// 作弊函数
	void draw_flash();					// 绘制帧动画

	int exit_carry;						// 主循函数控制参数
	int exit_move;						// 开始界面控制参数
	int num_type;						// 发射点格子类型参数
	int num_type_2;						// 发射点格子类型参数
	int num_type_3;						// 发射点格子类型参数
	int num_top;						// 顶层状态参数
	int num_shoot;						// 发射次数参数
	int num_flag;						// 标记参数
	int num_flash;						// 动画参数
	int x0, y2;							// 发射点坐标
	int x0_2, y2_2;						// 发射点坐标
	ExMessage m;						// 鼠标定义
	COLORREF color_num[16];				// 格子填充颜色

	clock_t start_t1;					// 游戏开始系统时间参数
	clock_t start_t2;					// 游戏进行系统时间参数
};

// 作弊函数
void Gary::cheat()
{
	int i, j, k;
	double t;

	// 初始化
	for(i = 0; i < 2000; i++)
	{
		eat[i].boxnum = 0;
		eat[i].d = 0;
	}
	num_flag = 0;
	// 根据点线距离检测
	// 层
	for(j = 1; j < 14; j++)
	{
		// 列
		for(i = ( j + num_top + 1 ) / 2; i < ( j + num_top + 1 ) / 2 + 8 + ( j + num_top + 1 ) % 2; i++)
		{
			// 本点和镜像点
			for(k = 0; k < 9; k++)
			{
				// 距离发射线距离小于直径即为可吸附的区域
				if(box[j * 100 + i].num_type > 0 && abs(-( m.x - x0 ) * box[j * 100 + i].posy + ( m.y - y2 ) * box[j * 100 + i].posx[k] + ( m.x - x0 ) * m.y - ( m.y - y2 ) * m.x) / sqrt(pow(double(m.x - x0), 2) + pow(double(m.y - y2), 2)) < 32)
				{
					// 记录可吸附点的本点编号和距发射点距离
					eat[num_flag].boxnum = j * 100 + i;
					eat[num_flag].d = box[j * 100 + i].d[k];
					num_flag++;
					break;
				}
				else if(box[j * 100 + i].num_type == 0 && abs(-( m.x - x0 ) * box[j * 100 + i].posy + ( m.y - y2 ) * box[j * 100 + i].posx[k] + ( m.x - x0 ) * m.y - ( m.y - y2 ) * m.x) / sqrt(pow(double(m.x - x0), 2) + pow(double(m.y - y2), 2)) < 20)
				{
					// 记录可吸附点的本点编号和距发射点距离
					eat[num_flag].boxnum = j * 100 + i;
					eat[num_flag].d = box[j * 100 + i].d[k];
					num_flag++;
					break;
				}
			}
		}
	}

A:
	// 排序,根据与发射点距离升序
	for(i = 0; i < num_flag - 1; i++)
	{
		for(j = num_flag - 1; j > i; j--)
		{
			if(eat[j].d < eat[j - 1].d)
			{
				k = eat[j].boxnum;
				t = eat[j].d;
				eat[j].boxnum = eat[j - 1].boxnum;
				eat[j].d = eat[j - 1].d;
				eat[j - 1].boxnum = k;
				eat[j - 1].d = t;
			}
		}
	}

	// 最远点置为墙
	eat[num_flag].boxnum = 0;
	box[0].num_type = -1;

	// 由近往远判定是否为空
	for(i = 0; i < num_flag && box[eat[i].boxnum].num_type == 0; i++)
	{
		// 直到下一个不为空时停止
		if(box[eat[i].boxnum].num_type == 0 && box[eat[i + 1].boxnum].num_type != 0)
		{
			// 修正
			if(( eat[i].boxnum / 100 + num_top + 1 ) % 2 == 1)
			{
				if(eat[i].boxnum % 100 == ( eat[i].boxnum / 100 + num_top + 1 ) / 2)
				{
					eat[i].boxnum += 1;
				}
				else if(eat[i].boxnum % 100 == ( ( eat[i].boxnum / 100 + num_top + 1 ) / 2 + 8 + ( eat[i].boxnum / 100 + num_top + 1 ) % 2 - 1 ))
				{
					eat[i].boxnum -= 1;
				}
			}
			// 修正
			if(box[eat[i].boxnum - 101].num_type == 0 && box[eat[i].boxnum - 100].num_type == 0 && box[eat[i].boxnum - 1].num_type == 0 && box[eat[i].boxnum + 1].num_type == 0 && box[eat[i].boxnum + 100].num_type == 0 && box[eat[i].boxnum + 101].num_type == 0)
			{
				eat[i].d = -1;
				goto A;
			}

			// 绘制目的地点
			setfillcolor(color_num[num_type + 7]);
			setlinecolor(color_num[num_type]);
			t = eat[i].boxnum;
			fillcircle(box[int(t)].posx[0], box[int(t)].posy, 8);

			FlushBatchDraw();
			break;
		}
	}
}

// 下沉函数
void Gary::sink()
{
	int i, j, t;
	// 胜利结束判断
	t = 0;
	for(j = 1; j < 14; j++)
	{
		// 奇偶层
		for(i = ( j + num_top + 1 ) / 2; i < ( j + num_top + 1 ) / 2 + 8 + ( j + num_top + 1 ) % 2; i++)
		{
			if(box[j * 100 + i].num_type > 0 && box[j * 100 + i].num_type < 7)
			{
				t = 1; break;
			}
		}
		if(t == 1)
		{
			break;
		}
	}
	if(t == 0)
	{
		num_flash = 2;
	}
	// 下移
	num_shoot++;
	// 每发射六次下沉
	if(num_shoot % 10 == 0 && exit_move == 0)
	{
		//
		num_flash++;
		//
		num_shoot = 0;
	}
}

// 悬空区域检测
void Gary::airborne_check()
{
	int i, j, k, t;
	// 初始化
	num_flag = 0;
	// 顶层数据检测,根据顶层非空点向下检索
	j = 1;
	for(i = ( j + num_top + 1 ) / 2; i < ( j + num_top + 1 ) / 2 + 8 + ( j + num_top + 1 ) % 2; i++)
	{
		k = j * 100 + i;
		if(box[k].num_type > 0)
		{
			eat[num_flag].boxnum = k;
			num_flag++;
		}
	}
	// 根据顶层非空点向下检索
	for(k = 0; k < num_flag; k++)
	{
		i = eat[k].boxnum % 100;
		j = eat[k].boxnum / 100;
		// 通过初始化中的命名规则,规避奇偶层分类讨论
		// 不为空则存储
		// 左上
		if(box[( j - 1 ) * 100 + ( i - 1 )].num_type > 0)
		{
			eat[num_flag].boxnum = ( j - 1 ) * 100 + ( i - 1 );
			num_flag++;
			for(t = 0; t < num_flag - 1; t++)
			{
				if(eat[t].boxnum == ( j - 1 ) * 100 + ( i - 1 )) { num_flag--; break; }
			}
		}
		// 左
		if(box[( j ) * 100 + ( i - 1 )].num_type > 0)
		{
			eat[num_flag].boxnum = ( j ) * 100 + ( i - 1 );
			num_flag++;
			for(t = 0; t < num_flag - 1; t++)
			{
				if(eat[t].boxnum == ( j ) * 100 + ( i - 1 )) { num_flag--; break; }
			}
		}
		// 左下
		if(box[( j + 1 ) * 100 + ( i )].num_type > 0)
		{
			eat[num_flag].boxnum = ( j + 1 ) * 100 + ( i );
			num_flag++;
			for(t = 0; t < num_flag - 1; t++)
			{
				if(eat[t].boxnum == ( j + 1 ) * 100 + ( i )) { num_flag--; break; }
			}
		}
		// 右下
		if(box[( j + 1 ) * 100 + ( i + 1 )].num_type > 0)
		{
			eat[num_flag].boxnum = ( j + 1 ) * 100 + ( i + 1 );
			num_flag++;
			for(t = 0; t < num_flag - 1; t++)
			{
				if(eat[t].boxnum == ( j + 1 ) * 100 + ( i + 1 )) { num_flag--; break; }
			}
		}
		// 右
		if(box[( j ) * 100 + ( i + 1 )].num_type > 0)
		{
			eat[num_flag].boxnum = ( j ) * 100 + ( i + 1 );
			num_flag++;
			for(t = 0; t < num_flag - 1; t++)
			{
				if(eat[t].boxnum == ( j ) * 100 + ( i + 1 )) { num_flag--; break; }
			}
		}
		// 右上
		if(box[( j - 1 ) * 100 + ( i )].num_type > 0)
		{
			eat[num_flag].boxnum = ( j - 1 ) * 100 + ( i );
			num_flag++;
			for(t = 0; t < num_flag - 1; t++)
			{
				if(eat[t].boxnum == ( j - 1 ) * 100 + ( i )) { num_flag--; break; }
			}
		}
	}

	// 统计非空格子
	k = 0;
	for(j = 1; j < 15; j++)
	{
		for(i = 1; i < 18; i++)
		{
			if(box[j * 100 + i].num_type > 0)
			{
				k++;
			}
		}
	}

	// 有悬空格则存储
	if(k != num_flag)
	{
		// 数量存储
		flash[num_shoot].num_airborne = k - num_flag;
		int a = 0, b;
		// 本点全遍历,未被还原的点皆已置空
		for(j = 1; j < 14; j++)
		{
			for(i = ( j + num_top + 1 ) / 2; i < ( j + num_top + 1 ) / 2 + 8 + ( j + num_top + 1 ) % 2; i++)
			{
				// 对不为空的格子进行判断
				if(box[j * 100 + i].num_type > 0)
				{
					t = box[j * 100 + i].num_type;
					// 赋空
					box[j * 100 + i].num_type = 0;
					// 储存点全遍历
					for(k = 0; k < num_flag; k++)
					{
						b = 0;
						// 在储存点中找到了
						if(eat[k].boxnum == j * 100 + i)
						{
							// 还原
							box[j * 100 + i].num_type = t;
							b = 1;
							break;
						}
					}
					// 点编号存储
					if(b == 0)
					{
						flash[num_shoot].boxnum_airborne[a] = j * 100 + i;
						a++;
					}
				}
			}
		}
	}
}

// 消除区域检测
void Gary::eliminate_check(int boxnum)
{
	int i, j, k, t;
	// 根据变色点位置开始搜索
	eat[0].boxnum = boxnum;
	num_flag = 1;
	for(k = 0; k < num_flag; k++)
	{
		// 变色点坐标
		i = eat[k].boxnum % 100;
		j = eat[k].boxnum / 100;
		// 通过初始化中的命名规则,规避奇偶层分类讨论
		// 颜色一致则存储
		// 左上
		if(box[( j - 1 ) * 100 + ( i - 1 )].num_type == box[boxnum].num_type)
		{
			eat[num_flag].boxnum = ( j - 1 ) * 100 + ( i - 1 );
			num_flag++;
			// 排除重复
			for(t = 0; t < num_flag - 1; t++)
			{
				if(eat[t].boxnum == ( j - 1 ) * 100 + ( i - 1 )) { num_flag--; break; }
			}
		}
		// 左
		if(box[( j ) * 100 + ( i - 1 )].num_type == box[boxnum].num_type)
		{
			eat[num_flag].boxnum = ( j ) * 100 + ( i - 1 );
			num_flag++;
			for(t = 0; t < num_flag - 1; t++)
			{
				if(eat[t].boxnum == ( j ) * 100 + ( i - 1 )) { num_flag--; break; }
			}
		}
		// 左下
		if(box[( j + 1 ) * 100 + ( i )].num_type == box[boxnum].num_type)
		{
			eat[num_flag].boxnum = ( j + 1 ) * 100 + ( i );
			num_flag++;
			for(t = 0; t < num_flag - 1; t++)
			{
				if(eat[t].boxnum == ( j + 1 ) * 100 + ( i )) { num_flag--; break; }
			}
		}
		// 右下
		if(box[( j + 1 ) * 100 + ( i + 1 )].num_type == box[boxnum].num_type)
		{
			eat[num_flag].boxnum = ( j + 1 ) * 100 + ( i + 1 );
			num_flag++;
			for(t = 0; t < num_flag - 1; t++)
			{
				if(eat[t].boxnum == ( j + 1 ) * 100 + ( i + 1 )) { num_flag--; break; }
			}
		}
		// 右
		if(box[( j ) * 100 + ( i + 1 )].num_type == box[boxnum].num_type)
		{
			eat[num_flag].boxnum = ( j ) * 100 + ( i + 1 );
			num_flag++;
			for(t = 0; t < num_flag - 1; t++)
			{
				if(eat[t].boxnum == ( j ) * 100 + ( i + 1 )) { num_flag--; break; }
			}
		}
		// 右上
		if(box[( j - 1 ) * 100 + ( i )].num_type == box[boxnum].num_type)
		{
			eat[num_flag].boxnum = ( j - 1 ) * 100 + ( i );
			num_flag++;
			for(t = 0; t < num_flag - 1; t++)
			{
				if(eat[t].boxnum == ( j - 1 ) * 100 + ( i )) { num_flag--; break; }
			}
		}
	}

	// 初始化存储
	flash[num_shoot].num_eliminate = 0;
	flash[num_shoot].boxnum_eliminate[0] = eat[0].boxnum;
	// 三个以上即可消除
	if(num_flag > 2)
	{
		// 数量存储
		flash[num_shoot].num_eliminate = num_flag;
		// 编号存储
		for(i = 0; i < num_flag; i++)
		{
			flash[num_shoot].boxnum_eliminate[i] = eat[i].boxnum;
		}

		for(i = 0; i < num_flag; i++)
		{
			// 赋空
			box[eat[i].boxnum].num_type = 0;
		}
		// 悬空区域检测
		airborne_check();
	}
}

// 可触区域检测
void Gary::attachable_area_check()
{
	// 存储
	flash[num_shoot].lifenum = 1;
	flash[num_shoot].flag = 1;
	flash[num_shoot].flash_x0 = m.x;
	flash[num_shoot].flash_y0 = m.y;
	flash[num_shoot].num_type = num_type;

	int i, j, k;
	double t;
	// 发射点更新,必须是当前有的颜色
	t = 0;
	while(t == 0 && exit_move == 0)
	{
		// 随机
		num_type_2 = rand() % 7 + 1;
		for(j = 1; j < 14; j++)
		{
			// 奇偶层
			for(i = ( j + num_top + 1 ) / 2; i < ( j + num_top + 1 ) / 2 + 8 + ( j + num_top + 1 ) % 2; i++)
			{
				if(num_type_2 == box[j * 100 + i].num_type)
				{
					t = 1;
				}
			}
		}
	}
	// 初始化
	for(i = 0; i < 2000; i++)
	{
		eat[i].boxnum = 0;
		eat[i].d = 0;
	}
	num_flag = 0;
	// 根据点线距离检测
	// 层
	for(j = 1; j < 14; j++)
	{
		// 列
		for(i = ( j + num_top + 1 ) / 2; i < ( j + num_top + 1 ) / 2 + 8 + ( j + num_top + 1 ) % 2; i++)
		{
			// 本点和镜像点
			for(k = 0; k < 9; k++)
			{
				// 距离发射线距离小于直径即为可吸附的区域
				if(box[j * 100 + i].num_type > 0 && abs(-( m.x - x0 ) * box[j * 100 + i].posy + ( m.y - y2 ) * box[j * 100 + i].posx[k] + ( m.x - x0 ) * m.y - ( m.y - y2 ) * m.x) / sqrt(pow(double(m.x - x0), 2) + pow(double(m.y - y2), 2)) < 32)
				{
					// 记录可吸附点的本点编号和距发射点距离
					eat[num_flag].boxnum = j * 100 + i;
					eat[num_flag].d = box[j * 100 + i].d[k];
					num_flag++;
					break;
				}
				else if(box[j * 100 + i].num_type == 0 && abs(-( m.x - x0 ) * box[j * 100 + i].posy + ( m.y - y2 ) * box[j * 100 + i].posx[k] + ( m.x - x0 ) * m.y - ( m.y - y2 ) * m.x) / sqrt(pow(double(m.x - x0), 2) + pow(double(m.y - y2), 2)) < 20)
				{
					// 记录可吸附点的本点编号和距发射点距离
					eat[num_flag].boxnum = j * 100 + i;
					eat[num_flag].d = box[j * 100 + i].d[k];
					num_flag++;
					break;
				}
			}
		}
	}

B:
	// 排序,根据与发射点距离升序
	for(i = 0; i < num_flag - 1; i++)
	{
		for(j = num_flag - 1; j > i; j--)
		{
			if(eat[j].d < eat[j - 1].d)
			{
				k = eat[j].boxnum;
				t = eat[j].d;
				eat[j].boxnum = eat[j - 1].boxnum;
				eat[j].d = eat[j - 1].d;
				eat[j - 1].boxnum = k;
				eat[j - 1].d = t;
			}
		}
	}

	// 最远点置为墙
	eat[num_flag].boxnum = 0;
	box[0].num_type = -1;

	// 最近的可接触点已不是空点
	if(box[eat[0].boxnum].num_type != 0)
	{
		draw_scene();
		exit_move = 1;
	}

	// 由近往远判定是否为空
	for(i = 0; i < num_flag && box[eat[i].boxnum].num_type == 0; i++)
	{
		// 直到下一个不为空时停止
		if(box[eat[i].boxnum].num_type == 0 && box[eat[i + 1].boxnum].num_type != 0)
		{
			// 修正
			if(( eat[i].boxnum / 100 + num_top + 1 ) % 2 == 1)
			{
				if(eat[i].boxnum % 100 == ( eat[i].boxnum / 100 + num_top + 1 ) / 2)
				{
					eat[i].boxnum += 1;
				}
				else if(eat[i].boxnum % 100 == ( ( eat[i].boxnum / 100 + num_top + 1 ) / 2 + 8 + ( eat[i].boxnum / 100 + num_top + 1 ) % 2 - 1 ))
				{
					eat[i].boxnum -= 1;
				}
			}
			// 修正
			if(box[eat[i].boxnum - 101].num_type == 0 && box[eat[i].boxnum - 100].num_type == 0 && box[eat[i].boxnum - 1].num_type == 0 && box[eat[i].boxnum + 1].num_type == 0 && box[eat[i].boxnum + 100].num_type == 0 && box[eat[i].boxnum + 101].num_type == 0)
			{
				eat[i].d = -1;
				goto B;
			}

			// 编号存储
			flash[num_shoot].boxnum_attachable = eat[i].boxnum;

			// 该空点赋上发射点颜色
			box[eat[i].boxnum].num_type = num_type;
			break;
		}
	}

	// 消除检测
	eliminate_check(eat[i].boxnum);
}

// 场景绘制函数
void Gary::draw_scene()
{
	int i, j;
	// 主界面
	// 背景绘制
	setbkcolor(RGB(148, 210, 249));
	cleardevice();
	setlinecolor(BLACK);
	setlinestyle(PS_SOLID, 2);
	// 层
	for(j = 1; j < 14; j++)
	{
		// 奇偶层
		for(i = ( j + num_top + 1 ) / 2; i < ( j + num_top + 1 ) / 2 + 8 + ( j + num_top + 1 ) % 2; i++)
		{
			// 修正
			if(( j + num_top + 1 ) % 2 == 1)
			{
				box[j * 100 + ( j + num_top + 1 ) / 2].num_type = ( box[j * 100 + ( j + num_top + 1 ) / 2 + 1].num_type > 0 ? -1 : 0 );
				box[j * 100 + ( j + num_top + 1 ) / 2 + 8 + ( j + num_top + 1 ) % 2 - 1].num_type = ( box[j * 100 + ( j + num_top + 1 ) / 2 + 8 + ( j + num_top + 1 ) % 2 - 2].num_type > 0 ? -1 : 0 );
			}

			if(box1[j * 100 + i].num_type > 0)
			{
				setfillcolor(color_num[box1[j * 100 + i].num_type + 7]);
				setlinecolor(color_num[box1[j * 100 + i].num_type]);
				fillcircle(box[j * 100 + i].posx[0], box[j * 100 + i].posy, 16);
			}
		}
	}
	// 绘制发射点
	setfillcolor(color_num[num_type_3 + 7]);
	setlinecolor(color_num[num_type_3]);
	fillcircle(x0, y2, 16);

	setfillcolor(color_num[num_type_2 + 7]);
	setlinecolor(color_num[num_type_2]);
	fillcircle(x0_2, y2_2, 16);
	// 绘制边界
	setlinestyle(PS_SOLID, 1);
	setlinecolor(RED);
	line(0, 14 * 34 - 10, 320, 14 * 34 - 10);
	FlushBatchDraw();
}

// 帧动画绘制函数
void Gary::draw_flash()
{
	int i, j, k;
	double t;

	setlinestyle(PS_SOLID, 2);
	// 结束判定
	if(num_flash > 1)
	{
		for(i = 0; i < 2000; i++)
		{
			box1[i].num_type = 0;
		}
		// 等待动画结束
		k = 0;
		for(i = 0; i < 10; i++)
		{
			if(flash[i].lifenum == 1)
			{
				k = 1;
			}
		}
		if(k == 0)
		{
			exit_move = 2;
		}
	}
	// 场景绘制
	draw_scene();
	// 作弊点绘制
	cheat();
	setlinestyle(PS_SOLID, 2);
	// 帧动画绘制
	for(i = 0; i < 10; i++)
	{
		// 一阶段:路径绘制
		if(flash[i].lifenum == 1 && flash[i].flag < 14 - flash[i].boxnum_attachable / 100)
		{
			// 颜色
			setfillcolor(color_num[flash[i].num_type + 7]);
			setlinecolor(color_num[flash[i].num_type]);

			t = x0 + ( box[flash[i].boxnum_attachable].posy - y2 ) * ( flash[i].flash_x0 - x0 ) / ( flash[i].flash_y0 - y2 ) * double(flash[i].flag) / ( 14 - flash[i].boxnum_attachable / 100 );
			// 横坐标修正
			if(t < -320 * 3) { t = 320 - ( -320 * 3 - t ); }
			else	if(t < -320 * 2) { t = -320 * 2 - t; }
			else	if(t < -320 * 1) { t = 320 - ( -320 - t ); }
			else	if(t < 320 * 0) { t = -t; }
			else	if(t > 320 * 4) { t = t - 320 * 4; }
			else	if(t > 320 * 3) { t = 320 - ( t - 320 * 3 ); }
			else	if(t > 320 * 2) { t = t - 320 * 2; }
			else	if(t > 320 * 1) { t = 320 - ( t - 320 ); }
			// 绘制
			fillcircle(int(t), int(y2 + ( box[flash[i].boxnum_attachable].posy - y2 ) * double(flash[i].flag) / ( 14 - flash[i].boxnum_attachable / 100 )), 16);

			flash[i].flag++;
			// 一阶段结束判定
			if(flash[i].flag == 14 - flash[i].boxnum_attachable / 100)
			{
				// 状态变更
				box1[flash[i].boxnum_attachable].num_type = flash[i].num_type;
				// 满足消除条件
				if(flash[i].num_eliminate > 2)
				{
					// 消除域清除
					for(j = 0; j < flash[i].num_eliminate; j++)
					{
						box1[flash[i].boxnum_eliminate[j]].num_type = 0;
					}
					// 悬空域清除
					for(j = 0; j < flash[i].num_airborne; j++)
					{
						box1[flash[i].boxnum_airborne[j]].num_type = 0;
					}
				}
			}
		}
		// 二阶段:掉落绘制
		else if(flash[i].lifenum == 1 && flash[i].flag < 14 - flash[i].boxnum_attachable / 100 + 14 - flash[i].boxnum_attachable / 100 && flash[i].num_eliminate>2)
		{
			// 步骤
			k = flash[i].flag - ( 14 - flash[i].boxnum_attachable / 100 );
			// 数量	
			for(j = 0; j < flash[i].num_eliminate; j++)
			{
				setfillcolor(color_num[flash[i].num_type + 7]);
				setlinecolor(color_num[flash[i].num_type]);
				fillcircle(box[flash[i].boxnum_eliminate[j]].posx[0], box[flash[i].boxnum_eliminate[j]].posy + 40 * k, 16);
			}
			flash[i].flag++;
		}
		// 三阶段:激活状态重置
		else if(flash[i].lifenum == 1)
		{
			flash[i].lifenum = 0;
			flash[i].num_eliminate = 0;
			flash[i].num_airborne = 0;
		}
	}
	setlinestyle(PS_SOLID, 1);

	// 激活状态全部结束,开始下沉
	if(flash[9].lifenum == 0 && num_flash == 1)
	{
		// 清空鼠标队列
		flushmessage();
		num_top = ( num_top == 0 ? 1 : 0 );
		// 整体左移
		// 层
		for(j = 1; j < 14; j++)
		{
			// 奇偶层
			for(i = ( j + num_top + 1 ) / 2; i < ( j + num_top + 1 ) / 2 + 8 + ( j + num_top + 1 ) % 2; i++)
			{
				// 纵坐标
				k = j * 100 + i;
				box[k].posy = j * 34;

				// 横坐标以及镜像点横坐标
				box[k].posx[0] = i * 40 - 20 * j - 20 * num_top;
				box[k].posx[1] = -box[k].posx[0];
				box[k].posx[2] = 320 + ( 320 - box[k].posx[0] );
				box[k].posx[3] = -box[k].posx[2];
				box[k].posx[4] = 320 * 2 + ( 320 * 2 - box[k].posx[2] );
				box[k].posx[5] = -box[k].posx[4];
				box[k].posx[6] = 320 * 3 + ( 320 * 3 - box[k].posx[4] );
				box[k].posx[7] = -box[k].posx[6];
				box[k].posx[8] = 320 * 4 + ( 320 * 4 - box[k].posx[6] );
				// 所有点距发射点距离
				for(t = 0; t < 9; t++)
				{
					box[k].d[int(t)] = sqrt(pow(double(box[k].posx[int(t)] - x0), 2) + pow(double(box[k].posy - y2), 2));
				}
			}
		}
		// 右下或左下移动
		for(j = 14; j > 1; j--)
		{
			for(i = 1; i < 18; i++)
			{
				if(box[( j - 1 ) * 100 + ( i - num_top )].num_type >= 0)
				{
					box[j * 100 + i].num_type = box[( j - 1 ) * 100 + ( i - num_top )].num_type;
				}
				// 底层判断失败
				if(j == 14 && box[j * 100 + i].num_type > 0)
				{
					exit_move = 1;
				}
			}
		}
		// 顶层随机
		j = 1;
		for(i = ( j + num_top + 1 ) / 2; i < ( j + num_top + 1 ) / 2 + 8 + ( j + num_top + 1 ) % 2; i++)
		{
			box[j * 100 + i].num_type = rand() % 4 + 1;
		}
		// 铺墙
		for(j = 0; j < 15; j++)
		{
			for(i = 0; i < 18; i++)
			{
				// 置为墙
				if(i < ( j + num_top + 2 ) / 2 || i >= ( j + num_top + 2 ) / 2 + 7 + ( j + num_top ) % 2)
				{
					box[j * 100 + i].num_type = -1;
				}
			}
		}
		// 备份
		for(i = 0; i < 2000; i++)
		{
			box1[i].num_type = box[i].num_type;
		}
		// 动画参数重置
		num_flash = 0;
	}
	FlushBatchDraw();
}
// 初始化函数
void Gary::initialization()
{
	int i, j, k, t;
	// 随机初始化
	srand((unsigned)time(NULL));
	// 初始化
	num_flash = 0;
	num_shoot = 0;
	for(i = 0; i < 6; i++)
	{
		flash[i].lifenum = 0;
	}
	// 颜色初始化
	color_num[0] = RGB(148, 210, 249);
	color_num[1] = RGB(33, 87, 193);
	color_num[2] = RGB(64, 138, 27);
	color_num[3] = RGB(187, 29, 23);
	color_num[4] = RGB(203, 163, 38);
	color_num[5] = RGB(118, 169, 164);
	color_num[6] = RGB(157, 36, 165);
	color_num[7] = RGB(25, 25, 67);

	color_num[8] = RGB(60, 156, 248);
	color_num[9] = RGB(112, 191, 62);
	color_num[10] = RGB(228, 40, 39);
	color_num[11] = RGB(245, 211, 62);
	color_num[12] = RGB(163, 203, 204);
	color_num[13] = RGB(230, 54, 226);
	color_num[14] = RGB(75, 75, 144);
	// 参数初始化
	num_top = 0;
	num_shoot = 0;
	x0 = 11 * 40 - 20 * 14;
	y2 = 14 * 34 + 20;
	x0_2 = 11 * 40 - 20 * 14 - 50;
	y2_2 = 14 * 34 + 20 + 50;
	// 格子初始化
	for(j = 0; j < 15; j++)
	{
		for(i = 0; i < 18; i++)
		{
			// 置为墙
			box[j * 100 + i].num_type = -1;
		}
	}
	// 层
	for(j = 1; j < 14; j++)
	{
		// 奇偶层
		for(i = ( j + num_top + 1 ) / 2; i < ( j + num_top + 1 ) / 2 + 8 + ( j + num_top + 1 ) % 2; i++)
		{
			// 纵坐标
			k = j * 100 + i;
			box[k].posy = j * 34;

			// 横坐标以及镜像点横坐标
			box[k].posx[0] = i * 40 - 20 * j;
			box[k].posx[1] = -box[k].posx[0];
			box[k].posx[2] = 320 + ( 320 - box[k].posx[0] );
			box[k].posx[3] = -box[k].posx[2];
			box[k].posx[4] = 320 * 2 + ( 320 * 2 - box[k].posx[2] );
			box[k].posx[5] = -box[k].posx[4] + 20;
			box[k].posx[6] = 320 * 3 + ( 320 * 3 - box[k].posx[4] );
			box[k].posx[7] = -box[k].posx[6];
			box[k].posx[8] = 320 * 4 + ( 320 * 4 - box[k].posx[6] );

			// 所有点距发射点距离
			for(t = 0; t < 9; t++)
			{
				box[k].d[t] = sqrt(pow(double(box[k].posx[t] - x0), 2) + pow(double(box[k].posy - y2), 2));
			}
			// 赋颜色
			if(j < 5) { box[k].num_type = rand() % 4 + 1; }
			// 赋空
			else { box[k].num_type = 0; }
		}
		// 补充
		if(( j + num_top + 1 ) % 2 == 1)
		{
			box[j * 100 + ( j + num_top + 1 ) / 2].num_type = 0;
			box[j * 100 + ( j + num_top + 1 ) / 2 + 8 + ( j + num_top + 1 ) % 2 - 1].num_type = 0;
		}
	}
	// 备份
	for(i = 0; i < 2000; i++)
	{
		box1[i].num_type = box[i].num_type;
	}

	// 发射点初始化
	num_type = rand() % 4 + 1;
	num_type_2 = rand() % 4 + 1;
	num_type_3 = num_type;
	// 绘制
	draw_scene();
}

// 窗口主视角函数,获取用户操作
void Gary::move()
{
	exit_move = 0;
	start_t1 = clock();
	start_t2 = clock();
	while(exit_move == 0)
	{
		start_t2 = clock();
		if(( start_t2 - start_t1 ) % 500 > 100)
		{
			start_t1 = clock();
			start_t2 = clock();
			// 动画绘制
			draw_flash();
		}

		// 鼠标信息
		if(peekmessage(&m, EM_MOUSE | EM_KEY)&& num_flash == 0)
		{
			// 左键单击判断
			if(m.message == WM_LBUTTONDOWN)
			{
				// 单击在可发射范围
				if(m.y < y2 - 50)
				{
					// 发射点更新
					num_type_3 = num_type_2;
					// 可触区域检测
					attachable_area_check();
					// 下沉函数
					sink();
					// 发射点更新
					num_type = num_type_3;
					// 绘制
					draw_scene();
					// 清空鼠标队列
					flushmessage();
				}
			}
			// 右键交换发射点
			else if(m.message == WM_RBUTTONDOWN)
			{
				// 交换
				num_type = num_type_2;
				num_type_2 = num_type_3;
				num_type_3 = num_type;
			}
		}
	}
	// 结束提示
	switch(exit_move)
	{
	case 1:
	{
		MessageBox(hOut, _T("触底啦,结束了"), _T("来自小豆子的提醒"), MB_OK);
		break;
	}
	case 2:
	{
		MessageBox(hOut, _T("恭喜成功,结束啦"), _T("来自小豆子的提醒"), MB_OK);
		break;
	}
	}

}

// 主进程
void Gary::carry()
{
	// 窗口定义
	hOut = initgraph(320, 576);
	SetWindowText(hOut, _T("泡泡龙"));
	// 进程控制
	exit_carry = 0;
	BeginBatchDraw();
	while(exit_carry == 0)
	{
		initialization();
		move();
	}
	EndBatchDraw();
	closegraph();
}

// 主函数
int main(void)
{
	Gary G;
	G.carry();
	return 0;
}

添加评论