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,可以告诉我,我会及时补充。

谢谢阅读

  • 12
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值