c++实现贪吃蛇

来源:互联网 发布:科比3d模型数据 编辑:程序博客网 时间:2024/06/08 01:09
```#include<iostream>#include<utility>#include<set>#include<deque>#include<Windows.h>#include <ctime>#include <stdexcept>#include<string>#include<conio.h>WORD SQUARE_COLOR[7] = { FOREGROUND_RED | FOREGROUND_INTENSITY,FOREGROUND_GREEN | FOREGROUND_INTENSITY,FOREGROUND_BLUE | FOREGROUND_INTENSITY,FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_INTENSITY,FOREGROUND_RED | FOREGROUND_BLUE | FOREGROUND_INTENSITY,FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY,FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY};义方向#define KEY_UP      72#define KEY_DOWN    80#define KEY_LEFT    75#define KEY_RIGHT   77#define KEY_ESC     27//边框属性#define MAPW 30#define MAPH 20#define OFFSET_L 2#define OFFSET_U 2using namespace std;class Bitmap;class Feed;class Snake;//获取句柄函数HANDLE initiate() {    HANDLE hOutput;    hOutput = GetStdHandle(STD_OUTPUT_HANDLE);    return hOutput;}//控制台输出函数bool textout(HANDLE hOutput, int x, int y, LPTSTR lpszCtring,WORD wColors[], int nColors) {    DWORD cWritten;    BOOL fSuccess;    COORD coord;    coord.X = x;    coord.Y = y;    fSuccess = WriteConsoleOutputCharacter(        hOutput,        lpszCtring,        lstrlen(lpszCtring),        coord,        &cWritten    );    for (;fSuccess && coord.X < lstrlen(lpszCtring) + x;coord.X += nColors) {        fSuccess = WriteConsoleOutputAttribute(            hOutput,            wColors,            nColors,            coord,            &cWritten        );    }    if (!fSuccess)        cout << "error:WriteConsoleOutputCharacter" << endl;    return 0;}//endbool textout1(HANDLE hOutput,int x,int y,LPTSTR lpszCtring) {    DWORD cWritten;    BOOL fSuccess;    COORD coord;    coord.X = x;    coord.Y = y;    fSuccess = WriteConsoleOutputCharacter(        hOutput,        lpszCtring,        lstrlen(lpszCtring),        coord,        &cWritten    );    if (!fSuccess)        cout << "error:WriteConsoleOutputCharacter" << endl;    return 0;}enum type {    bitmap_type,    feed_type,    snake_type,    none_type,};extern HANDLE handle;//打印游戏界面template<typename T> void print(T &t, enum type ty) {    LPTSTR lpszText = TEXT("◆") ;    switch (ty) {    case bitmap_type:        lpszText = TEXT("◆");        break;    case feed_type:        lpszText = TEXT("●");        break;    case snake_type:        lpszText = TEXT("■");        break;    case none_type:        lpszText = TEXT(" ");        break;    default:        runtime_error("无效的背景框!");        break;    }    for (T::iterator it = t.begin();it != t.end();++it)        textout(handle, OFFSET_L + 2 * it->coord.first, OFFSET_U + it->coord.second, lpszText, SQUARE_COLOR+it->color,1);}//Nodestruct Node {    pair<int, int> coord;    int color;    Node(int x,int y,int c):coord(x,y),color(c){}    friend inline bool operator<(const Node &lhs, const Node &rhs);};//比较两个节点是否相同的函数bool equalNode(Node node1, Node node2) {    if (node1.coord.first == node2.coord.first && node1.coord.second == node2.coord.second)        return true;    else        return false;}//运算符重载(因为set需要排序)inline bool operator<(const Node &lhs, const Node &rhs){    if (lhs.coord.second < rhs.coord.second)    {        return true;    }    else if (lhs.coord.second == rhs.coord.second)    {        return lhs.coord.first < rhs.coord.first;    }    else    {        return false;    }}//Bitmap 类class Bitmap{public:    friend class Feed;    friend class Snake;    Bitmap(int map_x,int map_y,int map_w,int map_h,int map_c):x(map_x),y(map_y),w(map_w),h(map_h),c(map_c){}    void printBitmap();    void Insert(pair<int, int> edge);private:    int x, y, w, h, c;    set<Node> bm;};void Bitmap::Insert(pair<int, int> edge) {    if (edge.first >= x && edge.first <= x + w - 1 && edge.second >= y && edge.second <= y + h - 1)        bm.insert(Node(edge.first, edge.second,c));    else        throw runtime_error("无效的背景框!");}void Bitmap::printBitmap() {    print(bm, bitmap_type);}//feed类class Feed {public:    friend class Snake;    void PrintFeed();private:    set<Node> fd;};void Feed::PrintFeed() {    print(fd, feed_type);}class Snake {public:    friend class Feed;    enum direction {        up,        down,        left,        right    };    Snake(pair<int, int> head, pair<int, int> tail);    void PrintSnake();    void EraseSnake();    void MoveFront(pair<int,int> t);    bool NextStep(direction d,Bitmap &b,Feed &fd,bool &eat);    void Snake::AddNewFeed(Bitmap &b, Feed &f);    direction GetDir() {        return this->dir;    }    bool ChangeDirection(direction d, Bitmap &b, Feed &f,  bool &eat);                 //判断方向改变是否合法private:    deque<Node> sn;    direction dir;    void AddFrontNode(Node n, Feed &f);};Snake::Snake(pair<int, int> head, pair<int, int> tail) {    srand(static_cast<unsigned int>(time(NULL)));    if (head.first == tail.first) {        if (head.second < tail.second) {            dir = up;            for (int i = head.second;i <= tail.second;++i)                sn.push_back(Node(head.first, i,rand()%7));        }        else if (head.second > tail.second) {            dir = down;            for (int i = head.second;i >= tail.second;--i)                sn.push_back(Node(head.first, i, rand() % 7));        }        else            throw runtime_error("无法绘蛇");    }    else if (head.second == tail.second) {        if (head.first > tail.first) {            dir = right;            for (int i = head.first;i >= tail.first;--i)                sn.push_back(Node(head.second, i, rand() % 7));        }        else if (head.first < tail.first) {            dir = left;            for (int i = head.first;i <= tail.first;++i)                sn.push_back(Node(head.second, i, rand() % 7));        }    }    else        throw runtime_error("无法绘蛇");}void Snake::PrintSnake() {    print(sn, snake_type);}void Snake::EraseSnake() {    print(sn, none_type);}void Snake::AddFrontNode(Node n, Feed &f) {    sn.push_front(n);    f.fd.erase(n);}void Snake::MoveFront(pair<int,int> t) {    for (deque<Node>::reverse_iterator it = sn.rbegin();it != sn.rend();it++) {        if (it != sn.rend() - 1) {            it->coord.first = (it + 1)->coord.first;            it->coord.second = (it + 1)->coord.second;        }        else {            it->coord.first = t.first;            it->coord.second = t.second;        }    }}bool Snake::NextStep(direction d, Bitmap &b, Feed &f, bool &eat) {    pair<int, int> temp;      //存放头节点    switch (d)    {    case up:        temp.first = sn[0].coord.first;        temp.second = sn[0].coord.second - 1;        break;    case down:        temp.first = sn[0].coord.first;        temp.second = sn[0].coord.second + 1;        break;    case left:        temp.first = sn[0].coord.first - 1;        temp.second = sn[0].coord.second;        break;    case right:        temp.first = sn[0].coord.first + 1;        temp.second = sn[0].coord.second;        break;    default:        throw runtime_error("反向无效");        break;    }    dir = d;    for (set<Node>::iterator it = b.bm.cbegin();it != b.bm.cend();it++)         if (equalNode(*it, Node(temp.first, temp.second,6)))             return false;    for (deque<Node>::iterator it = sn.begin();it != sn.end() - 1;it++)         if (equalNode(*it, Node(temp.first, temp.second,6)))            return false;    for (set<Node>::iterator it = f.fd.begin();it != f.fd.end();it++) {        if (equalNode(*it, Node(temp.first, temp.second,6))) {            eat = true;            AddFrontNode(*it, f);            AddNewFeed(b, f);            f.PrintFeed();            EraseSnake();            PrintSnake();            return true;        }    }    EraseSnake();    MoveFront(temp);    PrintSnake();    return true;}bool Snake::ChangeDirection(direction d, Bitmap &b, Feed &f, bool &eat) {    if (d == dir)  return true;         //不执行操作,但继续执行下面的代码    if (dir == up && d == down ||        dir == down && d == up ||        dir == left && d == right ||        dir == right && d == left)        return true;    return NextStep(d, b, f, eat);}void Snake::AddNewFeed(Bitmap &b, Feed &f) {    pair<int, int> temp;    bool ok = false;    set<Node>::iterator it;    srand(static_cast<unsigned int>(time(NULL)));    while (1) {        temp.first = rand() % b.w + b.x;        temp.second = rand() % b.h + b.y;        Node node(temp.first, temp.second,6);        for (it = b.bm.begin();it != b.bm.end(); it++) {            if (equalNode(*it, node)) {                ok = false;                break;            }            ok = true;        }        if (!ok) continue;        for (it = f.fd.begin();it != f.fd.end(); it++) {            if (equalNode(*it, node)) {                ok = false;                break;            }            ok = true;        }        if (!ok) continue;        deque<Node>::iterator dit;        for (dit = sn.begin();dit != sn.end();dit++) {            if (equalNode(*dit, node)) {                ok = false;                break;            }            ok = true;        }        if (!ok) continue;        f.fd.insert(Node(temp.first, temp.second,rand()%7));        break;    }}HANDLE handle;void init(Bitmap &b,Feed &feed,Snake &s){    handle = initiate();    for (int i = 0; i < MAPW; i++)    {        b.Insert(make_pair(i, 0));        b.Insert(make_pair(i, MAPH - 1));    }    for (int j = 1; j < MAPH - 1; j++)    {        b.Insert(make_pair(0, j));        b.Insert(make_pair(MAPW - 1, j));    }    b.printBitmap();    for (int i = 0;i < 3;++i)        s.AddNewFeed(b, feed);    feed.PrintFeed();    s.PrintSnake();    LPTSTR Text1 = TEXT("SCORE:");    LPTSTR Text2 = TEXT("LEVEL:");    LPTSTR Text = TEXT("❤按任意键开始!❤");    textout1(handle, 1, 1, Text);    textout1(handle, OFFSET_L + 2*MAPW , OFFSET_U, Text1);    textout1(handle, OFFSET_L + 2 * MAPW, OFFSET_U + 5, Text2);    char c = _getch();}int main() {    srand(static_cast<unsigned int>(time(NULL)));    Bitmap myBitmap(0, 0, MAPW, MAPH,rand()%7);    Snake mySnake(make_pair(10, 10), make_pair(10, 12));    Feed myFeed;    init(myBitmap,myFeed,mySnake);    int score = 0, level = 0, max_delay = 70 - 10 * level, uplevel = 5, speed = 6, minspeed = 4;    bool ret = true, eat = false;    while (1)    {        //textout(handle, OFFSET_L + 2 * MAPW + 2, 4, string);        /*_itoa_s(level, string, 10);        textout(handle, OFFSET_L + 2 * MAPW + 2, 15, string);*/        int delay = 0;        max_delay = 35 - 5 * level;        while (delay < max_delay)        {            if (_kbhit())            {                int key = _getch();                switch (key)                {                case KEY_UP:                    ret = mySnake.ChangeDirection(Snake::up, myBitmap, myFeed, eat);                    break;                case KEY_DOWN:                    ret = mySnake.ChangeDirection(Snake::down, myBitmap, myFeed, eat);                    break;                case KEY_LEFT:                    ret = mySnake.ChangeDirection(Snake::left, myBitmap, myFeed, eat);                    break;                case KEY_RIGHT:                    ret = mySnake.ChangeDirection(Snake::right, myBitmap, myFeed, eat);                    break;                case KEY_ESC:                    exit(EXIT_SUCCESS);                }                if (!ret) {                    textout1(handle, OFFSET_L + MAPW / 2, OFFSET_U + MAPH / 2, TEXT("游戏结束"));                    char c = _getch();                    exit(EXIT_SUCCESS);                }                if (eat) {                    eat = false;                    score++;                    if (score%uplevel == 0) {                        level++;                        uplevel += 3;                        --speed;                        speed = ((speed == minspeed) ? minspeed : speed);                    }                }            }            Sleep(speed);            delay++;        } //while (delay < max_delay)        ret = mySnake.NextStep(mySnake.GetDir(), myBitmap, myFeed, eat);        if (!ret) {            textout1(handle, OFFSET_L + MAPW / 2, OFFSET_U + MAPH / 2, TEXT("游戏结束"));            char c = _getch();            exit(EXIT_SUCCESS);        }        if (eat) {            eat = false;            score++;            if (score%uplevel == 0) {                level++;                uplevel += 3;                --speed;                speed = ((speed == minspeed) ? minspeed : speed);            }        }    }//while(1)    return 0;}
1 0
原创粉丝点击