|
马上注册,结交更多好友,享用更多功能^_^
您需要 登录 才可以下载或查看,没有账号?立即注册
x
学了小甲鱼的C第一季,写了一个贪吃蛇嘿嘿 ,下面是游戏效果图:
写出来就图一乐,为了纪念学完了C的第一季,其实代码语法很简单,逻辑也不难,感觉大概学完数组就可以写了;我的代码有点长,windows环境下运行,复制粘贴就可以玩,希望我们一起加油学,一起奋斗 ,怀挺!!!
代码附上,注释都写了,哪有不懂得或者有啥建议,欢迎大家讨论
- /**************************************************/
- /*作者:JZZC
- /*日期:2020.3.14
- /*可借鉴,可参考,祝君开心
- /**************************************************/
- #include <stdio.h>
- #include <stdlib.h>
- #include <windows.h> //光标设置的API,构建gotoxy()函数有使用
- #include <time.h> //食物随机
- #include <conio.h> //按键监控,构建directionJudge()函数使用
- #define MAPWIDTH 52 //地图宽
- #define MAPHEIGHT 22 //地图高
- #define BOUNDRY 78 //界面右边界
- #define MAXLENGTH 522 //蛇最大身长
- #define INITDIRECTION 'w' //初始化移动方向
- #define BUMP 1 //碰撞
- #define NOBUMP 0 //未碰撞
- //变量声明
- struct Food
- {
- int x;
- int y;
- }food; //食物的结构体
- struct Snake
- {
- int length;
- int speed;
- int x[MAXLENGTH];
- int y[MAXLENGTH];
- }snake; //蛇的结构体
- unsigned int unused = (srand((unsigned int)time(NULL)), 0);//撒随机种子
- char moveDirection = INITDIRECTION; //初始化移动方向
- int changeSnake = 0; //蛇身长度变化标志位
- int bumpFlag = 0; //碰撞标志位
- int score = 0; //得分
- //函数声明
- void initWall(void); //初始化围墙
- void gameExplain(void); //打印游戏说明
- void initSnake(void); //初始化一条蛇
- void creatFood(void); //生成食物
- void initGame(void); //游戏初始化(调用以上函数)
-
- void gotoxy(int x, int y); //控制光标的函数,会用即可,都是库函数
- void directionJudge(void); //接收按键键值,判断蛇移动方向
- int stateJudge(void); //计算出新的蛇坐标后,调用此函数判断是否发生碰撞
- void printSnake(void); //打印蛇,达到动态效果
-
- void gameOver(void); //打印结局
-
- //函数定义
- void gotoxy(int x, int y)
- {
- //1.找到控制台窗口
- HANDLE handle = GetStdHandle(STD_OUTPUT_HANDLE);
- //2.声明光标结构体
- COORD coord;
- //3.设置坐标
- coord.X = x;
- coord.Y = y;
- //4.同步到控制台
- SetConsoleCursorPosition(handle, coord);
- }
- void initWall(void)
- {
- int i;
- //1.打印竖起来的围墙
- for (i = 0; i <= MAPHEIGHT; i++)
- {
- gotoxy(0, i);
- printf("■");
- gotoxy(MAPWIDTH, i);
- printf("■");
- gotoxy(BOUNDRY, i);
- printf("■");
- }
- //2.打印上下两排围墙,注意 '■'占两个位置,所以要加2,后面不再强调
- for (i = 0; i <= BOUNDRY; i += 2)
- {
- gotoxy(i, 0);
- printf("■");
- gotoxy(i, MAPHEIGHT);
- printf("■");
- }
- }
- void gameExplain(void)
- {
- //打印游戏说明
- int a = 0;
- gotoxy(MAPWIDTH + 4, 2);
- printf("游戏说明:W键向上,");
- gotoxy(MAPWIDTH + 4, 3);
- printf("A键向左,S键向下,");
- gotoxy(MAPWIDTH + 4, 4);
- printf("D键向右(不区分大小写)");
- gotoxy(MAPWIDTH + 8, MAPHEIGHT / 2);
- printf("当前分数:%03d", score);
- gotoxy(MAPWIDTH + 8, MAPHEIGHT - 4);
- printf("游戏作者:JZZC");
- }
- void initSnake(void)
- {
- int i;
- //画蛇
- //1 初始化蛇的属性
- snake.length = 3;
- snake.speed = 180;
- //2 画蛇头
- snake.x[0] = MAPWIDTH / 2;
- snake.y[0] = MAPHEIGHT / 2;
- gotoxy(snake.x[0], snake.y[0]);
- printf("⊙");
- //3 画蛇身
- for (i = 1; i < snake.length; i++)
- {
- snake.x[i] = snake.x[i - 1] + 2;
- snake.y[i] = snake.y[i - 1];
- gotoxy(snake.x[i], snake.y[i]);
- printf("●");
- }
- }
- void creatFood(void)
- {
- int foodOnsnake;
- int i = 0;
- //注意产生的食物不能在蛇身上,横坐标也不能是奇数开头,
- //读者可以想一下为什么要这样规定,想不懂欢迎追问^_^
- do
- {
- foodOnsnake = 0;
- food.x = rand() % (MAPWIDTH - 4) + 2;
- if (food.x % 2)
- {
- food.x -= 1;
- }
- food.y = rand() % (MAPHEIGHT - 2) + 1;
- for (i = 0; i < snake.length; i++)
- {
- if (food.x == snake.x[i] && food.y == snake.y[i])
- {
- foodOnsnake = 1;
- break;
- }
- }
- } while (foodOnsnake);
- gotoxy(food.x, food.y);
- printf("◆");
- }
- void initGame(void)
- {
- //1初始化围墙
- initWall();
- //2游戏说明
- gameExplain();
- //3初始化蛇
- initSnake();
- //4画出食物
- creatFood();
- }
- void gameOver(void)
- {
- //1.打印框高
- for (int i = MAPHEIGHT / 4; i <= MAPHEIGHT / 4 * 3; i++)
- {
- gotoxy(MAPWIDTH / 4, i);
- printf("■");
- gotoxy(MAPWIDTH / 4 * 3, i);
- printf("■");
- }
- //2.打印框宽
- for (int i = MAPWIDTH / 4; i <= MAPWIDTH / 4 * 3; i += 2)
- {
- gotoxy(i, MAPHEIGHT / 4);
- printf("■");
- gotoxy(i, MAPHEIGHT / 4 * 3);
- printf("■");
- }
-
- //3.框内像素点清除(用两个空格清除)
- for (int i = MAPHEIGHT / 4 + 1; i < MAPHEIGHT / 4 * 3; i++)
- {
- for (int j = MAPWIDTH / 4 + 2; j < MAPWIDTH / 4 * 3; j += 2)
- {
- gotoxy(j, i);
- printf(" ");
- }
- }
-
- //4.打印Game Over!
- gotoxy(MAPWIDTH / 2 - 4, MAPHEIGHT / 2 - 2);
- printf("Game Over!");
- }
- void directionJudge(void)
- {
- char ch;
- char lastkey = moveDirection; //记录上次移动方向,防止蛇头往里缩(形象比喻)
- //接收按键值
- if (_kbhit())
- {
- //清除标准输入流缓存
- fflush(stdin);
-
- if ((ch = _getch()) == 'w' || ch == 'W' || ch == 'a' || ch == 'A' || ch == 's'
- || ch == 'S' || ch == 'd' || ch == 'D')
- {
- switch (ch)
- {
- case 'w':
- case 'W':
- if (lastkey == 's' || lastkey == 'S')
- {
- moveDirection = 's';
- break;
- }
- else
- {
- moveDirection = 'w';
- break;
- }
- case 'a':
- case 'A':
- if (lastkey == 'd' || lastkey == 'D')
- {
- moveDirection = 'd';
- break;
- }
- else
- {
- moveDirection = 'a';
- break;
- }
- case 's':
- case 'S':
- if (lastkey == 'w' || lastkey == 'W')
- {
- moveDirection = 'w';
- break;
- }
- else
- {
- moveDirection = 's';
- break;
- }
- case 'd':
- case 'D':
- if (lastkey == 'a' || lastkey == 'A')
- {
- moveDirection = 'a';
- break;
- }
- else
- {
- moveDirection = 'd';
- break;
- }
- }
- }
- }
- }
- int stateJudge(void)
- {
- int i;
-
- //1.判断是否撞到墙壁
- if (snake.x[0] == 0 || snake.x[0] == MAPWIDTH || snake.y[0] == 0 || snake.y[0] == MAPHEIGHT)
- {
- return BUMP;
- }
-
- //2.判断是否撞到自己
- for (i = 1; i < snake.length; i++)
- {
- if (snake.x[0] == snake.x[i] && snake.y[0] == snake.y[i])
- {
- return BUMP;
- }
- }
- return NOBUMP;
- }
- void printSnake(void)
- {
- //未算出蛇身新坐标前,先记录下当前的蛇尾坐标。
- int blockx = snake.x[snake.length - 1];
- int blocky = snake.y[snake.length - 1];
- static char lastkey;
-
- lastkey = moveDirection;
-
- //1.判断移动方向
- directionJudge();
-
- //2.计算蛇身坐标(不包含蛇头)
- for (int i = snake.length - 1; i > 0; i--)
- {
- snake.x[i] = snake.x[i - 1];
- snake.y[i] = snake.y[i - 1];
- }
- //3.计算蛇头坐标
- switch (moveDirection)
- {
- case 'w':
- case 'W':
- snake.y[0] -= 1;
- break;
- case 'a':
- case 'A':
- snake.x[0] -= 2;
- break;
- case 's':
- case 'S':
- snake.y[0] += 1;
- break;
- case 'd':
- case 'D':
- snake.x[0] += 2;
- break;
- default: break;
- }
-
- //4.判断是否发生碰撞,若产生碰撞会在main函数中直接跳出while(1),防止蛇“吃”墙
- if (stateJudge() == 1)
- {
- bumpFlag = 1;
- return;
- }
-
- //5.未发生碰撞,打印蛇
- gotoxy(snake.x[0], snake.y[0]);
- printf("⊙");
- for (int i = 1; i < snake.length; i++)
- {
- gotoxy(snake.x[i], snake.y[i]);
- printf("●");
- }
-
- //6.判断蛇头是否吃到食物
- if (snake.x[0] == food.x && snake.y[0] == food.y)
- {
- snake.length += 1;
- changeSnake = 1;
- }
- else
- {
- changeSnake = 0;
- }
-
- //7.根据是否吃到食物判断蛇尾是保留还是用空格替代,已达到蛇身增长和蛇移动的效果
- if (changeSnake == 0)
- {
- gotoxy(blockx, blocky);
- printf(" ");
- }
- else
- {
- snake.x[snake.length - 1] = blockx;
- snake.y[snake.length - 1] = blocky;
- score += 1;
- gotoxy(MAPWIDTH + 18, MAPHEIGHT / 2);
- printf("%03d", score);
- creatFood();
- }
- }
- int main(void)
- {
- initGame();
-
- while (1)
- {
- //1.打印蛇
- printSnake();
-
- //检测是否发生碰撞
- if (bumpFlag == 1)
- {
- break;
- }
-
- //短暂停顿
- Sleep(snake.speed);
- }
-
- gameOver();
- getchar();
- gotoxy(0, MAPHEIGHT +1);
- return 0;
- }
复制代码
|
评分
-
查看全部评分
|