首页 / C语言 / 小项目特供 贪吃蛇游戏(基于C语言)
小项目特供 贪吃蛇游戏(基于C语言)
内容导读
互联网集市收集整理的这篇技术教程文章主要介绍了小项目特供 贪吃蛇游戏(基于C语言),小编现在分享给大家,供广大互联网技能从业者学习和参考。文章包含23680字,纯文字阅读大概需要34分钟。
内容图文
C语言写贪吃蛇本来是打算去年暑假写的,结果因为ACM集训给耽搁了,因此借寒假的两天功夫写了这个贪吃蛇小项目,顺带把C语言重温了一次。
是发表博客的前一天开始写的,一共写了三个版本,第一天写了第一版,第二天写了第二版和第三版。
相信C语言写个小游戏或小项目是大多数计算机相关专业的学生都做的事情,但是作为一个数学专业的学生,我们教研室的老师对C语言的要求也就比较低了,大一没有让我们做个小项目实践一次。至今为止用C/C++做过的三个小项目(大作业),一个是外校同学让我帮忙写的学生信息管理系统(天呐,这名字都被大学用烂了...),一个是本校计院的同学让我帮忙写的链表设计的大作业,实话说,真的很无聊...
最后一个小项目就是贪吃蛇了,比前两个有意思多了,强烈建议大学老师让学生做些简单的界面程序而非黑框框下的所谓管理系统....让学生体会到乐趣才是真谛啊。
附:源码及游戏程序下载地址:贪吃蛇 访问密码 51b4
第一版:
首先是第一版的源码奉上,因为没有学过MFC,这一版是借鉴了其他网站上的C语言贪吃蛇算法思路和图形写成的。
我认为这里的贪吃蛇算法思路非常棒,虽然不知道这种算法的来由但是我对此算法创始人由衷敬佩...
这里的算法思路其实是将图上每一个点的二维坐标转换成一维序列,然后通过一维序列映射地图上的每一个坐标
最让我敬佩的地方就是在蛇头重绘的时候,这里的贪吃蛇移动地图上的二维坐标和原始地图的一维序列将随着蛇头的移动而不断发生交替改变,以适应贪吃蛇循环队列的算法要求。
操作说明:WSAD控制方向。
1 #include <stdio.h> 2 #include <ctype.h> 3 #include <conio.h> 4 #include <time.h> 5 #include <windows.h> 6 7//背景宽-高 8#define HEIGHT 20 9#define WIDTH 20 10//地图中心 11#define XCENTER HEIGHT/2 12#define YCENTER WIDTH/2 13//最大蛇长 14#define SNAKE_MAXLEN ((HEIGHT - 2) * (WIDTH - 2)) 15//坐标->编号 16#define NUM(x,y) ((x-1)*(WIDTH-2)+(y-1)) 17 18//模型 19struct Model{ 20char *ch; 21int color; 22char flag; 23} 24 border = { "□", 4, 1 }, 25 background = { "█", 2, 2 }, 26 snakeHead = { "★", 0xE, 3 }, 27 snakeBody = { "■", 0xE, 3 }, 28 food = { "●", 0xC, 4 }; 29 30int snakeLen = 3; //贪吃蛇长度 31 32//地图 33struct Map { 34int flag; //模型标识 35int num; //坐标编号 36}map[WIDTH][HEIGHT]; 37 38//坐标 39//贪吃蛇移动范围(循环队列),分数位置 40struct Coordinate{ 41int x, y; 42}snake[SNAKE_MAXLEN], scorePos; 43 44 45int score; //分数 46int header, tail; //蛇头蛇尾下标 47HANDLE hConsole; 48 49void setCursor(int x, int y) 50{ 51//参数x为行,y为列-与光标设置相反 52 COORD coord; 53 coord.X = 2*y; //宽字符决定占两列 54 coord.Y = x; 55 SetConsoleCursorPosition(hConsole, coord); 56} 57 58void setColor(int color) 59{ 60 SetConsoleTextAttribute(hConsole, color); 61} 62 63//随机生成食物 64void createFood() 65{ 66int num; //新食物对应的坐标编号 67int range; //新食物所在范围 68 srand((unsigned)time(NULL)); //初始种子 69 range = SNAKE_MAXLEN - snakeLen; //食物生成范围 70if (tail < header) 71 num = rand() % range + tail + 1; 72else { 73 num = rand() % range; 74if (num >= header) 75 num += snakeLen; 76 } 77//绘制食物 78int tx = snake[num].x; 79int ty = snake[num].y; 80 setCursor(tx, ty); 81 setColor(food.color); 82 printf("%s", food.ch); 83 map[tx][ty].flag = food.flag; 84} 85 86//游戏结束 87void gameOver() 88{ 89 setCursor(XCENTER, YCENTER - 4); 90 setColor(0xC); 91 92 printf("Game Over!"); 93 getch(); 94 exit(0); //结束程序 95} 96 97void move(char direction) 98{ 99//新蛇头100int tx = snake[header].x; 101int ty = snake[header].y; 102switch (direction) 103 { 104case‘w‘: 105 tx--; break; 106case‘s‘: 107 tx++; break; 108case‘a‘: 109 ty--; break; 110case‘d‘: 111 ty++; break; 112 } 113114//判断是否会出界或撞到自己115if (map[tx][ty].flag == border.flag || map[tx][ty].flag == snakeBody.flag) 116 gameOver(); 117118//新蛇头绘制(此时未refresh模型标识)119 setCursor(tx, ty); 120 setColor(snakeHead.color); 121 printf("%s", snakeHead.ch); 122//原蛇头重绘制123 setCursor(snake[header].x, snake[header].y); 124 printf("%s", snakeBody.ch); //小方块 125126//蛇头更新-队首移动127 header = header == 0 ? SNAKE_MAXLEN - 1 : header - 1; 128//旧编号位置更正129int preNum = map[tx][ty].num; //蛇头位置旧编号130 snake[preNum].x = snake[header].x; 131 snake[preNum].y = snake[header].y; 132 map[snake[preNum].x][snake[preNum].y].num = preNum; 133//蛇头位置更正134 snake[header].x = tx; 135 snake[header].y = ty; 136 map[tx][ty].num = header; //蛇头位置新编号 137138//判断是否吃到食物139if (map[tx][ty].flag == food.flag) 140 { 141 createFood(); //随机生成食物142 snakeLen++; //蛇身加长 143//更新-score144 setCursor(scorePos.x, scorePos.y); 145 printf("%d", ++score); 146 } 147else { 148//删除蛇尾149 setCursor(snake[tail].x, snake[tail].y); 150 map[snake[tail].x][snake[tail].y].flag = background.flag; 151 setColor(background.color); 152 printf("%s", background.ch); 153 tail = tail == 0 ? SNAKE_MAXLEN - 1 : tail - 1; 154 } 155156//更新-蛇头模型标识157 map[tx][ty].flag = snakeBody.flag; 158} 159160//初始化界面161void init() 162{ 163 CONSOLE_CURSOR_INFO cci; //光标信息164 header = 0; 165 tail = snakeLen - 1; 166167//设置光标不可见168 hConsole = GetStdHandle(STD_OUTPUT_HANDLE); 169 GetConsoleCursorInfo(hConsole, &cci); 170 cci.bVisible = 0; 171 SetConsoleCursorInfo(hConsole, &cci); 172173//dos命令设置窗口大小174 system("mode con:cols=100 lines=32"); 175176//绘制背景177for (int x = 0; x < HEIGHT; x++) 178 { 179for (int y = 0; y < WIDTH; y++) 180 { 181if (x == 0 || y == 0 || x == HEIGHT - 1 || y == WIDTH - 1) 182 { 183 map[x][y].flag = border.flag; 184 setColor(border.color); 185 printf("%s", border.ch); 186 } 187else { 188int num = NUM(x,y); 189 snake[num].x = x; 190 snake[num].y = y; 191//背景设置192 map[x][y].num = num; 193 map[x][y].flag = background.flag; 194 setColor(background.color); 195 printf("%s", background.ch); 196 } 197 } 198 printf("\n"); 199 } 200201//绘制初始贪吃蛇202 setCursor(XCENTER, YCENTER - snakeLen / 2); 203 header = NUM(XCENTER, YCENTER - 1); //蛇头位置204 tail = header + snakeLen - 1; 205 setColor(snakeBody.color); 206for (int i = header; i <= tail; i++) 207 { 208if (i == header) printf("%s", snakeHead.ch); 209else printf("%s", snakeBody.ch); 210 map[snake[i].x][snake[i].y].flag = snakeBody.flag; 211 } 212213//随机生成食物214 createFood(); 215216//其他信息217 setCursor(XCENTER - 1, WIDTH + 2); 218 printf(" score: 0"); 219 setCursor(XCENTER, WIDTH + 2); 220 printf(" Author: InkMark"); 221 setCursor(XCENTER + 1, WIDTH + 2); 222 printf(" Blog: www.cnblogs.com/inkblots"); 223//分数位置224 scorePos.x = XCENTER - 1; 225 scorePos.y = WIDTH + 7; 226} 227228229int main() 230{ 231//方向及其他初始化232char direction = ‘a‘; 233 init(); 234235char ch = tolower(getch()); 236if (ch == ‘a‘ || ch == ‘w‘ || ch == ‘s‘) 237 direction = ch; 238239while (1) { 240if (kbhit()) { 241 ch = tolower(getch()); 242if (ch == ‘‘) 243 ch = getch(); //实现空格-暂停244if(ch == ‘a‘ || ch == ‘d‘ || ch == ‘w‘ || ch==‘s‘) 245if (ch + direction != 234 && ch + direction != 197) 246 direction = ch; //不为反向时改变方向247 } 248 move(direction); 249 Sleep(500); 250 } 251252return0; 253 }
第二版:
第二版在第一版的算法基础上改进了图形界面和源码管理,新增了“加速”技能(比较方便实现)。
控制方向也改为方向键了。
第二版源码分为三个文件,运行源码需要链接一次。
先是一个头文件,定义了要用到的库文件,常用常量和结构体,以及声明main中要用到的函数
1 #ifndef CATALOG_H 2 #define CATALOG_H 3 4 #include<stdio.h> 5 #include<conio.h> 6 #include<time.h> 7 #include<windows.h> 8 9//背景上下伸展长度10#define TOP_EXTEND 3 11#define BOTTOM_EXTEND 3 12//背景宽-高13#define WIDTH 33 14#define HEIGHT 20 15//地图中心16#define XCENTER ((HEIGHT + 1)/2 + TOP_EXTEND) 17#define YCENTER (WIDTH + 1)/2 18//最大蛇长19#define SNAKE_MAXLEN ((HEIGHT - 2) * (WIDTH - 2)) 20//坐标->序号21#define ORDER(x,y) ((x - TOP_EXTEND - 1) * (WIDTH - 2) + (y - 1)) 22//点:在移动范围内23#define IN_RANGE(x,y) (x > TOP_EXTEND && x < HEIGHT + TOP_EXTEND - 1 && y > 0 && y < WIDTH - 1) 24//默认暂停时间25#define PAUSE_TIME 500 2627/*全局变量*/28externint snakeLen; 29externint direction; 30externint header, tail; 31externint score; 32externint skill; 33externint pauseTime; 34extern HANDLE hConsole; 3536//模型37 typedef struct Model { 38char *ch; 39int color; 40int flag; 41}Model; 4243//地图44 typedef struct Map { 45int flag; //模型标识46int order; //序号47}Map; 4849//坐标 50//贪吃蛇移动范围(循环队列),分数位置51 typedef struct Coordinate { 52int x, y; 53}Coordinate; 545556/******界面设定******/5758void setCursor(int x, int y); 5960void setColor(int color); 6162void control(char ch); 6364/******框架及功能******/6566void init(); 6768int move(char direction); 6970void createFood(); 717273#endif
第二个是功能部分源码
1 #include "catalog.h" 2 3 Model border = { NULL, 0x7, 1 }, 4 snakeHead = { "★", 0xE, 2 }, 5 snakeBody = { "■", 0xE, 2 }, 6 food = { "●", 0xC, 3 }; 7 8Map map[HEIGHT][WIDTH]; 9 10Coordinate snake[SNAKE_MAXLEN], scorePos, skillPos; 11 12/************游戏界面设定************/ 13 14//隐藏光标 15void hideCursor() 16{ 17 CONSOLE_CURSOR_INFO cci; //光标信息 18 hConsole = GetStdHandle(STD_OUTPUT_HANDLE); 19 GetConsoleCursorInfo(hConsole, &cci); 20 cci.bVisible = 0; 21 SetConsoleCursorInfo(hConsole, &cci); 22} 23 24//设置光标位置 25void setCursor(int x, int y) 26{ 27//参数x为行,y为列-与光标设置相反 28 COORD coord; 29 coord.X = 2 * y; //宽字符决定占两列 30 coord.Y = x; 31 SetConsoleCursorPosition(hConsole, coord); 32} 33 34//设置文字颜色 35void setColor(int color) 36{ 37 SetConsoleTextAttribute(hConsole, color); 38} 39 40//绘制游戏窗口(包括dos环境初始窗口) 41void createWindow() 42{ 43//dos命令设置窗口大小 44 system("mode con:cols=72 lines=27"); 45 46//╔ ╗ ╝ ╚ ═ ║ ╠ ╣ ╦ ╩ 47 setColor(0x7); 48 printf("╔════════════════╦════════════════╗\n"); //0~34 49for (int i = 1; i < TOP_EXTEND; i++) 50 printf("║ ║ ║\n"); 51 printf("╠════════════════╩════════════════╣\n"); 52for (int i = 1; i < HEIGHT - 1; i++) 53 printf("║ ║\n"); 54 printf("╠═════════════════════════════════╣\n"); 55for (int i = 1; i < BOTTOM_EXTEND; i++) 56 printf("║ ║\n"); 57 printf("╚═════════════════════════════════╝\n"); 58 setCursor(HEIGHT + TOP_EXTEND, 1); 59 printf(" 操作指南:方向键控制,空格可暂停,5分后可获得技能."); 60 setCursor(HEIGHT + TOP_EXTEND + 1, 1); 61 printf(" Version : 2.0"); 62 63for (int x = TOP_EXTEND; x < HEIGHT + TOP_EXTEND; x++) 64 { 65for (int y = 0; y < WIDTH; y++) 66if (IN_RANGE(x, y)) 67 { 68int order = ORDER(x, y); 69 snake[order].x = x; 70 snake[order].y = y; 71//背景设置 72 map[x][y].order = order; 73 map[x][y].flag = 0; 74 } 75else map[x][y].flag = border.flag; 76 } 77//其他信息 78 setColor(0x7); 79 setCursor(1, 1); 80 printf(" 你的分数:0"); 81 setCursor(2, 1); 82 printf(" 技能:无"); 83 setCursor(1, YCENTER + 1); 84 printf(" Author: InkMark"); 85 setCursor(2, YCENTER + 1); 86 printf(" Blog: www.cnblogs.com/inkblots"); 87 88//分数位置 89 scorePos.x = 1; scorePos.y = 11; 90 skillPos.x = 2; skillPos.y = 9; 91} 92 93//控制键 94void control(char ch) 95{ 96//本应取方向键高位再取低位,在此以简便为主 97if (ch != -32) return; 98 ch = getch(); 99//上72下80左75右77100if (ch == 72 || ch == 80 || ch == 75 || ch == 77) //低位相同101if (ch + direction != 152) direction = ch; //不为反向时改变方向102} 103104/************游戏信息输出************/105106void getSkill() 107{ 108 setCursor(skillPos.x, skillPos.y); 109 printf("加速(S键)"); 110 skill = 1; //加速技能开启111} 112113void alterScore(int addition) 114{ 115 score += addition; 116if (score >= 5) 117 getSkill(); 118 setCursor(scorePos.x, scorePos.y); 119 setColor(0x7); 120 printf("%d", score); 121} 122123void gameOver() 124{ 125if (IDYES == MessageBox(NULL, "是否重新开始游戏?", "Snake_2.0", MB_YESNO)) 126 { 127 system("CLS"); 128return; 129 } 130131 exit(0); 132} 133134/************游戏框架及功能************/135136//变量初始化及界面初始化137void init() 138{ 139 pauseTime = PAUSE_TIME; 140 skill = 0; 141 score = 0; 142 snakeLen = 1; 143 header = 0; 144 tail = snakeLen - 1; 145146 hideCursor();//隐藏光标147 createWindow(); //绘制背景148} 149150//贪吃蛇移动 151//return:1为成功,0为失败152int move(char direction) 153{ 154//新蛇头155int tx = snake[header].x; 156int ty = snake[header].y; 157//上72下80左75右77158switch (direction) 159 { 160case72: tx--; break; 161case80: tx++; break; 162case75: ty--; break; 163case77: ty++; break; 164 } 165166//判断是否撞墙或撞到自己167if (map[tx][ty].flag == border.flag || map[tx][ty].flag == snakeBody.flag) 168 { 169 gameOver(); 170return0; 171 } 172173//新蛇头绘制(此时未refresh模型标识)174 setCursor(tx, ty); 175 setColor(snakeHead.color); 176 printf("%s", snakeHead.ch); 177//原蛇头重绘制178 setCursor(snake[header].x, snake[header].y); 179 printf("%s", snakeBody.ch); 180181//蛇头更新-队首移动182 header = header == 0 ? SNAKE_MAXLEN - 1 : header - 1; 183//旧编号位置更正184int preNum = map[tx][ty].order; //蛇头位置旧编号185 snake[preNum].x = snake[header].x; 186 snake[preNum].y = snake[header].y; 187 map[snake[preNum].x][snake[preNum].y].order = preNum; 188//蛇头位置更正189 snake[header].x = tx; 190 snake[header].y = ty; 191 map[tx][ty].order = header; //蛇头位置新编号 192193//判断是否吃到食物194if (map[tx][ty].flag == food.flag) 195 { 196 snakeLen++; //蛇身加长197 createFood(); //随机生成食物 198//更新-score199 alterScore(1); 200 } 201else { 202//删除蛇尾203 setCursor(snake[tail].x, snake[tail].y); 204 map[snake[tail].x][snake[tail].y].flag = 0; 205 printf(""); 206 tail = tail == 0 ? SNAKE_MAXLEN - 1 : tail - 1; 207 } 208209//更新-蛇头模型标识210 map[tx][ty].flag = snakeBody.flag; 211212return1; 213} 214215//随机生成食物216void createFood() 217{ 218int order; //新食物对应的坐标编号219int range; //新食物所在范围220 srand((unsigned)time(NULL)); //初始种子221 range = SNAKE_MAXLEN - snakeLen; //食物生成范围222if (tail < header) 223 order = rand() % range + tail + 1; 224else { 225 order = rand() % range; 226if (order >= header) 227 order += snakeLen; 228 } 229//绘制食物230int tx = snake[order].x; 231int ty = snake[order].y; 232 setCursor(tx, ty); 233 setColor(food.color); 234 printf("%s", food.ch); 235 map[tx][ty].flag = food.flag; 236 }
第三个是主函数及初始化部分
1 #include "catalog.h" 2 3int snakeLen; //贪吃蛇长度 4int direction; //贪吃蛇移动方向 5int header, tail; //蛇头蛇尾下标 6int score; //分数 7int skill; //技能开关 8int pauseTime; //暂停时间(Ms) 9HANDLE hConsole; 1011extern Model border, snakeHead, snakeBody, food; 12extern Map map[HEIGHT][WIDTH]; 13extern Coordinate snake[SNAKE_MAXLEN], scorePos, skillPos; 1415//初始化方案16void scheme() 17{ 18//变量初始化及界面初始化19 init(); 2021//绘制初始贪吃蛇22 setCursor(XCENTER, YCENTER - snakeLen / 2); 23 header = ORDER(XCENTER, YCENTER - snakeLen / 2); //蛇头位置24 tail = header + snakeLen - 1; 25 setColor(snakeBody.color); 26for (int i = header; i <= tail; i++) 27 { 28if (i == header) printf("%s", snakeHead.ch); 29else printf("%s", snakeBody.ch); 30 map[snake[i].x][snake[i].y].flag = snakeBody.flag; 31 } 3233//随机生成食物34 createFood(); 3536//初始方向处理37 direction = 75; 38char ch = getch(); 39 control(ch); 40} 414243int main() 44{ 45//初始方案46 scheme(); 4748while (1) { 49if (kbhit()) { 50char ch = getch(); 51if (ch == ‘‘) MessageBox(NULL, " 暂停中...\n 请单击确定继续游戏", "暂停游戏", MB_OK); 52if (skill == 1 && (ch == ‘s‘ || ch == ‘S‘)) 53 pauseTime = pauseTime == PAUSE_TIME ? PAUSE_TIME / 2 : PAUSE_TIME; 54else control(ch); //控制方向55 } 56if (move(direction)) 57 Sleep(pauseTime); 58else scheme(); 59 } 6061return0; 62 }
第三版:
第三版加入了菜单,优化了部分界面,并将游戏分为两个基本模式。
和第二版一样,分为三个文件
头文件:
1 #ifndef CATALOG_H 2 #define CATALOG_H 3 4 #include<stdio.h> 5 #include<conio.h> 6 #include<time.h> 7 #include<windows.h> 8 9//背景上下伸展长度10#define TOP_EXTEND 3 11#define BOTTOM_EXTEND 3 12//背景宽-高13#define WIDTH 33 14#define HEIGHT 20 15//地图中心16#define XCENTER ((HEIGHT + 1)/2 + TOP_EXTEND) 17#define YCENTER (WIDTH + 1)/2 18//最大蛇长19#define SNAKE_MAXLEN ((HEIGHT - 2) * (WIDTH - 2)) 20//坐标->序号21#define ORDER(x,y) ((x - TOP_EXTEND - 1) * (WIDTH - 2) + (y - 1)) 22//点:在移动范围内23#define IN_RANGE(x,y) (x > TOP_EXTEND && x < HEIGHT + TOP_EXTEND - 1 && y > 0 && y < WIDTH - 1) 24//默认暂停时间25#define PAUSE_TIME 500 2627/*全局变量*/28externint snakeLen; 29externint direction; 30externint header, tail; 31externint score; 32externint skill; 33externint pauseTime; 34externint mode; 35extern HANDLE hConsole; 3637//模型38 typedef struct Model { 39char *ch; 40int color; 41int flag; 42}Model; 4344//地图45 typedef struct Map { 46int flag; //模型标识47int order; //序号48}Map; 4950//坐标 51//贪吃蛇移动范围(循环队列),分数位置52 typedef struct Coordinate { 53int x, y; 54}Coordinate; 555657/******界面设定******/5859externvoid setCursor(int x, int y); 6061externvoid setColor(int color); 6263externvoid control(char ch); 6465/******框架及功能******/6667externvoid init(); 6869externint move(char direction); 7071externvoid createFood(); 727374#endif
功能文件:
1 #include "catalog.h" 2 3 Model border = { NULL, 0x7, 1 }, 4 snakeHead = { "★", 0xE, 2 }, 5 snakeBody = { "■", 0xE, 2 }, 6 food = { "●", 0xC, 3 }; 7 8Map map[HEIGHT][WIDTH]; 9 10Coordinate snake[SNAKE_MAXLEN], scorePos, skillPos, dotPos; 11 12#define UP 4 //向上偏移量 13#define LEFT 6 //左移偏移量 14 15/************游戏界面设定************/ 16 17//隐藏光标 18void hideCursor() 19{ 20 CONSOLE_CURSOR_INFO cci; //光标信息 21 hConsole = GetStdHandle(STD_OUTPUT_HANDLE); 22 GetConsoleCursorInfo(hConsole, &cci); 23 cci.bVisible = 0; 24 SetConsoleCursorInfo(hConsole, &cci); 25} 26 27//设置光标位置 28void setCursor(int x, int y) 29{ 30//参数x为行,y为列-与光标设置相反 31 COORD coord; 32 coord.X = 2 * y; //宽字符决定占两列 33 coord.Y = x; 34 SetConsoleCursorPosition(hConsole, coord); 35} 36 37//设置文字颜色 38void setColor(int color) 39{ 40 SetConsoleTextAttribute(hConsole, color); 41} 42 43//绘制游戏窗口(包括dos环境初始窗口) 44void createWindow() 45{ 46//dos命令设置窗口大小 47 system("mode con:cols=72 lines=28"); 48 49//╔ ╗ ╝ ╚ ═ ║ ╠ ╣ ╦ ╩ 50 setColor(0x7); 51 printf("╔════════════════╦════════════════╗\n"); //0~34 52for (int i = 1; i < TOP_EXTEND; i++) 53 printf("║ ║ ║\n"); 54 printf("╠════════════════╩════════════════╣\n"); 55for (int i = 1; i < HEIGHT - 1; i++) 56 printf("║ ║\n"); 57 printf("╠═════════════════════════════════╣\n"); 58for (int i = 1; i < BOTTOM_EXTEND; i++) 59 printf("║ ║\n"); 60 printf("╚═════════════════════════════════╝\n"); 61 setCursor(HEIGHT + TOP_EXTEND, 1); 62 printf(" 操作指南:上下键及回车键选择."); 63 setCursor(HEIGHT + TOP_EXTEND + 1, 1); 64 printf(" Version : 3.0"); 65 66for (int x = TOP_EXTEND; x < HEIGHT + TOP_EXTEND; x++) 67 { 68for (int y = 0; y < WIDTH; y++) 69if (IN_RANGE(x, y)) 70 { 71int order = ORDER(x, y); 72 snake[order].x = x; 73 snake[order].y = y; 74//背景设置 75 map[x][y].order = order; 76 map[x][y].flag = 0; 77 } 78else map[x][y].flag = border.flag; 79 } 80//其他信息 81 setColor(0x7); 82 setCursor(1, 1); 83 printf(" 你的分数:0"); 84 setCursor(2, 1); 85 printf(" 技能:无"); 86 setCursor(1, YCENTER + 1); 87 printf(" Author: InkMark"); 88 setCursor(2, YCENTER + 1); 89 printf(" Blog: www.cnblogs.com/inkblots"); 90 91//分数位置 92 scorePos.x = 1; scorePos.y = 11; 93 skillPos.x = 2; skillPos.y = 9; 94} 95 96void menuButton(char ch) 97{ 98int tx = dotPos.x; 99int ty = dotPos.y; 100if (ch == 72) tx--; 101else tx++; 102103if (tx > XCENTER - UP && tx < XCENTER - UP + 4) 104 { 105 setCursor(dotPos.x, dotPos.y); 106 printf(""); 107 setCursor(tx, ty); 108 printf("●"); 109 dotPos.x = tx; 110 dotPos.y = ty; 111 } 112} 113114//绘制菜单并进行选择115void menu() 116{ 117//╔ ╗ ╚ ╝ ═ ║ ╠ ╣ ╦ ╩118 setCursor(XCENTER - UP, YCENTER - LEFT); 119 printf("╔═════════╗"); //11120for (int i = 1; i <= 3; i++) 121 { 122 setCursor(XCENTER - UP + i, YCENTER - LEFT); 123 printf("║ ║"); 124 } 125 setCursor(XCENTER - UP + 4, YCENTER - LEFT); 126 printf("╚═════════╝"); 127128 dotPos.x = XCENTER - UP + 1; 129 dotPos.y = YCENTER - 4; 130 setCursor(dotPos.x, dotPos.y); 131 printf("● 1.死亡模式"); 132 setCursor(XCENTER - UP + 2, YCENTER - 2); 133 printf("2.技能模式"); 134 setCursor(XCENTER - UP + 3, YCENTER - 2); 135 printf("3.退出游戏"); 136137char ch; 138while ((ch = getch()) != 13) //确定键:13139 { 140if (ch != -32) continue; 141 ch = getch(); 142if (ch == 72 || ch == 80) 143 menuButton(ch); 144 } 145146for (int i = 0; i < 5; i++) 147 { 148 setCursor(XCENTER - UP + i, YCENTER - LEFT); 149 printf(""); 150 } 151152 mode = dotPos.x - XCENTER + UP; 153if (mode == 3) exit(0); 154} 155156//控制键157void control(char ch) 158{ 159//本应取方向键高位再取低位,在此以简便为主160if (ch != -32) return; 161 ch = getch(); 162//上72下80左75右77163if (ch == 72 || ch == 80 || ch == 75 || ch == 77) //低位相同164if (ch + direction != 152) 165 direction = ch; //不为反向时改变方向166} 167168/************游戏信息输出************/169170void getSkill() 171{ 172 setCursor(skillPos.x, skillPos.y); 173 printf("加速(S键)"); 174 skill = 1; //加速技能开启175} 176177void alterScore(int addition) 178{ 179 score += addition; 180if (mode == 2 && score >= 8) 181 getSkill(); 182 setCursor(scorePos.x, scorePos.y); 183 setColor(0x7); 184 printf("%d", score); 185} 186187void printInfo() 188{ 189//╔ ╗ ╚ ╝ ═ ║ ╠ ╣ ╦ ╩190int col = 28; 191 setCursor(HEIGHT + TOP_EXTEND - 1, col); 192 printf("╦"); 193 setCursor(HEIGHT + TOP_EXTEND, col); 194 printf("║"); 195 setCursor(HEIGHT + TOP_EXTEND + 1, col); 196 printf("║ 模 式"); 197if (mode == 1) { 198199 setCursor(HEIGHT + TOP_EXTEND, 1); 200 printf(" 操作指南:方向键控制,空格可暂停."); 201 setCursor(HEIGHT + TOP_EXTEND, col + 1); 202 printf(" 无 尽"); 203 } 204else { 205 setCursor(HEIGHT + TOP_EXTEND, 1); 206 printf(" 操作指南:方向键控制,空格可暂停,8分后有惊喜."); 207 setCursor(HEIGHT + TOP_EXTEND, col + 1); 208 printf(" 技 能"); 209 } 210 setCursor(HEIGHT + TOP_EXTEND + 2, col); 211 printf("╩"); 212} 213214void gameOver() 215{ 216if (IDYES == MessageBox(NULL, "是否重新开始游戏?", "Snake_2.0", MB_YESNO)) 217 { 218 system("CLS"); 219return; 220 } 221222 exit(0); 223} 224225/************游戏框架及功能************/226227//变量初始化及界面初始化228void init() 229{ 230 pauseTime = PAUSE_TIME; 231 skill = 0; 232 score = 0; 233 snakeLen = 1; 234 header = 0; 235 tail = snakeLen - 1; 236237 hideCursor();//隐藏光标238 createWindow(); //绘制背景239240 menu(); //菜单操作241242 printInfo(); 243} 244245//贪吃蛇移动 246//return:1为成功,0为失败247int move(char direction) 248{ 249//新蛇头250int tx = snake[header].x; 251int ty = snake[header].y; 252//上72下80左75右77253switch (direction) 254 { 255case72: tx--; break; 256case80: tx++; break; 257case75: ty--; break; 258case77: ty++; break; 259 } 260261//判断是否撞墙或撞到自己262if (map[tx][ty].flag == border.flag || map[tx][ty].flag == snakeBody.flag) 263 { 264 gameOver(); 265return0; 266 } 267268//新蛇头绘制(此时未refresh模型标识)269 setCursor(tx, ty); 270 setColor(snakeHead.color); 271 printf("%s", snakeHead.ch); 272//原蛇头重绘制273 setCursor(snake[header].x, snake[header].y); 274 printf("%s", snakeBody.ch); 275276//蛇头更新-队首移动277 header = header == 0 ? SNAKE_MAXLEN - 1 : header - 1; 278//旧编号位置更正279int preNum = map[tx][ty].order; //蛇头位置旧编号280 snake[preNum].x = snake[header].x; 281 snake[preNum].y = snake[header].y; 282 map[snake[preNum].x][snake[preNum].y].order = preNum; 283//蛇头位置更正284 snake[header].x = tx; 285 snake[header].y = ty; 286 map[tx][ty].order = header; //蛇头位置新编号 287288//判断是否吃到食物289if (map[tx][ty].flag == food.flag) 290 { 291 snakeLen++; //蛇身加长292 createFood(); //随机生成食物 293//更新-score294if(pauseTime == PAUSE_TIME) alterScore(1); 295else alterScore(2); 296 } 297else { 298//删除蛇尾299 setCursor(snake[tail].x, snake[tail].y); 300 map[snake[tail].x][snake[tail].y].flag = 0; 301 printf(""); 302 tail = tail == 0 ? SNAKE_MAXLEN - 1 : tail - 1; 303 } 304305//更新-蛇头模型标识306 map[tx][ty].flag = snakeBody.flag; 307308return1; 309} 310311//随机生成食物312void createFood() 313{ 314int order; //新食物对应的坐标编号315int range; //新食物所在范围316 srand((unsigned)time(NULL)); //初始种子317 range = SNAKE_MAXLEN - snakeLen; //食物生成范围318if (tail < header) 319 order = rand() % range + tail + 1; 320else { 321 order = rand() % range; 322if (order >= header) 323 order += snakeLen; 324 } 325//绘制食物326int tx = snake[order].x; 327int ty = snake[order].y; 328 setCursor(tx, ty); 329 setColor(food.color); 330 printf("%s", food.ch); 331 map[tx][ty].flag = food.flag; 332 }
主文件:
1 #include "catalog.h" 2 3int snakeLen; //贪吃蛇长度 4int direction; //贪吃蛇移动方向 5int header, tail; //蛇头蛇尾下标 6int score; //分数 7int skill; //技能开关 8int pauseTime; //暂停时间(Ms) 9int mode; 10HANDLE hConsole; 1112extern Model border, snakeHead, snakeBody, food; 13extern Map map[HEIGHT][WIDTH]; 14extern Coordinate snake[SNAKE_MAXLEN], scorePos, skillPos; 1516//初始化方案17void scheme() 18{ 19//变量初始化及界面初始化20 init(); 2122//绘制初始贪吃蛇23 setCursor(XCENTER, YCENTER - snakeLen / 2); 24 header = ORDER(XCENTER, YCENTER - snakeLen / 2); //蛇头位置25 tail = header + snakeLen - 1; 26 setColor(snakeBody.color); 27for (int i = header; i <= tail; i++) 28 { 29if (i == header) printf("%s", snakeHead.ch); 30else printf("%s", snakeBody.ch); 31 map[snake[i].x][snake[i].y].flag = snakeBody.flag; 32 } 3334//随机生成食物35 createFood(); 3637//初始方向处理38 direction = 75; 39char ch = getch(); 40 control(ch); 41} 424344int main() 45{ 46//初始方案47 scheme(); 4849while (1) { 50if (kbhit()) { 51char ch = getch(); 52if (ch == ‘‘) MessageBox(NULL, " 暂停中...\n 请单击确定继续游戏", "暂停游戏", MB_OK); 53if (mode == 2 && skill == 1 && (ch == ‘s‘ || ch == ‘S‘)) 54 pauseTime = pauseTime == PAUSE_TIME ? PAUSE_TIME / 2 : PAUSE_TIME; 55else control(ch); //控制方向56 } 57if (move(direction)) 58 Sleep(pauseTime); 59else scheme(); 60 } 6162return0; 63 }
原文:http://www.cnblogs.com/Inkblots/p/5205267.html
内容总结
以上是互联网集市为您收集整理的小项目特供 贪吃蛇游戏(基于C语言)全部内容,希望文章能够帮你解决小项目特供 贪吃蛇游戏(基于C语言)所遇到的程序开发问题。 如果觉得互联网集市技术教程内容还不错,欢迎将互联网集市网站推荐给程序员好友。
内容备注
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 gblab@vip.qq.com 举报,一经查实,本站将立刻删除。
内容手机端
扫描二维码推送至手机访问。