您的位置:首页 > 编程语言 > C语言/C++

c++控制台贪吃蛇

2017-01-25 15:28 323 查看
网上看到一篇c++控制台实现贪吃蛇的博客,感觉思路很容易理解很适合当一个小项目练习。代码粘贴在下边(非我原创)。

用到的win32函数:_kbhit()检测有没有键盘输入,有返回1,没有返回0

                              _getch()获取一个输入字符

                              System("cls")  清屏

类:1 frame 框架类,是整个游戏的框架

    2 snake 蛇本身

    3 movement 运动

    

问题:1 让蛇动起来的方法就是不断地刷新屏幕(system("cls")->move->displayFrame),产生一种运动的感觉。

      2 蛇有蛇头和蛇尾,整个蛇用链表表示,当head坐标等于food,就吃到了食物,那么就addHead,相当于把这个位置加到了蛇上。

        注意一旦清屏,意味着已经进入了while(!_khbit)循环,运动方向就定了,下一次要到达的坐标已经知道了。

        如果没吃到食物就整个链表向dir方向推移,加头删尾。

      3  判断当蛇撞到自身或者墙,则GG,撞自身需要遍历一遍蛇。

      

#include<Windows.h>

#include <ctime>  

#include <cstdlib>   

#include <conio.h>  

#include<vector>

#include<string>

#include<iostream>

using namespace std;

enum Direction { UP, DOWN, LEFT, RIGHT };

class Frame {

public:

    friend class Snake;

    friend class Movement;

    unsigned width, height;

    Frame() : width(30), height(30) {}

    void setHeight(unsigned hgt) {

        height = hgt;

    }

    void setWidth(unsigned wid) {

        width = wid;

    }

    void initializeFrame();

    void displayFrame();

private:

    vector< vector<char> > window;

}frame;

void Frame::initializeFrame() {

    if (width <= 0 || height <= 0) {

        cerr << "WRONG FRAME DIMENSION!" << endl;

        exit(0);

    }

    window = vector<vector<char> >(height, vector<char>(width, ' '));

    for (int i = 0; i != height; ++i) {

        window[i][0] = window[i][width - 1] = '#';

    }

    for (int j = 0; j != width; ++j) {

        window[0][j] = window[height - 1][j] = '#';

    }

}

void Frame::displayFrame() {

    for (int i = 0; i != height; ++i) {

        for (char ch : window[i])

            cout << ch << ' ';    

        cout << endl;

    }

}

class Snake

{

    friend class Movement;

public:

    Snake(int x = 0, int y = 0){

        this->x = x;

        this->y = y;

        next = NULL;

        prior = NULL;

    }

    void addHead(int, int);

    void delTail();

private:

    int x, y;

    Snake *next, *prior;

} *head, *tail;        //全局的蛇头和蛇尾

void Snake::addHead(int ix, int iy)

{

    Snake *snode = new Snake(ix, iy);

    snode->next = head;

    if (head)

        head->prior = snode;

    else

        tail = snode;

    head = snode;

    frame.window[ix][iy] = '~';

}

void Snake::delTail()

{

    Snake *tmp = tail;

    frame.window[tail->x][tail->y] = ' ';

    tail = tail->prior;

    tail->next = NULL;

    if (tail)

        tail->next = nullptr;

    else

        head = nullptr;

    delete tmp;         //回收资源

}

class Movement

{

public:

    Movement() :dir(LEFT){ randomFood(); }

    void randomFood();

    void move();

    void changeDirection(char);

private:

    Direction dir;

    int fx, fy;

    bool outOfFrame(int h, int w)

    {

        return h<frame.height - 1 && h>0 && w<frame.width - 1 && w>0 ? false : true;

    }

    bool block(int h, int w)

    {

        for (Snake *tmp = head; tmp != NULL; tmp = tmp->next){

            if (tmp->x == h&&tmp->y == w)

                return true;

        }

        return false;

    }

};

void Movement::randomFood()

{

    srand((unsigned)time(0));

    bool onSnake = true;

    while (onSnake){

        onSnake = false;

        fx = rand() % (frame.height - 2) + 1;

        fy = rand() % (frame.width - 2) + 1;

        for (Snake *tmp = head; tmp != NULL; tmp = tmp->next){

            if (tmp->x == fx&&tmp->y == fy){

                onSnake = true;

                break;

            }

        }

    }

    frame.window[fx][fy] = 'x';

}

void Movement::move()

{

    int h = head->x, w = head->y;

    switch (dir){

    case UP: --h; break;

    case DOWN: ++h; break;

    case LEFT: --w; break;

    case RIGHT: ++w; break;

    }

    if (outOfFrame(h, w) || block(h, w)){

        cout << "Game over!" << endl;

        exit(0);

    }

    if (h == fx&&w == fy){

        head->addHead(fx, fy);

        randomFood();

    }

    else{

        head->addHead(h, w);

        head->delTail();

    }

}

void Movement::changeDirection(char key)

{

    switch (key){

    case 'w':if (dir != DOWN) dir = UP; break;

    case 's':if (dir != UP) dir = DOWN; break;

    case 'a':if (dir != RIGHT) dir = LEFT; break;

    case 'd':if (dir != LEFT) dir = RIGHT; break;

    }

}

int main()

{

    unsigned speed, h, w;

    char key;

    frame.initializeFrame();

    head->addHead(frame.height / 2, frame.width / 2);

    Movement myMove;

    while (true) {

        while (!_kbhit()) {

            system("cls");

            myMove.move();

            frame.displayFrame();

            Sleep(300);

        }

        key = _getch();

        myMove.changeDirection(key);

    }

    return 0;

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: