再来一次的C语言贪吃蛇小游戏(三)

8.游戏的不同界面

为了便于实现主要功能,之前我们所有的状态控制都是放在游戏中,但实际上我们应该把这些状态控制抽离出来,通过菜单来控制,以便在不同游戏界面间切换。

  1. 菜单界面
  2. 游戏界面
  3. 排行榜
  4. 游戏结束界面
  5. 其他一些扩展界面
enum state {
	in_menu, //菜单界面
	gaming, //游戏界面
	_check_ranking,//排行榜界面
	snake_dead,//游戏结束界面
	to_quit	//退出
}State;

9.菜单界面

首先在game.h头文件中,我们先定义好菜单中的内容

//game.h
#define WELCOME "SNAKE"
#define DEAD_INFO "WASTED"
#define RANKING "RANKING"
#define LONG_LINE "------------------------------------------------------------------"
#define CHOICE_NUM 3
#define MENU_ONE "开始游戏"
#define MENU_TWO "查看排名"
#define MENU_THREE "退出游戏"

然后就是选择菜单项的实现,按下前面定义的move_up,move_down按钮,实现上下翻,按下enter实现选择

//game.c
void menu() 
{
	show_menu();
	int input = no_option;
	int choice = 0;
	int last_choice = 0;
	while (State == in_menu)
	{
		if (_kbhit())
		{
			input = _getch();
			switch (input)
			{
				case move_up:
					if (choice - 1 >= 0)
					{
						last_choice = choice;
						choice = choice - 1;
					}
					break;
				case move_down:
					if (choice + 1 < CHOICE_NUM)
					{
						last_choice = choice;
						choice = choice + 1;
					}
					break;
				case enter:
					if (choice == 0)
					{
						State = gaming;
					}
					else if (choice == 1)
					{
						State = _check_ranking;
					}
					else if (choice == 2)
					{
						State = to_quit;
					}
					break;
				default:
					continue;
			}
			set_cursor_position(10, 6 + choice);
			printf("--->");
			set_cursor_position(10, 6 + last_choice);
			printf("     ");
		}
	}
}

void show_menu()
{
	set_console_color(3, 0);
	set_cursor_position(0, 0);
	printf("%s", LONG_LINE);
	set_cursor_position(15, 1);
	printf("%s", WELCOME);
	set_cursor_position(0, 2);
	printf("%s", LONG_LINE);
	set_console_color(8, 0);
	set_cursor_position(15, 6);
	printf("%s", MENU_ONE);
	set_cursor_position(15, 7);
	printf("%s", MENU_TWO);
	set_cursor_position(15, 8);
	printf("%s", MENU_THREE);
	set_cursor_position(10, 6);
	printf("--->");
}

10. 游戏界面

对前面定义的star_game()方法进行修改,将状态控制部分提出来即可。

void start_game() 
{
	struct game *Game = (struct game*)malloc(sizeof(struct game));
	Snake *snake = new_born_snake(5, 5);
	Game->score = 0;
	init_map(Game);
	display_map(Game);
	display_snake(Game, snake);
	grow_food(Game);
	int input = no_option;
	int last_input = no_option;
	while (State == gaming)
	{
		if (_kbhit())
		{
			input = _getch();
			FlushConsoleInputBuffer(GetStdHandle(STD_INPUT_HANDLE));
		}
		else input = no_option;
		switch (input)
		{
		case move_up:
		case move_right:
		case move_down:
		case move_left:
			judge_move_input(Game, snake, &input, &last_input);
			break;
		case esc:
			State = in_menu;
			break;
		case no_option:
		default:
			snake_move(Game, snake, snake->head->dir);
			break;
		}
	}
	free(Game);
}

11.排行界面

如果你的得分可以超过排行榜最后一名的分数,那么会跳出,可以输入名字,可以将得分与玩家名字保存至本地文件rank.txt

int if_can_rank(int score)
{
	FILE *fp;
	if (fopen_s(&fp, "./rank.txt", "r"))
		return 0;
	char each_info[15];
	int scores[RANK_NUM];
	for (int i = 0; i < RANK_NUM*2; i++)
	{
		fgets(each_info, 15, fp);
		if (!( i & 1))
		{
			scores[i / 2] = atoi(each_info);
		}
	}
	fclose(fp);
	return score >= scores[RANK_NUM - 1];
}


void save_score(int score, char* player)
{
	FILE *fp = NULL;
	if (fopen_s(&fp, "./rank.txt", "r+"))
		return;
	char each_info[15], new_player[15];
	int scores[RANK_NUM];
	char names[RANK_NUM][15];
	for (int i = 0; i < RANK_NUM * 2 && fgets(each_info, 15, fp) != NULL; i++)
	{
		if (i & 1)
			strcpy_s(*(names + i / 2), 15, each_info);
		else scores[i / 2] = atoi(each_info);
	}
	for (int i = 0; i < RANK_NUM; i++)
	{
		if (score > scores[i])
		{
			for (int j = RANK_NUM - 1; j > i; j--)
			{
				scores[j] = scores[j - 1];
				strcpy_s(*(names + j), 15, *(names + j-1));
			}
			scores[i] = score;
			strcpy_s(new_player, 15, player);
			strcat_s(new_player, 15, "\n");
			strcpy_s(*(names + i), 15, new_player);
			break;
		}
	}
	fseek(fp, 0, SEEK_SET);
	for (int i = 0; i < RANK_NUM; i++)
	{
		fprintf_s(fp, "%d\n%s", scores[i], *(names + i));
	}
	fclose(fp);
}

12.游戏失败界面

如果你的得分没有超过排行榜最后一名的分数,蛇死亡后直接进入游戏失败界面

不好意思放错图了....

13.总控制

void main() 
{
	State = in_menu;
	int quit = 0;
	while (!quit) 
	{
		switch (State)
		{
		case in_menu:
			system("cls");
			menu();
			break;
		case gaming:
			system("cls");
			start_game();
			break;
		case _check_ranking:
			system("cls");
			rank();
			break;
		case snake_dead:
			show_dead();
			break;
		case to_quit:
			quit = 1;
			break;
		default:
			break;
		}
	}
}

这样一来,才是比较连贯的游戏体验

13.游戏扩展内容

贪吃蛇小游戏还可以有很多的扩展内容!

  • 存档
  • 自动寻路
  • 多种道具
  • 多关卡闯关
  • 多人游戏

我将在下一篇博客中实现存档和自动寻路功能,剩下的扩展看时间和心情了哈哈
当然,你也可以自己在此基础版本上扩展!

基础版源码地址:github

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Hack Rabbit

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值