上课的时候突然有思路,就给写了下来。。。
思路:
2个线程,主线程获取输入的方向,子线程根据主线程得到的方向操作蛇的移动。。。
1个char型的2维数组用于存放坐标信息,其中‘0’为空地,‘1’为蛇的身体,‘2’为食物(就定义了这3个,其他的可以自定义)
1个deque存放蛇各位置的坐标信息
程序开始时,子线程启动,蛇按初始方向移动,每移动一步,则分别判断该位置坐标是否为蛇的身体,空地或者食物 ,如为蛇的身体则游戏结束;为空地则在该位置输出一个字符(如'*')代表蛇移动到了当前位置,然后将该位置的坐标压入deque前端,并弹出deque最后一个坐标(同时要擦除该坐标位置的图案);为食物,额。。大部分同遇到空地所做的操作,只是最后没有弹出deque的最后一个坐标(蛇的身体增长了。。。)(当然了,,,修改deque的时候要同时修改char型数组相应坐标的值。。。)
#include <Windows.h>
#include <conio.h>
#include <thread>
#include <deque>
#include <iostream>
#define LEFT 0
#define TOP 0
#define RIGHT 79
#define BOTTOM 24
#define INITLEN 3
char map[BOTTOM-TOP][RIGHT-LEFT]={'0'};
typedef struct myPOINT
{
int x;
int y;
}point;
int currentX=LEFT+INITLEN-1,currentY=(TOP+BOTTOM)/2;
int direction='d';
using std::deque;
using std::thread;
void gotoxy(point& p);
void snakerun();
void erase(deque<point>& snake);
bool add(deque<point>& snake,point& p);
void initialsnake(deque<point>& snake);
void snakemove(deque<point>& snake,point& p);
void createfood(deque<point>snake);
bool foodexist(deque<point>snake,point& p);
void snakerun()
{
deque<point>snake;
initialsnake(snake);
createfood(snake);
point p;
while(1)
{
switch(tolower(direction)) //穿墙。。。。
{
case 'w':
currentY-=1;
if(currentY==TOP-1) //避免越界
currentY=BOTTOM-1;
break;
case 's':
currentY+=1;
if(currentY==BOTTOM)
currentY=TOP;
break;
case 'a':
currentX-=1;
if(currentX==LEFT-1)
currentX=RIGHT-1;
break;
case 'd':
currentX+=1;
if(currentX==RIGHT)
currentX=LEFT;
break;
}
p.x=currentX;
p.y=currentY;
snakemove(snake,p);
Sleep(200);
}
}
void snakemove(deque<point>& snake,point& p)
{
bool eatFood=false;
eatFood=add(snake,p);
if(!eatFood)
erase(snake);
else
createfood(snake);
}
void erase(deque<point>& snake)
{
point p;
p=snake[snake.size()-1];
gotoxy(p);
snake.pop_back();
std::cout<<" ";//消除该位置的字符
map[p.y][p.x]='0';
}
bool foodexist(deque<point>snake,point& p)
{
for(deque<point>::iterator it=snake.begin();it!=snake.end();++it)
if(it->x==p.x && it->y==p.y)
return 1;
return 0;
}
void createfood(deque<point>snake) //没效率
{
point p;
while(1)
{
p.x=rand()%(RIGHT-LEFT);
p.y=rand()%(BOTTOM-TOP);
if(!foodexist(snake,p))
break;
}
gotoxy(p);
printf("#");
map[p.y][p.x]='2';
}
bool add(deque<point>& snake,point& p)
{
bool eatfood=false;
snake.push_front(p);
gotoxy(p);
std::cout<<"*";//输出蛇的身体
if(map[p.y][p.x]=='1' && !(p.x==snake[snake.size()-1].x && p.y==snake[snake.size()-1].y)) //判断是否吃到自己。。
{
p.x=(RIGHT+LEFT)/2-4;
p.y=(TOP+BOTTOM)/2;
gotoxy(p);
std::cout<<"Game Over"<<std::endl;
exit(0);
}
else if(map[p.y][p.x]=='2')//吃到食物鸟。。。。
eatfood=true;
map[p.y][p.x]='1';
return eatfood;
}
void initialsnake(deque<point>& snake) //初始化
{
int mid=(TOP+BOTTOM)/2,i;
point p;
for(i = LEFT;i<LEFT+INITLEN;++i)
{
p.x=i;
p.y=mid;
add(snake,p);
}
}
void gotoxy(point& p)
{
COORD pos;
pos.X=p.x;
pos.Y =p.y;
SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE),pos); //光标移动
}
int main()
{
char curDirection;
srand(time(NULL));
std::thread snakethr=std::thread(snakerun);
while(1)
{
curDirection=_getch();
switch(tolower(curDirection)) //方向不能跟原方向相反
{
case 'w':if(direction=='s') curDirection='s';break;
case 's':if(direction=='w') curDirection='w';break;
case 'a':if(direction=='d') curDirection='d';break;
case 'd':if(direction=='a') curDirection='a';break;
}
direction=curDirection;
}
}
运行时的截图
-----------------------------------------------13/10/11--------------------------------------------------------------
修改了下。。。之前的实在无法吐槽。。。现在改成了一个类。。。
#include <Windows.h>
#include <conio.h>
#include <deque>
#include <ctime>
#include <vector>
#include <iostream>
using std::deque;
using std::vector;
typedef class myPOINT
{
public:
myPOINT(int xpos,int ypos):x(xpos),y(ypos){}
myPOINT() {}
int x,y;
}point;
class greedysnake
{
public:
greedysnake(int left=20,int top=2,int right=60,int bottom=14,int initlen=3,int speed=1):
_left(left),_top(top),_right(right),_bottom(bottom),_initlen(initlen),_currentX(left+initlen-1),_currentY((top+bottom)/2),_direction('d'),
_speed(speed)
{
_map.resize(bottom-top);
for(int i=0;i<signed(_map.size());++i)
_map[i].resize(right-left);
if(_speed>5) _speed=5;
}
void changespeed(int speed) {_speed=speed>5?5:speed;}
void getinput();
private:
int _left,_top,_right,_bottom,_initlen,_direction;
int _currentX,_currentY;
int _speed;
point _p;
deque<point>_snake;
vector<vector<char> >_map;
void _gotoxy(point& p);
void _erase();
bool _add();
void _createframe();
void _snakemove();
void _createfood();
void _initialsnake();
void _snakerun();
bool _foodexist(point& p);
void _buildframe(point& p1,point& p2);
};
void greedysnake::_buildframe(point& p1,point& p2) //建外框
{
_gotoxy(p1);
for(int i=0;i<=p2.x-p1.x;++i)
if(i!=0 && i!=p2.x-p1.x)
printf("-");
else
printf("+");
_gotoxy(point(p1.x,p2.y));
for(int i=0;i<=p2.x-p1.x;++i)
if(i!=0 && i!=p2.x-p1.x)
printf("-");
else
printf("+");
for(int i=1;i<p2.y-p1.y;++i)
{
_gotoxy(point(p1.x,p1.y+i));
printf("|");
_gotoxy(point(p2.x,p1.y+i));
printf("|");
}
}
void greedysnake::_snakerun()
{
switch(tolower(_direction)) //穿墙。。。。
{
case 'w':
_currentY-=1;
if(_currentY==_top-1) //避免越界
_currentY=_bottom-1;
break;
case 's':
_currentY+=1;
if(_currentY==_bottom)
_currentY=_top;
break;
case 'a':
_currentX-=1;
if(_currentX==_left-1)
_currentX=_right-1;
break;
case 'd':
_currentX+=1;
if(_currentX==_right)
_currentX=_left;
break;
}
_p.x=_currentX;
_p.y=_currentY;
_snakemove();
Sleep(200-_speed*30); //蛇的速度
}
void greedysnake::_snakemove()
{
bool eatFood=false;
eatFood=_add();
if(!eatFood)
_erase();
else
_createfood();
}
void greedysnake::_erase()
{
point p;
p=_snake[_snake.size()-1];
_gotoxy(p);
_snake.pop_back();
std::cout<<" ";//消除该位置的字符
_map[p.y-_top][p.x-_left]='0';
}
bool greedysnake::_foodexist(point& p)
{
for(deque<point>::iterator it=_snake.begin();it!=_snake.end();++it)
if(it->x==p.x && it->y==p.y)
return 1;
return 0;
}
void greedysnake::_createfood() //没效率
{
point p;
while(1)
{
p.x=_left+rand()%(_right-_left);
p.y=_top+rand()%(_bottom-_top);
if(!_foodexist(p))
break;
}
_gotoxy(p);
printf("#");
_map[p.y-_top][p.x-_left]='2';
}
bool greedysnake::_add()
{
bool eatfood=false;
_snake.push_front(_p);
_gotoxy(_p);
std::cout<<"*";//输出蛇的身体
if(_map[_p.y-_top][_p.x-_left]=='1') //判断是否吃到自己。。
{
_p.x=(_right+_left)/2-4;
_p.y=(_top+_bottom)/2;
_gotoxy(_p);
std::cout<<"Game Over"<<std::endl;
exit(0);
}
else if(_map[_p.y-_top][_p.x-_left]=='2')//吃到食物鸟。。。。
eatfood=true;
_map[_p.y-_top][_p.x-_left]='1';
return eatfood;
}
void greedysnake::_initialsnake() //初始化
{
int mid=(_top+_bottom)/2,i;
for(i = _left;i<_left+_initlen;++i)
{
_p.x=i;
_p.y=mid;
_add();
}
}
void greedysnake::_gotoxy(point& p)
{
COORD pos;
pos.X=p.x;
pos.Y =p.y;
SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE),pos); //光标移动
}
void greedysnake::getinput()
{
char curDirection;
srand(signed(time(NULL)));
_initialsnake();
_buildframe(point(_left-1,_top-1),point(_right,_bottom));
_createfood();
while(1)
{
if(_kbhit())
{
curDirection=_getch();
switch(tolower(curDirection)) //方向不能跟原方向相反
{
case 'w':if(_direction=='s') curDirection='s';break;
case 's':if(_direction=='w') curDirection='w';break;
case 'a':if(_direction=='d') curDirection='d';break;
case 'd':if(_direction=='a') curDirection='a';break;
default: curDirection=_direction;
}
_direction=curDirection;
}
_snakerun();
}
}
int main()
{
greedysnake snake(10,2,40,14,6,2);
snake.changespeed(2);
snake.getinput();
}