CodeBus

分享代码,一起进步~

经典游戏 贪吃蛇

经典游戏贪吃蛇。 源代码如下: //////////////////////////////////////////// // 程序名称:贪吃蛇 // 编译环境:Visual C++ 6.0 / 2010,EasyX_2011惊蛰版 // 程序编写:轻雨漫步 <512655756@qq.com> // 最后更新:2011-3-11 // //////////////////////////////////////////// //开始编写游戏需要的类 //////////////////////////////////////////// #include <graphics.h> //EasyX_2011惊蛰版(绘图库) #include <stdio.h> #include <conio.h> #include <time.h> #define UP 1 #define DOWN 2 #define LEFT 3 #define RIGHT 4 //////////////////////////////////////////// //格子类,定义一个格子的属性及行为 //////////////////////////////////////////// class Cell { public: friend class GameArea; //设置友元函数 void setxy(short x, short y) //设置格子左上角坐标 { m_x = x, m_y = y; } void setfull(short full) //设置格子属性,0为空,1为障碍,2为食物 { m_full = full; } void display(COLORREF color) //设置格子颜色并显示 { m_color = color; setfillstyle(m_color); bar(m_x, m_y, m_x+7, m_y+7); } void LaserDisplay() //显示镭射状态的格子 { IMAGE image(10,10); SetWorkingImage(&image); DWORD* pMem = GetImageBuffer(&image); for(int i = 0; i < 10 * 10; i++) pMem[i] = BGR(RGB(0, 0, i * 256 / (10*10) )); SetWorkingImage(NULL); putimage(m_x,m_y,&image); } short ReturnFull() //返回格子状态 { return m_full; } Cell() //构造函数 { m_x = 0,m_y = 0,m_full = 0; m_color = BLACK; } private: short m_x; //格子的左上角X坐标 short m_y; //格子的左上角Y坐标 short m_full; //0为空,1为阻挡,2为食物 COLORREF m_color; //格子颜色 }; //////////////////////////////////////////// //游戏区类,编写有关游戏区的一些操作 //////////////////////////////////////////// class GameArea //游戏区域 { public: Cell m_game[60][60]; //定义游戏区域(由360个格子组成) friend void MessageDispose(); //设置友元函数 bool CreatFood() //产生随机食物 { srand(time(NULL)); //初始化随机数种子 m_random1 = rand()%58+1; //随机生成一个0 - 58的整数 m_random2 = rand()%58+1; //随机一个0 - 58的整数 if(m_game[m_random2][m_random2].m_full == 0) //检查生成的食物坐标是否在障碍上 { m_game[m_random1][m_random2].display(GREEN); m_game[m_random1][m_random2].m_full = 2; return true; } //如果随机的食物正好出现在蛇身上,则进入下面的循环寻找可以生成食物的地方 for(m_random1 = 1;m_random1 < 59;m_random1++) { for(m_random2 = 1;m_random2 < 59;m_random2++) { if(m_game[m_random2][m_random2].m_full == 0) { m_game[m_random1][m_random2].display(GREEN); m_game[m_random1][m_random2].m_full = 2; return true; } } } //如果没有找到可以生成食物的地方,则通关 return false; //返回false即表示通关 } void DelFood() //删除食物 { m_game[m_random1][m_random2].m_full = 0; //设置为0即代表格子属性为空 } void ChangeColor(int flag1,int flag2,COLORREF color) //设置指定格子的颜色 { m_game[flag1][flag2].display(color); } void Init() //初始化GAME区域 { int flag1,flag2; //标识变量 BeginBatchDraw(); //开始批量绘图 setfillstyle(BLACK); //设置当前颜色 bar(0,0,600,600); //画无边框填充矩形(在这里的用途是用黑色清空游戏区域) for(flag1 = 0;flag1 < 60;flag1++) { for(flag2 = 0;flag2 < 60;flag2++) { if(flag1 == 0 || flag1 == 59 || flag2 == 0 || flag2 == 59) //创建边界 { m_game[flag1][flag2].setfull(1); m_game[flag1][flag2].setxy(flag1*10,flag2*10); m_game[flag1][flag2].display(RGB(237,28,36)); } else //创建游戏区域 { m_game[flag1][flag2].setfull(0); m_game[flag1][flag2].setxy(flag1*10,flag2*10); m_game[flag1][flag2].display(BLACK); } } } CreatFood(); EndBatchDraw(); } private: int m_random1, m_random2; }; //////////////////////////////////////////// //蛇类,定义蛇的数据结构以及蛇的行为 //////////////////////////////////////////// class Snake { public: int toward; //蛇头朝向 friend void MessageDispose(); friend int HitDetect(); friend void ReInit(); Snake() { head = NULL; last = NULL; now = NULL; } void Init() //初始化蛇的结构 { if(head!=NULL) //重玩游戏时,释放原先的链表所有结点 { for(now = head->next;now->next != NULL;now = now->next) { free(now->prior); } } head = (struct node*)malloc(sizeof(struct node)); //为蛇头分配内存 head->prior = NULL; head->m_x = 300; head->m_y = 300; now = (struct node*)malloc(sizeof(struct node)); head->next = now; now->prior = head; now->next = NULL; now->m_x = 300; now->m_y = 290; last = now; toward = DOWN; } void SnakeAdd() { now = head; //当前指向蛇头 now->prior = (struct node*)malloc(sizeof(struct node)); //为新增的结点分配内存 now = now->prior; //让当前指向新分配的结点 now->prior = NULL; //置空当前结点的前趋 now->next = head; //让当前结点的后继指向蛇头 switch(toward) //根据当前蛇头方向确定新增部分的坐标 { case UP: now->m_x = head->m_x; now->m_y = head->m_y -10; break; case DOWN: now->m_x = head->m_x; now->m_y = head->m_y + 10; break; case LEFT: now->m_x = head->m_x - 10; now->m_y = head->m_y; break; case RIGHT: now->m_x = head->m_x + 10; now->m_y = head->m_y; break; } head = now; //设置当前结点为蛇头 } void SnakeDel() //释放蛇尾结点(删除蛇尾) { last = last->prior; free(last->next); last->next = NULL; } void SnakeMove() //蛇身移动一格 { SnakeAdd(); //增加蛇头 SnakeDel(); //删除蛇尾 } private: struct node //蛇身链表 { int m_x; int m_y; struct node *next; //下个结点 struct node *prior; //上个结点 }; struct node *head; struct node *last; struct node *now; }; //////////////////////////////////////////// //游戏类,用来初始化游戏的参数,及实现其他游戏操作 //////////////////////////////////////////// class Game { public: void Init() { closegraph(); initgraph(800,600); setbkmode(TRANSPARENT); //设置输出文字背景为透明 LOGFONT f; getfont(&f); // 获取当前字体设置 f.lfHeight = 50; // 设置字体高度为 48(包含行距) _tcscpy(f.lfFaceName, _T("黑体")); // 设置字体为“黑体” f.lfQuality = ANTIALIASED_QUALITY; // 设置输出效果为抗锯齿 setfont(&f); // 设置字体样式 } void FailGame() //游戏失败显示的画面 { setcolor(RED); setfont(70, 0, _T("微软雅黑")); outtextxy(150, 265, _T("YOU LOSE!")); } void WinGame() //游戏胜利时显示的画面 { setcolor(RED); setfont(70, 0, _T("微软雅黑")); outtextxy(150, 265, _T("YOU WIN!")); FlushBatchDraw(); Sleep(10000); exit(0); } }; //////////////////////////////////////////// //管理区类,定义管理区域的相关操作 //////////////////////////////////////////// class ManageArea { public: friend void MessageDispose(); void TimeAdd(double add) //增加时间(可在类外直接调用实现动态刷新时间) { m_time += add; DisplayTime(); } void ScoreAdd(short add) //增加分数(可在类外直接调用实现动态刷新分数) { m_score += add; DisplayScore(); } void DisplayPause() //显示暂停或者开始 { BeginBatchDraw(); _stprintf(m_str_score, _T("%d"), m_score); setfont(25, 0, _T("微软雅黑")); setfillstyle(m_bgcolor); bar(625,490,800,515); setcolor(BLUE); if(m_pause) outtextxy(625, 490, _T("开始(P键)")); else outtextxy(625, 490, _T("暂停(P键)")); EndBatchDraw(); } void Init() //初始化管理界面 { m_time = 0.0; m_score = 0; m_leave = 1; m_pause = false; _stprintf(m_str_score, _T("%d"), m_score); //格式化转换类型 _stprintf(m_str_time, _T("%.1lf"), m_time); m_bgcolor = BLACK; BeginBatchDraw(); setfillstyle(BLACK); bar(601,0,800,600); setfont(60, 0, _T("微软雅黑")); setcolor(GREEN); outtextxy(625, 30, _T("贪吃蛇")); setfont(30, 0, _T("微软雅黑")); setcolor(RGB(128,0,255)); outtextxy(625, 140, _T("制作:轻雨漫步")); setfont(25, 0, _T("微软雅黑")); setcolor(BLUE); outtextxy(625, 430, _T("时间:")); outtextxy(625, 460, _T("分数:")); outtextxy(625, 490, _T("暂停(P键)")); outtextxy(625, 520, _T("重新游戏(R键)")); setcolor(RED); outtextxy(720, 400, m_str_leave); outtextxy(680, 460, m_str_score); outtextxy(680, 430, m_str_time); EndBatchDraw(); } private: double m_time; short m_score; short m_leave; bool m_pause; TCHAR m_str_leave[2], m_str_time[33], m_str_score[5]; COLORREF m_bgcolor; void DisplayTime() //显示当前耗时 { BeginBatchDraw(); _stprintf(m_str_time, _T("%.1lf"), m_time); setfont(25, 0, _T("微软雅黑")); setfillstyle(m_bgcolor); bar(680,430,800,455); setcolor(RED); outtextxy(680,430,m_str_time); EndBatchDraw(); } void DisplayScore() //显示当前分数 { BeginBatchDraw(); _stprintf(m_str_score, _T("%d"), m_score); setfont(25, 0, _T("微软雅黑")); setfillstyle(m_bgcolor); bar(680,460,800,485); setcolor(RED); outtextxy(680,460,m_str_score); EndBatchDraw(); } }; //////////////////////////////////////////// //声明游戏需要的类 //////////////////////////////////////////// Game game; //用于初始化游戏、设置游戏相关参数 GameArea a; //用于初始化游戏区域,设置,改变游戏区域相关参数 ManageArea manager; //用于初始化管理区域,设置管理区相关参数 Snake s; //用于初始化蛇,数据化蛇,操作蛇 //////////////////////////////////////////// //游戏的消息控制,流程控制函数 //////////////////////////////////////////// void MessageDispose() //消息处理函数 { char c; s.now = NULL; bool Keepdown = false; while(true) { Keepdown = false; //是否持续按W A S D 中的一个按键 if(kbhit()) { switch(c = getch()) //处理按键消息(W A S D) { case 'w': case 'W': if(s.toward == UP)Keepdown = true; else if(s.toward != DOWN&&s.toward != UP)s.toward = UP; break; case 's': case 'S': if(s.toward == DOWN)Keepdown = true; else if(s.toward != UP&&s.toward != DOWN)s.toward = DOWN; break; case 'a': case 'A': if(s.toward == LEFT)Keepdown = true; else if(s.toward != RIGHT&&s.toward != LEFT)s.toward = LEFT; break; case 'd': case 'D': if(s.toward == RIGHT)Keepdown = true; else if(s.toward != LEFT&&s.toward != RIGHT)s.toward = RIGHT; break; case 'p': case 'P': manager.m_pause = !manager.m_pause; //设置暂停或开始 manager.DisplayPause(); //显示暂停或开始 break; case 'r': case 'R': ReInit(); break; } } if(true == manager.m_pause) //如果暂停,直接进行下次循环 { continue; } BeginBatchDraw(); switch(a.m_game[s.head->m_x/10][s.head->m_y/10].ReturnFull()) //检测蛇头遇到的情况 { case 2: //遇到食物,蛇身加长 a.ChangeColor(s.head->m_x/10,s.head->m_y/10,BLUE); s.SnakeAdd(); //蛇增长 a.ChangeColor(s.head->m_x/10,s.head->m_y/10,BLUE); a.DelFood(); //删除食物 if(a.CreatFood() == false) //创建新食物,并检查是否通关 { game.WinGame(); //游戏通关(当地图没地方创建食物时) } manager.ScoreAdd(1); //加一分 break; case 0: a.m_game[s.last->m_x/10][s.last->m_y/10].setfull(0); //设置蛇尾经过处无障碍 a.ChangeColor(s.last->m_x/10,s.last->m_y/10,BLACK); s.SnakeMove(); //蛇移动一次 a.ChangeColor(s.head->m_x/10,s.head->m_y/10,BLUE); a.m_game[s.head->next->m_x/10][s.head->next->m_y/10].setfull(1); //设置蛇头经过处有障碍 break; case 1: //遇到障碍物 game.FailGame(); a.ChangeColor(s.head->m_x/10,s.head->m_y/10,RGB(255,127,39)); FlushBatchDraw(); { char c = ' '; while(c != 'r' && c != 'R') //当游戏失败时,按R键可重新进行游戏 { if(kbhit()) { c = getch(); } Sleep(10); } } ReInit(); //重新开始游戏 break; } EndBatchDraw(); if(Keepdown==false) { Sleep(100); manager.TimeAdd(0.1); //增加时间 } else //当持续按下按方向键时 { Sleep(40); //适当休眠可以增加游戏流畅性 manager.TimeAdd(0.04); //增加时间 } } } //////////////////////////////////////////// //游戏初始化函数 //////////////////////////////////////////// void ReInit() { a.Init(); //初始化游戏区 s.Init(); //初始化蛇 manager.Init(); //初始化管理区 //绘制蛇的开始状态 s.now = s.head; a.ChangeColor(s.now->m_x/10,s.now->m_y/10,BLUE); s.now = s.last; a.ChangeColor(s.now->m_x/10,s.now->m_y/10,BLUE); } //////////////////////////////////////////// //main函数,程序入口 //////////////////////////////////////////// int main(void) { game.Init(); //初始化游戏参数、设置 ReInit(); //初始化其他 MessageDispose(); //消息处理函数 return 0; } 作者:轻雨漫步邮箱:512655756@qq.com

俄罗斯方块(Tetris) VC 源代码

童年的经典游戏~~ 。界面上没有做额外的修饰,需要的可以自己增加。执行效果如下: 上面的图是后来改的,下面这张是以前的执行效果。不知道这次的修改是不是对得起观众? 完整的 VC 源代码如下: //////////////////////////////////////////// // 程序名称:俄罗斯方块 // 编译环境:Visual C++ 6.0 / 2010,EasyX_v20131006(beta) // 程序编写:krissi <zhaoh1987@qq.com> // 更新记录:2010-12-18 zhaoh1987@qq.com 编写 //      2011-9-28 yw80@qq.com 修改了下落超时的逻辑 //      2013-10-7 zhaoh1987@qq.com 修改了绘制方法,将原来的立体效果修改为扁平效果 // #include <easyx.h> #include <conio.h> #include <time.h> ///////////////////////////////////////////// // 定义常量、枚举量、结构体、全局变量 ///////////////////////////////////////////// #define WIDTH 10 // 游戏区宽度 #define HEIGHT 22 // 游戏区高度 #define UNIT 20 // 每个游戏区单位的实际像素 // 定义操作类型 enum CMD { CMD_ROTATE, // 方块旋转 CMD_LEFT, CMD_RIGHT, CMD_DOWN, // 方块左、右、下移动 CMD_SINK, // 方块沉底 CMD_QUIT // 退出游戏 }; // 定义绘制方块的方法 enum DRAW { SHOW, // 显示方块 CLEAR, // 擦除方块 FIX // 固定方块 }; // 定义七种俄罗斯方块 struct BLOCK { WORD dir[4]; // 方块的四个旋转状态 COLORREF color; // 方块的颜色 } g_Blocks[7] = { {0x0F00, 0x4444, 0x0F00, 0x4444, RED}, // I {0x0660, 0x0660, 0x0660, 0x0660, BLUE}, // 口 {0x4460, 0x02E0, 0x0622, 0x0740, MAGENTA}, // L {0x2260, 0x0E20, 0x0644, 0x0470, YELLOW}, // 反L {0x0C60, 0x2640, 0x0C60, 0x2640, CYAN}, // Z {0x0360, 0x4620, 0x0360, 0x4620, GREEN}, // 反Z {0x4E00, 0x4C40, 0x0E40, 0x4640, BROWN}}; // T // 定义当前方块、下一个方块的信息 struct BLOCKINFO { byte id; // 方块 ID char x, y; // 方块在游戏区中的坐标 byte dir:2; // 方向 } g_CurBlock, g_NextBlock; // 定义游戏区 BYTE g_World[WIDTH][HEIGHT] = {0}; ///////////////////////////////////////////// // 函数声明 ///////////////////////////////////////////// void Init(); // 初始化游戏 void Quit(); // 退出游戏 void NewGame(); // 开始新游戏 void GameOver(); // 结束游戏 CMD GetCmd(); // 获取控制命令 void DispatchCmd(CMD _cmd); // 分发控制命令 void NewBlock(); // 生成新的方块 bool CheckBlock(BLOCKINFO _block); // 检测指定方块是否可以放下 void DrawUnit(int x, int y, COLORREF c, DRAW _draw); // 画单元方块 void DrawBlock(BLOCKINFO _block, DRAW _draw = SHOW); // 画方块 void OnRotate(); // 旋转方块 void OnLeft(); // 左移方块 void OnRight(); // 右移方块 void OnDown(); // 下移方块 void OnSink(); // 沉底方块 ///////////////////////////////////////////// // 函数定义 ///////////////////////////////////////////// // 主函数 void main() { Init(); CMD c; while(true) { c = GetCmd(); DispatchCmd(c); // 按退出时,显示对话框咨询用户是否退出 if (c == CMD_QUIT) { HWND wnd = GetHWnd(); if (MessageBox(wnd, _T("您要退出游戏吗?"), _T("提醒"), MB_OKCANCEL | MB_ICONQUESTION) == IDOK) Quit(); } } } // 初始化游戏 void Init() { initgraph(640, 480); srand((unsigned)time(NULL)); setbkmode(TRANSPARENT); // 设置图案填充的背景色为透明 // 显示操作说明 settextstyle(14, 0, _T("宋体")); outtextxy(20, 330, _T("操作说明")); outtextxy(20, 350, _T("上:旋转")); outtextxy(20, 370, _T("左:左移")); outtextxy(20, 390, _T("右:右移")); outtextxy(20, 410, _T("下:下移")); outtextxy(20, 430, _T("空格:沉底")); outtextxy(20, 450, _T("ESC:退出")); // 设置坐标原点 setorigin(220, 20); // 绘制游戏区边界 rectangle(-1, -1, WIDTH * UNIT, HEIGHT * UNIT); rectangle((WIDTH + 1) * UNIT - 1, -1, (WIDTH + 5) * UNIT, 4 * UNIT); // 开始新游戏 NewGame(); } // 退出游戏 void Quit() { closegraph(); exit(0); } // 开始新游戏 void NewGame() { // 清空游戏区 setfillcolor(BLACK); solidrectangle(0, 0, WIDTH * UNIT - 1, HEIGHT * UNIT - 1); ZeroMemory(g_World, WIDTH * HEIGHT); // 生成下一个方块 g_NextBlock.id = rand() % 7; g_NextBlock.dir = rand() % 4; g_NextBlock.x = WIDTH + 1; g_NextBlock.y = HEIGHT - 1; // 获取新方块 NewBlock(); } // 结束游戏 void GameOver() { HWND wnd = GetHWnd(); if (MessageBox(wnd, _T("游戏结束。\n您想重新来一局吗?"), _T("游戏结束"), MB_YESNO | MB_ICONQUESTION) == IDYES) NewGame(); else Quit(); } // 获取控制命令 DWORD m_oldtime; CMD GetCmd() { // 获取控制值 while(true) { // 如果超时,自动下落一格 DWORD newtime = GetTickCount(); if (newtime - m_oldtime >= 500) { m_oldtime = newtime; return CMD_DOWN; } // 如果有按键,返回按键对应的功能 if (kbhit()) { switch(getch()) { case 'w': case 'W': return CMD_ROTATE; case 'a': case 'A': return CMD_LEFT; case 'd': case 'D': return CMD_RIGHT; case 's': case 'S': return CMD_DOWN; case 27: return CMD_QUIT; case ' ': return CMD_SINK; case 0: case 0xE0: switch(getch()) { case 72: return CMD_ROTATE; case 75: return CMD_LEFT; case 77: return CMD_RIGHT; case 80: return CMD_DOWN; } } } // 延时 (降低 CPU 占用率) Sleep(20); } } // 分发控制命令 void DispatchCmd(CMD _cmd) { switch(_cmd) { case CMD_ROTATE: OnRotate(); break; case CMD_LEFT: OnLeft(); break; case CMD_RIGHT: OnRight(); break; case CMD_DOWN: OnDown(); break; case CMD_SINK: OnSink(); break; case CMD_QUIT: break; } } // 生成新的方块 void NewBlock() { g_CurBlock.id = g_NextBlock.id, g_NextBlock.id = rand() % 7; g_CurBlock.dir = g_NextBlock.dir, g_NextBlock.dir = rand() % 4; g_CurBlock.x = (WIDTH - 4) / 2; g_CurBlock.y = HEIGHT + 2; // 下移新方块直到有局部显示 WORD c = g_Blocks[g_CurBlock.id].dir[g_CurBlock.dir]; while((c & 0xF) == 0) { g_CurBlock.y--; c >>= 4; } // 绘制新方块 DrawBlock(g_CurBlock); // 绘制下一个方块 setfillcolor(BLACK); solidrectangle((WIDTH + 1) * UNIT, 0, (WIDTH + 5) * UNIT - 1, 4 * UNIT - 1); DrawBlock(g_NextBlock); // 设置计时器,用于判断自动下落 m_oldtime = GetTickCount(); } // 画单元方块 void DrawUnit(int x, int y, COLORREF c, DRAW _draw) { // 计算单元方块对应的屏幕坐标 int left = x * UNIT; int top = (HEIGHT - y - 1) * UNIT; int right = (x + 1) * UNIT - 1; int bottom = (HEIGHT - y) * UNIT - 1; // 画单元方块 switch(_draw) { case SHOW: // 画普通方块 setlinecolor(0x006060); roundrect(left + 1, top + 1, right - 1, bottom - 1, 5, 5); setlinecolor(0x003030); roundrect(left, top, right, bottom, 8, 8); setfillcolor(c); setlinecolor(LIGHTGRAY); fillrectangle(left + 2, top + 2, right - 2, bottom - 2); break; case FIX: // 画固定的方块 setfillcolor(RGB(GetRValue(c) * 2 / 3, GetGValue(c) * 2 / 3, GetBValue(c) * 2 / 3)); setlinecolor(DARKGRAY); fillrectangle(left + 1, top + 1, right - 1, bottom - 1); break; case CLEAR: // 擦除方块 setfillcolor(BLACK); solidrectangle(x * UNIT, (HEIGHT - y - 1) * UNIT, (x + 1) * UNIT - 1, (HEIGHT - y) * UNIT - 1); break; } } // 画方块 void DrawBlock(BLOCKINFO _block, DRAW _draw) { WORD b = g_Blocks[_block.id].dir[_block.dir]; int x, y; for(int i = 0; i < 16; i++, b <<= 1) if (b & 0x8000) { x = _block.x + i % 4; y = _block.y - i / 4; if (y < HEIGHT) DrawUnit(x, y, g_Blocks[_block.id].color, _draw); } } // 检测指定方块是否可以放下 bool CheckBlock(BLOCKINFO _block) { WORD b = g_Blocks[_block.id].dir[_block.dir]; int x, y; for(int i = 0; i < 16; i++, b <<= 1) if (b & 0x8000) { x = _block.x + i % 4; y = _block.y - i / 4; if ((x < 0) || (x >= WIDTH) || (y < 0)) return false; if ((y < HEIGHT) && (g_World[x][y])) return false; } return true; } // 旋转方块 void OnRotate() { // 获取可以旋转的 x 偏移量 int dx; BLOCKINFO tmp = g_CurBlock; tmp.dir++; if (CheckBlock(tmp)) { dx = 0; goto rotate; } tmp.x = g_CurBlock.x - 1; if (CheckBlock(tmp)) { dx = -1; goto rotate; } tmp.x = g_CurBlock.x + 1; if (CheckBlock(tmp)) { dx = 1; goto rotate; } tmp.x = g_CurBlock.x - 2; if (CheckBlock(tmp)) { dx = -2; goto rotate; } tmp.x = g_CurBlock.x + 2; if (CheckBlock(tmp)) { dx = 2; goto rotate; } return; rotate: // 旋转 DrawBlock(g_CurBlock, CLEAR); g_CurBlock.dir++; g_CurBlock.x += dx; DrawBlock(g_CurBlock); } // 左移方块 void OnLeft() { BLOCKINFO tmp = g_CurBlock; tmp.x--; if (CheckBlock(tmp)) { DrawBlock(g_CurBlock, CLEAR); g_CurBlock.x--; DrawBlock(g_CurBlock); } } // 右移方块 void OnRight() { BLOCKINFO tmp = g_CurBlock; tmp.x++; if (CheckBlock(tmp)) { DrawBlock(g_CurBlock, CLEAR); g_CurBlock.x++; DrawBlock(g_CurBlock); } } // 下移方块 void OnDown() { BLOCKINFO tmp = g_CurBlock; tmp.y--; if (CheckBlock(tmp)) { DrawBlock(g_CurBlock, CLEAR); g_CurBlock.y--; DrawBlock(g_CurBlock); } else OnSink(); // 不可下移时,执行“沉底方块”操作 } // 沉底方块 void OnSink() { int i, x, y; // 连续下移方块 DrawBlock(g_CurBlock, CLEAR); BLOCKINFO tmp = g_CurBlock; tmp.y--; while (CheckBlock(tmp)) { g_CurBlock.y--; tmp.y--; } DrawBlock(g_CurBlock, FIX); // 固定方块在游戏区 WORD b = g_Blocks[g_CurBlock.id].dir[g_CurBlock.dir]; for(i = 0; i < 16; i++, b <<= 1) if (b & 0x8000) { if (g_CurBlock.y - i / 4 >= HEIGHT) { // 如果方块的固定位置超出高度,结束游戏 GameOver(); return; } else g_World[g_CurBlock.x + i % 4][g_CurBlock.y - i / 4] = 1; } // 检查是否需要消掉行,并标记 BYTE remove = 0; // 低 4 位用来标记方块涉及的 4 行是否有消除行为 for(y = g_CurBlock.y; y >= max(g_CurBlock.y - 3, 0); y--) { i = 0; for(x = 0; x < WIDTH; x++) if (g_World[x][y] == 1) i++; if (i == WIDTH) { remove |= (1 << (g_CurBlock.y - y)); setfillcolor(LIGHTGREEN); setlinecolor(LIGHTGREEN); setfillstyle(BS_HATCHED, HS_DIAGCROSS); fillrectangle(0, (HEIGHT - y - 1) * UNIT + UNIT / 2 - 5, WIDTH * UNIT - 1, (HEIGHT - y - 1) * UNIT + UNIT / 2 + 5); setfillstyle(BS_SOLID); } } if (remove) // 如果产生整行消除 { // 延时 300 毫秒 Sleep(300); // 擦掉刚才标记的行 IMAGE img; for(i = 0; i < 4; i++, remove >>= 1) { if (remove & 1) { for(y = g_CurBlock.y - i + 1; y < HEIGHT; y++) for(x = 0; x < WIDTH; x++) { g_World[x][y - 1] = g_World[x][y]; g_World[x][y] = 0; } getimage(&img, 0, 0, WIDTH * UNIT, (HEIGHT - (g_CurBlock.y - i + 1)) * UNIT); putimage(0, UNIT, &img); } } } // 产生新方块 NewBlock(); }

涂格子游戏(也叫点灯游戏)(by 豆腐果)

该游戏是经典的涂格子游戏,很有挑战性。 游戏运行效果: 完整的 VC 源代码如下: /********************************************************** * 程序功能:涂格子游戏 * 程序版本:v0.1 基本功能演示版本,简单动态效果,可以过关 * 编译环境:Visual C++ 6.0,EasyX_20130506(beta) * 最后更新:2010-11-9 **********************************************************/ #include <graphics.h> #include <conio.h> #define MaxNum 14 //单边最大格子数 #define G_length 30 //格子边长 #define USER_LBUTTONDOWN 101 #define USER_RBUTTONDOWN 102 #define USER_MBUTTONDOWN 103 /////////////////////////////////////////////// void PaintGrid(int Mid_x, int Mid_y, int num, int color); // 绘制游戏格子,初始化格子 void OnLButtonDown(MOUSEMSG m, int num); // 左键按下 void OnRButtonDown(int num); // 右键按下 void OnMButtonDown(); // 中键按下*暂无定义* void welcome(); // 显示游戏主界面 void goodbye(int num); // 显示结束画面 void NextLevel(int num); // 下一关 int GetMessage(MOUSEMSG m); // 获取鼠标信息 int DispatchMessage(MOUSEMSG m, int opt); // 分发鼠标信息 int JudgeFull(int num, int array[MaxNum][MaxNum]); // 格子是否填满 /////////////////////////////////////////////// // 定义游戏格子结构体 struct Grid { int left; // 游戏区域边界 int right; int top; int bottom; int array[MaxNum][MaxNum]; // 记录格子状态 int num; // 记录边界格子数目 }grid; /////////////////////////////////////////////// void main() { int opt, end=0; grid.num=4; welcome(); PaintGrid(320, 240, grid.num, RGB(0,255,0)); MOUSEMSG m; while(end!=1) { m = GetMouseMsg(); opt = GetMessage(m); end=DispatchMessage(m, opt); } goodbye(grid.num); closegraph(); } /////////////////////////////////////////////// // 获取鼠标信息 int GetMessage(MOUSEMSG m) { //鼠标循环 switch(m.uMsg) { case WM_LBUTTONDOWN: return USER_LBUTTONDOWN; case WM_RBUTTONDOWN: return USER_RBUTTONDOWN; case WM_MBUTTONDOWN: return USER_MBUTTONDOWN; } return 0; } /////////////////////////////////////////////// // 分发消息 int DispatchMessage(MOUSEMSG m, int opt) { switch(opt) { case USER_LBUTTONDOWN: // 左键填色 OnLButtonDown(m, grid.num); // 判断是否填满 if(JudgeFull(grid.num, grid.array)==1) { grid.num++; // 格子数目超过最大值通关 if(grid.num>MaxNum) { return 1; break; } else NextLevel(grid.num); } break; case USER_RBUTTONDOWN: // 右键清除 OnRButtonDown(grid.num); break; case USER_MBUTTONDOWN: return 1; break; } return 0; } /////////////////////////////////////////////// // 左键按下 void OnLButtonDown(MOUSEMSG m, int num) { int nx, ny, x, y; if(m.x>grid.left && m.x<grid.right && m.y>grid.top && m.y<grid.bottom) { // 计算位置 nx=(int)(m.x - grid.left)/G_length; ny=(int)(m.y - grid.top )/G_length; // 转换格子状态 grid.array[nx][ny] = -grid.array[nx][ny]; if(nx >= 0 && nx < num-1) grid.array[nx+1][ny] = -grid.array[nx+1][ny]; if(nx > 0 && nx <= num-1) grid.array[nx-1][ny] = -grid.array[nx-1][ny]; if(ny >= 0 && ny < num-1) grid.array[nx][ny+1] = -grid.array[nx][ny+1]; if(ny > 0 && ny <= num-1) grid.array[nx][ny-1] = -grid.array[nx][ny-1]; // 扫描填色 for(nx=0; nx<num; nx++) for(ny=0; ny<num; ny++) { if(grid.array[nx][ny] == 1) setfillcolor(GREEN); else setfillcolor(BLACK); x= nx * G_length + grid.left; y= ny * G_length + grid.top; solidrectangle(x+1, y+1, x+G_length-1, y+G_length-1); } } } /////////////////////////////////////////////// // 右键按下清空 void OnRButtonDown(int num) { int x, y, nx, ny; for(x=0; x<num; x++) for(y=0; y<num; y++) grid.array[x][y] = -1; for(nx=0; nx<num; nx++) for(ny=0; ny<num; ny++) { setfillcolor(BLACK); x= nx*G_length + grid.left; y= ny*G_length + grid.top; solidrectangle(x+1, y+1, x+G_length-1, y+G_length-1); } } /////////////////////////////////////////////// // 显示下一关 // 参数: // num: 下一关的边界格子数 void NextLevel(int num) { // 清屏 BeginBatchDraw(); for(int y=0; y<=480; y+=5) { setlinecolor(RGB(0, 255, 0)); settextcolor(RGB(0, 255, 0)); line(0, y, 640, y); line(0, 480-y, 640, 480-y); outtextxy(300, y, "下一关"); FlushBatchDraw(); Sleep(16); setfillcolor(BLACK); solidrectangle(0, y+4, 640, y-5); solidrectangle(0, 480-y, 640, 480-y+5); } EndBatchDraw(); // 绘制下一关格子 PaintGrid(320, 240, num, RGB(0,255,0)); } /////////////////////////////////////////////// // 判断格子是否填满 // 参数: // num: 单边格子数目 // array: 生成数组接收实参 int JudgeFull(int num, int array[MaxNum][MaxNum]) { int c=-1; int nx=0, ny=0; while(nx<num && ny<num) { for(nx=0; nx<num; nx++) for(ny=0; ny<num; ny++) if(array[nx][ny]==1) continue; else return c; } c=1; return c; } /////////////////////////////////////////////// // 绘制游戏格子,初始化格子 // 参数: // Mid_x: 屏幕中心 x 坐标 // Mid_y: 屏幕中心 y 坐标 // num: 单边格子数目 // color: 格子线条颜色 void PaintGrid(int Mid_x, int Mid_y, int num, int color) { int x,y,nx,ny; // 游戏区域大小 grid.left = Mid_x-num*G_length/2; grid.right = Mid_x+num*G_length/2; grid.top = Mid_y-num*G_length/2; grid.bottom = Mid_y+num*G_length/2; // 绘制格子 setlinecolor(color); for(x=grid.left; x<=grid.right; x+=G_length) { line(x, grid.top, x, grid.bottom); Sleep(10); } for(y=grid.top; y<=grid.bottom; y+=G_length) { line(grid.left, y, grid.right, y); Sleep(10); } // 外边框 for(x=20;x>10;x--) { line(grid.left-x, grid.top-x, grid.right+x, grid.top-x); line(grid.left-x, grid.bottom+x, grid.right+x, grid.bottom+x); line(grid.left-x, grid.top-x, grid.left-x, grid.bottom+x); line(grid.right+x, grid.top-x, grid.right+x, grid.bottom+x); Sleep(5); } // 清空单元格 for(x=0; x<num; x++) for(y=0; y<num; y++) grid.array[x][y] = -1; for(nx=0; nx<num; nx++) for(ny=0; ny<num; ny++) { setfillcolor(BLACK); x = nx * G_length + grid.left; y = ny * G_length + grid.top; solidrectangle(x+1, y+1, x+G_length-1, y+G_length-1); } } /////////////////////////////////////////////// // 显示游戏主界面 void welcome() { // 初始化窗口 initgraph(640, 480); // 输出屏幕提示 cleardevice(); settextcolor(RGB(0,255,0)); settextstyle(64, 0, "黑体"); outtextxy(70, 50, "涂格子游戏(点灯)"); settextcolor(WHITE); settextstyle(16, 0, "宋体"); outtextxy(100, 200, "每点一个格子,上下左右的格子也会做出于现状相反的动作"); outtextxy(100, 240, "总共11关,左键填色,右键重来,中键退出"); outtextxy(100, 280, "只是一个功能演示版本,以后再改进"); outtextxy(400, 320, "by:doufuguolyl"); settextstyle(16, 0, "黑体"); outtextxy(400, 340, "Ver 0.1"); // 实现闪烁的"按任意键继续" int c=255; while(!kbhit()) { settextcolor(RGB(0, c, 0)); outtextxy(280, 400, "按任意键继续"); c -= 8; if (c < 0) c = 255; Sleep(20); } getch(); cleardevice(); } /////////////////////////////////////////////// // 显示结束画面 void goodbye(int num) { int c=255; // 清屏 BeginBatchDraw(); for(int y=0; y<=480; y+=5) { setlinecolor(RGB(0, 255, 0)); line(0, y, 640, y); line(0, 480-y, 640, 480-y); FlushBatchDraw(); Sleep(16); setfillcolor(BLACK); solidrectangle(0, y+4, 640, y-5); solidrectangle(0, 480-y, 640, 480-y+5); } EndBatchDraw(); //判断显示文字 if(num == MaxNum+1) { settextcolor(RGB(0, c, 0)); settextstyle(48, 0, "黑体"); outtextxy(280, 200, "通关"); settextstyle(20, 0, "黑体"); } else { settextcolor(RGB(0, c, 0)); settextstyle(48, 0, "黑体"); outtextxy(200, 200, "再接再厉"); settextstyle(20, 0, "黑体"); } while(!kbhit()) { settextcolor(RGB(0, c, 0)); outtextxy(400, 400, "QQ: 372480348"); c -= 8; if (c < 0) c = 255; Sleep(20); } getch(); } 作者:豆腐果贴吧:https://www.baidu.com/p/doufuguolyl

打字母游戏

某天突然来兴趣了,就写了这么个打字母的小程序,就是以前学习机上那种字母往下掉,然后按相应键字母消失的游戏。 程序不长,尤其很大篇幅都是开始和结束的文字绘制,除去这些没几行代码了,感觉做个范例还是很有用的。 又补了个小特效,加了点注释。。。一看,整100行,呵呵。 完整的源代码如下: //////////////////////////////////////////// // 程序名称:打字母游戏 // 编译环境:Visual C++ 6.0,EasyX 2011惊蛰版 // 程序编写:yangw80 <yw80@qq.com> // 最后更新:2010-8-26 // #include <graphics.h> #include <conio.h> #include <time.h> // 欢迎界面 void welcome() { // 输出屏幕提示 cleardevice(); setcolor(YELLOW); setfont(64, 0, "黑体"); outtextxy(160, 50, "打字母游戏"); setcolor(WHITE); setfont(16, 0, "宋体"); outtextxy(100, 200, "就是很传统的那个掉字母然后按相应键就消失的游戏"); outtextxy(100, 240, "只是做了一个简单的实现"); outtextxy(100, 280, "功能并不很完善,比如生命数、分数等都没有写"); outtextxy(100, 320, "感兴趣的自己加进去吧"); // 实现闪烁的“按任意键继续” int c=255; while(!kbhit()) { setcolor(RGB(c, 0, 0)); outtextxy(280, 400, "按任意键继续"); c -= 8; if (c < 0) c = 255; Sleep(20); } getch(); cleardevice(); } // 退出界面 void goodbye() { cleardevice(); setcolor(YELLOW); setfont(48, 0, "黑体"); outtextxy(104, 180, "多写程序 不老青春"); getch(); } // 主函数 void main() { initgraph(640, 480); // 初始化屏幕为 640x480 welcome(); // 显示欢迎界面 srand(time(NULL)); // 设置随机种子 setfont(16, 0, "Arial"); // 设置字母的字体和大小 setfillstyle(BLACK); // 设置清除字母的填充区域颜色 char target; // 目标字母 char key; // 用户的按键 int x, y; // 字母的位置 // 主循环 while(true) { target = 65 + rand() % 26; // 产生任意大写字母 x = rand() % 620; // 产生任意下落位置 for (y=0; y<460; y++) { setcolor(WHITE); // 设置字母的颜色 outtextxy(x, y, target); // 显示字母 if(kbhit()) { key = getch(); // 获取用户按键 if((key == target) || (key == target + 32)) { // 按键正确,“击落”字母(画黑色方块擦除) bar(x, y, x + 16, y + 16); break; // 跳出循环,进行下一个字母 } else if (key == 27) { goto EXIT; // 如果按 ESC,退出游戏主循环 } } // 延时,并清除字母 Sleep(10); bar(x, y, x + 16, y + 16); } } EXIT: // 退出部分 goodbye(); // 关闭图形界面 closegraph(); }