这位朋友,你见过自动进食的贪吃蛇吗!想不想用C语言自己写一个...

效果图

静态效果图
动态效果图

说明

  • 由于本人水平有限,算法并不完美,所以每次的运行结果都不尽相同,得分有高有低
  • 本程序中使用ege图形库,所以如果你之前没有安装,需要先安装一下这个库。这个库相对于其它的图形库来说是比较简单的,很容易上手的。本程序只是使用了其中几个基础的绘图函数
  • ege图形库的官网链接

源代码

#include <stdio.h>
// 这个就是 ege图形库的头文件
#include <graphics.h>
#include <time.h>
#include <conio.h>
#include <stdlib.h>

// 定义坐标
typedef struct {
	int x;
	int y;
}Pos;

// 定义蛇
struct Snake{
	// 用数组来保存蛇身的每一块的坐标,最长100节
	Pos xy[100];
	int len;	// 保存蛇身的长度
	char dir;	// 定义蛇的前进方向
}snake;

enum dir{up,down,left,right};

// 定义食物
struct Food{
	Pos fdxy;	// 食物的位置
	int flag;	// 蛇是否吃到了食物
	int grade;	// 定义食物的分数
}food;

// 定义一些全局变量
// 停顿时间,越小越快
int speed=300;
// 方块的大小
int size=10;
// 窗口的宽高
int width = 400;
int height = 300;

void initSnake() {
	// 创建前三节
	snake.xy[2].x = 0;
	snake.xy[2].y = 0;
	snake.xy[1].x = size;
	snake.xy[1].y = 0;
	snake.xy[0].x = 2*size;
	snake.xy[0].y = 0;

	snake.len = 3;
	snake.dir = right;
}

void drawSnake() {
	// 把蛇身绘制出来 
	setfillcolor(YELLOW);
	bar(snake.xy[0].x, snake.xy[0].y, snake.xy[0].x + size, snake.xy[0].y + size);
	bar(snake.xy[1].x, snake.xy[1].y, snake.xy[1].x + size, snake.xy[1].y + size);
	for (int i = 2; i < snake.len; i++) {
		//setcolor(BLACK);
		setfillcolor(BLUE);
		bar(snake.xy[i].x, snake.xy[i].y, snake.xy[i].x + size, snake.xy[i].y + size);
	}
}

void moveSnake() {
	// 除蛇头外的蛇身都向前移动
	for (int i = snake.len - 1; i > 0; i--) {
		snake.xy[i].x = snake.xy[i-1].x;
		snake.xy[i].y = snake.xy[i-1].y;
	}
	// 根据前进方向决定蛇头的位置
	switch (snake.dir) {
		case up:
			snake.xy[0].y -= size;
			break;
		case down:
			snake.xy[0].y += size;
			break;
		case left:
			snake.xy[0].x -= size;
			break;
		case right:
			snake.xy[0].x += size;
			break;
		default:
			break;
	}
}
// 检测蛇是否撞到自己或墙
// 1:会撞到 0:撞不到
int check(Pos nextPos) {
	int i;
	for (i = 1; i < snake.len; i++) {
		if (nextPos.x == snake.xy[i].x && nextPos.y == snake.xy[i].y) {
			return 1;
		}
	}
	if (nextPos.x<0 || nextPos.x>=width || nextPos.y<0 || nextPos.y>=height) {
		return 1;
	}
	return 0;
}

// 
void switchDir() {
	Pos nextPos;

	switch (snake.dir)
	{
		case up:
			nextPos.x = snake.xy[0].x;
			nextPos.y = snake.xy[0].y - size;
			// 如果前面走不通或者食物出现在身后
			if (check(nextPos) || food.fdxy.y > snake.xy[0].y) {
				nextPos.x = snake.xy[0].x - size;
				nextPos.y = snake.xy[0].y;
				if (!check(nextPos)) {
					snake.dir = left;
				}
				else {
					snake.dir = right;
				}
			}
			break;
		case down:
			nextPos.x = snake.xy[0].x;
			nextPos.y = snake.xy[0].y + size;
			if (check(nextPos) || food.fdxy.y < snake.xy[0].y) {
				nextPos.x = snake.xy[0].x - size;
				nextPos.y = snake.xy[0].y;
				if (!check(nextPos)) {
					snake.dir = left;
				}
				else {
					snake.dir = right;
				}
			}
			break;
		case left:
			nextPos.x = snake.xy[0].x - size;
			nextPos.y = snake.xy[0].y;
			if (check(nextPos) || food.fdxy.x > snake.xy[0].x) {
				nextPos.x = snake.xy[0].x;
				nextPos.y = snake.xy[0].y - size;
				if (!check(nextPos)) {
					snake.dir = up;
				}
				else {
					snake.dir = down;
				}
			}
			break;
		case right:
			nextPos.x = snake.xy[0].x + size;
			nextPos.y = snake.xy[0].y;
			if (check(nextPos) || food.fdxy.x < snake.xy[0].x) {
				nextPos.x = snake.xy[0].x;
				nextPos.y = snake.xy[0].y - size;
				if (!check(nextPos)) {
					snake.dir = up;
				}
				else {
					snake.dir = down;
				}
			}
			break;
	}
}

// 根据食物的位置改变前进方向
void keyDown() {
	// 获取按键
	Pos nextPos;
	if (snake.dir == left || snake.dir == right) {
		if (food.fdxy.y < snake.xy[0].y) {
			nextPos.x = snake.xy[0].x;
			nextPos.y = snake.xy[0].y-size;
			if (!check(nextPos)) {
				snake.dir = up;
			}
			else {
				snake.dir = down;
			}
		}
		else if(food.fdxy.y > snake.xy[0].y){
			nextPos.x = snake.xy[0].x;
			nextPos.y = snake.xy[0].y+size;
			if (!check(nextPos)) {
				snake.dir = down;
			}
			else {
				snake.dir = up;
			}
		}
		else {
			if (snake.xy[0].y <= 0) {
				snake.dir = down;
			}
			if (snake.xy[0].y >= height-size) {
				snake.dir = up;
			}
			switchDir();
		}
	}
	else {
		if (food.fdxy.x < snake.xy[0].x) {
			nextPos.x = snake.xy[0].x - size;
			nextPos.y = snake.xy[0].y;
			if (!check(nextPos)) {
				snake.dir = left;
			}
			else {
				snake.dir = right;
			}
		}
		else if(food.fdxy.x > snake.xy[0].x){
			nextPos.x = snake.xy[0].x + size;
			nextPos.y = snake.xy[0].y;
			if (!check(nextPos)) {
				snake.dir = right;
			}
			else {
				snake.dir = left;
			}
		}
		else {
			if (snake.xy[0].x <= 0) {
				snake.dir = right;
			}
			if (snake.xy[0].x >= width-size) {
				snake.dir = left;
			}
			switchDir();
		}
	}

	switchDir();
}

void initFood() {
	// 随机数播种
	srand(time(NULL));
	// 生成随机坐标
	food.fdxy.x = rand() % (width/size) * size;
	food.fdxy.y = rand() % (height/size) * size;

	// 判断食物是否与蛇身重合
	for (int i = 0; i < snake.len; i++) {
		if (snake.xy[i].x == food.fdxy.x && snake.xy[i].y == food.fdxy.y) {
			// 重新生成坐标
			food.fdxy.x = rand() % (width/size) * size;
			food.fdxy.y = rand() % (height/size) * size;			
		}
	}
	// 蛇还没吃到食物
	food.flag = 1;
}

void drawFood() {
	setfillcolor(RED);
	bar(food.fdxy.x, food.fdxy.y, food.fdxy.x+size, food.fdxy.y+size);
}

void eatFood() {
	// 如果蛇头与食物重合,我们就认为蛇吃到了食物
	if (snake.xy[0].x == food.fdxy.x && snake.xy[0].y == food.fdxy.y) {
		// 蛇吃到了食物
		food.flag = 0;
		// 蛇身变长
		snake.len++;
		// 加分
		food.grade += 10;
	}
}

void showScore() {
	LOGFONTA f;
	getfont(&f);                          // 获取当前字体设置
	f.lfHeight = 16;    
	setfont(&f);

	char str[100] = "";
	sprintf(str, "分数:%d", food.grade);
	// 分数越高,速度越快,但不能小于50
	if (speed > 50) {
		speed -= 50 * (food.grade / 50);
	}
	setbkmode(TRANSPARENT);
	setcolor(LIGHTGREEN);
	outtextxy(300, 20, str);
}

// 判断蛇是否死亡,1代表死亡,0代表活着
int snakeDie() {

	LOGFONTA f;
	getfont(&f);                          // 获取当前字体设置
	f.lfHeight = 48;                      // 设置字体高度为 48(包含行距)
	f.lfWidth = 0;
	strcpy(f.lfFaceName, "黑体");         // 设置字体为“黑体”
	f.lfQuality = ANTIALIASED_QUALITY;    // 设置输出效果为抗锯齿  
	setfont(&f);                          // 设置字体样式

	if (check(snake.xy[0])) {
		outtextxy(width/2-120,height/2-24,"Game Over!!!");
		return 1;
	}
	
	return 0;
}

int main() {

	// 创建窗口
	initgraph(width, height);  
	setcaption("欢迎来到贪吃蛇世界!!!");
	// 设置背景颜色 
	setbkcolor(WHITE);
	// 使用背景颜色清屏
	cleardevice();

	initSnake();
	initFood();
	while (1) {
		drawSnake();
		drawFood();
		eatFood();
		showScore();
		if (snakeDie()) {
			// 如果蛇死亡就结束循环
			break;
		}
		// 如果蛇吃到了食物,重新生成食物
		if (food.flag == 0) {
			initFood();
		}
		keyDown();
		moveSnake();
		Sleep(speed);
		// 刷新屏幕
		cleardevice();
	}
	
	// conio.h 和 ege.h 中都定义了此函数,需要指明是那个文件中的
	ege::getch();          // 按任意键继续
	closegraph();          // 关闭绘图窗口
}
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值