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
    评论
好的,以下是用C语言实现贪吃蛇游戏代码: ```c #include <stdio.h> #include <stdlib.h> #include <conio.h> #include <time.h> #include <windows.h> #define MAX_X 20 // 横向边界 #define MAX_Y 20 // 纵向边界 #define SNAKE_MAX_LENGTH 100 // 蛇的最大长度 // 定义蛇的结构体 typedef struct Snake{ int x; // 蛇头的横坐标 int y; // 蛇头的纵坐标 int length; // 蛇的长度 int body[SNAKE_MAX_LENGTH][2]; // 蛇的身体 } Snake; // 定义食物的结构体 typedef struct Food{ int x; // 食物的横坐标 int y; // 食物的纵坐标 } Food; char map[MAX_X][MAX_Y]; // 地图数组,用于绘制地图 Snake snake; // 蛇的结构体 Food food; // 食物的结构体 // 初始化地图 void initMap(){ int i, j; for(i = 0; i < MAX_X; i++){ for(j = 0; j < MAX_Y; j++){ if(i == 0 || i == MAX_X - 1 || j == 0 || j == MAX_Y - 1){ map[i][j] = '#'; } else{ map[i][j] = ' '; } } } } // 初始化蛇 void initSnake(){ snake.length = 3; // 初始化蛇的长度为3 snake.x = MAX_X / 2; // 初始化蛇头的横坐标 snake.y = MAX_Y / 2; // 初始化蛇头的纵坐标 // 初始化蛇的身体,初始时蛇头在中间,蛇身在蛇头左边 int i; for(i = 0; i < snake.length; i++){ snake.body[i][0] = snake.x - i; snake.body[i][1] = snake.y; } } // 初始化食物 void initFood(){ // 随机生成食物坐标 srand((int)time(NULL)); // 设置随机数种子 food.x = rand() % (MAX_X - 2) + 1; food.y = rand() % (MAX_Y - 2) + 1; } // 绘制地图 void drawMap(){ system("cls"); // 清屏 int i, j; for(i = 0; i < MAX_X; i++){ for(j = 0; j < MAX_Y; j++){ printf("%c", map[i][j]); } printf("\n"); } } // 绘制蛇 void drawSnake(){ int i; for(i = 0; i < snake.length; i++){ map[snake.body[i][0]][snake.body[i][1]] = '*'; } map[snake.body[0][0]][snake.body[0][1]] = '@'; } // 绘制食物 void drawFood(){ map[food.x][food.y] = '$'; } // 移动蛇 void moveSnake(){ int i; // 记录蛇尾坐标 int tail_x = snake.body[snake.length - 1][0]; int tail_y = snake.body[snake.length - 1][1]; // 将蛇身向前移动一格 for(i = snake.length - 1; i > 0; i--){ snake.body[i][0] = snake.body[i - 1][0]; snake.body[i][1] = snake.body[i - 1][1]; } // 将蛇头向前移动一格 if(kbhit()){ // 检测是否有键盘输入 char ch = getch(); // 获取键盘输入 switch(ch){ case 'w': // 上 snake.body[0][0] -= 1; break; case 's': // 下 snake.body[0][0] += 1; break; case 'a': // 左 snake.body[0][1] -= 1; break; case 'd': // 右 snake.body[0][1] += 1; break; default: break; } } else{ // 如果没有键盘输入,则继续朝前移动 snake.body[0][0] -= 1; } // 判断是否吃到食物 if(snake.body[0][0] == food.x && snake.body[0][1] == food.y){ snake.length++; // 蛇长加一 snake.body[snake.length - 1][0] = tail_x; // 将蛇尾坐标加入蛇身 snake.body[snake.length - 1][1] = tail_y; initFood(); // 重新生成食物 } } // 判断蛇是否死亡 int isDead(){ int i; // 判断是否撞墙 if(snake.body[0][0] == 0 || snake.body[0][0] == MAX_X - 1 || snake.body[0][1] == 0 || snake.body[0][1] == MAX_Y - 1){ return 1; } // 判断是否咬到自己 for(i = 1; i < snake.length; i++){ if(snake.body[0][0] == snake.body[i][0] && snake.body[0][1] == snake.body[i][1]){ return 1; } } return 0; } int main(){ initMap(); // 初始化地图 initSnake(); // 初始化蛇 initFood(); // 初始化食物 while(1){ drawMap(); // 绘制地图 drawSnake(); // 绘制蛇 drawFood(); // 绘制食物 moveSnake(); // 移动蛇 if(isDead()){ // 判断蛇是否死亡 printf("Game Over!\n"); break; } Sleep(100); // 等待100毫秒 } return 0; } ``` 代码中使用了Windows API中的Sleep函数,需要在Windows系统下编译运。如果在其他系统下运,需要使用其他方式实现等待功能。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值