C语言_贪吃蛇

C语言_贪吃蛇

1.主要原理

蛇身:由数组构造

移动:绘制一个新蛇头,擦掉蛇尾,更新数组

进食:判断一旦蛇头遇到食物,则只增加蛇头而不擦除蛇尾,更新数组

2.操作说明

1)用户通过w, s, a, d键控制蛇的上下左右移动(一次移动一个方格长度)

2)一般情况下界面保持有一个随机的食物,由“□”表示;即蛇每吃掉一个食物,再随机出现下一个食物;界面初始化时会给出一个食物

3)蛇的长度不能超过80;蛇不能碰壁; 否则游戏结束,显示最终得分

3.准备环节——所需库函数、全局变量和结构体声明
#include<stdio.h>
#include<stdlib.h>
#include<Windows.h>
#include<time.h>
#include<conio.h>

#define MAX_LEN 80//the longest length for the snake
#define WIDETH 56
#define HIGHTH 30

int x, y;//coordinate for food, one at a time
int score = 0;

typedef struct {
	int x;
	int y;
} point;

struct {
	int len = 3;
	point arr[MAX_LEN];
	point head;
} snake;

4.所需代码块(函数)
1)光标移动到指定位置
void gotoxy(int, int);

关于移动光标的函数,更详细的解释在这篇文章里:

gotoxy函数的简单说明

代码实现:

void gotoxy(int x, int y) {
	COORD coord = { x, y };
	SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), coord);
}
2)打印游戏边框及初始画面

边框可自己视情况设定;

初始的蛇设长度为3;

以实心方块打印边框和蛇;

void initialize();

代码实现:

void initialize() {
	int i;
	for (i = 0; i < WIDETH + 1; i++) {
		printf("■");
	}
	gotoxy(0, HIGHTH);
	for (i = 0; i < WIDETH + 1; i++) {
		printf("■");
	}
	for (i = 0; i < HIGHTH + 1; i++) {
		gotoxy(0, i);
		printf("■");
	}
	for (i = 0; i < HIGHTH + 1; i++) {
		gotoxy(WIDETH * 2, i);
		printf("■");
	}

	gotoxy(WIDETH - 2, HIGHTH / 2);
	
	snake.head = { WIDETH + 4, HIGHTH / 2 };//to print the tail first

	for (i = 0; i < snake.len; i++) {
		snake.arr[i] = { WIDETH - 2 + 2 * i , HIGHTH / 2 };
		printf("■");
	}
}
3)相应按键操作

利用函数getch()从控制台读取一个字符,返回一个整数,方便给下一步的移动操作指令

(当然这一块是可以和move合并的)

int key();

代码实现:

int key() {
	int ch, op;
	ch = _getch();
	switch ((char)ch) {
	case 'w':op = 1;break;//up
	case 's':op = 2;break;//down
	case 'a':op = 3;break;//left
	case 'd':op = 4;break;//right
	default:op = 0;
	}
	return op;
}
4)蛇的移动

找到新蛇头;

若 蛇头碰到了食物:

​ 增加长度;增加分数;打印新蛇头

若 未碰到食物:

​ 更新蛇身数组;打印新蛇头;擦除蛇尾

int move(int);

代码实现:

int move(int op) {
	point new_head;
	switch (op) {
	case 1:new_head.x = snake.head.x; new_head.y = snake.head.y - 1; break;
	case 2:new_head.x = snake.head.x; new_head.y = snake.head.y + 1; break;
	case 3:new_head.x = snake.head.x - 2; new_head.y = snake.head.y; break;
	case 4:new_head.x = snake.head.x + 2; new_head.y = snake.head.y; break;
	}
	if (new_head.x <= 0 || new_head.y <= 0) return -1;
	if (new_head.x == x && new_head.y == y) {
		snake.len++;
		score++;
		snake.arr[snake.len - 1] = { x, y };
		snake.head = new_head;
		gotoxy(x, y);
		printf("■");
		return 1;
	}
	else {
		int i;
		gotoxy(snake.arr[0].x, snake.arr[0].y);
		printf("  ");//erasure the tail
		gotoxy(new_head.x, new_head.y);
		printf("■");
		for (i = 1; i < snake.len; i++) {
			snake.arr[i - 1] = snake.arr[i];
		}
		snake.arr[snake.len - 1] = new_head;
		snake.head = new_head;
		return 0;
	}
}
5)随机生成食物

注意:表示食物的方块在x轴(横坐标)占2个单位长度

void food();

代码实现:

void food() {
	while (1) {
		x = rand() % (WIDETH * 2 - 2) + 2;
		if (x % 2 == 0) break;
	}
	y = rand() % (HIGHTH - 1) + 1;
	gotoxy(x, y);
	printf("□");
}
6)判断蛇的运动是否合法

判断蛇身是否达到设定最长;

判断是否碰壁;

int judge();

代码实现:

int judge() {
	if (snake.len >= MAX_LEN) return -1;
	if (snake.head.x >= 112 || snake.head.y >= 30) {
		return -1;
	}
	return 0;
}
5.main函数

思路:

初始准备;

循环{

​ 一旦遇到输入,进行移动并判断,直到判断结果非法,游戏结束

}

int main() {
	srand((unsigned)time(NULL));
	initialize();
	food();
	while (1) {
		if (_kbhit) {
			int t = key();
			if (t < 0) {
				gotoxy(120, 32);
				printf("Game Over1 : %d", score);
				return 0;
			}
			int b = move(t);
			if (b == 1) food();
			if (judge() < 0) {
				gotoxy(120, 32);
				printf("Game Over2 : %d", score);
				return 0;
			}
		}
	}
	return 0;
}
6.反思
1)关于判断:

关于各个边界条件的判断分散在不同的地方(函数块),显得杂乱无章

2)细节/升级版:

很多细节有待完善,譬如

蛇的直接回头(蛇头方向调转180°)可以设为非法操作;

蛇不能碰到自己的身体;

增加暂停功能;

实时显示分数变化;

用户不进行操作时也让蛇保持移动,用户操作只改变蛇的加速度方向

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值