贪吃蛇大概我们都玩过,作为一名优秀(并不)的程序猿,当然要自己造一条出来啦
整体的构思如下面的伪代码所示
输出字符矩阵
WHILE not 游戏结束 DO
ch=等待输入
CASE ch DO
‘A’:左前进一步,break
‘D’:右前进一步,break
‘W’:上前进一步,break
‘S’:下前进一步,break
END CASE
输出字符矩阵
END WHILE
输出 Game Over!!!
接着我们就一步一步实现
定义变量
我们在开始要定义一些要用的变量
char map[12][12];
int snakeX[100] = { 1, 1, 1, 1, 1 };
int snakeY[100] = { 1, 2, 3, 4, 5 };
int foodX = rand() % 10 + 1;
int foodY = rand() % 10 + 1;
int snake_head = 4;
这里的map就是整个游戏区域,下面两个snake就是我们的蛇了,food嘛自然就是吃的,这里给了个随机初始化让游戏开始的时候食物随机放,然后最底下的是蛇头所在的数组位置,可以当作蛇的长度
输出字符
作为一名PS玩家,我把画面分成几个“图层”,从底向上覆盖输出,虽然看上去就很麻烦很没效率,不过做起来简单啊,又不是不能用
void print_map() {
system("cls");
set_boundry();
set_snake();
set_food();
print_all();
}
思路就是先清屏→画边框→画蛇→画食物,这里的set相当于逐步画图层,然后print就是输出最终结果。接下来再分解来看。
画边框
void set_boundry() {
for (int i = 0; i < 12; i++) {
map[0][i] = map[11][i] = '*';
}
for (int i = 1; i < 11; i++) {
map[i][0] = map[i][11] = '*';
for (int j = 1; j < 11; j++)
map[i][j] = ' ';
}
}
这个其实就没什么好说的了,超简单的是吧。
画蛇
这里就是照着蛇的数组给“图层”上的特点位置打上“H”和“X”
void set_snake() {
map[snakeX[snake_head]][snakeY[snake_head]] = 'H'; //the head
for (int i = snake_head - 1; i >= 0; i--) {
map[snakeX[i]][snakeY[i]] = 'X';
}//the body
}
画食物
这里的设定是蛇头碰到食物时重新设定食物位置,这里我直接用了个暴力的随机方法,到游戏后面空间小的时候电脑会挺惨的吧。。。不过我是玩不到那么厉害了
void set_food() {
//if the snake eat the food, change the place of the food
if (snakeX[snake_head] == foodX && snakeY[snake_head] == foodY) {
srand(time(0));
while (1) {
foodX = rand() % 10 + 1;
foodY = rand() % 10 + 1;
if (map[foodX][foodY] == ' ') {
break;
}//place the food in a blank place
}
}
map[foodX][foodY] = '$';
}
输出字符
这里就是把通过以上设定调教好的map数组输出就行了
void print_all() {
for (int i = 0; i < 12; i++) {
for (int j = 0; j < 12; j++)
printf("%c", map[i][j]);
printf("\n");
}
}
游戏环节
这里的设定:按下按键一次,蛇往相应方向走一格,然后判定有没有吃自己/怼墙/吃到东西等判定,如果有前两个就game over,至于后一个就重设食物位置,以及给蛇续一格
判断游戏是否继续
int game_run() {
//when the snake hits the wall
if (snakeX[snake_head] == 0 || snakeX[snake_head] == 11)
return 0;
if (snakeY[snake_head] == 0 || snakeY[snake_head] == 11)
return 0;
//when the snake eats itself
for (int i = 0; i < snake_head - 1; i++) {
if (snakeX[snake_head] == snakeX[i] && snakeY[snake_head] == snakeY[i])
return 0;
}
return 1;
}
如果游戏能愉快地继续就返回1,gg了的话就返回0。
蛇的移动
首先通过getch()读入字符,然后通过不同字符对数组进行不同操作
char ch = _getch();
switch (ch) {
case 'w':
snake_move(-1, 0);
break;
case 's':
snake_move(1, 0);
break;
case 'a':
snake_move(0, -1);
break;
case 'd':
snake_move(0, 1);
break;
}
void snake_move(int X, int Y) {
//the snake eat the food, replace the food with a new head
if (snakeX[snake_head] + X == foodX && snakeY[snake_head] + Y == foodY) {
snake_head++;
snakeX[snake_head] = foodX;
snakeY[snake_head] = foodY;
}
//the snake doesn't hit the food, move forward
else {
int tempX = snakeX[snake_head];
int tempY = snakeY[snake_head];
snakeX[snake_head] += X;
snakeY[snake_head] += Y;
for (int i = 0; i < snake_head - 1; i++) {
snakeX[i] = snakeX[i + 1];
snakeY[i] = snakeY[i + 1];
}
snakeX[snake_head - 1] = tempX;
snakeY[snake_head - 1] = tempY;
}
}
这里看着挺复杂的,大概就是:如果吃到东西了就把食物位置加在snake数组后面,同时数组长度变量+1;如果没吃到就将蛇头像相应方向移动一格,接着数组中从头开始将[i+1]的值赋给[i],实现蛇的前进。
这样来看,每次按键都给数组进行相应的操作,最后一层一层输出,这样我们的低配贪吃蛇就做好啦
完整代码如下:
#include "stdafx.h"
#include <conio.h>
#include <stdlib.h>
#include <time.h>
//create data of the game
char map[12][12];
int snakeX[100] = { 1, 1, 1, 1, 1 };
int snakeY[100] = { 1, 2, 3, 4, 5 };
int foodX = rand() % 10 + 1;
int foodY = rand() % 10 + 1;
int snake_head = 4;
//make the snake move
void snake_move(int X, int Y) {
//the snake eat the food, replace the food with a new head
if (snakeX[snake_head] + X == foodX && snakeY[snake_head] + Y == foodY) {
snake_head++;
snakeX[snake_head] = foodX;
snakeY[snake_head] = foodY;
}
//the snake doesn't hit the food, move forward
else {
int tempX = snakeX[snake_head];
int tempY = snakeY[snake_head];
snakeX[snake_head] += X;
snakeY[snake_head] += Y;
for (int i = 0; i < snake_head - 1; i++) {
snakeX[i] = snakeX[i + 1];
snakeY[i] = snakeY[i + 1];
}
snakeX[snake_head - 1] = tempX;
snakeY[snake_head - 1] = tempY;
}
}
//determine if the game is over
int game_run() {
//when the snake hits the wall
if (snakeX[snake_head] == 0 || snakeX[snake_head] == 11)
return 0;
if (snakeY[snake_head] == 0 || snakeY[snake_head] == 11)
return 0;
//when the snake eats itself
for (int i = 0; i < snake_head - 1; i++) {
if (snakeX[snake_head] == snakeX[i] && snakeY[snake_head] == snakeY[i])
return 0;
}
return 1;
}
//set the wall
void set_boundry() {
for (int i = 0; i < 12; i++) {
map[0][i] = map[11][i] = '*';
}
for (int i = 1; i < 11; i++) {
map[i][0] = map[i][11] = '*';
for (int j = 1; j < 11; j++)
map[i][j] = ' ';
}
}
//set the snake
void set_snake() {
map[snakeX[snake_head]][snakeY[snake_head]] = 'H'; //the head
for (int i = snake_head - 1; i >= 0; i--) {
map[snakeX[i]][snakeY[i]] = 'X';
}//the body
}
//set the food
void set_food() {
//if the snake eat the food, change the place of the food
if (snakeX[snake_head] == foodX && snakeY[snake_head] == foodY) {
srand(time(0));
while (1) {
foodX = rand() % 10 + 1;
foodY = rand() % 10 + 1;
if (map[foodX][foodY] == ' ') {
break;
}//place the food in a blank place
}
}
map[foodX][foodY] = '$';
}
//print the map
void print_all() {
for (int i = 0; i < 12; i++) {
for (int j = 0; j < 12; j++)
printf("%c", map[i][j]);
printf("\n");
}
}
//a whole process to print
void print_map() {
system("cls");
set_boundry();
set_snake();
set_food();
print_all();
}
int main() {
print_map();
while (game_run()) {
char ch = _getch();
switch (ch) {
case 'w':
snake_move(-1, 0);
break;
case 's':
snake_move(1, 0);
break;
case 'a':
snake_move(0, -1);
break;
case 'd':
snake_move(0, 1);
break;
}
print_map();
}
printf("Game Over!!!");
getchar();
}
然后我们就可以愉快(?)地调戏这条蛇啦~