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 }
snake.c
 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
snake.h

posted @ 2023-09-30 12:13  真是服了你个老六!!  阅读(58)  评论(0编辑  收藏  举报