C++实战小项目贪吃蛇网游化框架搭建2

xiaoxiao2021-02-28  144

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

四、Snake类的设计

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

#pragma once #include <deque> #include "Point.h" #include <conio.h> class Snake { public: Snake(initializer_list<Point> 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<Point> 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完成数据的重置。 ###五、Point类的设计   point类基本上就是一个pair加上了几个接口,需要能够完成point的绘制及清除、数据的返回即可:

#pragma once #include <Windows.h> #include <iostream> 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; };

###六、公用数据和函数

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则用于一些函数的返回值检测。

转载请注明原文地址: https://www.6miu.com/read-65073.html

最新回复(0)