欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

c/c++ 贪吃蛇控制台版

程序员文章站 2022-06-23 22:05:04
贪吃蛇控制台版(操作系统win7 64位;编译环境gcc, vs2017通过,其它环境未测试 不保证一定通过) 运行效果: 代码应该还可以 做一些精简化处理!!!暂时先就这样了; save_date()保存数据函数对内存做了一定优化处理,以达到使用较小内存可永久运行程序。 (虽然现在的电脑内存根本不 ......

贪吃蛇控制台版(操作系统win7 64位;编译环境gcc, vs2017通过,其它环境未测试 不保证一定通过)

运行效果:

c/c++ 贪吃蛇控制台版

 

 

#include <iomanip>
#include <windows.h>
#include <conio.h>
using namespace std;

HANDLE hOut = GetStdHandle(STD_OUTPUT_HANDLE);//全局句柄
class snake;
void Init_Console();//控制台初始化
void gotoPos(SHORT x = 0, SHORT y = 0);//光标坐标控制
void Init_Map();//画边框
void KeyConctrl(snake &,int);//键盘控制函数
void is_gameover();//结束提示
void Prompt_info(int, int);//提示信息
void dis_date(int, int, double, int);//得分信息

bool gameOver = false;
bool withdraw = false;

class snake
{
private:
    bool flash;
    int speed, length, print_bit, clear_bit;
    COORD in_Pos, bit_Pos;
    COORD _Pos[255];
    enum direction{go_stop = 0, go_left, go_right, go_up, go_down}dir;
    public:
    snake(SHORT x = 9, SHORT y = 5)
    {
        clear_bit = print_bit = length = speed = 0;
        in_Pos.X = x; in_Pos.Y = y; bit_Pos.X = 11; bit_Pos.Y = 8;
        flash = true ;
        dir = go_stop;
        _Pos[0].X = in_Pos.X;
        _Pos[0].Y = in_Pos.Y;
    }
    ~snake(){}
    void up_speed()
    {
        if(this->speed < 5)(this->speed)++;


    }
    double get_speed()
    {
        return this->speed;
    }
    int get_length()
    {
        return this->length;
    }
//
    void dir_control(char _dir)
    {
        switch(_dir)
        {
        case 's': this->dir = go_stop;
            break;
        case 'l': if(this->dir != go_right)this->dir = go_left;
            break;
        case 'r': if(this->dir != go_left)this->dir = go_right;
            break;
        case 'u': if(this->dir != go_down)this->dir = go_up;
            break;
        case 'd': if(this->dir != go_up)this->dir = go_down;
            break;

        }
    }

    //光标位置
    void setPos(COORD pos)
    {
        SetConsoleCursorPosition(hOut, pos);
    }

    //碰撞检测
    void check_bit()
    {
        if(in_Pos.X == bit_Pos.X && in_Pos.Y == bit_Pos.Y)
        {
            length++;
            if((length % 5 == 0))
            {
                if(this->speed < 5)this->speed++;
            }
            if(length == 254)
            {
                cout << "游戏通关!" ;
            }
            do
            {
                srand(time(NULL));
                bit_Pos.X = 3 + (rand()%20)*2;
                bit_Pos.Y = 2 + rand()%20;
            }while(check_snk(bit_Pos));
        }
        else
        {
            cle();
            clear_bit++;
        }
    }
    //撞蛇 撞边检测
    bool check_snk(COORD snk_Pos)
    {
        //边界检测
        if(snk_Pos.Y <= 1 || (snk_Pos.Y >= 23) || (snk_Pos.X <= 1) || snk_Pos.X >= 45)
        {
            return true;
        }
        for(int i = clear_bit; i <= print_bit; i++)
        {
           if(_Pos[i].X == snk_Pos.X && _Pos[i].Y == snk_Pos.Y) return true;
        }
        return false;
    }

    //显示
    void dis()
    {
        if(!flash)
        {
            setPos(bit_Pos);
            SetConsoleTextAttribute(hOut, 0x0e);
            cout << " ";
            flash = true;
        }
        else
        {
            setPos(bit_Pos);
            SetConsoleTextAttribute(hOut, 0x0e);
            cout << "■";
            flash = false;
        }
        setPos(in_Pos);
        SetConsoleTextAttribute(hOut, 0x09);
        cout << "■";

    }
    void cle()
    {

        setPos(_Pos[clear_bit]);
        SetConsoleTextAttribute(hOut, 0x05);
        cout << " ";
    }

    void save_date()
    {

        if(print_bit == 254)
        {
            for(int i = 0; i <= length; i++)
            {
                _Pos[i].X = _Pos[clear_bit + i].X;
                _Pos[i].Y = _Pos[clear_bit + i].Y;
            }
            clear_bit = 0;
            print_bit = length;
        }
        print_bit++;
        _Pos[print_bit].X = in_Pos.X;
        _Pos[print_bit].Y = in_Pos.Y;

    }

    //    //移动
    bool move()
    {
            switch(this->dir)
            {
            case go_stop:
                break;
            case go_left:
                in_Pos.X -= 2;
                if(check_snk(in_Pos))
                {
                    return true;
                }
                dis();
                save_date();
                check_bit();
                break;
            case go_right:
                in_Pos.X += 2;
                if(check_snk(in_Pos))
                {
                    return true;
                }
                dis();
                save_date();
                check_bit();
                break;
            case go_up:
                in_Pos.Y--;
                if(check_snk(in_Pos))
                {
                    return true;
                }
                dis();
                save_date();
                check_bit();
                break;
            case go_down:
                in_Pos.Y++;
                if(check_snk(in_Pos))
                {
                    return true;
                }
                dis();
                save_date();
                check_bit();
                break;
            }
            return false;
    }
};

int main()
{
    do
    {
        Init_Console();
        Init_Map();
        Prompt_info(3, 3);
        snake s(27, 11);
        clock_t t_in, t_out;
        t_in = clock();
        s.dis();
        //
        while (!gameOver)
        {
            if (_kbhit())
            {
                KeyConctrl(s, _getch());
            }

            t_out = clock();
            dis_date(3, 5, s.get_speed(), s.get_length());
            if (t_out - t_in > ((0.25 - (s.get_speed() / 25)) * CLOCKS_PER_SEC))
            {
                t_in = t_out;
                gameOver = s.move();
                if (gameOver)
                {
                    is_gameover();
                }
            }
            Sleep(10);
        }
        //
        while (gameOver)
        {
            if (_kbhit())
            {
                switch (_getch())
                {
                case 'y':
                case 'Y':
                    gameOver = false;
                    system("cls");
                    break;
                case 'n':
                case 'N':
                    gameOver = false;
                    withdraw = true;
                    break;
                }
            }
            Sleep(10);
        }
    }while (!withdraw);
    gotoPos(15, 13);
    return 0;
}

//控制台初始化
void Init_Console()
{
     SetConsoleTitleA("Console_贪吃蛇");
     COORD dSiz = {80, 25};
     SetConsoleScreenBufferSize(hOut, dSiz);//设置窗口缓冲区大小
     CONSOLE_CURSOR_INFO _guan_biao = {1, FALSE};//设置光标大小,隐藏光标
     SetConsoleCursorInfo(hOut, &_guan_biao);
     system("color 0f");//设置画布颜色

}
//光标位置
void gotoPos(SHORT x, SHORT y)
{
    COORD pos = {x, y};
    SetConsoleCursorPosition(hOut, pos);
}
//画边框
void Init_Map()
{
    //SetConsoleTextAttribute(hOut, 0xF0); //设置前景色,背景色
    system("cls");
    //左边框
    for(int i = 0; i < 23 ; i++)
    {
        cout << endl << " ●";
    }
    //上边框
    gotoPos(3, 1);
    for(int i = 0; i < 21 ; i++)
    {
        cout << "●";
    }
    //下边框
    gotoPos(3, 23);
    for(int i = 0; i < 21 ; i++)
    {
        cout << "●";
    }
    //右边框
    for(SHORT i = 1; i <= 23 ; i++)
    {
        gotoPos(45, i);
        cout << "●";
    }
}
//键盘控制函数
void KeyConctrl(snake &_snk, int _key)
{
    switch(_key)
    {
    case ' ':
        _snk.dir_control('s');
        break;
    case 'w':
    case 'W':
    case 72: _snk.dir_control('u');
        break;
    case 'a':
    case 'A':
    case 75: _snk.dir_control('l');
        break;
    case 'd':
    case 'D':
    case 77: _snk.dir_control('r');
        break;
    case 's':
    case 'S':
    case 80: _snk.dir_control('d');
        break;
    case '+': _snk.up_speed();
        break;
    default: break;
    }
}
//结束提示
void is_gameover()
{

    gotoPos(17, 11);
    SetConsoleTextAttribute(hOut, 0xec);
    cout << "game over!";
    gotoPos(15, 12);
    cout << "Y重新开始/N退出";
    SetConsoleTextAttribute(hOut, 0x0f);

}
//提示信息
void Prompt_info(int _x, int _y)
{

    SetConsoleTextAttribute(hOut, 0xB);
    gotoPos(_x+47, _y+0);
    cout << "■游戏说明:";
    gotoPos(_x+51, _y+2);
    cout << "A.每得500分移速自动加1";
    gotoPos(_x+51, _y+3);
    cout << "B.可手动加速,最高移速5";
    gotoPos(_x+47, _y+5);
    cout << "■操作说明:";
    gotoPos(_x+51, _y+7);
    cout << "□向左移动:← A";
    gotoPos(_x+51, _y+8);
    cout << "□向右移动:→ D";
    gotoPos(_x+51, _y+9);
    cout << "□向下移动:↓ S";
    gotoPos(_x+51, _y+10);
    cout << "□向上移动:↑ W";
    gotoPos(_x+51, _y+11);
    cout << "□控制加速:+";
    gotoPos(_x+51, _y+12);
    cout << "□暂停游戏:空格";
    gotoPos(_x+51, _y+13);
    cout << "□开始游戏:任意方向键";
    gotoPos(_x+47, 22);
    cout <<"■By: Flowingwind 18.01.11";
}
//速度积分显示
void dis_date(int _x, int _y, double Sped, int Score)
{
    SetConsoleTextAttribute(hOut, 0xB);
    gotoPos(_x+47, _y+13);
    cout << setw(2) << "◆ 移动速度: ";
    SetConsoleTextAttribute(hOut, FOREGROUND_RED | FOREGROUND_INTENSITY);
    cout << Sped;
    gotoPos(_x+47, _y+14);
    SetConsoleTextAttribute(hOut, 0xB);
    cout << "◆ 当前积分: ";
    SetConsoleTextAttribute(hOut, FOREGROUND_RED | FOREGROUND_INTENSITY);
    cout << setw(2) << Score * 100;
}

 

代码应该还可以 做一些精简化处理!!!暂时先就这样了;

save_date()保存数据函数对内存做了一定优化处理,以达到使用较小内存可永久运行程序。

(虽然现在的电脑内存根本不用考虑这个,但想起我第一次玩贪吃蛇,还是在一款 掌机上玩的,有机会能拷贝上去也不错)

c/c++ 贪吃蛇控制台版