欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

进化的贪吃蛇(一)

程序员文章站 2022-03-21 20:33:50
有很多学习C语言或者C++的朋友可能写过贪吃蛇的作业,我也是其中之一。在最开始写的时候自己水平很差,写出的效果还不如许多同学从网上抄的。 这一系列博客都是使用C语言写贪吃蛇,逐步提升难度,当然自己也好久不动手了,也算是自己复习一次C语言。 第一个贪吃蛇,因为许多刚学完C的同学并不了解太多东西,所以我 ......

有很多学习C语言或者C++的朋友可能写过贪吃蛇的作业,我也是其中之一。在最开始写的时候自己水平很差,写出的效果还不如许多同学从网上抄的。

这一系列博客都是使用C语言写贪吃蛇,逐步提升难度,当然自己也好久不动手了,也算是自己复习一次C语言。

第一个贪吃蛇,因为许多刚学完C的同学并不了解太多东西,所以我们只使用最基本的方法,完成最基本的功能。当然,我们得到的效果可能也就不是很好。

  1 #include <stdio.h>
  2 
  3 //随机数生成
  4 #include <stdlib.h>
  5 #include <time.h>
  6 
  7 //Windows API
  8 #include <Windows.h>
  9 
 10 //游戏常量设置
 11 #define MAP_H 10
 12 #define MAP_W 20
 13 #define INIT_LEN 2
 14 #define GAME_SPEED 200
 15 
 16 #define CH_SNAKE 'O'
 17 #define CH_FOOD '*'
 18 #define CH_WALL 'H'
 19 #define CH_SPACE ' '
 20 
 21 char map[MAP_H][MAP_W];
 22 struct _point{
 23     int y;
 24     int x;
 25 }snake[MAP_H*MAP_W];
 26 int snakeLength;
 27 enum _direction{
 28     UP,LEFT,RIGHT,DOWN
 29 }direction;
 30 
 31 void initialize();//初始化
 32 int update();//更新画面
 33 void generateFood();//生成食物
 34 void changeDirection();//方向控制
 35 void showMap();//显示画面
 36 
 37 /*************
 38 * 基本的游戏逻辑:显示、控制、更新
 39 */
 40 int main(){
 41 
 42     initialize();
 43     do{
 44         showMap();
 45         changeDirection();
 46     }while(update());
 47 
 48     return 0;
 49 }
 50 
 51 /*******************
 52 * 初始化画面数组、蛇身体的坐标数组、蛇的长度、最后在地图上生成一个食物
 53 */
 54 void initialize(){
 55     int i,j;
 56     snakeLength=INIT_LEN;
 57     direction=RIGHT;
 58 
 59     for(i=0;i<MAP_H;i++){
 60         for(j=0;j<MAP_W;j++){
 61             map[i][j]=CH_SPACE;
 62         }
 63     }
 64 
 65     for(i=0;i<INIT_LEN;i++){
 66         snake[i].x=INIT_LEN-i-1;
 67         snake[i].y=0;
 68     }
 69 
 70     for(i=0;i<snakeLength;i++){
 71         map[snake[i].y][snake[i].x]=CH_SNAKE;
 72     }
 73 
 74     generateFood();
 75 }
 76 
 77 /*******************
 78 * Sleep控制游戏速度,system函数调用console指令cls清屏,最后循环输出画面
 79 */
 80 void showMap(){
 81     system("cls");
 82     int i,j;
 83 
 84     for(i=0;i<MAP_W+2;i++){
 85         putchar(CH_WALL);
 86     }
 87     putchar('\n');
 88 
 89     for(i=0;i<MAP_H;i++){
 90         putchar(CH_WALL);
 91         for(j=0;j<MAP_W;j++){
 92             putchar(map[i][j]);
 93         }
 94         putchar(CH_WALL);
 95         putchar('\n');
 96     }
 97 
 98     for(i=0;i<MAP_W+2;i++){
 99         putchar(CH_WALL);
100     }
101 }
102 
103 /*******************
104 * 使用随机数产生食物的坐标
105 */
106 void generateFood(){
107     int x,y;
108     srand(time(0));
109     while(1){
110         x=rand()%MAP_W;
111         y=rand()%MAP_H;
112         if(map[y][x]==CH_SPACE)
113             break;
114     }
115     map[y][x]=CH_FOOD;
116 }
117 
118 /*******************
119 * 更新画面(游戏逻辑处理的部分)
120 * 通过direction计算下一个画面蛇头到达的位置,检查该位置的物体,分别处理不同情形
121 */
122 int update(){
123     Sleep(GAME_SPEED);
124     int i,head_y,head_x;
125 
126     switch(direction){
127     case UP:
128         head_y=snake[0].y-1;
129         head_x=snake[0].x;
130         break;
131     case LEFT:
132         head_y=snake[0].y;
133         head_x=snake[0].x-1;
134         break;
135     case RIGHT:
136         head_y=snake[0].y;
137         head_x=snake[0].x+1;
138         break;
139     case DOWN:
140         head_y=snake[0].y+1;
141         head_x=snake[0].x;
142         break;
143     }
144     if(head_x<0||head_x>MAP_W||head_y<0||head_y>MAP_H){
145         return 0;//撞墙
146     }
147 
148     if(map[head_y][head_x]==CH_SNAKE){
149         return 0;//撞自己
150     }
151     if(map[head_y][head_x]==CH_FOOD){
152         for(i=snakeLength;i>0;i--){
153             snake[i]=snake[i-1];
154         }
155         snake[0].x=head_x;
156         snake[0].y=head_y;
157         map[head_y][head_x]=CH_SNAKE;
158         snakeLength+=1;
159         generateFood();
160         return 1;//吃食物
161     }
162     if(map[head_y][head_x]==CH_SPACE){
163         map[snake[snakeLength-1].y][snake[snakeLength-1].x]=CH_SPACE;
164         for(i=snakeLength-1;i>0;i--){
165             snake[i]=snake[i-1];
166         }
167         snake[0].x=head_x;
168         snake[0].y=head_y;
169         map[head_y][head_x]=CH_SNAKE;
170         return 1;//继续前进
171     }
172 
173     return 1;
174 }
175 
176 /*******************
177 * 使用GetKeyState获取键盘输入,改变direction变量来控制行进方向
178 */
179 void changeDirection(){
180     if(GetKeyState(VK_UP)<0&&direction!=DOWN)
181         direction=UP;
182     else if(GetKeyState(VK_LEFT)<0&&direction!=RIGHT)
183         direction=LEFT;
184     else if(GetKeyState(VK_DOWN)<0&&direction!=UP)
185         direction=DOWN;
186     else if(GetKeyState(VK_RIGHT)<0&&direction!=LEFT)
187         direction=RIGHT;
188 }

 

这差不多就是我第一次写的,相当的简陋,使用体验很差。但是除了Sleep,system,GetKeyState之外并没有什么C语言课本上没教过的。

Sleep函数使控制台挂起(停下来),控制游戏速度。

system函数是用于输入控制台命令的,cls是控制台用于清屏的命令

GetKeyState函数用于读取键盘上某个特定按键的状态,这里用于读取用户输入(控制方向)

当然,现在上面的代码除了基本的游戏逻辑什么都没有。而且还会闪屏,最坑的是因为Sleep函数,按键有时候并不能被读取,这是因为Sleep挂起了整个程序,而读取输入正是程序的一部分。