即日起在codingBlog上分享您的技术经验即可获得积分,积分可兑换现金哦。

C++学习与进阶日志之二—贪吃蛇网游化框架搭建2

编程语言 liu3612162 11℃ 0评论
本文目录
[隐藏]

  上篇记录了main函数、game类和food类的设计,本片继续记录Snake类的设计。

1.四、Snake类的设计

  同样从Game类中对Snake类的需求出发,Snake类用一个deque保存一系列点,每次循环需要根据其方向完成点的更新、方向更新、食物是否与蛇身重合等等一些列功能:

#pragma once
#include 
#include "Point.h"
#include 

class Snake
{
public:
    Snake(initializer_list li = { {20,20},{20,21},{20,22} }, char c = 'd') :body(li), direction(c) { bodysize = body.size(); };
    void paintbody(HANDLE);
    bool hititself()
    {
        Point head = body.front();
        for (auto k = --body.end(); k != (body.begin() + 2); k--)
            if (head == *k)
                return true;
        return false;
    }
    bool overlap(const Point &p)//判断刷新的食物是否与蛇身重合
    {
        for (auto k = --body.end(); k != (body.begin() ); k--)
            if (p == *k)
                return true;
        return false;
    }

    bool senddata(int &sock);

    bool recvdata(int &sock);

    void painthead(HANDLE hand)
    {
        body.front().paint(hand);
    }

    void tailclear(HANDLE hand)
    {
        body.back().clear(hand);
        body.pop_back();
    }

    const Point& Head()
    {
        return body.front();
    }

    bool changedirection(char &k);

    void update();

    void reset();

    bool press(char &k)
    {
        return k == direction;
    }
private:
    deque body;
    char direction;
    size_t bodysize;
};

inline
bool Snake::changedirection(char &k)
{
    if (k == 'A' || k == 'S' || k == 'W' || k == 'D')
        k = tolower(k);
    if (k == 'a' || k == 's' || k == 'w' || k == 'd') {
        if ((k + direction) == 234 || (k + direction) == 197 || k == direction)
            return false;
        direction = k;
        return true;
    }
    return false;
}

inline
void Snake::update()
{
    switch (direction) {
    case 'w':
        body.emplace_front(body.front().xx(), body.front().yy() - 1);
        break;
    case 's':
        body.emplace_front(body.front().xx(), body.front().yy() + 1);
        break;
    case 'a':
        body.emplace_front(body.front().xx() - 2, body.front().yy());
        break;
    case 'd':
        body.emplace_front(body.front().xx() + 2, body.front().yy());
        break;
    }
}

蛇身绘制方面,因为整个程序中food的绘制颜色及符号与蛇身一致,因此在吃上食物后不需进行任何操作,而未吃上食物则只需在头部多绘制一个点并抹掉尾部的点即可。因为需要在Game中判定是否撞墙,因此定义一个返回头部数据的接口;reset完成数据的重置。

2.五、Point类的设计

  point类基本上就是一个pair加上了几个接口,需要能够完成point的绘制及清除、数据的返回即可:

#pragma once
#include 
#include 

using namespace std;

class Point
{
public:
    Point(int a=0,int b=0):x(a),y(b){}
    void paint(HANDLE hand)
    {
        SetOutputposition(x, y, hand);
        cout << "■";
    }
    void clear(HANDLE hand)
    {
        SetOutputposition(x, y, hand);
        cout << "  ";
    }
    int& xx() {
        return x;
    }
    const int& xx() const
    {
        return x;
    }
    int& yy() {
        return y;
    }
    const int &yy() const
    {
        return y;
    }
    bool operator==(const Point& point) const
    {
        if (x == point.x&&y == point.y)
            return true;
        else
            return false;
    }
private:
    int x;
    int y;
};

3.六、公用数据和函数

static HANDLE hout = GetStdHandle(STD_OUTPUT_HANDLE);

static bool chekans(const int &sock)
{
    char buff[4];
    int n;
    while ((n = recv(sock, buff, 4, 0)) < 0)//可将此处单独顶一个为一个Recv函数代替原函数
    {
        if (errno == EINTR)
            continue;
        else
            return false;
    }
    buff[n] = 0;
    return (strcmp("LWB", buff) ? false : true);
}

static void SetOutputposition(int x, int y, HANDLE hand)
{
    COORD position;
    position.X = x;
    position.Y = y;
    SetConsoleCursorPosition(hand, position);
}

static int n;

chekanks用于check服务器在成功接受数据后返回的消息,SetOutputposition则用于设置光标位置,这个函数在程序中使用很多,主要是对SetConsoleCursorPosition进行了封装。n则用于一些函数的返回值检测。

转载请注明:CodingBlog » C++学习与进阶日志之二—贪吃蛇网游化框架搭建2

喜欢 (0)or分享 (0)
发表我的评论
取消评论

*

表情