C语言数组贪吃蛇(VS2022版)


大家好,这一篇博客讲的是我对 C语言贪吃蛇 的理解。以下代码使用的是 VS2022环境下的 C语言,如果有错误,还请读者大大们指出。

声明

这篇博客中的贪吃蛇核心代码参考自【河海大学·童晶】做游戏,学编程(C语言)P38 课时35.贪吃蛇

游戏演示

贪吃蛇演示视频

游戏基础内容实现

首先准备好 game.h、game.c、test.c

伪图形界面实现

在game.h中:

#pragma

#define _CRT_SECURE_NO_WARNINGS

#include <stdio.h>
#include <time.h> // 获取时间戳的准备
#include <windows.h> // 使用gotoxy()、HideCursor()函数的准备
#include <conio.h> // khbit()、getch()函数准备
#include <stdlib.h> // srand()、rand()函数准备

#define HIGH 20 // 画面的高
#define WIGHT 30 // 画面的宽

void game(); // 游戏框架

void HideCursor();  // 隐藏光标

void gotoxy(int x, int y); // 固定画面

在test.c中:

#include "game.h"

void explain()
{
	printf("********** 操作说明 **********\n");
	printf("* 移动键(小写)   上:w 下:s *\n");
	printf("*                左:a 右:d *\n");
	printf("* 空格:加速开关             *\n");
	printf("* 加速吃果实分数为2,反之为1 *\n");
	printf("* 小写字母j:暂停开关        *\n");
	printf("********** 操作说明 **********\n");
	printf("------------------------------\n");
	printf("空格返回\n");
	while (_getch() != ' ')
		Sleep(10);
	system("cls");
}

void menu()
{
	int inputY = 0;
	char arr[3][13] = { "开始游戏", "操作说明", "结束游戏" };

	while (1) // 伪图形处理
	{
		gotoxy(0, 0);
		// 打印
		printf("**********************\n");
		if (inputY == 0) // \033方式改变字体颜色
			printf("*****\033[41m %10s \033[0m*****\n", &arr[0][0]);
		else
			printf("***** %-11s*****\n", &arr[0][0]);
		if (inputY == 1)
			printf("*****\033[41m %10s \033[0m*****\n", &arr[1][0]);
		else 
			printf("***** %-11s*****\n", &arr[1][0]);
		if (inputY == 2)
			printf("*****\033[41m %10s \033[0m*****\n", &arr[2][0]);
		else
			printf("***** %-11s*****\n", &arr[2][0]);
		printf("**********************\n");

		printf("上:w 下:s\n");
		printf("空格键确定\n");
		// 输入
		char ch = _getch();
		// 执行
		switch (ch)
		{
		case 'w':
			inputY = (inputY - 1 + 3) % 3;
			break;
		case 's':
			inputY = (inputY + 1) % 3;
			break;
		case ' ':
			if (inputY == 0)
			{
				system("cls");
				game();
			}
			else if (inputY == 1)
			{
				system("cls");
				explain();
			}
			else if (inputY == 2)
				return;
		}
		// 帧数限制
		Sleep(10);
	}
}

void game()
{

}

void test()
{
	HideCursor();
	srand((unsigned int)time(NULL)); // 获得时间戳以生成随机数
	menu();
}

int main()
{
	test();
	return 0;
}

在game.c中:

#include "game.h"

void gotoxy(int x, int y)  // 光标移动到(x,y)的位置,可以让画面刷新
{
	HANDLE handle = GetStdHandle(STD_OUTPUT_HANDLE);
	COORD pos;
	pos.X = x;
	pos.Y = y;
	SetConsoleCursorPosition(handle, pos);
}

void HideCursor()  // 隐藏光标
{
	CONSOLE_CURSOR_INFO cursor_info = { 1, 0 };  // 第二个值为0表示隐藏光标
	SetConsoleCursorInfo(GetStdHandle(STD_OUTPUT_HANDLE), &cursor_info);
}

初始化与打印

在game.h中:

void init(int frame[HIGH][WIGHT]); // 游戏初始化

void display(int frame[HIGH][WIGHT]); // 画面展示

在game.c中:

void init(int frame[HIGH][WIGHT])
{
	// 初始化周围墙壁
	for (int i = 0; i < HIGH; i++)
		for (int j = 0; j < WIGHT; j++)
			frame[i][j] = ((!i || i == HIGH - 1 || !j || j == WIGHT - 1) ? -1 : 0);

	// 初始化蛇身蛇头
	for (int i = 1; i <= 4; i++) // 这样蛇尾最大,方便查找
		frame[HIGH / 2][WIGHT / 2 - i] = i;

	// 生成食物
	// fruitGenerate(frame); 
}

void display(int frame[HIGH][WIGHT])
{
	for (int i = 0; i < HIGH; i++)
	{
		for (int j = 0; j < WIGHT; j++)
		{ // 这里采用数字记录逻辑,显示时用符号
			if (frame[i][j] == 0) // 打印空白
				printf(" ");
			else if (frame[i][j] == -1) // 打印墙壁
				printf("#");
			else if (frame[i][j] == 1) // 打印蛇头
				printf("@");
			else if (frame[i][j] > 1) // 打印蛇身
				printf("O");
			else if (frame[i][j] == -2) // 打印食物
				printf("F");
		}
		printf("\n");
	}
}

在test.c中:

void game()
{
	int frame[HIGH][WIGHT] = { 0 };
	init(frame);
	while (1)
	{
		gotoxy(0, 0); // 固定画面

		display(frame);

		Sleep(200);
	}
}

生成果实

在game.h中:

void fruitGenerate(int frame[HIGH][WIGHT]); // 生成果实

在game.c中:

void fruitGenerate(int frame[HIGH][WIGHT])
{
	while (1)
	{
		int y = rand() % (HIGH - 2) + 1;
		int x = rand() % (WIGHT - 2) + 1;
		if (frame[y][x] == 0) // 当放入的地方为空地
		{
			frame[y][x] = -2;
			break;
		}
	}
}

蛇自动移动与检测游戏状态(重点)

这里需要细讲一下:
如图,-1为墙壁,-2为果实,1为蛇头,2、3、4为蛇身,空白格子为0。
在这里插入图片描述

在game.h中:

int snakeAutomaticMove(int frame[HIGH][WIGHT], int moveDirection); // 蛇自动移动

int detectGameState(int frame[HIGH][WIGHT], int newHeadY, int newHeadX, int tailY, int tailX); // 检测游戏状态

在game.c中:

int snakeAutomaticMove(int frame[HIGH][WIGHT], int moveDirection) // 蛇自动移动
{
	// 存储蛇头位置
	int headX = 0;
	int headY = 0;

	// 存储蛇尾位置
	int tailX = 0;
	int tailY = 0;
	int max = 0;

	// 查找
	for (int i = 1; i < HIGH - 1; i++)
	{
		for (int j = 1; j < WIGHT - 1; j++)
		{
			// 第一步:蛇头蛇身+1
			frame[i][j] > 0 ? frame[i][j]++ : 0;
			
			// 第二步:
			// 记录蛇头
			if (frame[i][j] == 2)
			{
				headX = j;
				headY = i;
			}

			// 记录蛇尾
			if (frame[i][j] > max)
			{
				max = frame[i][j];
				tailX = j;
				tailY = i;
			}
		}
	}

	// 第三步:
	// 存储新蛇头
	int newHeadY = 0;
	int newHeadX = 0;

	switch (moveDirection)
	{
	case 1: // 上
		newHeadY = headY - 1;
		newHeadX = headX;
		break;
	case 2: // 下
		newHeadY = headY + 1;
		newHeadX = headX;
		break;
	case 3: // 左
		newHeadY = headY;
		newHeadX = headX - 1;
		break;
	case 4: // 右
		newHeadY = headY;
		newHeadX = headX + 1;
		break;
	}

	// 检测游戏状态并返回
	return detectGameState(frame, newHeadY, newHeadX, tailY, tailX);
}

int detectGameState(int frame[HIGH][WIGHT], int newHeadY, int newHeadX, int tailY, int tailX)
{
	// 当蛇吃到食物不用去掉旧蛇尾
	if (frame[newHeadY][newHeadX] == -2)
	{
		fruitGenerate(frame); // 重新生成果实
	}
	else // 去掉旧蛇尾
		frame[tailY][tailX] = 0;

	//         	吃到自己				  或			撞墙		
	if (frame[newHeadY][newHeadX] > 0 || frame[newHeadY][newHeadX] == -1)
		return 0;
	else // 放置新蛇头
		frame[newHeadY][newHeadX] = 1;

	return 1;
}

在test.c中:

void game()
{
	// 开始移动方向为右
	int moveDirection = 4;
	// 检测游戏状态
	int detect = 1;
	int frame[HIGH][WIGHT] = { 0 };
	init(frame);
	while (1)
	{
		gotoxy(0, 0); // 固定画面

		detect = snakeAutomaticMove(frame, moveDirection);

		display(frame);

		if (!detect)
		{
			printf("游戏结束,按空格返回\n");
			while (_getch() != ' ')
				Sleep(10);
			system("cls");
			break;
		}
		// 帧数限制
		Sleep(200);
	}
}

玩家操作

玩家操作主要是改变蛇自动移动的方向
在game.h中:

void playerMove(int* moveDirection); // 玩家操作

在game.c中:

void playerMove(int* moveDirection)
{
	char input = _getch();
	//  确定移动方向  且  禁止反方向移动
	if (input == 'w' && *moveDirection != 2) // 上
		*moveDirection = 1;
	else if (input == 's' && *moveDirection != 1) // 下
		*moveDirection = 2;
	else if (input == 'a' && *moveDirection != 4) // 左
		*moveDirection = 3;
	else if (input == 'd' && *moveDirection != 3) // 右
		*moveDirection = 4;
}

在test.c中:

void game()
{
	// 开始移动方向为右
	int moveDirection = 4;
	// 检测游戏状态
	int detect = 1;
	int frame[HIGH][WIGHT] = { 0 };
	init(frame);
	while (1)
	{
		gotoxy(0, 0); // 固定画面

		detect = snakeAutomaticMove(frame, moveDirection);

		display(frame);

		if (!detect)
		{
			printf("游戏结束,按空格返回\n");
			while (_getch() != ' ')
				Sleep(10);
			system("cls");
			break;
		}

		if (_kbhit()) // 检测玩家键盘是否有输入
			playerMove(&moveDirection);
		// 帧数限制
		Sleep(200);
	}
}

基础内容源代码

对于game.h

#pragma

#define _CRT_SECURE_NO_WARNINGS

#include <stdio.h>
#include <time.h> // 获取时间戳的准备
#include <windows.h> // 使用gotoxy()、HideCursor()函数的准备
#include <conio.h> // khbit()、getch()函数准备
#include <stdlib.h> // srand()、rand()函数准备

#define HIGH 20 // 画面的高
#define WIGHT 30 // 画面的宽

void game(); // 游戏框架

void HideCursor();  // 隐藏光标

void gotoxy(int x, int y); // 固定画面

void init(int frame[HIGH][WIGHT]); // 游戏初始化

void display(int frame[HIGH][WIGHT]); // 画面展示

void fruitGenerate(int frame[HIGH][WIGHT]); // 生成果实

int snakeAutomaticMove(int frame[HIGH][WIGHT], int moveDirection); // 蛇自动移动

int detectGameState(int frame[HIGH][WIGHT], int newHeadY, int newHeadX, int tailY, int tailX); // 检测游戏状态

void playerMove(int* moveDirection); // 玩家操作

对于test.c

#include "game.h"

void explain()
{
	printf("********** 操作说明 **********\n");
	printf("* 移动键(小写)   上:w 下:s *\n");
	printf("*                左:a 右:d *\n");
	printf("* 空格:加速开关             *\n");
	printf("* 加速吃果实分数为2,反之为1 *\n");
	printf("* 小写字母j:暂停开关        *\n");
	printf("********** 操作说明 **********\n");
	printf("------------------------------\n");
	printf("空格返回\n");
	while (_getch() != ' ')
		Sleep(10);
	system("cls");
}

void menu()
{
	int inputY = 0;
	char arr[3][13] = { "开始游戏", "操作说明", "结束游戏" };

	while (1) // 伪图形化
	{
		gotoxy(0, 0);
		// 打印
		printf("**********************\n");
		if (inputY == 0)
			printf("*****\033[41m %10s \033[0m*****\n", &arr[0][0]);
		else
			printf("***** %-11s*****\n", &arr[0][0]);
		if (inputY == 1)
			printf("*****\033[41m %10s \033[0m*****\n", &arr[1][0]);
		else 
			printf("***** %-11s*****\n", &arr[1][0]);
		if (inputY == 2)
			printf("*****\033[41m %10s \033[0m*****\n", &arr[2][0]);
		else
			printf("***** %-11s*****\n", &arr[2][0]);
		printf("**********************\n");

		printf("上:w 下:s\n");
		printf("空格键确定\n");
		// 输入
		char ch = _getch();
		// 执行
		switch (ch)
		{
		case 'w':
			inputY = (inputY - 1 + 3) % 3;
			break;
		case 's':
			inputY = (inputY + 1) % 3;
			break;
		case ' ':
			if (inputY == 0)
			{
				system("cls");
				game();
			}
			else if (inputY == 1)
			{
				system("cls");
				explain();
			}
			else if (inputY == 2)
				return;
		}
		// 帧数限制
		Sleep(10);
	}
}

void game()
{
	// 开始移动方向为右
	int moveDirection = 4;
	// 检测游戏状态
	int detect = 1;
	int frame[HIGH][WIGHT] = { 0 };
	init(frame);
	while (1)
	{
		gotoxy(0, 0); // 固定画面

		detect = snakeAutomaticMove(frame, moveDirection);

		display(frame);

		if (!detect)
		{
			printf("游戏结束,按空格返回\n");
			while (_getch() != ' ')
				Sleep(10);
			system("cls");
			break;
		}

		if (_kbhit()) // 检测玩家键盘是否有输入
			playerMove(&moveDirection);
		// 帧数限制
		Sleep(200);
	}
}

void test()
{
	HideCursor();
	srand((unsigned int)time(NULL)); // 获得时间戳以生成随机数
	menu();
}

int main()
{
	test();
	return 0;
}

对于game.c

#include "game.h"

void gotoxy(int x, int y)  // 光标移动到(x,y)的位置,可以让画面刷新
{
	HANDLE handle = GetStdHandle(STD_OUTPUT_HANDLE);
	COORD pos;
	pos.X = x;
	pos.Y = y;
	SetConsoleCursorPosition(handle, pos);
}

void HideCursor()  // 隐藏光标
{
	CONSOLE_CURSOR_INFO cursor_info = { 1, 0 };  // 第二个值为0表示隐藏光标
	SetConsoleCursorInfo(GetStdHandle(STD_OUTPUT_HANDLE), &cursor_info);
}

void init(int frame[HIGH][WIGHT])
{
	// 初始化墙壁
	for (int i = 0; i < HIGH; i++)
		for (int j = 0; j < WIGHT; j++)
			frame[i][j] = ((!i || i == HIGH - 1 || !j || j == WIGHT - 1) ? -1 : 0);

	// 初始化蛇身蛇头
	for (int i = 1; i <= 4; i++)
		frame[HIGH / 2][WIGHT / 2 - i] = i;

	// 生成食物
	fruitGenerate(frame); 
}

void display(int frame[HIGH][WIGHT])
{
	for (int i = 0; i < HIGH; i++)
	{
		for (int j = 0; j < WIGHT; j++)
		{
			if (frame[i][j] == 0) // 打印空白
				printf(" ");
			else if (frame[i][j] == -1) // 打印墙壁
				printf("#");
			else if (frame[i][j] == 1) // 打印蛇头
				printf("@");
			else if (frame[i][j] > 1) // 打印蛇身
				printf("O");
			else if (frame[i][j] == -2) // 打印食物
				printf("F");
		}
		printf("\n");
	}
}

void fruitGenerate(int frame[HIGH][WIGHT])
{
	while (1)
	{
		int y = rand() % (HIGH - 2) + 1;
		int x = rand() % (WIGHT - 2) + 1;
		if (frame[y][x] == 0)
		{
			frame[y][x] = -2;
			break;
		}
	}
}

int snakeAutomaticMove(int frame[HIGH][WIGHT], int moveDirection) // 蛇自动移动
{
	// 存储蛇头位置
	int headX = 0;
	int headY = 0;

	// 存储蛇尾位置
	int tailX = 0;
	int tailY = 0;
	int max = 0;

	// 查找
	for (int i = 1; i < HIGH - 1; i++)
	{
		for (int j = 1; j < WIGHT - 1; j++)
		{
			// 第一步:蛇头蛇身+1
			frame[i][j] > 0 ? frame[i][j]++ : 0;

			// 第二步:
			// 记录蛇头
			if (frame[i][j] == 2)
			{
				headX = j;
				headY = i;
			}

			// 记录蛇尾
			if (frame[i][j] > max)
			{
				max = frame[i][j];
				tailX = j;
				tailY = i;
			}
		}
	}

	// 第三步:
	// 存储新蛇头
	int newHeadY = 0;
	int newHeadX = 0;

	switch (moveDirection)
	{
	case 1: // 上
		newHeadY = headY - 1;
		newHeadX = headX;
		break;
	case 2: // 下
		newHeadY = headY + 1;
		newHeadX = headX;
		break;
	case 3: // 左
		newHeadY = headY;
		newHeadX = headX - 1;
		break;
	case 4: // 右
		newHeadY = headY;
		newHeadX = headX + 1;
		break;
	}

	// 检测游戏状态并返回
	return detectGameState(frame, newHeadY, newHeadX, tailY, tailX);
}

int detectGameState(int frame[HIGH][WIGHT], int newHeadY, int newHeadX, int tailY, int tailX)
{
	// 当蛇吃到食物不用去掉旧蛇尾
	if (frame[newHeadY][newHeadX] == -2)
	{
		fruitGenerate(frame); // 重新生成果实
	}
	else // 去掉旧蛇尾
		frame[tailY][tailX] = 0;

	//         	吃到自己				  或			撞墙		
	if (frame[newHeadY][newHeadX] > 0 || frame[newHeadY][newHeadX] == -1)
		return 0;
	else // 放置新蛇头
		frame[newHeadY][newHeadX] = 1;

	return 1;
}

void playerMove(int* moveDirection)
{
	char input = _getch();
	//  确定移动方向  且  禁止反方向移动
	if (input == 'w' && *moveDirection != 2) // 上
		*moveDirection = 1;
	else if (input == 's' && *moveDirection != 1) // 下
		*moveDirection = 2;
	else if (input == 'a' && *moveDirection != 4) // 左
		*moveDirection = 3;
	else if (input == 'd' && *moveDirection != 3) // 右
		*moveDirection = 4;
}

游戏补充内容实现

这里只是补充了一些小功能,就直接放源码了。
对于game.c

#pragma

#define _CRT_SECURE_NO_WARNINGS

#include <stdio.h>
#include <time.h>
#include <windows.h>
#include <conio.h>
#include <stdlib.h>

#define HIGH 20
#define WIGHT 30

void game();

void HideCursor();  // 隐藏光标

void gotoxy(int x, int y); // 固定画面

void init(int frame[HIGH][WIGHT]); // 游戏初始化

void display(int frame[HIGH][WIGHT], int scores, int quickly, int length); // 画面展示

int snakeAutomaticMove(int frame[HIGH][WIGHT], int moveDirection, int* scores, int quickly, int* length); // 蛇自动移动

void playerMove(int* moveDirection, int* quickly, int* stop); // 玩家操作

void fruitGenerate(int frame[HIGH][WIGHT]); // 生成果实

int detectGameState(int frame[HIGH][WIGHT], int newHeadY, int newHeadX, int tailY, int tailX, int* scores, int quickly, int* length); // 检测游戏状态

对于test.c

#include "game.h"

void explain()
{
	printf("********** 操作说明 **********\n");
	printf("* 移动键(小写)   上:w 下:s *\n");
	printf("*                左:a 右:d *\n");
	printf("* 空格:加速开关             *\n");
	printf("* 加速吃果实分数为2,反之为1 *\n");
	printf("* 小写字母j:暂停开关        *\n");
	printf("********** 操作说明 **********\n");
	printf("------------------------------\n");
	printf("空格返回\n");
	while (_getch() != ' ')
		Sleep(10);
	system("cls");
}

void menu()
{
	int inputY = 0;
	char arr[3][13] = { "开始游戏", "操作说明", "结束游戏" };

	while (1)
	{
		gotoxy(0, 0);

		printf("**********************\n");
		if (inputY == 0)
			printf("*****\033[41m %10s \033[0m*****\n", &arr[0][0]);
		else
			printf("***** %-11s*****\n", &arr[0][0]);
		if (inputY == 1)
			printf("*****\033[41m %10s \033[0m*****\n", &arr[1][0]);
		else
			printf("***** %-11s*****\n", &arr[1][0]);
		if (inputY == 2)
			printf("*****\033[41m %10s \033[0m*****\n", &arr[2][0]);
		else
			printf("***** %-11s*****\n", &arr[2][0]);
		printf("**********************\n");

		printf("上:w 下:s\n");
		printf("空格键确定\n");

		char ch = _getch();

		switch (ch)
		{
		case 'w':
			inputY = (inputY - 1 + 3) % 3;
			break;
		case 's':
			inputY = (inputY + 1) % 3;
			break;
		case ' ':
			if (inputY == 0)
			{
				system("cls");
				game();
			}
			else if (inputY == 1)
			{
				system("cls");
				explain();
			}
			else if (inputY == 2)
				return;
		}

		Sleep(10);
	}
}

void game()
{
	// 开始移动方向为右
	int moveDirection = 4;
	// 检测游戏状态
	int detect = 1;
	// 获得的分数
	int scores = 0;
	// 是否为加速状态
	int quickly = 0;
	// 蛇的总长度
	int length = 4;
	// 游戏暂停
	int stop = 0;
	int frame[HIGH][WIGHT] = { 0 };
	init(frame);
	while (1)
	{
		gotoxy(0, 0);

		detect = snakeAutomaticMove(frame, moveDirection, &scores, quickly, &length);

		display(frame, scores, quickly, length);

		if (!detect)
		{
			printf("游戏结束,按空格返回\n");
			while (_getch() != ' ')
				Sleep(10);
			system("cls");
			break;
		}

		if (_kbhit()) // 检测玩家键盘是否有输入
			playerMove(&moveDirection, &quickly, &stop);

		if (stop)
		{
			while (_getch() != 'j')
				Sleep(10);
			stop = 0;
		}

		// 帧数限制
		quickly ? Sleep(100) : Sleep(200);
	}
}

void test()
{
	HideCursor();
	srand((unsigned int)time(NULL)); // 获得时间戳以生成随机数
	menu();
}

int main()
{
	test();
	return 0;
}

对于game.c

#include "game.h"

void gotoxy(int x, int y)  // 光标移动到(x,y)的位置,可以让画面刷新
{
	HANDLE handle = GetStdHandle(STD_OUTPUT_HANDLE);
	COORD pos;
	pos.X = x;
	pos.Y = y;
	SetConsoleCursorPosition(handle, pos);
}

void HideCursor()  // 隐藏光标
{
	CONSOLE_CURSOR_INFO cursor_info = { 1, 0 };  // 第二个值为0表示隐藏光标
	SetConsoleCursorInfo(GetStdHandle(STD_OUTPUT_HANDLE), &cursor_info);
}

void init(int frame[HIGH][WIGHT])
{
	// 初始化墙壁
	for (int i = 0; i < HIGH; i++)
		for (int j = 0; j < WIGHT; j++)
			frame[i][j] = ((!i || i == HIGH - 1 || !j || j == WIGHT - 1) ? -1 : 0);

	// 初始化蛇身蛇头
	for (int i = 1; i <= 4; i++)
		frame[HIGH / 2][WIGHT / 2 - i] = i;

	// 生成食物
	fruitGenerate(frame);
}

void display(int frame[HIGH][WIGHT], int scores, int quickly, int length)
{
	for (int i = 0; i < HIGH; i++)
	{
		for (int j = 0; j < WIGHT; j++)
		{
			if (frame[i][j] == 0) // 打印空白
				printf(" ");
			else if (frame[i][j] == -1) // 打印墙壁
				printf("#");
			else if (frame[i][j] == 1) // 打印蛇头
				printf("%s", quickly ? "\033[31;1m@\033[0m" : "\033[34;1m@\033[0m");
			else if (frame[i][j] > 1) // 打印蛇身
				printf("%s", quickly ? "\033[31;1mO\033[0m" : "\033[34;1mO\033[0m");
			else if (frame[i][j] == -2) // 打印食物
				printf("\033[32;1mF\033[0m");
		}
		if (!i)
			printf("***********************");
		else if (i == 1)
			printf("*****  分数为:%-4d*****", scores);
		else if (i == 2)
			printf("***********************");
		else if (i == 3)
			printf("** 是否为加速状态:%s **", quickly ? "\033[31;1m是\033[0m" : "\033[34;1m否\033[0m");
		else if (i == 4)
			printf("***********************");
		else if (i == 5)
			printf("***********************");
		else if (i == 6)
			printf("*** 蛇的总长度:%-4d ***", length);
		else if (i == 7)
			printf("***********************");
		printf("\n");
	}
}

int snakeAutomaticMove(int frame[HIGH][WIGHT], int moveDirection, int* scores, int quickly, int* length) // 蛇自动移动
{
	// 存储蛇头位置
	int headX = 0;
	int headY = 0;

	// 存储蛇尾位置
	int tailX = 0;
	int tailY = 0;
	int max = 0;

	for (int i = 1; i < HIGH - 1; i++)
	{
		for (int j = 1; j < WIGHT - 1; j++)
		{
			// 蛇头蛇身自增
			frame[i][j] > 0 ? frame[i][j]++ : 0;

			// 记录蛇头
			if (frame[i][j] == 2)
			{
				headX = j;
				headY = i;
			}

			// 记录蛇尾
			if (frame[i][j] > max)
			{
				max = frame[i][j];
				tailX = j;
				tailY = i;
			}
		}
	}

	// 存储新蛇头
	int newHeadY = 0;
	int newHeadX = 0;

	switch (moveDirection)
	{
	case 1:
		newHeadY = headY - 1;
		newHeadX = headX;
		break;
	case 2:
		newHeadY = headY + 1;
		newHeadX = headX;
		break;
	case 3:
		newHeadY = headY;
		newHeadX = headX - 1;
		break;
	case 4:
		newHeadY = headY;
		newHeadX = headX + 1;
		break;
	}

	// 检测游戏状态并返回
	return detectGameState(frame, newHeadY, newHeadX, tailY, tailX, scores, quickly, length);
}

void playerMove(int* moveDirection, int* quickly, int* stop)
{
	char input = _getch();
	//  确定移动方向  且  禁止反方向移动
	if (input == 'w' && *moveDirection != 2) // 上0x48
		*moveDirection = 1;
	else if (input == 's' && *moveDirection != 1) // 下0x50
		*moveDirection = 2;
	else if (input == 'a' && *moveDirection != 4) // 左0x4b
		*moveDirection = 3;
	else if (input == 'd' && *moveDirection != 3) // 右0x4d
		*moveDirection = 4;
	else if (input == 'j') // 暂停
		*stop = !(*stop);
	else if (input == ' ') // 加速
		*quickly = !(*quickly);
}

void fruitGenerate(int frame[HIGH][WIGHT])
{
	while (1)
	{
		int y = rand() % (HIGH - 2) + 1;
		int x = rand() % (WIGHT - 2) + 1;
		if (frame[y][x] == 0)
		{
			frame[y][x] = -2;
			break;
		}
	}
}

int detectGameState(int frame[HIGH][WIGHT], int newHeadY, int newHeadX, int tailY, int tailX, int* scores, int quickly, int* length)
{
	// 当蛇吃到食物不用去掉旧蛇尾
	if (frame[newHeadY][newHeadX] == -2)
	{
		quickly ? (*scores) += 2 : (*scores)++;
		(*length)++;
		fruitGenerate(frame);
	}
	else // 去掉旧蛇尾
		frame[tailY][tailX] = 0;

	//         	吃到自己				  或			撞墙		
	if (frame[newHeadY][newHeadX] > 0 || frame[newHeadY][newHeadX] == -1)
		return 0;
	else // 放置新蛇头
		frame[newHeadY][newHeadX] = 1;

	return 1;
}

结语

以上是便是全部内容,若文章有问题或游戏有bug,可以告诉我,我会及时补充。

谢谢阅读

  • 11
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
好的,以下是一个简单的C语言实现贪吃的代码示例: ```c #include <stdio.h> #include <stdlib.h> #include <time.h> #include <conio.h> #include <windows.h> #define WIDTH 40 // 地图宽度 #define HEIGHT 20 // 地图高度 #define SNAKE_MAX_LENGTH 100 // 的最大长度 int map[HEIGHT][WIDTH]; // 地图数组,0表示空格,1表示身,2表示食物 int snake[SNAKE_MAX_LENGTH][2]; // 身坐标数组,存储每个节的横纵坐标 int snake_length = 3; // 的长度 int food_x, food_y; // 食物的横纵坐标 int direction = 0; // 的移动方向,0表示上,1表示右,2表示下,3表示左 // 初始化地图 void init_map() { for (int i = 0; i < HEIGHT; i++) { for (int j = 0; j < WIDTH; j++) { map[i][j] = 0; } } } // 初始化 void init_snake() { snake[0][0] = HEIGHT / 2; snake[0][1] = WIDTH / 2; map[snake[0][0]][snake[0][1]] = 1; snake[1][0] = HEIGHT / 2 + 1; snake[1][1] = WIDTH / 2; map[snake[1][0]][snake[1][1]] = 1; snake[2][0] = HEIGHT / 2 + 2; snake[2][1] = WIDTH / 2; map[snake[2][0]][snake[2][1]] = 1; } // 生成食物 void generate_food() { int x, y; do { x = rand() % HEIGHT; y = rand() % WIDTH; } while (map[x][y] != 0); food_x = x; food_y = y; map[food_x][food_y] = 2; } // 显示地图 void show_map() { system("cls"); // 清屏 for (int i = 0; i < HEIGHT; i++) { for (int j = 0; j < WIDTH; j++) { if (i == food_x && j == food_y) { // 食物 printf("O"); } else if (map[i][j] == 1) { // 身 printf("#"); } else { // 空格 printf(" "); } } printf("\n"); } } // 检测是否吃到食物 void check_eat_food() { if (snake[0][0] == food_x && snake[0][1] == food_y) { snake_length++; generate_food(); } } // 检测是否撞到墙或自己 void check_dead() { if (snake[0][0] < 0 || snake[0][0] >= HEIGHT || snake[0][1] < 0 || snake[0][1] >= WIDTH) { exit(0); } for (int i = 1; i < snake_length; i++) { if (snake[i][0] == snake[0][0] && snake[i][1] == snake[0][1]) { exit(0); } } } // 移动 void move_snake() { // 计算头新的位置 int new_head_x = snake[0][0], new_head_y = snake[0][1]; switch (direction) { case 0: new_head_x--; break; // 上 case 1: new_head_y++; break; // 右 case 2: new_head_x++; break; // 下 case 3: new_head_y--; break; // 左 } // 更新身坐标数组和地图数组 for (int i = snake_length - 1; i > 0; i--) { snake[i][0] = snake[i - 1][0]; snake[i][1] = snake[i - 1][1]; map[snake[i][0]][snake[i][1]] = 1; } snake[0][0] = new_head_x; snake[0][1] = new_head_y; map[snake[0][0]][snake[0][1]] = 1; } // 键盘输入事件 void keyboard_event() { if (_kbhit()) { // 判断是否有键盘输入 char ch = _getch(); switch (ch) { case 'w': direction = 0; break; // 上 case 'd': direction = 1; break; // 右 case 's': direction = 2; break; // 下 case 'a': direction = 3; break; // 左 } } } int main() { // 初始化 srand(time(NULL)); // 设置随机数种子 init_map(); init_snake(); generate_food(); // 游戏循环 while (1) { show_map(); check_eat_food(); check_dead(); move_snake(); keyboard_event(); Sleep(100); // 等待一段时间,控制的移动速度 } return 0; } ``` 该示例代码使用了Windows系统的控制台API,如果在其他操作系统下运行需要进行适当修改。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值