解决展示的设计思路及代码(新人从0到1调试到运动正常大概需要1~2个小时,如果再带深究一些内容点,半天怎么都能完成的)
day2解决的问题:
- 蛇动起来。在控制台中,一个比较好的思路就是刷新控制台,然后输出结果。综合框架设计如下所示,分为清屏、输出、延时、处理四个步骤。清屏用window的是system(“cls”)linux下为system(“printf “\033c””),但是貌似会直接输出最终结果,输出上一节已经完成,延时有好几种实现方案,新手可以调用sleep(),我这里用的是clock(),处理则是上下左右的设定及移动,以及是否吃到了食物,以及如何更新。以下代码给出了整体思路以及abc的完整实现,d的实现比较复杂,单独来讲。
#include <ctime>
#include <iostream>
using namespace std;
void delay(int time) {
clock_t now = clock();
while (clock() - now < time) {}
}
int main() {
Snake snake;
Food food;
auto beg = snake.gethead();
auto end = snake.gettail();
while (snake.live()) {
vvc[beg.first][beg.second] = body_smb;
system("cls");
print_all(vvc);
delay(500);
beg = snake.gethead();
if (end != snake.gettail()) {
vvc[end.first][end.second] = ' ';
end = snake.gettail();
}
}
}
- Food类内容的增加。对对象是否有效(逻辑上存在或者不存在),我的设计思路是类内部有个flag,并且能够提供返回接口。因此,Food中的flag能够判断自己是否被吃掉,接口为eated()。同时有个reset(),就是更换食物的位置。
struct Food {
int x = 1;
int y = 2;
bool flag = true;
bool eated() {
return !flag;
}
bool setflag(bool b){
flag=b;
}
void reset() {
x = 2;
y = 1;
setflag(true);
}
};
- Snake类内容的增加。首先是要记录上下左右四个方向,这里采用enum实现。然后是新增snake的移动状态。每次采用eat(Food)函数来进行移动,即检查下一步结果的生死,生则修改snake的body状态,死则修改snake的alive的状态。因此这里采用了一个next()计算下一步的状态的函数,需要返回下一步的pair,增加了一个check()来检测某个点是否可以成为蛇的下一步,返回的bool值决定了蛇的生死。
enum Status {
up, down, left, right
};
class Snake {
private:
deque<pair<int, int>> body;
bool alive = true;
Status stat = Status::up;
public:
Snake() :body({ pair<int, int>(birth, birth) }) {}
pair<int, int> gethead()const { return body.front(); }
pair<int, int> gettail()const {return body.back();}
bool live() const { return alive; }
size_t size() const { return body.size(); }
size_t getstatus() const {return stat;}
void eat(Food& food) {
auto temp = next();
if (check(temp)) {
body.push_front(temp);
if (temp.first == food.x && temp.second == food.y)
food.setflag(false);
else
body.pop_back();
}
else {
alive = false;
}
}
pair<int, int> next() {
auto temp = gethead();
switch (getstatus()) {
case Status::up:
return{ temp.first - 1, temp.second };
case Status::down:
return{ temp.first + 1, temp.second };
case Status::right:
return{ temp.first, temp.second + 1 ;
case Status::left:
return{ temp.first, temp.second - 1};
default:
return temp;
}
}
bool check(pair<int,int>& p) const{
if (p.first<0||p.first>norm_size-1||p.second<0||p.second>norm_size-1 ||
vvc[p.first][p.second] == body_smb)
return false;
return true;
}
};
- main函数完善,其实就是加一行代码snake.eat(food)。
int main() {
Snake snake;
Food food;
auto beg = snake.gethead();
auto end = snake.gettail();
while (snake.live()) {
vvc[beg.first][beg.second] = body_smb;
system("cls");
print_all(vvc);
delay(500);
snake.eat(food);
beg = snake.gethead();
if (end != snake.gettail()) {
vvc[end.first][end.second] = ' ';
end = snake.gettail();
}
}
}
到这里,就可以得到如下的最终结果了,蛇往上走吃掉第一个食物,然后撞死,游戏结束。
|