赞
踩
每天一个C语言小项目,提升你的编程能力!
贪吃蛇游戏大家应该都不陌生了,要说没玩过的话,可能你是15后吧?
贪吃蛇游戏最初为单机模式,后续又陆续推出团战模式、赏金模式、挑战模式等多种玩法。
用游戏把子上下左右控制蛇的方向,寻找吃的东西,每吃一口就能得到一定的积分,而且蛇的身子会越吃越长,身子越长玩的难度就越大,不能碰墙,不能咬到自己的身体,更不能咬自己的尾巴,等到了一定的分数,就能过关,然后继续玩下一关。
贪吃蛇的唯一的目标就是长成最长的一条蛇!滑动摇杆控制小蛇走位,吃掉地图上彩色的小圆点,就会变长。
效果展示:
改变此款游戏的特别多。比如在蛋的方面,可能放上带道具的蛋,使蛇吃完后具有保护,穿墙等特种功能,而且难度逐渐变难。如果有编程技术比较强大的伙伴也可以去尝试一下哦!做出一个趋近完美的贪吃蛇那可就是能力的展现啦~
本项目编译环境:Visual Studio 2019/2022,EasyX插件
代码展示:
- #include <graphics.h>
- #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;
- }
大家赶紧去动手试试吧!
此外,我也给大家分享我收集的其他资源,从最零基础开始的教程到C语言C++项目案例,帮助大家在学习C语言的道路上披荆斩棘!
整理分享(多年学习的源码、项目实战视频、项目笔记,基础入门教程)最重要的是你可以在群里面交流提问编程问题哦!
欢迎转行和学习编程的伙伴,利用更多的资料学习成长比自己琢磨更快哦!(↓↓↓↓↓↓)
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。