小游戏一之---------贪食蛇教程
1.个人认为,学编程最重要的是多动手写代码,只有你真正去写,你才能发现自己的问题所在,发现并改正,你的能力就能得到提升。对于大多数人而言,你踏踏实实把所学到的知识理解并运用好,你就能成为一个不错的程序员。
2.写一些小游戏用于练习是一个很不错的选择,代码量不算多,也不算少,既可以巩固知识,又可以提升兴趣。
3.游戏最重要的是逻辑实现而并非画面表现,所以黑窗口也无所谓,明白原理才最重要。
废话不多说,开始。
1)蛇移动的原理
蛇的移动是静态的移动,就是不断重绘蛇的位置,由于重绘速度很快,在人眼看来就是在移动。
2)蛇移动的规律
蛇的移动可以看作只有蛇头在变化。比如,蛇向右移动,其实就是蛇头向右移动一格,原来蛇头的位置就变为第一节蛇身的位置,原来第一节蛇身的位置,就变为第二节蛇身的位置,其余类推。
3)用到的知识
数组,结构体,指针
4)大概思路
定义一个结构体表示“点”(x,y),用一个数组来储存蛇,每一节蛇其实就是一个坐标点。知道蛇的坐标就很容易了,只需在对应的坐标画蛇就可以了。
如何移动到对应的坐标:用到一个API函数------gotoxy(int x,int y),会将光标移到对应的位置。
如何获取用户的输入:kbhit()函数可以获取用户输入的按键,返回按键的ASCII,非阻塞。
5)游戏效果
代码有具体注释,大概200多行,很合适练手。
1 #include<stdio.h> 2 #include<stdlib.h> 3 #include<conio.h> 4 #include<Windows.h> 5 //游戏画面大小 6 #define HEIGHT 25//高 7 #define WIDE 45//宽 8 typedef struct 9 { 10 int x;//x坐标 11 int y;//y坐标 12 13 }Point; 14 15 char direction='w';//方向 16 int point=0;//分数 17 18 void init(Point*snake,int bodyNum);//初始化,设定蛇身的坐标 19 void move(Point*snake,int *bodyNum);// 20 void printSnake(Point * snake,int bodyNum);//打印蛇 21 char controlMove();//控制移动 22 23 void change(Point*snake,int bodyNum);//改变蛇的坐标 24 void clean(Point*snake,int bodyNum);//在屏幕上清除之前的蛇 25 26 void printWall();//打印墙壁 27 int isDead(Point*snake,int bodyNum);//判断蛇是否死亡 是返回1 非返回0 28 void food(Point*snake,int bodyNum);//随机产生食物 29 int eatFood(Point*snake,int *bodyNum);//判断是否吃到食物 是返回1 非返回0 30 31 void HideCursor();//隐藏光标 32 void gotoxy (int x,int y);//光标位置移动到指定的坐标 33 34 void HideCursor() 35 { 36 CONSOLE_CURSOR_INFO cursor_info = {1, 0}; 37 SetConsoleCursorInfo(GetStdHandle(STD_OUTPUT_HANDLE), &cursor_info); 38 } 39 void gotoxy (int x,int y) 40 { 41 HANDLE handle=GetStdHandle(STD_OUTPUT_HANDLE); 42 COORD pos; 43 pos.X=x; 44 pos.Y=y; 45 SetConsoleCursorPosition(handle,pos); 46 } 47 48 int main() 49 { 50 Point snake[64];//表示蛇 51 int bodyNum=6;//蛇身的个数,初始化6个 52 srand(time(NULL));//设置随机种子 53 54 HideCursor(); 55 init(snake,bodyNum); 56 printWall(); 57 food(snake,bodyNum); 58 printSnake(snake,bodyNum); 59 60 while(1) 61 { 62 move(snake,&bodyNum); 63 Sleep(200-point);//分数越高速度越快 64 } 65 66 } 67 68 void init(Point*snake,int bodyNum) 69 { 70 int i; 71 snake[0].x=HEIGHT/2; 72 snake[0].y=WIDE/2; 73 for(i=1;i<bodyNum;i++) 74 { //让蛇一开始在画面中间 75 snake[i].x=HEIGHT/2+i; 76 snake[i].y=WIDE/2; 77 } 78 } 79 80 void move(Point*snake,int *bodyNum) 81 { 82 char dir=controlMove();//获取用户输入的按键 83 clean(snake,*bodyNum);//清除之前的蛇 84 change(snake,*bodyNum);//每次移动时都改变坐标 85 //改变蛇头的坐标 86 switch(dir) 87 { 88 case 'w': 89 snake[0].y--; 90 break; 91 case 's': 92 snake[0].y++; 93 break; 94 case 'a': 95 snake[0].x--; 96 break; 97 case 'd': 98 snake[0].x++; 99 break; 100 default: 101 break; 102 } 103 104 if(eatFood(snake,bodyNum))//如果吃到食物 105 { 106 107 if(point>100) 108 point+=5; 109 else 110 point+=10; 111 112 food(snake,*bodyNum);//随机产生新的食物 113 } 114 115 printSnake(snake,*bodyNum);//打印新的蛇 116 if(isDead(snake,*bodyNum))//如果死亡 117 { 118 gotoxy(WIDE,HEIGHT); 119 printf("\n\n\nGAVE OVER"); 120 exit(0);//退出游戏 121 } 122 } 123 124 void printSnake(Point * snake,int bodyNum) 125 { 126 int i; 127 gotoxy(snake[0].x,snake[0].y);//蛇头位置 128 printf("@"); //蛇头 129 for(i=1;i<bodyNum;i++) 130 { 131 132 gotoxy(snake[i].x,snake[i].y); 133 printf("*");//蛇身 134 } 135 } 136 137 char controlMove()//控制移动 138 { 139 char input; 140 if(kbhit())//检测是否有输入 有返回1 没有返回0 (非阻塞函数) 141 { 142 input=getch();//返回按下的键 143 if(input=='w'||input=='s'||input=='a'||input=='d') 144 direction=input; 145 } 146 return direction; 147 } 148 149 void change(Point*snake,int bodyNum) 150 { 151 int i; 152 //移动 原来的蛇头坐标变为第一节蛇身,其余依此类推, 153 for(i=bodyNum-1;i>0;i--) 154 snake[i]=snake[i-1]; 155 } 156 157 158 159 void clean(Point*snake,int bodyNum) 160 { 161 int i; 162 for(i=0;i<bodyNum;i++) 163 { 164 gotoxy(snake[i].x,snake[i].y); 165 printf(" "); 166 167 } 168 } 169 void printWall() 170 { 171 int i; 172 for(i=0;i<WIDE;i++) 173 { 174 gotoxy(i,0); 175 printf("#"); 176 gotoxy(i,HEIGHT); 177 printf("#"); 178 } 179 for(i=0;i<HEIGHT;i++) 180 { 181 gotoxy(0,i); 182 printf("#"); 183 gotoxy(WIDE,i); 184 printf("#"); 185 } 186 } 187 188 int isDead(Point*snake,int bodyNum) 189 { 190 int i; 191 if(snake[0].x==WIDE||snake[0].x==0) 192 return 1; 193 if(snake[0].y==HEIGHT||snake[0].y==0) 194 return 1; 195 for(i=1;i<bodyNum;i++) 196 { 197 if(snake[0].x==snake[i].x&&snake[0].y==snake[i].y) 198 return 1; 199 } 200 return 0; 201 } 202 203 void food(Point*snake,int bodyNum) 204 { 205 int x,y; 206 x=rand()%(WIDE-1); 207 y=rand()%(HEIGHT-1); 208 gotoxy(x,y); 209 printf("o"); 210 //将食物的坐标存在数组中 211 snake[bodyNum].x=x; 212 snake[bodyNum].y=y; 213 } 214 215 int eatFood(Point*snake,int *bodyNum) 216 { 217 218 if(snake[0].x==snake[*bodyNum].x&&snake[0].y==snake[*bodyNum].y) 219 { 220 gotoxy(snake[*bodyNum].x,snake[*bodyNum].y); 221 printf(" "); 222 snake[*bodyNum]=snake[*bodyNum-1]; 223 snake[*bodyNum].x++; 224 (*bodyNum)++; 225 return 1; 226 } 227 return 0; 228 }
有不懂的,可以问我。
今后会继续更新小游戏系列。