贪吃蛇2

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);
    }
以上是边看别人的边记的笔记,但是在抄的过程中有疏漏【蛇吃到食物游戏就卡了】


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值