285行c语言代码实现简易贪吃蛇

前言

因为想做属于自己的游戏所以选择从事计算机行业,如今大三了,注意全在web和算法,游戏碰都没碰。
下面的代码是在观看一个贪吃蛇教程后自行制作,这是教程地址。自己在其基础上做了些改进,如添加背景音乐、校验键盘输入控制方向…等等。由于实力有限,代码有不足之处,还望多多包涵。

运行环境

vs2019(注:背景音乐路径地址请自行修改,这是下载地址

源代码

#include<stdio.h>
#include<stdlib.h>
#include<conio.h>
#include<time.h>
#include <windows.h>
#include<mmsystem.h>
#pragma comment(lib,"winmm.lib")

#define MAP_MODE "■" // 地图边缘样式
#define FOOD_MODE "■" // 食物样式
#define SNAKE_HEAD "○" // 蛇头
#define SNAKE_BODY "□" // 蛇身
#define MAP_WIDTH 60 // 地图宽度
#define MAP_HEIGHT 20 // 地图高度
#define BGM_LOCATION L"C:\\Users\\BestRiven\\source\\repos\\GluttonousSnake\\music.wav" // 背景音乐路径(注:去除""前的L,会导致播放音乐失效)

void first_page();
void play_music();
void start_game();
void create_map();
void gotoxy(int x, int y);
void reback();
void create_foot();
void create_snake();
void move_snake();
int judge_statement();

struct Food {
	int x;
	int y;
	int isCreate;
} food;

struct Snake {
	int x[MAP_WIDTH * MAP_HEIGHT];
	int y[MAP_WIDTH * MAP_HEIGHT];
	int currentLen;
	int direct;
} snake;

int main() {
	// 显示首页
	first_page();
	// 播放音乐
	play_music();
	// 准备开始游戏
	start_game();
	// 创建地图
	create_map();
	// 创建食物
	create_foot();
	// 创建蛇
	create_snake();
	// 移动蛇
	while (TRUE) {
		// 判断蛇的状态
		if (judge_statement()) {
			gotoxy(MAP_WIDTH / 2 - 6, MAP_HEIGHT / 2);
			printf("GAME  OVER!");
			gotoxy(MAP_WIDTH / 2 - 6, MAP_HEIGHT - 3);
			printf("您的得分是:%d", snake.currentLen - 3);
			reback();
			system("pause");
			exit(0); // 退出程序
		}

		// 如果食物未创建就创建食物
		if (food.isCreate == 0) {
			create_foot();
		}

		// 移动蛇
		move_snake();
		Sleep(300);
	}
	return 0;
}

int judge_statement() {
	// 如果蛇头撞到蛇身就返回1
	for (int i = 1; i < snake.currentLen; i++) {
		if (snake.x[0] == snake.x[i] && snake.y[0] == snake.y[i]) return 1;
	}
	// 如果蛇头越界也返回1
	if (snake.x[0] < 1 || snake.x[0] > MAP_WIDTH - 1 || snake.y[0] < 1 || snake.y[0] > MAP_HEIGHT - 1) {
		return 1;
	}

	return 0;
}

// 输入两个字符,判断是否方向相反
int judge_contrary(char c1, char c2) {
	if (c1 == c2) return 0;

	switch(c1) {
		case 'w':
		case 'W':
			return c2 == 's' || c2 == 'S';
		case 's':
		case 'S':
			return c2 == 'w' || c2 == 'W';
		case 'a':
		case 'A':
			return c2 == 'd' || c2 == 'D';
		case 'd':
		case 'D':
			return c2 == 'a' || c2 == 'A';
	}

	return 0;
}

// 输入一个字符,判断是否合法
int judge_valid(char c) {
	switch (c) {
		case 'w':
		case 'W':
		case 's':
		case 'S':
		case 'a':
		case 'A':
		case 'd':
		case 'D':
			return 1;
	}
	return 0;
}

void move_snake() {
	char cur_direct = snake.direct;
	if (_kbhit()) { // 监听键盘输入
		fflush(stdin);
		cur_direct = _getch();
	}
	// 先判断输入是否合法,并且方向和原方向不相反,都满足就更新
	if (judge_valid(cur_direct) && !judge_contrary(snake.direct,cur_direct))
		snake.direct = cur_direct;

	// 擦掉蛇尾(刚生成的蛇尾需要过滤
	if (snake.x[snake.currentLen - 1] != 0) {
		gotoxy(snake.x[snake.currentLen - 1], snake.y[snake.currentLen - 1]);
		printf("  ");
	}

	// 打印蛇身
	for (int i = snake.currentLen - 1; i > 0; i--) {
		snake.x[i] = snake.x[i - 1];
		snake.y[i] = snake.y[i - 1];

		gotoxy(snake.x[i], snake.y[i]);
		printf(SNAKE_BODY);
	}

	// 根据方向更新蛇头
	switch(snake.direct) {
		case 'w':
		case 'W':
			snake.y[0]--;
			break;
		case 's':
		case 'S':
			snake.y[0]++;
			break;
		case 'a':
		case 'A':
			snake.x[0] -= 2;
			break;
		case 'd':
		case 'D':
			snake.x[0] += 2;
			break;
	}
	// 打印蛇头
	gotoxy(snake.x[0], snake.y[0]);
	printf(SNAKE_HEAD);

	// 如果蛇头和食物重合,那么蛇长++
	if (snake.x[0] == food.x && snake.y[0] == food.y) {
		snake.currentLen++;
		// 设置食物未创建
		food.isCreate = 0;
	}

	reback();
}

void create_snake() {
	// 初始化变量
	snake.x[0] = MAP_WIDTH / 2;
	snake.y[0] = MAP_HEIGHT / 2;
	snake.currentLen = 3;
	snake.direct = 'a';

	// 画蛇头
	gotoxy(snake.x[0], snake.y[0]);
	printf(SNAKE_HEAD);

	// 画蛇身
	for (int i = 1; i < snake.currentLen; i++) {
		snake.x[i] = snake.x[i - 1] + 2;
		snake.y[i] = snake.y[i - 1];

		gotoxy(snake.x[i], snake.y[i]);
		printf(SNAKE_BODY);
	}

	reback();
}

void create_foot() {
	// 设置食物已创建
	food.isCreate = 1;
	int flag = 1;

	while(flag == 1){
		// 产生随机数
		srand(time(NULL));
		// 生成随机食物
		food.x = rand() % (MAP_WIDTH - 1) + 2;
		if (food.x&1) continue;
		food.y = rand() % (MAP_HEIGHT - 1) + 1;
		flag = 0;

		// 判断生成的随机食物是否和蛇身冲突
		for (int i = 0; i < snake.currentLen; i++) {
			if (food.x == snake.x[i] && food.y == snake.y[i]) {
				flag = 1;
				break;
			}
		}
	}

	gotoxy(food.x, food.y);
	printf(FOOD_MODE);

	reback();
}

void create_map() {
	// 打印上下
	for (int i = 0; i <= MAP_WIDTH; i++) {
		gotoxy(i, 0);
		printf(MAP_MODE);
		gotoxy(i, MAP_HEIGHT);
		printf(MAP_MODE);
	}

	// 打印左右
	for (int i = 1; i < MAP_HEIGHT; i++) {
		gotoxy(0, i);
		printf(MAP_MODE);
		gotoxy(MAP_WIDTH, i);
		printf(MAP_MODE);
	}

	reback();
}

void first_page() { // 显示封面
	printf("\t\t欢迎试玩《贪吃蛇》\n\n");
	printf("开始游戏:\t按空格开始游戏\n");
	printf("控制方向:\tw a s d控制蛇的方向\n\n\n\n");
}

void play_music() {
	PlaySound(BGM_LOCATION, NULL, SND_FILENAME | SND_ASYNC);
}

void start_game() {
	// 读入空格进入游戏	
	while (' ' != _getch());
	// 暂停音乐
	PlaySound(NULL, 0, 0);
	// 清屏
	system("cls");
}

void gotoxy(int x, int y) { // 系统辅助函数
	COORD pos = { x , y };
	HANDLE hOut = GetStdHandle(STD_OUTPUT_HANDLE);
	SetConsoleCursorPosition(hOut, pos);
}

// 光标归位
void reback() {
	gotoxy(MAP_WIDTH + 8, 0);
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值