泡泡龙
2023-2-19 ~ 2023-4-11
(0)
程序简介
泡泡龙,游戏玩法是玩家从下方中央的弹珠发射台射出彩珠,多于 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;
}
添加评论
取消回复