贪吃蛇
贪吃蛇是大家从小到大耳熟能详的游戏,规则十分简单:wsad控制上下左右移动,蛇吃到钱币身体长度增加,碰到障碍物或者身体gameover。今天我们就来尝试制作简单的C语言版贪吃蛇。
思路
- 用每隔一秒打印地图的方式动态的显示蛇的运行轨迹。
- 用kbhit()来接收键盘指令。
- 根据自顶向下原理设置如下函数:
void start(); //开始
void snakeMove(); //蛇移动
void put_money(); //产生钱币的坐标
int if_die(); //判断蛇是否死亡
void turn_left(); //左转
void turn_right(); //右转
void turn_down(); //向下转
void turn_up(); //向上转
void create_map(); //产生地图
void clear_map(); //清空地图
void snake_moveon(); //蛇身体跟着蛇头移动
void print_map(); //打印地图
void snake_eat_money(); //判断蛇是否吃到钱币
代码
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
#define SNAKE_MAX_LENGTH 20 //蛇的最大长度
#define SNAKE_HEAD H
#define SNAKE_BODY X
void start(); //开始
void snakeMove(); //蛇移动
void put_money(); //产生钱币的坐标
int if_die(); //判断蛇是否死亡
void turn_left(); //左转
void turn_right(); //右转
void turn_down(); //向下转
void turn_up(); //向上转
void create_map(); //产生地图
void clear_map(); //清空地图
void snake_moveon(); //蛇身体跟着蛇头移动
void print_map(); //打印地图
void snake_eat_money(); //判断蛇是否吃到钱币
char map[12][12] = { //初始地图
"************",
"* *",
"* * *",
"* * *",
"* * *",
"* * *",
"* * *",
"* *",
"* *",
"* *",
"* *",
"************"
};
int snakeX[SNAKE_MAX_LENGTH] = {1,2,3,4,5}; //蛇的初始X坐标
int snakeY[SNAKE_MAX_LENGTH] = {1,1,1,1,1}; //蛇的初始Y坐标
int snake_length = 5; //蛇的初始长度
char snake_direction = 'd'; //蛇的初始方向
int moneyX; //钱币的X坐标
int moneyY; //钱币的Y坐标
void put_money() { //随机产生钱币的X,Y坐标
while(1) {
moneyX = rand() % 10 + 1;
moneyY = rand() % 10 + 1;
int i;
for(i=0;i<snake_length;i++) {
if(snakeX[i] == moneyX && snakeY[i] == moneyY || (moneyX == 6 && (moneyY == 2 || moneyY == 3 || moneyY == 4 || moneyY == 5 || moneyY == 6)) ) {
break;
}
}
if(i == snake_length) {
return;
}
}
}
void create_map() { //根据信息创造地图
int i,j,z;
for(i=1;i<11;i++) {
for(j=1;j<11;j++) {
if(j == 6 && (i == 2 || i == 3 || i == 4 || i == 5 || i == 6)) {
map[i][j] = '*';
}
if(i == snakeY[snake_length-1] && (j == snakeX[snake_length-1])) {
map[i][j] = 'H';
}
if(i == moneyY && (j == moneyX)) {
map[i][j] = '$';
}
for(z=0;z<snake_length-1;z++) {
map[snakeY[z]][snakeX[z]] = 'X';
}
}
}
}
void print_map() { //打印地图
int i,j;
for(i=0;i<12;i++) {
for(j=0;j<12;j++) {
printf("%c",map[i][j]);
}
printf("\n");
}
}
void clear_map() { //清空地图内部
int i,j;
for(i=1;i<11;i++) {
for(j=1;j<11;j++) {
map[i][j] = ' ';
}
}
}
int if_die() { //判断蛇是否死亡
int i;
if(snakeX[snake_length-1] == 0 || snakeX[snake_length-1] == 11 || snakeY[snake_length-1] == 0 || snakeY[snake_length-1] == 11 || (snakeX[snake_length-1] == 6 && (snakeY[snake_length-1] == 2 || snakeY[snake_length-1] == 3 || snakeY[snake_length-1] == 4 || snakeY[snake_length-1] == 5 || snakeY[snake_length-1] == 6))) {
system("cls"); //判断蛇是否撞到障碍物
printf("game over");
exit(0);
}
for(i=0;i<snake_length-1;i++) {
if(snakeX[snake_length-1] == snakeX[i] && snakeY[snake_length-1] == snakeY[i]) {
system("cls"); //判断蛇是否撞到自己
printf("game over");
exit(0);
}
}
return 1;
}
void snake_moveon() { //蛇的身体跟着蛇头走
int i;
for(i=0;i<snake_length-1;i++) {
snakeX[i] = snakeX[i+1];
snakeY[i] = snakeY[i+1];
}
}
void snake_eat_money() { //判断蛇是否吃到钱币
int i;
if(snakeX[snake_length-1] == moneyX && snakeY[snake_length-1] == moneyY) {
map[moneyY][moneyX] = ' ';
snake_length++;
for(i=snake_length-1;i>1;i--) {
snakeX[i] = snakeX[i-1];
snakeY[i] = snakeY[i-1];
}
put_money();
}
}
void turn_left() { //蛇向左转
while(!kbhit()) {
sleep(1);
system("cls");
int i,j,z;
snake_moveon();
snakeX[snake_length-1]--;
clear_map();
if(!if_die()) {
return;
}
snake_eat_money();
create_map();
print_map();
}
return;
}
void turn_right() { //蛇向右转
while(!kbhit()) {
sleep(1);
system("cls");
int i,j,z;
snake_moveon();
snakeX[snake_length-1]++;
clear_map();
if(!if_die()) {
return;
}
snake_eat_money();
create_map();
print_map();
}
return;
}
void turn_up() { //蛇向上转
while(!kbhit()) {
sleep(1);
system("cls");
int i,j,z;
snake_moveon();
snakeY[snake_length-1]--;
clear_map();
if(!if_die()) {
return;
}
snake_eat_money();
create_map();
print_map();
}
return;
}
void turn_down() { //蛇向下转
while(!kbhit()) {
sleep(1);
system("cls");
int i,j,z;
snake_moveon();
snakeY[snake_length-1]++;
clear_map();
if(!if_die()) {
return;
}
snake_eat_money();
create_map();
print_map();
}
return;
}
void snakeMove() { //根据输入判断蛇的方向转变
char choice = _getch();
if(choice == 'w' && snake_direction != 'w' && snake_direction != 's') {
turn_up();
snake_direction = choice;
snakeMove();
}
else if(choice == 's' && snake_direction != 'w' && snake_direction != 's') {
turn_down();
snake_direction = choice;
snakeMove();
}
else if(choice == 'a' && snake_direction != 'a' && snake_direction != 'd') {
turn_left();
snake_direction = choice;
snakeMove();
}
else if(choice == 'd' && snake_direction != 'a' && snake_direction != 'd') {
turn_right();
snake_direction = choice;
snakeMove();
}
else{
snakeMove();
}
}
void start() { //开始的地图
int i,j;
for(i=0;i<12;i++) {
for(j=0;j<12;j++) {
if(i==1 && (j==2||j==3||j==4||j==5||j==1)) {
if(j==5) {
map[i][j] = 'H';
}
else {
map[i][j] = 'X';
}
}
printf("%c",map[i][j]);
}
printf("\n");
}
put_money();
snakeMove();
}
int main() {
printf("欢迎来到C语言版贪吃蛇~\n");
printf("按回车键开始游戏\n");
printf("wsad控制上下左右\n");
while(1){
if(getchar() == '\n') {
system("cls");
start();
break;
}
}
}
注意
- 需要格外注意的是,贪吃蛇身体的方向对于玩家操控的限制。比如说贪吃蛇向上走时,玩家不能让贪吃蛇直接向下走。
- 可以通过改变sleep()的数值来控制游戏难度。
- 自顶向下原则,尽量分解,写成函数,方便调用修改。