先说明下:本文来源: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;
}