Code Blocks打开project像这次的,打开.cbp文件
这个编辑器有问题,我好好的代码硬生生要弄成乱七八糟的,不开心 -_-||
根据教程先看tool,point两个
point.h
#ifndef POINT_H
#define POINT_H
class Point
{
public:
Point(){};
Point(const int x,const int y):x(x),y(y){}
void Print();
void PrintCircular();
void Clear();
void ChangePosition(const int x,const int y);
bool operator== (const Point& point){return (point.x == this->x) && (point.y == this->y);}
int GetX(){return this->x;}
int GetY(){return this->y;}
private:
int x,y;
};
#endif // POINT_H
/*#ifndef POINT_H#define POINT_H
#endif //这些是将里面的内容规定只能在程序中被编译一次,因为在C、C++里面是不允许一个函数,类或者其他变量被编译多次的,所以使用这个头文件卫士就可以保证在程序中只进行一次编译//#if !defined(_POINT_H)这句表示如果_POINT_H没有被define过就定义那个类如果_POINT_H被define的话,就不用定义那个类了//#define _POINT_H后面没有值是因为没有必要,因为只需要判断 _POINT_H 是否被define过//为了防止重复调用文件。如在一个文件中已经#include <iostream>,在另一文件中也#include <iostream>,程序为了防止多次调用iostream.h这个头文件,估计在其前面就加入了类似#ifndef *** #define ***,***可以是任意的字符串。只是为了便于阅读等,一般***采用大写,字符串无点,只有下划线。例如此文件就是point.h
*/
tools.cpp
#include"tools.h"
#include<windows.h>
#include<stdio.h>
void SetWindowsSize(int cols,int lines)
{
system("title 贪吃蛇");
char cmd[30];
sprintf(cmd,"mode con cols=%d lines=%d",cols*2,lines);//一个图形■占两个字符,故宽度乘以2
system(cmd);
/*int system(char *command);//发出一个DOS命令 TITLE 设置 CMD.EXE 会话的窗口标题。system详解 头文件#include<windows.h>int sprintf( char *buffer, const char *format, [ argument] … );//sprintf 返回以format为格式argument为内容组成的结果被写入buffer 的字节数,结束字符‘\0’不计入内改变DOS窗口的尺寸:打开命令提示符cmd,键入mode con cols=100 lines=40则DOS窗口的尺寸将会变为40行100列的,cols最小值为13,lines最小值为1。在C语言中也可以通过system函数调用这个dos命令来实现这个功能。如:system("mode con cols=30 lines=20");*/
}
void SetCursorPosition(const int x,const int y)
{
COORD position;
/*COORD是Windows API中定义的一种结构【头文件#include<windows.h>】,表示一个字符在控制台屏幕上的坐标。其定义为:typedef struct _COORD {SHORT X; // horizontal coordinateSHORT Y; // vertical coordinate} COORD;GetStdHandle是一个Windows API函数,GetStdHandle()返回标准的输入、输出或错误的设备的句柄,也就是获得输入、输出/错误的屏幕缓冲区的句柄。SetConsoleCursorPosition() //参数1:控制台句柄;参数2:COORD结构存放的坐标*/
position.X = x*2;
position.Y = y;
SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE),position);
}
void Setcolor(int colorID)//设置文本颜色
{
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),colorID);
}
void SetBackColor()//设置文本背景色
{
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),
FOREGROUND_BLUE |
BACKGROUND_BLUE |
BACKGROUND_GREEN |
BACKGROUND_RED);
/*SetConsoleTextAttribute函数是靠一个字节的低四来控制前景色,高四位来控制背景色。*/
}
startinterface.h
#ifndef STARTINTERFACE_H
#define STARTINTERFACE_H
#include<deque>
#include<vector>
#include"point.h"
class StartInterface
{
private:
std::deque<Point>startsnake;
std::vector<Point>textsnake;
int speed;
public:
StartInterface():speed(35){
startsnake.emplace_back(Point(0,14));//snake
/*
emplace_back和push_back都是向容器内添加数据.
对于在容器中添加类的对象时, 相比于push_back,emplace_back可以避免额外类的复制和移动操作.
*/
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
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();
void PrintSecond();
void PrintThird();
void PrintText();
void ClearText();
void Action();
};
#endif // STARTINTERFACE_H
根据上面的代码描出点的大致位置,有利于进一步的分析
startinterface.cpp
#include"startinterface.h"
#include<windows.h>
void StartInterface::PrintFirst()//蛇从左边出现到完全出现的过程
{
for(auto& point: startsnake)
/*
在C++11标准的语法中,auto被定义为自动推断变量的类型。
如果要更改字符串中的字符值,我们必须将循环变量定义为引用类型.引用只是给定对象的另一个名称。当我们使用引用作为我们的控制变量时,该变量依次绑定到序列中的每个元素。
*/
{
point.Print();
Sleep(speed);
/*
执行挂起一段时间,头文件#include<windows.h>,返回值:若进程/线程挂起到参数所指定的时间则返回0,若有信号中断则返回剩余秒数,Sleep()单位为毫秒,sleep()单位为秒【百度百科】
*/
}
}
void StartInterface::PrintSecond()//蛇从左向右移动的过程
{
for(int i = 10;i != 40;++ i)//蛇头需要从10移动到40
{
int j = (((i-2)%8)<4)?(15+(i-2)%8):(21-(i-2)%8);//这个公式大概是因为把蛇分为两个线段,每个线段上的移动公式不一样
startsnake.emplace_back((Point(i,j)));
startsnake.back().Print();
startsnake.front().Clear();
startsnake.pop_front();
Sleep(speed);
}
}
void StartInterface::PrintThird()//蛇从接触右边到消失的过程
{
while(!startsnake.empty() || textsnake.back().GetX()<33)//当蛇还没有消失或者文字没移动到指定位置
{
if(!startsnake.empty())//如果蛇还没有消失,继续移动
{
startsnake.front().Clear();
startsnake.pop_front();
}
ClearText();
PrintText();
Sleep(speed);
}
}
void StartInterface::PrintText()
{
for(auto&point:textsnake)//清除的同时将文字整体向右移动一格
{
if(point.GetX()>=0)
point.Print();
point.ChangePosition(point.GetX()+1,point.GetY());
}
}
void StartInterface::Action()
{
PrintFirst();
PrintSecond();
PrintThird();
}
food.h
#ifndef FOOD_H
#define FOOD_H
#include"snake.h"
class Snake;
class Food
{
private:
int cnt;
bool flash_flag;//闪烁标记
bool big_flag;//是否有限时食物标记
int x,y;
int big_x,big_y;
int progress_bar;//限时食物进度条
friend class Snake;
/*
C++中的friend关键字其实做这样的事情:在一个类中指明其他的类(或者)函数能够直接访问该类中的private和protected成员。
Snake可以直接访问Food中private的成员 C++中的friend详细解析
*/
public:
Food():cnt(0),flash_flag(false),big_flag(false),x(0),y(0),big_x(0),big_y(0),progress_bar(0){}
void DrawFood(Snake&);
void DrawBigFood(Snake&);
int GetCnt();
void FlashBigFood();
bool GetBigFlag();
int GetProgressBar();
};
#endif // FOOD_H
snake.h
#ifndef SNAKE_H
#define SNAKE_H
#include<deque>
#include"point.h"
#include"food.h"
class Food;//声明?定义
class Snake
{
public:
enum Direction{UP,DOWN,LEFT,RIGHT};
/*
enum 枚举名{ 枚举值表 };
enum是枚举型 union是共用体,成员共用一个变量缓冲区。
枚举值是常量,不是变量
枚举元素本身由系统定义了一个表示序号的数值,从0开始顺序定义为0,1,2…。
*/
Snake()
{
snake.emplace_back(14,8);
snake.emplace_back(15,8);
snake.emplace_back(16,8);
direction = Direction::DOWN;
}
void InitSnake();
void Move();
void NormslMove();
bool OverEdge();
bool HitItself();
bool ChangeDirection();
bool GetFood(const Food&);
bool GetBigFood(Food&);
private:
std::deque<Point> snake;//蛇是Point的队列
Direction direction;//public enum Direction?
friend class Food;
};
#endif // SNAKE_H
map.h
#ifndef MAP_H
#define MAP_H
#include<vector>
#include"point.h"
class Map
{
private:
std::vector<Point> initmap;
public:
Map()
{
for(int i = 1;i <= 30;i ++)
initmap.emplace_back(Point(i,1));
/* initmap.emplace_back(Point(1,1));//可以用for循环
initmap.emplace_back(Point(2,1));
initmap.emplace_back(Point(3,1));
initmap.emplace_back(Point(4,1));
initmap.emplace_back(Point(5,1));
initmap.emplace_back(Point(6,1));
initmap.emplace_back(Point(7,1));
initmap.emplace_back(Point(8,1));
initmap.emplace_back(Point(9,1));
initmap.emplace_back(Point(10,1));
initmap.emplace_back(Point(11,1));
initmap.emplace_back(Point(12,1));
initmap.emplace_back(Point(13,1));
initmap.emplace_back(Point(14,1));
initmap.emplace_back(Point(15,1));
initmap.emplace_back(Point(16,1));
initmap.emplace_back(Point(17,1));
initmap.emplace_back(Point(18,1));
initmap.emplace_back(Point(19,1));
initmap.emplace_back(Point(20,1));
initmap.emplace_back(Point(21,1));
initmap.emplace_back(Point(22,1));
initmap.emplace_back(Point(23,1));
initmap.emplace_back(Point(24,1));
initmap.emplace_back(Point(25,1));
initmap.emplace_back(Point(26,1));
initmap.emplace_back(Point(27,1));
initmap.emplace_back(Point(28,1));
initmap.emplace_back(Point(29,1));
initmap.emplace_back(Point(30,1));*/
initmap.emplace_back(Point(1,2));
initmap.emplace_back(Point(30,2));
initmap.emplace_back(Point(1,3));
initmap.emplace_back(Point(30,3));
initmap.emplace_back(Point(1,4));
initmap.emplace_back(Point(30,4));
initmap.emplace_back(Point(1,5));
initmap.emplace_back(Point(30,5));
initmap.emplace_back(Point(1,6));
initmap.emplace_back(Point(30,6));
initmap.emplace_back(Point(1,7));
initmap.emplace_back(Point(30,7));
initmap.emplace_back(Point(1,8));
initmap.emplace_back(Point(30,8));
initmap.emplace_back(Point(1,9));
initmap.emplace_back(Point(30,9));
initmap.emplace_back(Point(1,10));
initmap.emplace_back(Point(30,10));
initmap.emplace_back(Point(1,11));
initmap.emplace_back(Point(30,11));
initmap.emplace_back(Point(1,12));
initmap.emplace_back(Point(30,12));
initmap.emplace_back(Point(1,13));
initmap.emplace_back(Point(30,13));
initmap.emplace_back(Point(1,14));
initmap.emplace_back(Point(30,14));
initmap.emplace_back(Point(1,15));
initmap.emplace_back(Point(30,15));
initmap.emplace_back(Point(1,16));
initmap.emplace_back(Point(30,16));
initmap.emplace_back(Point(1,17));
initmap.emplace_back(Point(30,17));
initmap.emplace_back(Point(1,18));
initmap.emplace_back(Point(30,18));
initmap.emplace_back(Point(1,19));
initmap.emplace_back(Point(30,19));
initmap.emplace_back(Point(1,20));
initmap.emplace_back(Point(30,20));
initmap.emplace_back(Point(1,21));
initmap.emplace_back(Point(30,21));
initmap.emplace_back(Point(1,22));
initmap.emplace_back(Point(30,22));
initmap.emplace_back(Point(1,23));
initmap.emplace_back(Point(30,23));
initmap.emplace_back(Point(1,24));
initmap.emplace_back(Point(30,24));
initmap.emplace_back(Point(1,25));
initmap.emplace_back(Point(30,25));
initmap.emplace_back(Point(1,26));
initmap.emplace_back(Point(30,26));
initmap.emplace_back(Point(1,27));
initmap.emplace_back(Point(30,27));
initmap.emplace_back(Point(1,28));
initmap.emplace_back(Point(30,28));
initmap.emplace_back(Point(1,29));
initmap.emplace_back(Point(30,29));
initmap.emplace_back(Point(1,30));
initmap.emplace_back(Point(30,30));
initmap.emplace_back(Point(2,30));
initmap.emplace_back(Point(3,30));
initmap.emplace_back(Point(4,30));
initmap.emplace_back(Point(5,30));
initmap.emplace_back(Point(6,30));
initmap.emplace_back(Point(7,30));
initmap.emplace_back(Point(8,30));
initmap.emplace_back(Point(9,30));
initmap.emplace_back(Point(10,30));
initmap.emplace_back(Point(11,30));
initmap.emplace_back(Point(12,30));
initmap.emplace_back(Point(13,30));
initmap.emplace_back(Point(14, 30));
initmap.emplace_back(Point(15, 30));
initmap.emplace_back(Point(16, 30));
initmap.emplace_back(Point(17, 30));
initmap.emplace_back(Point(18, 30));
initmap.emplace_back(Point(19, 30));
initmap.emplace_back(Point(20, 30));
initmap.emplace_back(Point(21, 30));
initmap.emplace_back(Point(22, 30));
initmap.emplace_back(Point(23, 30));
initmap.emplace_back(Point(24, 30));
initmap.emplace_back(Point(25, 30));
initmap.emplace_back(Point(26, 30));
initmap.emplace_back(Point(27, 30));
initmap.emplace_back(Point(28, 30));
initmap.emplace_back(Point(29, 30));
initmap.emplace_back(Point(30, 30));
}
void PrintInitmap();
};
#endif // MAP_H
对于控制台的界面,通过函数SetCursorPosition()选择位置,SetColor()设置文字颜色,SetBackColor()设置背景色代表当前的选中,由getch()获得按键值,判断是上下(左右)移动。
以垂直方向为例:(tmp或tmp_key记录现在选中的是哪一个,默认第一个)
Up:第一个不能在往上移动了,其他的在当前情况往上移动一个,即取消当前的背景色,把上一个带背景色地输出,tmp(tmp_key)--;
Down:最后一个不能往下移动,其他的在当前情况往下移,tmp(tmp_key)++;
用flag记录是否按了Enter键,如果按下,停止上下选择的循环。
例如:
int ch;
int tmp_key = 1;
bool flag = false;
while(ch = getch())
{
switch(ch)
{
case 72://up
if(tmp_key > 1)
{
switch(tmp_key)
{
case 2:
SetCursorPosition(34,21);
SetBackColor();
std::cout <<"继续游戏";
SetCursorPosition(34,23);
SetColor(11);
std::cout <<"重新开始";
--tmp_key;
break;
case 3:
SetCursorPosition(34,23);
SetBackColor();
std::cout << "重新开始";
SetCursorPosition(34,25);
SetColor(11);
std::cout << "退出游戏";
--tmp_key;
break;
}
}
break;
case 80://down
if(tmp_key < 3)
{
switch(tmp_key)
{
case 1:
SetCursorPosition(34,23);
SetBackColor();
std::cout << "重新开始";
SetCursorPosition(34,21);
SetColor(11);
std::cout << "继续游戏";
++ tmp_key;
break;
}
}
break;
case 13://enter
flag = true;
break;
default:
break;
}
if(flag)
break;
SetCursorPosition(0,31);
}
以上是边看别人的边记的笔记,但是在抄的过程中有疏漏【蛇吃到食物游戏就卡了】