程序设计-team1-贪吃蛇

#include <iostream>
#include <list>//使用双向链表
#include <cstdio>
#include <cstring>
#include <Windows.h>//使用windows API函数(1.本代码使用函数来更改dos窗口标题,使美观2.使用COORD)
#include <string>
#include <ctime>//随机化种子,达到随机生成食物的目的
#include <conio.h>
#include <fstream>
#include <vector>//不定长数组用来储存从文件中读取的成绩
#include <algorithm>//用sort
#include <sstream>//用stringstream
#include <cstdlib>

using namespace std;

list<COORD> snake;//双链表储存蛇身
list<COORD> ai_snake;//双链表储存ai蛇身

string game_map[25];//储存地图
int direction_before;//因为有了上面的映射,所以可以用int来表示蛇的运动方向。上一步的运动方向
int direction_now;//新的运动方向

int ai_direction_before;//ai蛇的运动方向信息
int chse;//游戏模式选择
int score;//得分
bool die;//判断游戏是否结束
bool ai_die;//ai蛇的生死
int speed = 500;//控制速度
vector<int> sc;//不定长数组用来储存从文件中读取的成绩
COORD food;

void Init();//更改dos窗口标题,初始化地图,初始化蛇身,蛇运动方向, 随机化种子
void Generate_food();//随机生成食物
void Press_key();//监听键盘并处理从键盘上读取的字符
void Move_snake();//移动蛇,并检测是否合理
void Move_ai_snake();//自动移动ai蛇,并检测是否合理
void Draw_map();//输出地图,蛇,食物,操作提示
void File_action();//成绩读入文件并计算名次
void Init_ai();//初始化ai蛇

int main()
{
	cout << "Press 1(solo) or 2(vs ai) to choose mod:" << endl;
	cin >> chse;
	
	if (chse == 1)//单人游戏
	{
		Init();
		Draw_map();

		COORD coord; coord.X = 5; coord.Y = 10;//下标为[10][5]的位置
		SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), coord);//移动光标位置
		cout << "Press any key to start" << endl;//在指定位置输出提示语

		//按下任意键,游戏开始
		char c = _getch();//利用阻塞函数,当按下任意键,程序才继续向下运行,游戏才开始

		Generate_food();//生成第一个食物

		while (!die)
		{
			Press_key();//监听键盘并处理从键盘上读取的字符
			Move_snake();//移动蛇,并检测是否合理

			system("cls");//清屏
			Draw_map();//重新画

			if (speed < 0)
				speed = 0;
			Sleep(speed);//控制速度
		}

		File_action();

	}
	else//人机
	{
		Init();//初始化地图,dos窗口标题和玩家控制的蛇
		Init_ai();//初始化ai蛇

		Draw_map();

		COORD coord; coord.X = 5; coord.Y = 10;//下标为[10][5]的位置
		SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), coord);//移动光标位置
		cout << "Press any key to start" << endl;//在指定位置输出提示语

		//按下任意键,游戏开始
		char c = _getch();//利用阻塞函数,当按下任意键,程序才继续向下运行,游戏才开始

		Generate_food();//生成第一个食物

		while (!die && !ai_die)
		{
			Press_key();//监听键盘并处理从键盘上读取的字符
			Move_ai_snake();//移动ai蛇,并检测是否合理
			Move_snake();//移动蛇,并检测是否合理

			system("cls");//清屏
			Draw_map();//重新画

			if (speed < 0)
				speed = 0;

			Sleep(speed);//控制速度
		}
	}
	system("pause");
	return 0;
}

void Init()
{
	SetConsoleTitleW(L"程序设计——team1——贪吃蛇");//更改dos窗口标题

										  //上下边界
	game_map[0] = "$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$";//三十个字符
	game_map[19] = "$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$";//三十个字符

													//左右边界
	for (int i = 1; i < 19; i++)
		game_map[i] = "$                            $";//三十个字符

													   //初始化蛇身,长度为两节
	snake.push_back({ 10, 15 });
	snake.push_back({ 10, 16 });

	//默认一个蛇的初始运动方向
	direction_before = 1;//默认朝上运动

	srand((unsigned int)time(NULL));
}

void Generate_food()
{
	do
	{
		food.Y = rand() % 20;
		food.X = rand() % 30;
	} while (game_map[food.Y][food.X] != ' ');//当食物生成在地图边界或者蛇身上时重新生成

	game_map[food.Y][food.X] = '*';//生成食物
}

void Press_key()
{
	while (_kbhit())
	{
		char temp = _getch();

		if (temp == ' ')//暂停的功能实现
		{
			Sleep(2000);
		}

		switch (temp)
		{
		case 'o':
		case 'O': speed -= 200; break;
		case 'p':
		case 'P': speed += 200; break;

		case 'w':
		case 'W':	direction_now = 1; break;
		case 's':
		case 'S':	direction_now = 2; break;
		case 'a':
		case 'A':	direction_now = 3; break;
		case 'd':
		case 'D':	direction_now = 4; break;

		default:	direction_now = 0;//其他情况的输入
		}

		//处理变向
		if (direction_now)//当合法输入时
		{
			if (direction_before + direction_now != 3 && direction_before + direction_now != 7)//当之前的运动方向和之后的运动方向夹角不是180度时(即可以合理变向)
				direction_before = direction_now;//变向
		}
	}
}

void Move_snake()
{
	COORD temp;//储存新的蛇头坐标

	switch (direction_before)//获取新的蛇头坐标
	{
	case 1: temp.X = snake.front().X, temp.Y = snake.front().Y - 1; break;
	case 2: temp.X = snake.front().X, temp.Y = snake.front().Y + 1; break;
	case 3: temp.X = snake.front().X - 1, temp.Y = snake.front().Y; break;
	case 4: temp.X = snake.front().X + 1, temp.Y = snake.front().Y; break;
	}

	if (game_map[temp.Y][temp.X] == '$' || game_map[temp.Y][temp.X] == '+' || game_map[temp.Y][temp.X] == '%')//碰到墙壁或者自身或者ai蛇蛇身
	{
		COORD coord; coord.X = 5; coord.Y = 10;//下标为[10][5]的位置
		SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), coord);//移动光标位置

		if (chse == 1)//根据模式不同输出不同的信息
			cout << "Game over." << endl;//在指定位置输出提示语
		else
			cout << "AI snake is winner." << endl;
		die = true;

		Sleep(1000);//函数在此停止1000ms,方便用户反应知道结果
	}
	else if (game_map[temp.Y][temp.X] == '*')//吃到食物
	{
		game_map[snake.front().Y][snake.front().X] = '+';//原蛇头变成蛇身
		snake.push_front(temp);//新蛇头入链表
		game_map[snake.front().Y][snake.front().X] = '=';//在地图上绘出新蛇头

		score += 10;//加分

		Generate_food();//生成新的食物
	}
	else//如果只是向前移动一步的话,加入新蛇头,去掉蛇尾即可
	{
		game_map[snake.front().Y][snake.front().X] = '+';//原蛇头变蛇身
		snake.push_front(temp);//加入新蛇头
		game_map[snake.front().Y][snake.front().X] = '=';//画出新蛇头
		game_map[snake.back().Y][snake.back().X] = ' ';//尾部变为空白
		snake.pop_back();//去尾巴
	}
}

void Draw_map()
{
	for (int i = 0; i < 20; i++)
		cout << game_map[i] << endl;
	cout << endl;

	if(chse == 1)//单人模式中才记录分数
		cout << "Score:" << score << endl;

	cout << "操作方式:" << endl;
	cout << "w(W)上 s(S)下 a(A)左 d(D)右" << endl;
	cout << "o(O)实现游戏加速,p(P)实现游戏减速" << endl;
	cout << "按空格键暂停2秒" << endl;
}

void File_action()
{
	ofstream fout("record.txt", ios::out | ios::app);

	fout << score << ' ';//成绩读入文件中

	fout.close();

	ifstream fin("record.txt"); //待读取文件的目录

	string line;

	while (getline(fin, line))
	{
		stringstream ss(line);//定义输入流并且传值进去

		if (!ss.eof())
		{
			int temp;
			while (ss >> temp)//提取int
				sc.push_back(temp);//加入到vector数组中
		}
	}

	sort(sc.begin(), sc.end());//通过迭代器来利用sort排序

	COORD coord; coord.X = 5; coord.Y = 10;//下标为[10][5]的位置
	SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), coord);//移动光标位置

																	 //求排名
	int rank = 1;
	for (auto x : sc)
		if (x > score) rank++;
	cout << "你的排名是:" << rank;

	fin.close();
}

void Init_ai()
{
	//初始化蛇身,长度为两节
	ai_snake.push_back({ 10, 10 });
	ai_snake.push_back({ 10, 11 });

	//默认一个蛇的初始运动方向
	ai_direction_before = 1;//默认朝上运动
}

void Move_ai_snake()
{
	//实现ai蛇的转向,向靠近食物的方向运动
	if (ai_direction_before == 1)//ai蛇运动朝上
	{
		if (ai_snake.front().Y <= food.Y)//食物在蛇头此行或者下面某行
		{
			if (ai_snake.front().X >= food.X)
				ai_direction_before = 3;
			else if (ai_snake.front().X < food.X)
				ai_direction_before = 4;
		}
	}
	else if (ai_direction_before == 2)//ai蛇运动朝下
	{
		if (ai_snake.front().Y >= food.Y)//食物在蛇头此行或者上面某行
		{
			if (ai_snake.front().X >= food.X)
				ai_direction_before = 3;
			else if (ai_snake.front().X < food.X)
				ai_direction_before = 4;
		}
	}
	else if (ai_direction_before == 3)//ai蛇运动朝左
	{
		if (ai_snake.front().X <= food.X)//食物在蛇头此列或者右边某列
		{
			if (ai_snake.front().Y >= food.Y)
				ai_direction_before = 1;
			else if (ai_snake.front().Y < food.Y)
				ai_direction_before = 2;
		}
	}
	else//ais蛇运动朝右
	{
		if (ai_snake.front().X >= food.X)//食物在蛇头此列或者左边某列
		{
			if (ai_snake.front().Y >= food.Y)
				ai_direction_before = 1;
			else if (ai_snake.front().Y < food.Y)
				ai_direction_before = 2;
		}
	}

	//移动并判断合理性
	COORD temp;//储存新的蛇头坐标

	switch (ai_direction_before)//获取新的蛇头坐标
	{
	case 1: temp.X = ai_snake.front().X, temp.Y = ai_snake.front().Y - 1; break;
	case 2: temp.X = ai_snake.front().X, temp.Y = ai_snake.front().Y + 1; break;
	case 3: temp.X = ai_snake.front().X - 1, temp.Y = ai_snake.front().Y; break;
	case 4: temp.X = ai_snake.front().X + 1, temp.Y = ai_snake.front().Y; break;
	}

	if (game_map[temp.Y][temp.X] == '$' || game_map[temp.Y][temp.X] == '%' || game_map[temp.Y][temp.X] == '+')//碰到墙壁或者自身或者玩家蛇身体
	{
		COORD coord; coord.X = 5; coord.Y = 10;//下标为[10][5]的位置
		SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), coord);//移动光标位置
		cout << "You is winner" << endl;

		ai_die = true;

		Sleep(1000);//函数在此停止1000ms,方便用户反应知道结果
	}
	else if (game_map[temp.Y][temp.X] == '=')//蛇头碰到蛇头
	{
		COORD coord; coord.X = 5; coord.Y = 10;//下标为[10][5]的位置
		SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), coord);//移动光标位置
		cout << "No winner." << endl;//在指定位置输出提示语

		ai_die = true;

		Sleep(1000);//函数在此停止1000ms,方便用户反应知道结果
	}
	else if (game_map[temp.Y][temp.X] == '*')//吃到食物
	{
		game_map[ai_snake.front().Y][ai_snake.front().X] = '%';//原蛇头变成蛇身
		ai_snake.push_front(temp);//新蛇头入链表
		game_map[ai_snake.front().Y][ai_snake.front().X] = '#';//在地图上绘出新蛇头

		Generate_food();//生成新的食物
	}
	else//如果只是向前移动一步的话,加入新蛇头,去掉蛇尾即可
	{
		game_map[ai_snake.front().Y][ai_snake.front().X] = '%';//原蛇头变蛇身
		ai_snake.push_front(temp);//加入新蛇头
		game_map[ai_snake.front().Y][ai_snake.front().X] = '#';//画出新蛇头
		game_map[ai_snake.back().Y][ai_snake.back().X] = ' ';//尾部变为空白
		ai_snake.pop_back();//去尾巴
	}
}
posted @ 2020-05-28 23:30  sunnyday0725  阅读(128)  评论(0编辑  收藏  举报