基于STL容器的贪吃蛇

先说明下:本文来源:https://blog.csdn.net/silence1772/article/details/55005008

类的描述:

Tool类:

主要调用一些Windows系统函数,完成光标的定位(光标定位用于屏幕各种打印的位置),改变字体颜色,改变背景颜色这些功能。

Tools.头文件

	void SetWindowSize(int cols, int lines);//设置游戏窗口的大小
	void SetCursorPosition(const int x, const int y);//设置光标位置,用来输出文字或者空格(覆盖)
	void SetColor(int colorID);//设置文本颜色
	void SetBackColor();//设置文本背景颜色

Tool.源文件

#pragma warning(disable:4996)
#include "tool.h"
#include <windows.h>
#include <stdio.h>

void SetWindowSize(int cols, int lines)//设置窗口大小
{
    system("title 贪吃蛇");//设置窗口标题,黑款左上角会显示贪吃蛇,固定的“title+....."
    char cmd[30];
    sprintf(cmd, "mode con cols=%d lines=%d", cols * 2, lines);//一个图形■占两个字符,故宽度乘以2
    system(cmd);//system(mode con cols=88 lines=88):设置窗口宽度和高度,固定的库函数以及写法
}

void SetCursorPosition(const int x, const int y)//设置光标位置,相当于是个接口,还要调用windows里 的函数,SetConsoleCursorPosition
{
    HANDLE hout;
    hout = GetStdHandle(STD_OUTPUT_HANDLE);//GetStdHandle(STD_OUTPUT_HANDLE):标准输出程序的句柄
    COORD position;//COORD:固定的结构体变量,有两个成员X,Y
    position.X = x * 2;//一个图形■占两个字符,故宽度乘以2
    position.Y = y;
    SetConsoleCursorPosition(hout, position);//SetConsoleCursorPosition:在写入输出之前将光标移动到所需位置,即(x,y)的位置m   
}

void SetColor(int colorID)//设置文本颜色
{
    //懂了
    SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), colorID);
    //GetStdHandle(STD_OUTPUT_HANDLE):固定输出句柄
    //
}

void SetBackColor()//设置文本背景色
{
    //懂了
    SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),
        FOREGROUND_BLUE |
        BACKGROUND_BLUE |
        BACKGROUND_GREEN |
        BACKGROUND_RED);
}

Point类:

1.某位置打印正方形(地图,大食物)
2.某位置打印圆形(蛇身)
3.某位置进行覆盖(用空格)
4.某位置改变坐标(传入参数)
5.重载==运算符(不明白)
6.返回X,Y坐标(经常被调用)
Point.h

#pragma once
#include"tool.h"
class Point
{
public:
	//Point() {};
	Point(int x, int y) :m_x(x), m_y(y) {}
	void point_square();
	void point_circular();
	void Clear();//空格进行覆盖
	void change_position(int x,int y);//改变坐标
	bool operator == (const Point& point) { return (point.m_x == this->m_x) && (point.m_y == this->m_y); }//重载 == 运算符
	int GetX() { return this->m_x; }//得到坐标
	int GetY() { return this->m_y; }


	int m_x;
	int m_y;

};

Point.cpp

#include"point.h"
#include<iostream>
using namespace std;

void Point::point_square()
{
	SetCursorPosition(m_x, m_y);
	cout << "■";//Alt+41462,一个方块占2个字节,

}
void Point::point_circular()
{
	SetCursorPosition(m_x, m_y);
	cout << "●";
}
void Point::Clear()//空格进行覆盖
{
	SetCursorPosition(m_x, m_y);//清除(x,y)这个点,不是真正清除,是通过覆盖,用空格来覆盖原来的点
	std::cout << "  ";//此处是两个空格,因为都是占了2个字节的

}

void Point::change_position(int x, int y)//改变坐标
{
	this->m_x = x;
	this->m_y = y;
}

Map类:

把所有的点(所有point对象)放到vector容器中,并且for循环遍历容器,进行输出打印,用Sleep()营造动画效果。

Map.h

#pragma once
#include"point.h"
#include"tool.h"
#include<vector>
using namespace std;

class Map
{
	private:
	vector<Point>map;
	public:
	Map() ;
	void PrintInitmap();

};

Map.cpp

using namespace std;
#include<iostream>
#include <algorithm>

#include <windows.h>

Map::Map()
{
   map.push_back(Point(1, 1));//四周的点
   map.push_back(Point(2, 1));//创建点类对象的同时,调用有参构造函数(对m_x,m_y进行初始化),把对象放到vector容器里
   map.push_back(Point(3, 1));
   map.push_back(Point(4, 1));
   map.push_back(Point(5, 1));
   map.push_back(Point(6, 1));
   map.push_back(Point(7, 1));
   map.push_back(Point(8, 1));
   map.push_back(Point(9, 1));
   map.push_back(Point(10, 1));
   map.push_back(Point(11, 1));
   map.push_back(Point(12, 1));
   map.push_back(Point(13, 1));
   map.push_back(Point(14, 1));
   map.push_back(Point(15, 1));
   map.push_back(Point(16, 1));
   map.push_back(Point(17, 1));
   map.push_back(Point(18, 1));
   map.push_back(Point(19, 1));
   map.push_back(Point(20, 1));
   map.push_back(Point(21, 1));
   map.push_back(Point(22, 1));
   map.push_back(Point(23, 1));
   map.push_back(Point(24, 1));
   map.push_back(Point(25, 1));
   map.push_back(Point(26, 1));
   map.push_back(Point(27, 1));
   map.push_back(Point(28, 1));
   map.push_back(Point(29, 1));
   map.push_back(Point(30, 1));
   map.push_back(Point(1, 2));
   map.push_back(Point(30, 2));
   map.push_back(Point(1, 3));
   map.push_back(Point(30, 3));
   map.push_back(Point(1, 4));
   map.push_back(Point(30, 4));
   map.push_back(Point(1, 5));
   map.push_back(Point(30, 5));
   map.push_back(Point(1, 6));
   map.push_back(Point(30, 6));
   map.push_back(Point(1, 7));
   map.push_back(Point(30, 7));
   map.push_back(Point(1, 8));
   map.push_back(Point(30, 8));
   map.push_back(Point(1, 9));
   map.push_back(Point(30, 9));
   map.push_back(Point(1, 10));
   map.push_back(Point(30, 10));
   map.push_back(Point(1, 11));
   map.push_back(Point(30, 11));
   map.push_back(Point(1, 12));
   map.push_back(Point(30, 12));
   map.push_back(Point(1, 13));
   map.push_back(Point(30, 13));
   map.push_back(Point(1, 14));
   map.push_back(Point(30, 14));
   map.push_back(Point(1, 15));`在这里插入代码片`
   map.push_back(Point(30, 15));
   map.push_back(Point(1, 16));
   map.push_back(Point(30, 16));
   map.push_back(Point(1, 17));
   map.push_back(Point(30, 17));
   map.push_back(Point(1, 18));
   map.push_back(Point(30, 18));
   map.push_back(Point(1, 19));
   map.push_back(Point(30, 19));
   map.push_back(Point(1, 20));
   map.push_back(Point(30, 20));
   map.push_back(Point(1, 21));
   map.push_back(Point(30, 21));
   map.push_back(Point(1, 22));
   map.push_back(Point(30, 22));
   map.push_back(Point(1, 23));
   map.push_back(Point(30, 23));
   map.push_back(Point(1, 24));
   map.push_back(Point(30, 24));
   map.push_back(Point(1, 25));
   map.push_back(Point(30, 25));
   map.push_back(Point(1, 26));
   map.push_back(Point(30, 26));
   map.push_back(Point(1, 27));
   map.push_back(Point(30, 27));
   map.push_back(Point(1, 28));
   map.push_back(Point(30, 28));
   map.push_back(Point(1, 29));
   map.push_back(Point(30, 29));
   map.push_back(Point(1, 30));
   map.push_back(Point(2, 30));
   map.push_back(Point(3, 30));
   map.push_back(Point(4, 30));
   map.push_back(Point(5, 30));
   map.push_back(Point(6, 30));
   map.push_back(Point(7, 30));
   map.push_back(Point(8, 30));
   map.push_back(Point(9, 30));
   map.push_back(Point(10, 30));
   map.push_back(Point(11, 30));
   map.push_back(Point(12, 30));
   map.push_back(Point(13, 30));
   map.push_back(Point(14, 30));
   map.push_back(Point(15, 30));
   map.push_back(Point(16, 30));
   map.push_back(Point(17, 30));
   map.push_back(Point(18, 30));
   map.push_back(Point(19, 30));
   map.push_back(Point(20, 30));
   map.push_back(Point(21, 30));
   map.push_back(Point(22, 30));
   map.push_back(Point(23, 30));
   map.push_back(Point(24, 30));
   map.push_back(Point(25, 30));
   map.push_back(Point(26, 30));
   map.push_back(Point(27, 30));
   map.push_back(Point(28, 30));
   map.push_back(Point(29, 30));
   map.push_back(Point(30, 30));
}
void Map::PrintInitmap()//遍历围墙,即打印出来
{
	
	for (vector<Point>::iterator it=map.begin();it!=map.end();it++)
	{
		it->point_square();
		Sleep(10);
	}//这里it可以看成指针
	
	基于范围的for循环,point是一个引用变量
	对容器中每个元素进行相同的操作
	//for (auto& point : map)
	//{
	//	point.point_square();
	//	Sleep(10);//调用Sleep函数可营造动画效果
	//}


}

Food类:

1.函数:
一个构造函数:
三个打印函数:(只要食物位置合理,即进行打印,否则退出循环。)
三个接口函数: (只是为类外访问私有成员提供接口。)

2.调用关系:food类里面的所有函数都只在control类中PlayGame()中被调用

Food.h

#pragma once
#include"snake.h"
class Snake;
class Food
{
	
	private:
	int cnt;              //记录连续吃到多少次食物
	bool flash_flag;      //闪烁标记
	bool big_flag;		  //是否有限时食物标记
	int m_x, m_y;		  //小食物坐标
	int big_x, big_y;     //限时食物坐标
	int progress_bar;	  //限时食物进度条
	friend class Snake;

	public:
	Food() :cnt(0), flash_flag(false), big_flag(false),m_x(0),m_y(0),big_x(0),big_y(0),progress_bar(0) {}
	
	void DrowFood(Snake& snake);	  //绘制小食物
	void DrowBigFood(Snake& snake);	  //绘制限时食物
	void FlashBigFood();  //限时食物动画
	
	bool GetBigFlag();	  //判断是否有限时食物
	int GetCnt();		  //返回连续吃到的小食物次数
	int GetProgress();	  //返回吃到限时食物得到的分数

};

food.cpp


```bash

```cpp
```cpp
#include"food.h"
#include<iostream>
using namespace std;
#include"windows.h"

void Food::DrowFood(Snake& csnake)//绘制小食物,之所以传递蛇,是因为要判断蛇和食物是否重叠。
{
	while (true)
	{
		int r_x = rand() % (29 - 2 + 1) + 2;	//取【2—29】的随机数
		int r_y = rand() % (29 - 2 + 1) + 2;	
		bool flag = false;
		for (auto& point : csnake.snake)		//遍历deque容器,判断是否有蛇的坐标和食物坐标重叠。
		{
			if ((point.GetX() == r_x && point.GetY() == r_y) || (point.GetX() == big_x && point.GetY() == big_y))
			{
				flag = true;
				break;
			}
		}
		if (flag)						//若重叠,则结束当前while循环。
		{
			continue;
		}
		else
		{
			m_x = r_x;							//以下打印坐标
			m_y = r_y;
			SetCursorPosition(m_x, m_y);
			SetColor(13);
			cout << "★";						//每打印5次小食物,则打印一次限时食物
			cnt++;
			cnt = cnt % 5;
			if (cnt == 0)
			{
				DrowBigFood( csnake);
			}
			break;
		}
	}
}

void Food::DrowBigFood(Snake& csnake)//绘制限时食物
{
	SetCursorPosition(2, 33);
	SetColor(11);
	cout << "******************************************";
	progress_bar = 42;

	while (true)
	{
		int r_x = rand() % (29 - 2 + 1) + 2;
		int r_y = rand() % (29 - 2 + 1) + 2;
		bool flag = false;
		for (auto& point : csnake.snake)
		{
			if ((point.GetX() == r_x && point.GetY() == r_y) || (r_x == m_x && r_y == m_y))	//判断随机坐标是否会和这个蛇的坐标,或者和前一个小食物坐标重合。
			{
				flag = true;
				break;
			}
		}
		if (flag)
		{
			continue;
		}
		else
		{
			big_x = m_x;
			big_y = r_y;
			SetCursorPosition(big_x, big_y);
			SetColor(18);
			cout << "■";
			flash_flag = true;
			big_flag = true;
		}
		break;
	}
}



void Food::FlashBigFood()	//限时食物闪烁
{
	SetCursorPosition(big_x, big_y);
	SetColor(18);
	if (flash_flag)
	{
		cout << " ";
		flash_flag = false;
	}
	else
	{
		cout<< "■";
		flash_flag = true;
	}
	SetCursorPosition(23,33);
	SetColor(11);
	for (int i = 42; i >= progress_bar; --i)//进度条缩短
		std::cout << "\b \b";
	--progress_bar;
	if (progress_bar == 0) 
	{
		SetCursorPosition(big_x, big_y);
		std::cout << "  ";
		SetCursorPosition(2, 33);
		std::cout << "                                          ";//用空格去掉进度条

		big_flag = false;
		big_x = 0;
		big_y = 0;
	
	}
	
}

bool Food::GetBigFlag()
{
	return big_flag;
}


int Food::GetCnt()
{
	return cnt;
}


int Food::GetProgress()
{
	return progress_bar;

}

Snake类:

1.函数:
2.载体:用deque容器(双端队列),方便在NormalMove()中实现蛇的移动
2.调用:所有函数都在control类中PlayGame()中被调用
Snake.h:

#pragma once
#include<deque>
#include"point.h"
#include"food.h"
using namespace std;
class Food;
class Snake
{
public:
	enum Direction { UP, DOWN, LEFT, RIGHT };
	Snake()
	{
		snake.emplace_back(14,8);
		snake.emplace_back(14, 9);
		snake.emplace_back(14, 10);
		dir = Direction::DOWN;
	}
	void InitSnake();	//初始化蛇
	void Move();		//增长
	void NormalMove();	//正常移动
	bool OverEdge();	//判断是否碰撞墙体
	bool HitItself();	//判断是否撞到自己
	bool ChangeDir();	//判断是否改变方向
	bool GetFood(const Food& cfood);	    //判断是否吃到小食物
	bool GetBigFood( Food& cfood);		//判断是否吃到限时食物



private:
	deque<Point>snake;
	Direction dir;
	friend class Food;
};

Snake.cpp

#include "startflash.h"
#include <windows.h>

void startflash::PrintFirst()//蛇从左边出现到完全出现的过程,
{
    //明白了
    for (auto& point : startsnake)
    {
        point.point_square();
        Sleep(speed);//sleep():延时,执行挂起一段时间,也就是等待一段时间在继续执行,,
        //这样就有蛇在移动了的效果,因为直接打印点,太快了,一下子全部打出来了,通过Sleep(),延时打印,就好像在动
    }
}

//下面几个函数要好好理解
void startflash::PrintSecond()//蛇从左向右移动的过程
{
    //懂啦
    for (int i = 10; i != 40; ++i)//蛇头需要从10 移动到40,因为屏幕设置就是41*32,
    {
        /*计算蛇头的下一个位置,并将其压入startsnake中,绘制出来,将蛇尾去掉*/
        int j = (((i - 2) % 8) < 4) ? (15 + (i - 2) % 8) : (21 - (i - 2) % 8);
        //15+(i-2)%8 :往下降
        //21-(i-2)%8 :往上升
        startsnake.emplace_back(Point(i, j));//双端队列,放入队列的后面,实际上在屏幕上是蛇头,也就是最右方
        startsnake.back().point_square();//最后一个元素打印出来,也就是蛇头打印出来,
        startsnake.front().Clear();//然后清除屏幕上的一个点,也就是屏幕最左边的,即蛇尾
        startsnake.pop_front();//从队列中删除,即保证蛇的长度不变
        Sleep(speed);
    }
}

void startflash::PrintThird()//蛇从接触右边到消失的过程
{
    //懂啦
    while (!startsnake.empty() || textsnake.back().GetX() < 33) //当蛇还没消失或文字没移动到指定位置
    {
        if (!startsnake.empty()) //如果蛇还没消失,继续移动
        {
            startsnake.front().Clear();//清除屏幕最左边的,将最左边的出队
            startsnake.pop_front();
        }
        ClearText();//清除已有文字,
        PrintText();//文字SNAKE开始慢慢出现
        //这里其实就是,先把显示的文字,直接用空格清除,但是在ClearText()时,已经显示的文字会被空格代替,并且会把所有文字向右移动一格
        Sleep(speed);
    }
}
void startflash::PrintText()
{
    //懂啦
    for (auto& point : textsnake)
    {
        if (point.GetX() >= 0)
            point.point_square();//只显示X大于0的位置
    }
}
void startflash::ClearText()
{
    //懂啦
    for (auto& point : textsnake) //把在屏幕上显示的文字,SNAKE全用空格覆盖,覆盖后再把所有的点往右移一格
    {
        if (point.GetX() >= 0)
            point.Clear();//清除已经显示的文字,也就是x>=0 的文字
        point.change_position(point.GetX() + 1, point.GetY());
    }
}

void startflash::Action()
{
    PrintFirst();
    PrintSecond();
    PrintThird();
}

startflash.h


```cpp
#pragma once
#include <deque>
#include <vector>
#include "point.h"

class startflash
{
public:
    startflash() : speed(35) {
        startsnake.emplace_back(Point(0, 14));//Éß,蛇刚开始的像v字形一样
        startsnake.emplace_back(Point(1, 14));
        startsnake.emplace_back(Point(2, 15));
        startsnake.emplace_back(Point(3, 16));
        startsnake.emplace_back(Point(4, 17));
        startsnake.emplace_back(Point(5, 18));
        startsnake.emplace_back(Point(6, 17));
        startsnake.emplace_back(Point(7, 16));
        startsnake.emplace_back(Point(8, 15));
        startsnake.emplace_back(Point(9, 14));

        textsnake.emplace_back(Point(-26, 14));//S,刚开始SNAKE的点在X轴的负半轴
        textsnake.emplace_back(Point(-25, 14));
        textsnake.emplace_back(Point(-27, 15));
        textsnake.emplace_back(Point(-26, 16));
        textsnake.emplace_back(Point(-25, 17));
        textsnake.emplace_back(Point(-27, 18));
        textsnake.emplace_back(Point(-26, 18));

        textsnake.emplace_back(Point(-23, 14));//N
        textsnake.emplace_back(Point(-23, 15));
        textsnake.emplace_back(Point(-23, 16));
        textsnake.emplace_back(Point(-23, 17));
        textsnake.emplace_back(Point(-23, 18));
        textsnake.emplace_back(Point(-22, 15));
        textsnake.emplace_back(Point(-21, 16));
        textsnake.emplace_back(Point(-20, 17));
        textsnake.emplace_back(Point(-19, 14));
        textsnake.emplace_back(Point(-19, 15));
        textsnake.emplace_back(Point(-19, 16));
        textsnake.emplace_back(Point(-19, 17));
        textsnake.emplace_back(Point(-19, 18));

        textsnake.emplace_back(Point(-17, 18));//A
        textsnake.emplace_back(Point(-16, 17));
        textsnake.emplace_back(Point(-15, 16));
        textsnake.emplace_back(Point(-14, 15));
        textsnake.emplace_back(Point(-14, 16));
        textsnake.emplace_back(Point(-13, 14));
        textsnake.emplace_back(Point(-13, 16));
        textsnake.emplace_back(Point(-12, 15));
        textsnake.emplace_back(Point(-12, 16));
        textsnake.emplace_back(Point(-11, 16));
        textsnake.emplace_back(Point(-10, 17));
        textsnake.emplace_back(Point(-9, 18));

        textsnake.emplace_back(Point(-7, 14));//K
        textsnake.emplace_back(Point(-7, 15));
        textsnake.emplace_back(Point(-7, 16));
        textsnake.emplace_back(Point(-7, 17));
        textsnake.emplace_back(Point(-7, 18));
        textsnake.emplace_back(Point(-6, 16));
        textsnake.emplace_back(Point(-5, 15));
        textsnake.emplace_back(Point(-5, 17));
        textsnake.emplace_back(Point(-4, 14));
        textsnake.emplace_back(Point(-4, 18));

        textsnake.emplace_back(Point(-2, 14));//E
        textsnake.emplace_back(Point(-2, 15));
        textsnake.emplace_back(Point(-2, 16));
        textsnake.emplace_back(Point(-2, 17));
        textsnake.emplace_back(Point(-2, 18));
        textsnake.emplace_back(Point(-1, 14));
        textsnake.emplace_back(Point(-1, 16));
        textsnake.emplace_back(Point(-1, 18));
        textsnake.emplace_back(Point(0, 14));
        textsnake.emplace_back(Point(0, 16));
        textsnake.emplace_back(Point(0, 18));
    }
    void PrintFirst();//蛇(v字形)出现再界面上
    void PrintSecond();//蛇从左移动到右,
    void PrintThird();//蛇逐渐消失
    void PrintText();//SNAKE文字的移动
    void ClearText();//SNAKE文字的消失
    void Action();
private:
    std::deque<Point> startsnake;//开始动画中的蛇
    std::vector<Point> textsnake;//开始动画中的文字
    int speed;//动画的速度
};

startflash.cpp

#include "startflash.h"
#include <windows.h>

void startflash::PrintFirst()//蛇从左边出现到完全出现的过程,
{
    //明白了
    for (auto& point : startsnake)
    {
        point.point_square();
        Sleep(speed);//sleep():延时,执行挂起一段时间,也就是等待一段时间在继续执行,,
        //这样就有蛇在移动了的效果,因为直接打印点,太快了,一下子全部打出来了,通过Sleep(),延时打印,就好像在动
    }
}

//下面几个函数要好好理解
void startflash::PrintSecond()//蛇从左向右移动的过程
{
    //懂啦
    for (int i = 10; i != 40; ++i)//蛇头需要从10 移动到40,因为屏幕设置就是41*32,
    {
        /*计算蛇头的下一个位置,并将其压入startsnake中,绘制出来,将蛇尾去掉*/
        int j = (((i - 2) % 8) < 4) ? (15 + (i - 2) % 8) : (21 - (i - 2) % 8);
        //15+(i-2)%8 :往下降
        //21-(i-2)%8 :往上升
        startsnake.emplace_back(Point(i, j));//双端队列,放入队列的后面,实际上在屏幕上是蛇头,也就是最右方
        startsnake.back().point_square();//最后一个元素打印出来,也就是蛇头打印出来,
        startsnake.front().Clear();//然后清除屏幕上的一个点,也就是屏幕最左边的,即蛇尾
        startsnake.pop_front();//从队列中删除,即保证蛇的长度不变
        Sleep(speed);
    }
}

void startflash::PrintThird()//蛇从接触右边到消失的过程
{
    //懂啦
    while (!startsnake.empty() || textsnake.back().GetX() < 33) //当蛇还没消失或文字没移动到指定位置
    {
        if (!startsnake.empty()) //如果蛇还没消失,继续移动
        {
            startsnake.front().Clear();//清除屏幕最左边的,将最左边的出队
            startsnake.pop_front();
        }
        ClearText();//清除已有文字,
        PrintText();//文字SNAKE开始慢慢出现
        //这里其实就是,先把显示的文字,直接用空格清除,但是在ClearText()时,已经显示的文字会被空格代替,并且会把所有文字向右移动一格
        Sleep(speed);
    }
}
void startflash::PrintText()
{
    //懂啦
    for (auto& point : textsnake)
    {
        if (point.GetX() >= 0)
            point.point_square();//只显示X大于0的位置
    }
}
void startflash::ClearText()
{
    //懂啦
    for (auto& point : textsnake) //把在屏幕上显示的文字,SNAKE全用空格覆盖,覆盖后再把所有的点往右移一格
    {
        if (point.GetX() >= 0)
            point.Clear();//清除已经显示的文字,也就是x>=0 的文字
        point.change_position(point.GetX() + 1, point.GetY());
    }
}

void startflash::Action()
{
    PrintFirst();
    PrintSecond();
    PrintThird();
}

controller.h

#pragma once
class Controller
{
public:
	Controller():speed(1), key(1), score(0) {}
	void Start() ;		//游戏开始界面
	void Select() ;		//选择模式
	void DrowGame() ;		//绘制界面
	int PlayGame() ;		//玩游戏
	void UpdateScore(const int& tem) ;	//更新分数
	void RewriteScore() ;	//更新的分数输入到屏幕上
	int Menu() ;			//菜单
	void Game() ;			//整个游戏入口
	int GameOver() ;		//绘制游戏结束界面


private:
	int speed;
	int key;
	int score;
};

controller.cpp

1).controller类里面要调用许多其他的类的函数,它会声明的时一个指向类对象的指针。传递参数时也是一个对象,在DrawFood的函数里的参数形式应该也对应Snake的对象。申明指针类的对象和声明普通对象不同在于,指针类需要-> 来访问成员变量以及函数,另外需要自己来delete释放内存,而且传递参数时永远都是4个字节,也就是传递参数速度会快一些,另外它还能实现多态

2). RewriteScore()函数,就是为了保证在输出的时候以右对齐的方式输出。

3).会不会有人在想,蛇移动的快慢是怎么设置的,其实是在选择模式时,不同的模式有个对应的Key值,不同的key值会 对应不同的speed,每次蛇在移动的时候,想想之前是怎么制造动态效果的,其实就是,通过Sleep()函数来做到的,Sleep(speed)这样就可以控制速度啦。

#include"controller.h"
#include<iostream>
#include"food.h"
#include"map.h"
#include"tool.h"
#include"windows.h"
#include "controller.h"
#include "snake.h"
#include <conio.h>
#include <time.h>
#include"startflash.h"

using namespace std;

void Controller::Start()//游戏开始界面
{
    SetWindowSize(41, 32);//设置窗口大小

    SetColor(2);//设置开始动画颜色,2对应蛇的颜色,也就是蓝色
    startflash* start = new startflash();//动态分配一个StartInterface类start,
    //new StartInterface() : 点就开始构造好了
    start->Action();//开始动画
    delete start;//释放内存空间
    /*设置关标位置,并输出提示语,等待任意键输入结束*/
    //文字 "请按任意键继续"   是system("pause"):的效果

    SetCursorPosition(13, 26);
    std::cout << "Press any key to start... ";//
    SetCursorPosition(13, 27);
    system("pause");//暂停窗口,让用户按键,用户按键后,Start()函数就结束了-》Select()函数

}	
void Controller::Select()//选择模式
{
    //初始化选择界面
    SetColor(3);
    SetCursorPosition(13,26);
    cout << "                          ";
    SetCursorPosition(13, 27);
    cout << "                          ";
    SetCursorPosition(6, 21);
    cout << "请选择游戏难度";
    SetCursorPosition(2,22);
    cout << "选择:上下键  确认:回车";
    SetCursorPosition(27,22);
    SetBackColor(); //默认第一个设置背景颜色
    cout << "简单模式";
    SetCursorPosition(27, 24);
    SetColor(3);
    cout << "普通模式";
    SetCursorPosition(27, 26);
    cout << "困难模式";
    SetCursorPosition(27, 28);
    cout << "炼狱模式";
    SetCursorPosition(0,31);
    score = 0;

    //选择
    int ch ;
    key = 1;
    bool flag = false;
    while ((ch = _getch()))
    {
        switch (ch)
        {
        case 72://UP键
            if (key > 1)
            {
                switch (key)
                {
                case 2:
                    SetCursorPosition(27, 22);
                    SetBackColor();
                    cout << "简单模式";
                    SetCursorPosition(27, 24);
                    SetColor(3);
                    cout << "普通模式";
                    key--;
                    break;

                case 3:
                    SetCursorPosition(27, 24);
                    SetBackColor();
                    cout << "普通模式";
                    SetCursorPosition(27, 26);
                    SetColor(3);
                    cout << "困难模式";
                    key--;
                    break;

                case 4:
                    SetCursorPosition(27, 26);
                    SetBackColor();
                    cout << "困难模式";
                    SetCursorPosition(27, 28);
                    SetColor(3);
                    cout << "炼狱模式";
                    key--;
                    break;

                default:
                    break;
                }
            }
        break;
        case 80://DOWN键
            if (key < 4)
            {
                switch (key)
                {
                case 1:
                    SetCursorPosition(27, 24);
                    SetBackColor();
                    cout << "普通模式";
                    SetCursorPosition(27, 22);
                    SetColor(3);
                    cout << "简单模式";
                    key++;
                    break;

                case 2:
                    SetCursorPosition(27, 26);
                    SetBackColor();
                    cout << "困难模式";
                    SetCursorPosition(27, 24);
                    SetColor(3);
                    cout << "普通模式";
                    key++;
                    break;

                case 3:
                    SetCursorPosition(27, 28);
                    SetBackColor();
                    cout << "炼狱模式";
                    SetCursorPosition(27, 26);
                    SetColor(3);
                    cout << "困难模式";
                    key++;
                    break;

                default:
                    break;
                }
            }
            break;
            case 13://回车键
                flag = true;
                break;
            
            default:
            break;   
        }
        if (flag) break;//输入Enter回车键确认,退出检查输入循环

        SetCursorPosition(0, 31);//将光标置于左下角,避免关标闪烁影响游戏体验
    }
    //while循环结束,选择难度模式结束
    //根据所选选项设置蛇的移动速度,speed值越小,速度越快
    switch (key)
    {
    case 1:
        speed = 135;
        break;
    case 2:
        speed = 100;
        break;
    case 3:
        speed = 60;
        break;
    case 4:
        speed = 30;
        break;
    default:
        break;
    }
    //结束选择->DrawGame();
}

void Controller::DrowGame()//绘制界面
{
    system("cls");
    //***绘制地图****
    Map* point = new Map;
    point->PrintInitmap();
    delete point;

    //***绘制侧边栏***
    SetColor(3);
    SetCursorPosition(40,1);
    cout << "贪吃蛇";
    SetCursorPosition(39, 2);
    cout << "Greed Snake";
    SetCursorPosition(37,4);
    cout << "难度:";
    SetCursorPosition(40, 4);
    switch (key)
    {
    case 1:
        cout << "简单模式";
        break;
    case 2:
        cout << "普通模式";
        break;
    case 3:
        cout << "困难模式";
        break;
    case 4:
        cout << "炼狱模式";
        break;
    default:
        break;
    }
    SetCursorPosition(37,7);
    cout << "得分:";
    SetCursorPosition(40, 7);
    cout << "0";
    SetCursorPosition(37,10);
    cout << "操作:";
    SetCursorPosition(40,10);
    cout << "移动:方向键";
    SetCursorPosition(40, 12);
    cout << "暂停:Esc";
}

int Controller::PlayGame()//玩游戏
{
    //*****初始化蛇和食物,即打印出来
    Snake* csnake = new Snake();
    Food* food = new Food();
    SetColor(6);
    csnake->InitSnake(); srand((unsigned)time(NULL));//设置随机数种子
    food->DrowFood(*csnake);    //解引用传递对象进去,引用方式接收

    //****游戏循环
    while (csnake->HitItself() && csnake->OverEdge())
    {
        //如果按下了Esc键
        if (!csnake->ChangeDir())
        {
            int tmp = Menu();//调用菜单,返回值:1,2,3赋给tmp
            switch (tmp)
            {
            case 1://继续游戏
                break;

            case 2://重新开始
                delete csnake;
                delete food;
                return 1;

            case 3://退出游戏
                delete csnake;
                delete food;
                return 2;

            default:
                break;
            }

        }
        //如果吃到普通食物
        if (csnake->GetFood(*food)==true) //吃到食物,传递指针类的对象
        {
            csnake->Move();//蛇增长
            UpdateScore(1);//更新分数,1为分数权重,每次加上key*10,key是对应难度
            RewriteScore();//重新绘制分数
            food->DrowFood(*csnake);//绘制新食物
        }
        else
        {
            csnake->NormalMove();
        }

        //如果吃到限时食物
        if (csnake->GetBigFood(*food))
        {
            csnake->Move();
            UpdateScore(food->GetProgress()/5);
            RewriteScore();
        }
        if (food->GetBigFlag())
        {
            food->FlashBigFood();
        }
        Sleep(speed);
    }
    delete csnake;
    delete food;
    int tmp = GameOver();
    switch (tmp)
    {
    case 1:
        return 1;//重新开始
    case 2:
        return 2;//退出游戏
    default:
        return 2;
    }

}

void Controller::UpdateScore(const int& tem)//更新分数
{
    score += 10 * key * tem;
}
void Controller::RewriteScore()//更新的分数输入到屏幕上
{
    SetCursorPosition(40,7);
    SetColor(11);
    int bit = 0;
    int tmp = score;
    while (tmp != 0)
    {
        ++bit;
        tmp /= 10;
    }
    for (int i = 0; i < (6 - bit); ++i)
    {
        std::cout << " ";
    }
    std::cout << score;

}
int Controller::Menu()//菜单
{
    SetCursorPosition(37,17);
    SetColor(11);
    cout << "菜单:";
    Sleep(100);
    SetCursorPosition(40, 17);
    SetBackColor();
    cout << "继续游戏";
    Sleep(100);
    SetCursorPosition(40, 19);
    SetColor(11);
    cout << "重新开始";
    Sleep(100);
    SetCursorPosition(40, 21);
    SetColor(11);
    cout << "退出游戏";
    SetCursorPosition(0, 31);

    int ch;
    int tmp_key = 1;
    bool flag = false;
    while ((ch=_getch()))
    {
        switch (ch)
        {
        case 72:
            if (tmp_key > 1)
            {
                switch (tmp_key)
                {
                case 2:
                    SetCursorPosition(40,11);
                    SetBackColor();
                    std::cout << "继续游戏";
                    SetCursorPosition(40,13);
                    SetColor(11);
                    std::cout << "重新开始";
                    --tmp_key;
                    break;
                case 3:
                    SetCursorPosition(40,13);
                    SetBackColor();
                    std::cout << "重新开始";
                    SetCursorPosition(40,15);
                    SetColor(11);
                    std::cout << "退出游戏";

                    --tmp_key;
                    break;
                }
            }
            break;

        case 80:
            if (tmp_key < 3)
            {
                switch (tmp_key)
                {
                case 1:
                    SetCursorPosition(40,13);
                    SetBackColor();
                    std::cout << "重新开始";
                    SetCursorPosition(40,11);
                    SetColor(11);
                    std::cout << "继续游戏";

                    ++tmp_key;
                    break;
                case 2:
                    SetCursorPosition(40,15);
                    SetBackColor();
                    std::cout << "退出游戏";
                    SetCursorPosition(40,13);
                    SetColor(11);
                    std::cout << "重新开始";
                    ++tmp_key;
                    break;
                }
            }
            break;
           

        case 13:
            flag = true;
            break;
        default:
            break;
        }
        if (flag)
            break;
        SetCursorPosition(0, 31);
    }//while结束
    if (tmp_key == 1) //选择继续游戏,则将菜单擦除
    {
        SetCursorPosition(37,11);
        std::cout << "      ";
        SetCursorPosition(40,11);
        std::cout << "        ";
        SetCursorPosition(40,13);
        std::cout << "        ";
        SetCursorPosition(40,15);
        std::cout << "        ";
    }
    return tmp_key;
}

void Controller::Game()//整个游戏入口
{
    Start();//开始界面
    while (true)//死循环
    {

        Select();//选择界面
        DrowGame();//绘制游戏界面
        int tmp = PlayGame();//开启游戏循环,当重新开始或退出游戏时,结束循环并返回值给tmp:1,2
        if (tmp == 1) //返回值为1时重新开始游戏
        {
            system("cls");
            continue;
        }
        else if (tmp == 2) //返回值为2时退出游戏
        {
            break;
        }
        else
        {
            break;
        }
    
    }

}
int Controller::GameOver()//绘制游戏结束界面
{
    /*绘制游戏结束界面*/
    Sleep(500);
    SetColor(11);
    SetCursorPosition(6, 8);
    std::cout << "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━";
    Sleep(30);
    SetCursorPosition(5, 9);
    std::cout << " ┃               Game Over !!!              ┃";
    Sleep(30);
    SetCursorPosition(5, 10);
    std::cout << " ┃                                          ┃";
    Sleep(30);
    SetCursorPosition(5, 11);
    std::cout << " ┃              很遗憾!你挂了              ┃";
    Sleep(30);
    SetCursorPosition(5, 12);
    std::cout << " ┃                                          ┃";
    Sleep(30);
    SetCursorPosition(5, 13);
    std::cout << " ┃             你的分数为:                 ┃";
    SetCursorPosition(20, 13);
    std::cout << score;
    Sleep(30);
    SetCursorPosition(5, 14);
    std::cout << " ┃                                          ┃";
    Sleep(30);
    SetCursorPosition(5, 15);
    std::cout << " ┃   是否再来一局?                         ┃";
    Sleep(30);
    SetCursorPosition(5, 16);
    std::cout << " ┃                                          ┃";
    Sleep(30);
    SetCursorPosition(5, 17);
    std::cout << " ┃                                          ┃";
    Sleep(30);
    SetCursorPosition(5, 18);
    std::cout << " ┃    嗯,好的        不了,还是学习有意思  ┃";
    Sleep(30);
    SetCursorPosition(5, 19);
    std::cout << " ┃                                          ┃";
    Sleep(30);
    SetCursorPosition(5, 20);
    std::cout << " ┃                                          ┃";
    Sleep(30);
    SetCursorPosition(6, 21);
    std::cout << "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━";

    Sleep(100);
    SetCursorPosition(8, 18);
    SetBackColor();
    std::cout << "嗯,好的";//默认选中,”嗯,好的“
    SetCursorPosition(0, 31);

    int ch;
    int tmp_key = 1;
    bool flag = false;
    while ((ch = _getch()))
    {
        switch (ch)
        {
        case 75://LEFT
            if (tmp_key > 1)
            {
                SetCursorPosition(8, 18);
                SetBackColor();
                std::cout << "嗯,好的";
                SetCursorPosition(16, 18);
                SetColor(11);
                std::cout << "不了,还是学习有意思";
                --tmp_key;
            }
            break;

        case 77://RIGHT
            if (tmp_key < 2)
            {
                SetCursorPosition(16, 18);
                SetBackColor();
                std::cout << "不了,还是学习有意思";
                SetCursorPosition(8, 18);
                SetColor(11);
                std::cout << "嗯,好的";
                ++tmp_key;
            }
            break;

        case 13://Enter
            flag = true;
            break;

        default:
            break;
        }//switch结束

        SetCursorPosition(0, 31);
        if (flag)       
            break;
    }//while结束

    SetColor(11);
    switch (tmp_key)//判断重新开始,还是结束
    {
    case 1:
        return 1;//重新开始,也就是,“嗯,好的”
    case 2:
        return 2;//退出游戏,也就是”不了,还是学习有意思“
    default:
        return 1;
    }
}


main.cpp

#include"controller.h"
int main()
{
	Controller k;
	k.Game();
	return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值