【C/EasyX】十字消除游戏的实现方法

来源:互联网 发布:博弈矩阵怎么画 编辑:程序博客网 时间:2024/04/30 10:20

十字消除游戏是以前百度上火过一段时间的一个Flash小游戏。

游戏逻辑比较简单,是我初次接触EasyX图形库后使用EasyX写的第一个i程序。

游戏开始后,在棋盘中随机生成成对的随即颜色的方块,预留一些空白位置。玩家点击空白位置,如果所在位置延伸出的十字线上,能遇到相同颜色的方块,则消除之,累加分数。消除一对方块会恢复一定时间,不进行任何操作时间条会自动减少,直至耗尽游戏结束。如果棋盘上剩余方块少于一定数量,会继续随机生成一定数量的新方块。


效果图如下:







源代码如下:

/////////////////////////////////////////////////////////// 程序名称:AyaCrossX(十字消除游戏)// 编译环境:Visual C++ 6.0 / 2012,EasyX 2013霜降版// 作    者:ls9512 <http://www.baidu.com/p/ls9512>// 最后修改:2013-11-2////系统函数库#include <stdio.h>#include <stdlib.h>#include <string.h>#include <conio.h>#include <math.h>#include <time.h>//EasyX图形库#include <graphics.h>//////////////////////////////以下是 宏定义参数 //////////////////////////////#define WIN_WIDTH600//屏幕宽度#define WIN_HEIGHT430//屏幕高度#define WIN_BLANKTOP45//屏幕顶部空边#define WIN_BLANK25//屏幕边缘留空#define G_BN20//方块横向数量#define G_BM12//方块纵向数量#define G_BW20//方块宽度#define G_BS8//方块间隔宽度#define G_BSELECT3//方块选中大小#define G_FLOATW4//选中浮动大小#define G_BDWO1//消失初始大小#define G_BDW6//消失大小#define G_CN10//颜色数量#define G_BUL25//方块增量程度#define C_BLOCKPANELRGB(255, 255, 221)//底板颜色#define C_HPBARRGB(255, 170, 255)//HP条颜色//////////////////////////////以下是数据结构定义////////////////////////////////方块结构struct Block{COLORREF color;//颜色float FLOAT;//浮动大小float DIS;//消除延迟bool isDIS;//是否消失中bool isClick;//是否被点击};//点结构struct Point{int x;int y;};//矩形结构struct Rect{int x;int y;int w;int h;};//////////////////////////////以下是  全局变量  //////////////////////////////int GamePhase = 0;//游戏阶段 0 准备 1 进行 2 结束 3 帮助界面int isShowFPS = 0;//是否显示帧数int mouseX;//鼠标位置坐标Xint mouseY;//鼠标位置坐标Yint time_max;//总游戏时间int time_now;//当前剩余时间int level;//等级int score;//分数bool isMouseDown;//鼠标按下Block block[G_BM][G_BN];//方块数组COLORREF Defcolor[G_CN];//候选颜色数组//////////////////////////////以下是  函数声明  //////////////////////////////floatGetFPS();//获取帧数voidHpSleep(DWORD ms);//绝对延时PointGetMouseLocal(int x, int y);//获取鼠标所在坐标voidAddBlock(int n);//添加指定个数的未选中方块voidInit();//初始化voidDisCheck(int x, int y);//检测指定位置的消除intCountBlock();//统计方块个数voidManager();//逻辑处理voidDraw();//绘图处理voidStartDraw();//游戏开始绘图voidGamingDraw();//游戏进行中绘图voidEndDraw();//游戏结束绘图voidHelpDraw();//游戏帮助绘图voidEndFrame();//帧结束处理boolIsInRect(int x, int y, Rect r);//是否在矩形内//////////////////////////////以下是辅助功能函数////////////////////////////////计算画面FPS(每秒帧数)float GetFPS(){#define FPS_COUNT 8static int i = 0;static DWORD oldTime = GetTickCount();static float fps;if (i > FPS_COUNT){i = 0;int newTime = GetTickCount();int elapsedTime = newTime - oldTime;fps = FPS_COUNT / (elapsedTime / 1000.0f);oldTime = newTime;}i++;return fps;}//绝对延时void HpSleep(DWORD ms){static clock_t oldclock = clock();// 静态变量,记录上一次 tickoldclock += ms * CLOCKS_PER_SEC / 1000;// 更新 tickif (clock() > oldclock)// 如果已经超时,无需延时oldclock = clock();elsewhile(clock() < oldclock)// 延时Sleep(1);// 释放 CPU 控制权,降低 CPU 占用率}//获取鼠标选中点Point GetMouseLocal(int x, int y){Point p;x = (x - WIN_BLANK) / (G_BW + G_BS);y = (y - WIN_BLANK - WIN_BLANKTOP) / (G_BW + G_BS);if (x < 0 || x >= G_BN) x = -1;if (y < 0 || y >= G_BM) y = -1;p.x = x;p.y = y;return p;}//是否在矩形内bool IsInRect(int x, int y, Rect r){return ((x >= r.x && x <= r.w) && (y >= r.y && y <= r.h));}//添加制定个数的未选中方块void AddBlock(int n){//随机生成方块int num = 0, x1, y1, x2, y2;int num_max = n;while(num < num_max){x1 = rand() % G_BN;y1 = rand() % G_BM;x2 = rand() % G_BN;y2 = rand() % G_BM;if(block[y1][x1].isClick && block[y2][x2].isClick){COLORREF color = Defcolor[rand() % G_CN];block[y1][x1].color = color;block[y1][x1].isClick = false;block[y1][x1].FLOAT = 0;block[y1][x1].DIS = 0;block[y1][x1].isDIS = false;block[y2][x2].color = color;block[y2][x2].isClick = false;block[y2][x2].FLOAT = 0;block[y2][x2].DIS = 0;block[y2][x2].isDIS = false;num += 2;}}}//初始化void Init(){//预置颜色Defcolor[0] = RGB(255, 153, 0);Defcolor[1] = RGB(204, 102, 0);Defcolor[2] = RGB(27,  118, 255);Defcolor[3] = RGB(255, 136, 255);Defcolor[4] = RGB(204, 204, 102);Defcolor[5] = RGB(104, 204, 204);Defcolor[6] = RGB(255, 125, 125);Defcolor[7] = RGB(204, 104, 204);Defcolor[8] = RGB(190, 190, 190);Defcolor[9] = RGB(0,   204, 0);//初始化时间time_max = 10000;time_now = 10000;//初始化分数score = 0;//置全选中for(int i = 0; i < G_BM; i++){for(int j = 0; j < G_BN; j++){block[i][j].isClick = true;block[i][j].FLOAT = 0;block[i][j].DIS = 0;}}//添加方块AddBlock(G_BN * G_BM * 2 / 3);//清除鼠标消息队列FlushMouseMsgBuffer();}//统计方块个数int CountBlock(){int n = 0;for(int i = 0; i < G_BN; i++){for(int j = 0; j < G_BM; j++){if(!block[j][i].isClick) n++;}}return n;}//检测指定位置消除void DisCheck(int x, int y){//记录待消除的方块Block* b[4];int i, j, n = 0;//向左for(i = x; i >= 0; i--){if(!block[y][i].isClick){b[n] = &block[y][i];n++;break;}}//向右for(i = x; i < G_BN; i++){if(!block[y][i].isClick){b[n] = &block[y][i];n++;break;}}//向上for(j = y; j >= 0; j--){if(!block[j][x].isClick){b[n] = &block[j][x];n++;break;}}//向下for(j = y; j < G_BM; j++){if(!block[j][x].isClick){b[n] = &block[j][x];n++;break;}}//消除for(i = 0; i < n; i++){for(j = i + 1; j < n; j++){if(b[i]->color == b[j]->color){if(!b[i]->isDIS){b[i]->DIS = G_BDWO;b[i]->isDIS = true;}if(!b[j]->isDIS){b[j]->DIS = G_BDWO;b[j]->isDIS = true;}}}}isMouseDown = false;}//逻辑处理void Manager(){//如果在游戏中if(GamePhase == 1){Point p = GetMouseLocal(mouseX, mouseY);int x = p.x, y = p.y;//如果选中if(p.x != -1 && p.y != -1){//如果单击if(isMouseDown && block[y][x].isClick){//触发消除检测DisCheck(x, y);}}//添加新方块添加随机个数新方块if(CountBlock() < G_BN * G_BM / 3){AddBlock((rand() % 15 + 15) * 2);//时间恢复time_now += 500;if(time_now > time_max) time_now = time_max;}}}//开始绘图void StartDraw(){settextstyle(52, 30, _T("Impact"));//标题settextcolor(RGB(255, 17, 102));outtextxy(143, 93, _T("AyaCrossX"));settextcolor(RGB(255, 153, 238));outtextxy(140, 90, _T("AyaCrossX"));//版本settextstyle(22, 10, _T("Verdana"));settextcolor(RGB(255, 51, 68));outtextxy(340, 153, _T("v0.91 By:ls9512"));//开始游戏按钮Rect r;r.x = 240;r.y = 220;r.w = r.x + 125;r.h = r.y + 35;setlinecolor(RGB(255, 17, 102));if(IsInRect(mouseX, mouseY, r)) {setfillcolor(RGB(255, 187, 119));//开始游戏按键响应if(isMouseDown){Init();GamePhase = 1;isMouseDown = false;}}elsesetfillcolor(RGB(255, 255, 204));fillrectangle(r.x, r.y, r.w, r.h);settextstyle(25, 10, _T("Verdana"));settextcolor(RGB(255, 51, 68));outtextxy(r.x + 5, r.y + 5, _T("PLAY GAME"));//帮助游戏按钮r.x = 240;r.y = 270;r.w = r.x + 125;r.h = r.y + 35;setlinecolor(RGB(255, 17, 102));if(IsInRect(mouseX, mouseY, r)){setfillcolor(RGB(255, 187, 119));//帮助按键响应if(isMouseDown) GamePhase = 3;}elsesetfillcolor(RGB(255, 255, 204));fillrectangle(r.x, r.y, r.w, r.h);settextstyle(25, 10, _T("Verdana"));settextcolor(RGB(255, 51, 68));outtextxy(r.x + 5, r.y + 5, _T("HELP INFO"));//退出游戏按钮r.x = 240;r.y = 320;r.w = r.x + 125;r.h = r.y + 35;setlinecolor(RGB(255, 17, 102));if(IsInRect(mouseX, mouseY, r)){setfillcolor(RGB(255, 187, 119));//退出按键响应if(isMouseDown) exit(0);}elsesetfillcolor(RGB(255, 255, 204));fillrectangle(r.x, r.y, r.w, r.h);settextstyle(25, 10, _T("Verdana"));settextcolor(RGB(255, 51, 68));outtextxy(r.x + 5, r.y + 5, _T("EXIT GAME"));//说明settextstyle(16, 5, _T("Verdana"));settextcolor(RGB(255, 51, 68));outtextxy(175, 400, _T("Programing By VC++ & EasyX     Date:2013.11.01"));}//游戏中绘图void GameingDraw(){int x, y;COLORREF c, c2;//时间条x = WIN_BLANK;y = WIN_BLANK;int HPBARW = (G_BW + G_BS) * G_BN - 200;setlinecolor(RGB(255, 17, 255));setfillcolor(WHITE);fillrectangle(x, y, x + HPBARW, y + 10);setfillcolor(C_HPBAR);fillrectangle(x, y, x + (int)(HPBARW * (1.0 * time_now / time_max)), y + 10);//底板setlinecolor(RGB(255, 25, 22));setfillcolor(C_BLOCKPANEL);x = WIN_BLANK - G_BS;y = WIN_BLANK + WIN_BLANKTOP - G_BS;fillrectangle(x, y, x + (G_BW + G_BS) * G_BN + G_BS, y + (G_BW + G_BS) * G_BM + G_BS);//画方块for(int i = 0; i < G_BM; i++){for(int j = 0; j < G_BN; j++){if(!block[i][j].isClick){c = block[i][j].color;c = RGB(GetRValue(c) - (BYTE)G_BUL, GetGValue(c) - (BYTE)G_BUL, GetBValue(c) - (BYTE)G_BUL);int fw = (int)block[i][j].FLOAT;int fd = (int)block[i][j].DIS;setlinecolor(c);setfillcolor(block[i][j].color);x = j * (G_BW + G_BS) + WIN_BLANK - fw - fd;y = i * (G_BW + G_BS) + WIN_BLANK + WIN_BLANKTOP - fw - fd;fillrectangle(x, y, x + G_BW + 2 * (fw + fd), y + G_BW + 2 * (fw + fd));//浮动缩减if(block[i][j].FLOAT > 0) block[i][j].FLOAT -= 0.4f;//消失延迟if(block[i][j].isDIS){if(block[i][j].DIS < G_BDW)block[i][j].DIS += 0.4f;else{//消除block[i][j].isClick = true;//加分score += 100;time_now += 25;if (time_now > time_max) time_now = time_max;}}}}}//获取鼠标位置Point p = GetMouseLocal(mouseX, mouseY);//画出鼠标光标if(p.x != -1 && p.y != -1){c = RED;x = p.x, y = p.y;int fw;if(block[y][x].isClick) fw = 0;else fw = (int)block[y][x].FLOAT;x = x * (G_BW + G_BS) + WIN_BLANK - G_BSELECT - fw;y = y * (G_BW + G_BS) + WIN_BLANK + WIN_BLANKTOP - G_BSELECT -fw;//选中方块加亮if(!block[p.y][p.x].isClick){//置浮动大小block[p.y][p.x].FLOAT = G_FLOATW;c2 = block[p.y][p.x].color;}else{c2 = C_BLOCKPANEL;}setlinecolor(c);setfillcolor(c2);fillrectangle(x, y, x + G_BW + 2 * (G_BSELECT + fw), y + G_BW + 2 * (G_BSELECT + fw));}//画出分数settextstyle(25, 10, _T("Verdana"));settextcolor(RGB(155, 51, 68));TCHAR b[10];#if _MSC_VER > 1200_stprintf_s(b, _T("%d"), score);#else_stprintf(b, _T("%d"), score);#endifouttextxy(390, 15, _T("分数:"));settextcolor(RGB(255, 51, 68));outtextxy(440, 16, b);}//游戏结束绘图void EndDraw(){//标题settextstyle(52, 30, _T("Impact"));settextcolor(RGB(255, 17, 102));outtextxy(143, 103, _T("GAME OVER"));settextcolor(RGB(215, 193, 238));outtextxy(140, 100, _T("GAME OVER"));//版本settextstyle(34, 12, _T("Verdana"));settextcolor(RGB(255, 51, 68));TCHAR b[10];#if _MSC_VER > 1200_stprintf_s(b, _T("%d"), score);#else_stprintf(b, _T("%d"), score);#endifouttextxy(232, 173, _T("分数:"));outtextxy(290, 173, b);//重新开始游戏按钮Rect r;r.x = 240;r.y = 240;r.w = r.x + 125;r.h = r.y + 35;setlinecolor(RGB(255, 17, 102));if(IsInRect(mouseX, mouseY, r)){setfillcolor(RGB(255, 187, 119));//开始游戏按键响应if(isMouseDown){Init();GamePhase = 1;}}elsesetfillcolor(RGB(255, 255, 204));fillrectangle(r.x, r.y, r.w, r.h);settextstyle(25, 10, _T("Verdana"));settextcolor(RGB(255, 51, 68));outtextxy(r.x + 5, r.y + 5, _T("   REPLAY"));//退出r.x = 240;r.y = 290;r.w = r.x + 125;r.h = r.y + 35;setlinecolor(RGB(255, 17, 102));if(IsInRect(mouseX, mouseY, r)) {setfillcolor(RGB(255, 187, 119));//退出按键响应if(isMouseDown) exit(0);}elsesetfillcolor(RGB(255, 255, 204));fillrectangle(r.x, r.y, r.w, r.h);settextstyle(25, 10, _T("Verdana"));settextcolor(RGB(255, 51, 68));outtextxy(r.x + 5, r.y + 5, _T("EXIT GAME"));}//游戏帮助绘图void HelpDraw(){//标题settextstyle(52, 30, _T("Impact"));settextcolor(RGB(255, 17, 152));outtextxy(233, 33, _T("HELP"));settextcolor(RGB(215, 193, 238));outtextxy(230, 30, _T("HELP"));//底板setlinecolor(RGB(255, 17, 204));setfillcolor(RGB(255, 221, 255));fillrectangle(60, 100, 550, 280);//版本settextstyle(18, 10, _T("黑体"));settextcolor(RGB(245, 126, 92));outtextxy(70, 110, _T("十字消除是一款经典消除类小游戏。"));outtextxy(70, 145, _T("【玩法】"));outtextxy(80, 170, _T("1.点击空白处,所在横纵十字线上同色方块会被消除。"));outtextxy(80, 195, _T("2.消除方块会累加得分,并恢复一定量的时间."));outtextxy(80, 220, _T("3.方块数量少于某数值会出现新方块并回复时间."));outtextxy(80, 245, _T("4.时间耗尽时则游戏结束."));//返回Rect r;r.x = 240;r.y = 360;r.w = r.x + 125;r.h = r.y + 35;setlinecolor(RGB(255, 17, 102));if(IsInRect(mouseX, mouseY, r)) {setfillcolor(RGB(255, 187, 119));//返回按键响应if(isMouseDown) GamePhase = 0;}elsesetfillcolor(RGB(255, 255, 204));fillrectangle(r.x, r.y, r.w, r.h);settextstyle(25, 9, _T("Verdana"));settextcolor(RGB(255, 51, 68));outtextxy(r.x + 5, r.y + 5, _T("BACK MENU"));}//输出帧数void DrawFPS(){//输出帧数if(isShowFPS){settextcolor(RED);settextstyle(14, 0, _T("宋体"));TCHAR s[5];#if _MSC_VER > 1200_stprintf_s(s, _T("%.1f"), GetFPS());#else_stprintf(s, _T("%.1f"), GetFPS());#endifouttextxy(0, 0, s);}}//绘图void Draw(){//清屏setlinecolor(WHITE);setfillcolor(WHITE);fillrectangle(0, 0, WIN_WIDTH, WIN_HEIGHT);switch(GamePhase){case 0:StartDraw();break;case 1:GameingDraw();break;case 2:EndDraw();break;case 3:HelpDraw();break;}DrawFPS();}//帧结束处理void EndFrame(){time_now -= 2;//游戏结束if(time_now <= 0 && GamePhase == 1){GamePhase = 2;}}//主入口函数int main(){//置随机数种子srand((unsigned)time(NULL));//初始化设备,加载图片initgraph(WIN_WIDTH, WIN_HEIGHT);//设置窗口标题SetWindowText(GetHWnd(), _T("AyaCrossX v0.91 By:ls9512"));cleardevice();//设置黑色背景setbkmode(TRANSPARENT);settextcolor(BLACK);//开启双缓冲,防止闪屏BeginBatchDraw();// 鼠标消息变量MOUSEMSG mmsg;//初始化Init();while(true){//处理鼠标消息while(MouseHit()){mmsg = GetMouseMsg();switch(mmsg.uMsg){case WM_MOUSEMOVE:mouseX = mmsg.x; mouseY = mmsg.y;break;case WM_LBUTTONDOWN:isMouseDown = true;break;case WM_LBUTTONUP:isMouseDown = false;break;}}//逻辑处理Manager();//绘图处理Draw();//显示缓存的绘制内容FlushBatchDraw();//帧结束处理EndFrame();//延迟,帧数控制HpSleep(18);}// 关闭EndBatchDraw();closegraph();return 0;}

这个程序是我在13年10月时写的,有些细节也记不太清楚了,在这就不赘述了,如果有疑问的地方可以留言我看到了会回复解答。


【注】

此程序已被EasyX官网收录为范例:http://www.easyx.cn/samples/View.aspx?id=147


0 0
原创粉丝点击