zoukankan      html  css  js  c++  java
  • 程序设计-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();//去尾巴
    	}
    }
    
  • 相关阅读:
    北京燃气IC卡充值笔记
    随机分析、随机控制等科目在量化投资、计算金融方向有哪些应用?
    量化交易平台大全
    Doctor of Philosophy in Computational and Mathematical Engineering
    Institute for Computational and Mathematical Engineering
    Requirements for the Master of Science in Computational and Mathematical Engineering
    MSc in Mathematical and Computational Finance
    万字长文:详解多智能体强化学习的基础和应用
    数据处理思想和程序架构: 使用Mbedtls包中的SSL,和服务器进行网络加密通信
    31-STM32+W5500+AIR202/302基本控制篇-功能优化-W5500移植mbedtls库以SSL方式连接MQTT服务器(单向忽略认证)
  • 原文地址:https://www.cnblogs.com/scl0725/p/12984764.html
Copyright © 2011-2022 走看看