“贪吃蛇”作为一款经典的小游戏承载了我们的童年回忆。这次我们试着用C语言制作一个简单的贪吃蛇字符小游戏。
首先,我们用自顶向下的思路去考虑这个问题,先做一个可以在一定范围内通过键盘控制来移动的“蛇”。
用伪代码来表示这个过程, 就是:
输出字符矩阵
WHILE not 游戏结束 DO
ch=等待输入
CASE ch DO
‘A’:左前进一步,break
‘D’:右前进一步,break
‘W’:上前进一步,break
‘S’:下前进一步,break
END CASE
输出字符矩阵
END WHILE
输出 Game Over!!!
游戏结束的标志是贪吃蛇的头部撞到了“墙”。
经过这样的分析,我们的游戏已经有了一定的框架。下面我们套用这个框架完成游戏的设计吧。
#include <stdio.h>
#include <time.h>
#include <stdlib.h>
#include <conio.h>
#define head 'H'
#define body 'X'
#define blank_char ' '
这是整个程序的头部。
游戏的对象“蛇”的属性包括位置和长度,用一个结构体来定义:
struct SNAKE
{
int x[100];
int y[100];
int lenth ;
}snake;
定义两个参数分别控制游戏的进程和方向:
int gamerun = 1;
char ch;
采用字符型式打印出游戏的界面:
char map[10][11] =
{
"**********",
"* *",
"* *",
"* *",
"* *",
"* *",
"* *",
"* *",
"* *",
"**********" };
以下是实现游戏的几个重要步骤:
void PrintMap ()
{
int i=0;
system("cls");
for ( i=0; i<10; i++ ) {
printf("%s\n", map[i]);
}
}
void GameOver ()
{
gamerun = 0;
printf("GAME OVER!\n");
}
void InitGame()
{
snake.y[0] = snake.y[1] = snake.y[2] = snake.y[3] = 1;
snake.x[0] = 5;
snake.x[1] = 4;
snake.x[2] = 3;
snake.x[3] = 2;
snake.lenth = 4;
map[snake.y[0]][snake.x[0]] = head;
map[snake.y[1]][snake.x[1]] = body;
map[snake.y[2]][snake.x[2]] = body;
map[snake.y[3]][snake.x[3]] = body;
map[snake.y[4]][snake.x[4]] = body;
gamerun = 1;
PrintMap();
}
void MoveSnake ()
{
int i = 0;
ch = _getch();
map[snake.y[snake.lenth-1]][snake.x[snake.lenth-1]] = blank_char;
map[snake.y[0]][snake.x[0]] = body;
for( i=snake.lenth-1; i; i-- )
{
snake.x[i] = snake.x[i-1];
snake.y[i] = snake.y[i-1];
}
switch(ch)
{
case 'w': snake.y[0]--; break;
case 'a': snake.x[0]--; break;
case 's': snake.y[0]++; break;
case 'd': snake.x[0]++; break;
}
if(map[snake.y[0]][snake.x[0]] != blank_char ) GameOver();
else map[snake.y[0]][snake.x[0]] = head;
}
其中 system(“cls”); 指令不断的清空屏幕上的内容,接下来的指令再进行反复地填充。
void InitGame() 初始化整个游戏的对象。
map[snake.y[snake.lenth-1]][snake.x[snake.lenth-1]] = blank_char;
则是实现了蛇改变方向时“头尾互换”的操作。
游戏通过键盘上的小写‘w’,’a’,’s’,’d’控制蛇的移动。
int main()
{
InitGame() ;
while (gamerun)
{
MoveSnake();
PrintMap();
}
return 0;
}
一条会动的蛇,就完成啦!
下面我们仅需要做一些简单的改动,就可以让它实现“会吃”的功能了。
在定义头部时加上食物:
#define food_char '$'
对象“食物”的属性是它的位置:
struct FOOD
{
int x;
int y;
}food;
主程序中加上一步 SpawnFood();
int main()
{
InitGame() ;
while (gamerun)
{
srand(time(NULL));
MoveSnake();
if(!IsFood) SpawnFood ();
PrintMap();
}
return 0;
}
void SpawnFood ()
{
food.x = rand() % 8 + 1;
food.y = rand() % 9 + 1;
while(map[food.y][food.x] != blank_char) {
food.x = rand() % 8 + 1;
food.y = rand() % 9 + 1;
}
map[food.y][food.x] = food_char;
IsFood = 1;
}
.......
if(map[snake.y[0]][snake.x[0]] != blank_char && map[snake.y[0]][snake.x[0]] != food_char) GameOver();
if(map[snake.y[0]][snake.x[0]] == food_char )
{
map[snake.y[0]][snake.x[0]] = head;
snake.lenth++;
IsFood = 0;
}
else map[snake.y[0]][snake.x[0]] = head;
}
即贪吃蛇的头部位置与随机位置出现的食物位置相同时长度加一。
尽管这次制作的小游戏界面简陋,玩法单一,(移动起来还略显zhizhang) 但还是一次有趣的尝试啦~