再來一次的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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章