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();//去尾巴
    	}
    }
    
  • 相关阅读:
    新年第一个项目思考
    ICP通讯(EN)
    将绝对路径变成URL路径(原创)
    [图像处理] 铁路轨道道岔检测(一)
    一个外国的好网站 http://www.ilovejackdaniels.com/
    内容全面的企业网站策划书
    asp.net2.0学习历程 菜鸟到中级程序员的飞跃
    TimeSpan 用法 求离最近发表时间的函数
    ASP.NE导出Excel
    在网页中,鼠标放在Flash链接上,光标形状会在手型和鼠标之间不停的闪 的解决办法
  • 原文地址:https://www.cnblogs.com/scl0725/p/12984764.html
Copyright © 2011-2022 走看看