NO.3 C语言实现贪吃蛇游戏(Linux)
一、简易说明:
- 实现了初步的游戏模型,可以玩,但有一些细节bug没有解决。
- 用WASD控制方向
- 只能在Linux下运行,(界面刷新+系统延时调用的是Linux系统的库文件)
二、源代码+头文件
1 #include <stdio.h> 2 #include "snake.h" 3 4 5 6 7 int main(int argc, const char *argv[]) 8 { 9 10 11 system("clear"); 12 srand(time(NULL)); //播种随机数种子 13 14 initSnake(); //初始化蛇和食物 15 initFood(); 16 17 18 initWall(); //初始化墙 19 initUi(); //画出蛇头 20 21 playGame(); //启动游戏 22 23 return 0; 24 } 25 26 27 //初始化蛇函数 28 void initSnake() 29 { 30 snake.size = 4; //初始化蛇长度 31 32 snake.body[0].X = WIDTH/2; //初始化蛇头 33 snake.body[0].Y = HEIGHT/2; 34 35 snake.body[1].X = WIDTH/2 - 1; //初始化蛇身体第一节 36 snake.body[1].Y = HEIGHT/2; 37 38 snake.body[2].X = WIDTH/2 - 2; //初始化蛇身体第二节 39 snake.body[2].Y = HEIGHT/2; 40 41 snake.body[3].X = WIDTH/2 - 3; //初始化蛇身体第三节 42 snake.body[3].Y = HEIGHT/2; 43 44 return ; 45 } 46 47 //初始化食物函数 48 void initFood() 49 { 50 food.X = rand() % WIDTH-1; 51 food.Y = rand() % HEIGHT-2; 52 53 return ; 54 } 55 56 void initUi() 57 { 58 //画出蛇头和蛇身体 59 for(int i=0; i<snake.size; ++i) 60 { 61 MOVETO(snake.body[i].X,snake.body[i].Y); 62 if(0 == i) 63 putchar('@'); 64 else 65 putchar('*'); 66 67 } 68 69 //画出食物 70 MOVETO(food.X,food.Y); 71 putchar('#'); 72 73 //删除蛇尾 74 MOVETO(lastX,lastY); 75 putchar(' '); 76 77 //防止光标干扰 78 MOVETO(0,HEIGHT+2); 79 // printf("当前速度: %dcm/s\n",(210000-sleepSecond)/10000); //实时打印分数 80 printf("当前分数: %d 分\n",score); //实时打印分数 81 82 return ; 83 } 84 85 //开始游戏 86 void playGame() 87 { 88 char key = 'd'; 89 90 91 //蛇撞墙 92 while(snake.body[0].X > 0 && snake.body[0].X <WIDTH 93 &&snake.body[0].Y > 0 && snake.body[0].Y <HEIGHT-1) 94 { 95 96 // initWall(); 97 //更新蛇 98 initUi(); 99 100 //判断用户按键 101 if(kbhit()) 102 { 103 key = getch(); 104 } 105 106 //获取按键后坐标 107 switch(key) 108 { 109 case'w':kx = 0; ky = -1;break; 110 case's':kx = 0; ky = +1;break; 111 case'a':kx = -1; ky = 0;break; 112 case'd':kx = +1; ky = 0;break; 113 default:break; 114 } 115 116 //蛇撞身体 蛇头==任意一节身体 117 for(int i=1; i<snake.size; ++i) 118 { 119 if(snake.body[0].X == snake.body[i].X 120 &&snake.body[0].Y == snake.body[i].Y) 121 { 122 return ; //退出游戏 123 } 124 } 125 126 //蛇撞食物 127 if(snake.body[0].X == food.X && snake.body[0].Y == food.Y) 128 { 129 //食物消失,新的食物 130 initFood(); 131 //身体增长 132 snake.size++; 133 //加分 134 score += 10; 135 //加速 136 sleepSecond -= 10000; 137 138 } 139 140 //保存蛇尾坐标 141 lastX = snake.body[snake.size-1].X; 142 lastY = snake.body[snake.size-1].Y; 143 144 //蛇移动 145 for(int i=snake.size-1; i>0; i--) 146 { 147 148 snake.body[i].X = snake.body[i-1].X; 149 snake.body[i].Y = snake.body[i-1].Y; 150 } 151 snake.body[0].X += kx; 152 snake.body[0].Y += ky; 153 154 usleep(sleepSecond); 155 // system("clear"); 156 } 157 158 return ; 159 } 160 161 //定义阻塞函数 162 int kbhit(void) 163 { 164 struct termios oldt, newt; 165 int ch; 166 int oldf; 167 168 tcgetattr(STDIN_FILENO, &oldt); 169 newt = oldt; 170 newt.c_lflag &= ~(ICANON | ECHO); 171 tcsetattr(STDIN_FILENO, TCSANOW, &newt); 172 oldf = fcntl(STDIN_FILENO, F_GETFL, 0); 173 fcntl(STDIN_FILENO, F_SETFL, oldf | O_NONBLOCK); 174 ch = getchar(); 175 tcsetattr(STDIN_FILENO, TCSANOW, &oldt); 176 fcntl(STDIN_FILENO, F_SETFL, oldf); 177 if(ch != EOF) 178 { 179 ungetc(ch, stdin); 180 return 1; 181 } 182 return 0; 183 } 184 185 //无回显获取字符 186 int getch(void) 187 { 188 struct termios tm, tm_old; 189 int fd = 0, ch; 190 191 if (tcgetattr(fd, &tm) < 0) {//保存现在的终端设置 192 return -1; 193 } 194 195 tm_old = tm; 196 cfmakeraw(&tm);//更改终端设置为原始模式,该模式下所有的输入数据以字节为单位被处理 197 if (tcsetattr(fd, TCSANOW, &tm) < 0) {//设置上更改之后的设置 198 return -1; 199 } 200 201 ch = getchar(); 202 if (tcsetattr(fd, TCSANOW, &tm_old) < 0) {//更改设置为最初的样子 203 return -1; 204 } 205 206 return ch; 207 } 208 209 void initWall() 210 { 211 for(int i=0; i<=HEIGHT-3; i++) 212 { 213 for(int j =0; j<=WIDTH-1; j++) 214 { 215 if(j == WIDTH-1) 216 printf("|"); 217 else if(i == HEIGHT-3) 218 printf("_"); 219 else 220 printf(" "); 221 } 222 printf("\n"); 223 } 224 }
1 #ifndef __SNAKE_H__ 2 #define __SNAKE_H__ 3 4 #include <stdlib.h> 5 #include <time.h> 6 #include <termio.h> 7 8 #include <stdio.h> 9 #include <termios.h> 10 #include <unistd.h> 11 #include <fcntl.h> 12 13 14 #define HEIGHT 30 15 #define WIDTH 60 16 //定位光标 17 #define MOVETO(y,x) printf("\033[%d;%dH", (x), (y)) 18 19 //定义蛇身体对象 20 struct BODY 21 { 22 int X; 23 int Y; 24 }body; 25 26 //定义蛇对象 27 struct SNAKE 28 { 29 struct BODY body[HEIGHT*WIDTH]; 30 int size; 31 }snake; 32 33 //定义食物对象 34 struct FOOD 35 { 36 int X; 37 int Y; 38 }food; 39 40 //定义总分数 41 int score = 0; 42 43 //定义key坐标 44 int kx; 45 int ky; 46 47 //定义蛇尾坐标 48 int lastX; 49 int lastY; 50 51 //定义速度 52 int sleepSecond = 200000; 53 54 //声明函数 55 void initSnake(); 56 void initFood(); 57 void initUi(); 58 int getch(void); 59 void playGame(); 60 int kbhit(void); 61 void initWall(); 62 63 #endif