初学编程,利用现有的知识编写了一个贪吃蛇小游戏。
目前游戏的制作程度仅限于“能玩”。
还有一定BUG有待改善。
以下是代码:
#include
#include
#include
#include
#include
#define SNAKE_MAX_LENGTH 30
#define SNAKE_HEAD 'H'
#define SNAKE_BODY 'X'
#define BLANK_CELL ' '
#define SNAKE_FOOD '$'
#define WALL_CELL '*'
//snake stepping: dy=-1(up),1(down); dx=-1(left),1(right),0(move)
void snakeMove(int, int);
//put a food randomized on a blank cell
void put_money(void);
//out cells of the grid
void output(void);
//outs when gameover
void gameover(void);
//lengthen the snake
void lengthen(void);
char map[12][23]=
{"**********************", //初始状态
"* *", //直接打表
"* welcome! *",
"* *",
"* *",
"* *",
"* *",
"* press any button *",
"* to start *",
"* *",
"* *",
"**********************"};
char map1[12][23] =
{"**********************", //初始状态
"*XXXXH *", //直接打表
"* *",
"* *",
"* *",
"* *",
"* *",
"* *",
"* *",
"* *",
"* *",
"**********************"};
// #define vars for snake, notice name of vars in C
int snakeX[SNAKE_MAX_LENGTH] = {1, 2, 3, 4, 5}; //蛇身和蛇头的坐标
int snakeY[SNAKE_MAX_LENGTH] = {1, 1, 1, 1, 1};
int snakeLength = 5;
int flag = 0; // gameover为1,否则为0
int tailx, taily; // 用于增加长度
int moneyx, moneyy; // 随机生成money坐标
int moneyflag = 0; // 标识是否已经确定位置放money
void snakeMove(int dy, int dx) { //只要控制蛇头
tailx = snakeX[0];
taily = snakeY[0]; // 保存尾部位置增加长度
int tmp, i;
tmp = snakeLength;
// 尾部消失
map[snakeY[0]][snakeX[0]] = ' ';
//身体重复前一个部分
for (i = 0; i < tmp - 1; i++) { // 身体先移动一格
snakeX[i] = snakeX[i + 1];
snakeY[i] = snakeY[i + 1];
}
// 头部移动
if (dy == -1)
snakeY[snakeLength - 1]--;
if (dy == 1)
snakeY[snakeLength - 1]++;
if (dx == 1)
snakeX[snakeLength - 1]++;
if (dx == -1)
snakeX[snakeLength - 1]--;
}
void put_money(void) {
if (moneyflag == 1) // 若已经放了食物
return;
else {
srand((unsigned int)time(NULL)); // 产生随机坐标
moneyx = rand() % 21 + 1;
moneyy = rand() % 10 + 1;
// 要将money放在空白处
if (map[moneyy][moneyx] == ' ') {
moneyflag = 1;
} else
put_money();
}
// 得到最终坐标
map[moneyy][moneyx] = '$';
}
void output(void) {
int i, j;
for (i = 0, j = 0; i < snakeLength - 1, j 1; j++, i++)
map[snakeY[i]][snakeX[j]] = 'X'; //头部位置
map[snakeY[snakeLength - 1]][snakeX[snakeLength - 1]] = 'H'; //身体
for (i = 0; i < 12; i++) { // 输出图形
for (j = 0; j < 23; j++) {
printf("%c", map[i][j]);}
printf("\n");
} }
void gameover(void) {
int i;
// 判断头部是否出界
if (snakeX[snakeLength - 1] == 0 || snakeX[snakeLength - 1] == 21
|| snakeY[snakeLength - 1] == 0 || snakeY[snakeLength - 1] == 11)
flag = 1;
// 判断头部是否与身体重合
for (i = 0; i < snakeLength - 1;i++)
if (snakeX[snakeLength - 1] == snakeX[i] && snakeY[snakeLength - 1] == snakeY[i])
flag = 1;
}
void lengthen(void) {
int i;
snakeLength++; // 长度+1
for (i = snakeLength - 1; i > 0; i--) {
snakeY[i] = snakeY[i - 1]; // 将 所有坐标赋值给下一位,用于增大长度
snakeX[i] = snakeX[i - 1];
}
snakeX[0] = tailx; // 尾部为增加的部位
snakeY[0] = taily;
}
int main() {
char move;
int i,j, hard;
for (i = 0; i < 12; i++) { // 欢迎界面
for (j = 0; j < 23; j++) {
printf("%c", map[i][j]);}
printf("\n");}
getch();
system("cls");
for (i = 0; i < 12; i++) // 初始化地图
for (j = 0; j < 23; j++)
map[i][j]=map1[i][j];
put_money(); // 初始的食物
for (i = 0; i < 12; i++) {
for (j = 0; j < 23; j++) {
printf("%c", map[i][j]);}
printf("\n");}
move = 'D';
int speed = 300;
while (1) { // 未gameover则一直输入
Sleep(speed);
if (kbhit()!=0) {
move=getch();
}
switch (move) { // 对输入的处理
case 'W':
snakeMove(-1, 0);
break;
case 'S':
snakeMove(1, 0);
break;
case 'A':
snakeMove(0, -1);
break;
case 'D':
snakeMove(0, 1);
break;
}
// 若头部与食物重合,即吃到食物
if (snakeX[snakeLength - 1] == moneyx && snakeY[snakeLength - 1] == moneyy) {
moneyflag = 0; // 食物消去
put_money(); // 产生新的食物
lengthen(); // 伸长
speed -= 20;
}
gameover(); // 判断是否gameover
system("cls"); // 清屏
output(); // 输出当前地图
if (flag==1)
break;
} printf("GAMEOVER\n");
return 0;
}
没有用到较复杂的知识点,只是用了二维数组来表示地图。
注意:getch(),kbhit() 需要引用头文件 conio.h
Sleep() 需要引用头文件 windows.h