当前位置: 首页 > news >正文

项目:贪吃蛇实现

头文件 snake.h

#include<stdio.h>
#include<stdlib.h>
#include<windows.h>
#include<locale.h>
#include<stdbool.h>
#include<time.h>#define POS_X 24#define POS_Y 5
#define BODY L'●' 
#define FOOD L'★'
#define KEY_PRESS(VK)  ((GetAsyncKeyState(VK)&0x1) ? 1 : 0)enum DIRECTION
{UP = 1,DOWN,LEFT,RIGHT};enum GAME_STATES
{OK,//正常状态KILL_BY_WALL,//撞墙KILL_BY_SELF,//撞到自己END_NORMAL//正常结束
};typedef struct SnakeNode
{//坐标int x;int y;//指向下一个节点的指针struct SnakeNode* next;}SnakeNode,*pSnakeNode;typedef struct Snake
{pSnakeNode _pSnake;//指向蛇头的指针pSnakeNode _pFood;//指向食物的指针enum DIRECTION _dir;//蛇的方向enum GAME_STATES _state; //游戏的状态int _food_weight;//食物的分数int _score;//总成绩int _sleep_time;//休息时间,时间越短速度越快
}Snake, * pSnake;void GameStart(pSnake ps);void WelcomGame();void CreatMap();void InitSnake(pSnake ps);void CreatFood(pSnake ps);void GameRun(pSnake ps);void SnakeMove(pSnake ps);int NextIsFood(pSnakeNode pn, pSnake ps);void EatFood(pSnakeNode psn, pSnake ps);void NoFood(pSnakeNode psn, pSnake ps);int KillByWall(pSnake ps);int KillBySelf(pSnake ps);void GameOver(pSnake ps);

snake.c

#include"snake.h"//设置光标的坐标
void SetPos(short x, short y)
{COORD pos = { x, y };HANDLE hOutput = NULL;//获取标准输出的句柄(⽤来标识不同设备的数值)hOutput = GetStdHandle(STD_OUTPUT_HANDLE);//设置标准输出上光标的位置为posSetConsoleCursorPosition(hOutput, pos);
}
void WelcomGame()
{SetPos(40,14);wprintf(L"欢迎来到贪吃蛇小游戏\n");SetPos(42, 20);system("pause");system("cls");SetPos(25, 14);wprintf(L"用↑.↓.←.→ 来控制蛇的移动,F3加速F4减速\n");SetPos(25, 15);wprintf(L"加速获得的分数更多\n");SetPos(42, 20);system("pause");system("cls");
}
void CreatMap()
{int i = 0;//上for(i = 0; i < 29; i++){wprintf(L"%lc", L'□');}//下SetPos(0, 26);for (i = 0; i < 29; i++){wprintf(L"%lc", L'□');}//左for (i = 1; i <= 25; i++){SetPos(0, i);wprintf(L"%lc", L'□');}//右for (i = 1; i <= 25; i++){SetPos(56, i);wprintf(L"%lc", L'□');}}void InitSnake(pSnake ps)
{pSnakeNode cur = NULL;int i = 0;for (i = 0;i<5; i++){cur = (pSnakeNode)malloc(sizeof(SnakeNode));if (cur == NULL){perror("malloc");exit(1);}cur->next = NULL;cur->x = POS_X + 2 * i;cur->y = POS_Y;//头插法if (ps->_pSnake == NULL){ps->_pSnake = cur;}else//非空{cur->next = ps->_pSnake;ps->_pSnake = cur;}}//打印蛇的身体cur = ps->_pSnake;while (cur){SetPos(cur->x, cur->y);wprintf(L"%lc", BODY);cur = cur->next;}//设置游戏初始数据ps->_state = OK;//游戏状态ps->_dir = RIGHT;//蛇的初始方向朝右ps->_food_weight = 10;//一个食物10分ps->_score = 0;//初始为0分ps->_sleep_time = 200;//单位ms}void CreatFood(pSnake ps)
{int x = 0;int y = 0;
again:do{x = rand() % 53 + 2;y = rand() % 25 + 1;} while (x % 2 != 0);//x y 的坐标不能和蛇的身体冲突pSnakeNode cur = ps->_pSnake;while (cur){if (x == cur->x && y == cur->y){goto again;}cur = cur->next;}//创建食物的节点pSnakeNode pFood = (pSnakeNode)malloc(sizeof(SnakeNode));if (pFood == NULL){perror("malloc");exit(1);}pFood->x = x;pFood->y = y;pFood->next = NULL;SetPos(x, y);wprintf(L"%lc", FOOD);ps->_pFood = pFood;}void GameStart(pSnake ps)
{//先设置窗口大小,光标隐藏system("mode con cols=100 lines=30");system("title 贪吃蛇");HANDLE houtput = GetStdHandle(STD_OUTPUT_HANDLE);//隐藏光标操作CONSOLE_CURSOR_INFO CursorInfo;GetConsoleCursorInfo(houtput, &CursorInfo);//获取控制台光标信息CursorInfo.bVisible = false; //隐藏控制台光标SetConsoleCursorInfo(houtput, &CursorInfo);//设置控制台光标状态//getchar();//初始化游戏//打印环境界面WelcomGame();//地图绘制CreatMap();//创建蛇InitSnake(ps);//创建食物CreatFood(ps);
}
void PrintHelpInfo()
{//打印提⽰信息SetPos(64, 14);wprintf(L"先按esc启动贪吃蛇\n");SetPos(64, 15);wprintf(L"不能穿墙,不能咬到自己\n");SetPos(64, 16);wprintf(L"用↑.↓.←.→ 来控制蛇的移动\n");SetPos(64, 17);wprintf(L"F3 为加速,F4为减速\n");SetPos(64, 18);wprintf(L"ESC :退出游戏.space:暂停游戏");SetPos(64, 20);wprintf(L"景风制作");}//pSnakeNode psn 是下⼀个节点的地址
//pSnake ps 维护蛇的指针
int NextIsFood(pSnakeNode psn, pSnake ps)
{return (psn->x == ps->_pFood->x) && (psn->y == ps->_pFood->y);
}//pSnakeNode psn 是下⼀个节点的地址
//pSnake ps 维护蛇的指针
void EatFood(pSnakeNode psn, pSnake ps)
{//头插法psn->next = ps->_pSnake;ps->_pSnake = psn;//打印蛇pSnakeNode cur = ps->_pSnake;while (cur){SetPos(cur->x, cur->y);wprintf(L"%c", BODY);cur = cur->next;}ps->_score += ps->_food_weight;//释放⻝物节点free(ps->_pFood);//创建新的⻝物CreatFood(ps);}void NoFood(pSnakeNode psn, pSnake ps)
{//头插法psn->next = ps->_pSnake;ps->_pSnake = psn;//打印蛇pSnakeNode cur = ps->_pSnake;while (cur->next->next){SetPos(cur->x, cur->y);wprintf(L"%c", BODY);cur = cur->next;}//最后⼀个位置打印空格,然后释放节点SetPos(cur->next->x, cur->next->y);printf("  ");free(cur->next);cur->next = NULL;
}void SnakeMove(pSnake ps)
{//创建下⼀个节点pSnakeNode pNextNode = (pSnakeNode)malloc(sizeof(SnakeNode));if (pNextNode == NULL){perror("SnakeMove()::malloc()");return;}//确定下⼀个节点的坐标,下⼀个节点的坐标根据,蛇头的坐标和⽅向确定switch(ps->_dir){case UP:{pNextNode->x = ps->_pSnake->x;pNextNode->y = ps->_pSnake->y - 1;}break;case DOWN:{pNextNode->x = ps->_pSnake->x;pNextNode->y = ps->_pSnake->y + 1; }break;case LEFT:{pNextNode->x = ps->_pSnake->x-2;pNextNode->y = ps->_pSnake->y;}break;case RIGHT:{pNextNode->x = ps->_pSnake->x+2;pNextNode->y = ps->_pSnake->y;}break;}//如果下⼀个位置就是食物if (NextIsFood(pNextNode, ps)){EatFood(pNextNode, ps);}else//如果没有食物{NoFood(pNextNode, ps);}KillByWall(ps);KillBySelf(ps);}void pause()
{while (1){Sleep(300);if (KEY_PRESS(VK_ESCAPE)){break;}}
}
int KillByWall(pSnake ps)
{if ((ps->_pSnake->x == 0)|| (ps->_pSnake->x == 56)|| (ps->_pSnake->y == 0)|| (ps->_pSnake->y == 26)){ps->_state = KILL_BY_WALL;return 1;}return 0;
}int KillBySelf(pSnake ps)
{pSnakeNode cur = ps->_pSnake->next;while (cur){if ((ps->_pSnake->x == cur->x)&& (ps->_pSnake->y == cur->y)){ps->_state = KILL_BY_SELF;return 1;}cur = cur->next;}return 0;
}void GameRun(pSnake ps)
{//打印右侧帮助信息PrintHelpInfo();do{SetPos(64, 10);printf("得分:% d ", ps->_score);printf("每个食物得分:%2d分", ps->_food_weight);if (KEY_PRESS(VK_UP) && ps->_dir != DOWN){ps->_dir = UP;}else if (KEY_PRESS(VK_DOWN) && ps->_dir != UP){ps->_dir = DOWN;}else if (KEY_PRESS(VK_LEFT) && ps->_dir != RIGHT){ps->_dir = LEFT;}else if (KEY_PRESS(VK_RIGHT) && ps->_dir != LEFT){ps->_dir = RIGHT;}else if (KEY_PRESS(VK_SPACE)){pause();}else if (KEY_PRESS(VK_ESCAPE)){ps->_state = END_NORMAL;break;}else if (KEY_PRESS(VK_F3)){if (ps->_sleep_time >= 50){ps->_sleep_time -= 30;ps->_food_weight += 2;//⼀个⻝物分数最⾼是20分}}else if (KEY_PRESS(VK_F4)){if (ps->_sleep_time < 350){ps->_sleep_time += 30;ps->_food_weight -= 2;//⼀个⻝物分数最⾼是20分}}//蛇每次⼀定之间要休眠的时间,时间短,蛇移动速度就快Sleep(ps->_sleep_time);SnakeMove(ps);} while (ps->_state == OK);}void GameOver(pSnake ps)
{pSnakeNode cur = ps->_pSnake;SetPos(24, 12);switch (ps->_state){case END_NORMAL:printf("您主动退出游戏\n");break;case KILL_BY_SELF:printf("您撞上自己了,游戏结束!\n");SetPos(0, 27);break;case KILL_BY_WALL:printf("您撞墙了,游戏结束!\n");SetPos(0, 27);break;}//释放蛇⾝的节点while (cur){pSnakeNode del = cur;cur = cur->next;free(del);}
}

test.c

#include"snake.h"void test()
{int ch = 0;do{system("cls");//创建贪吃蛇Snake snake = { 0 };//初始化游戏//打印环境界面//功能介绍//地图绘制//创建蛇//创建食物//设置游戏相关数据GameStart(&snake);//运行游戏GameRun(&snake);//结束游戏,善后工作GameOver(&snake);SetPos(20, 15);printf("再来一局吗(y/n)\n");ch = getchar();getchar();SetPos(0, 27);} while(ch=='y'||ch=='Y');
}int main()
{setlocale(LC_ALL, "");srand((unsigned int)time(NULL));test();return 0;
}

相关文章:

  • 流媒体协议分析:流媒体传输的基石
  • Jinja2 模板继承机制
  • Mybatis ORM SpringORM
  • 【代码坏味道】膨胀类 Bloaters
  • Go语言的context
  • 《高等数学》(同济大学·第7版) 第一节《映射与函数》超详细解析
  • 【算法】递归与分治策略
  • Cesium快速入门到精通系列教程一
  • 【Linux】进程地址空间揭秘(初步认识)
  • 【计算机网络】 ARP协议和DNS协议
  • 计算机网络物理层基础练习
  • 【CC协议】知识共享许可协议(Creative Commons Licenses)体系解析
  • Python 中Vector类的格式化实现,重点拆解其超球面坐标系的设计精髓
  • 15分钟讲解所有较知名编程语言
  • DAY 16 numpy数组与shap深入理解
  • GD32F103系列工程模版创建记录
  • js数据类型有哪些?它们有什么区别?
  • 如何找到一条适合自己企业的发展之路?
  • Agent开发详解
  • 【Qt】Bug:findChildren找不到控件
  • 洛阳霞光seo网络公司/百度怎么优化网站排名
  • 网站建设前期准备方案/网站如何提升seo排名
  • 西安模板建站定制/百度爱采购关键词优化
  • 深圳市南山区住房和建设局网站/关键词指数查询
  • 关于网站建设外文文献/软文推广名词解释
  • 聊城做网站的公司教程/百度开户渠道