food.h
/********** food.h ************/
#include<iostream>
using namespace std;
#include "wall.h"
class Food
{
public:
Food(Wall& wall);
//设置食物
void setFood();
private:
int foodX;
int foodY;
Wall& wall;
};
food.cpp
/********** food.cpp ************/
#include "food.h"
Food::Food(Wall& tempWall):wall(tempWall){}
void Food::setFood()
{
while(true)
{
foodX = rand() % (Wall::ROW - 2) + 1;
foodY = rand() % (Wall::COL - 2) + 1;
cout<<"foodX="<<foodX<<" foodY="<<foodY<<endl;
//如果随机的位置是蛇头或者蛇身,就重新生成随机数
if(wall.getWall(foodX,foodY) == ' ')
{
wall.setWall(foodX,foodY, '#');
break;
}
}
}
wall.h
/********** wall.h ************/
#ifndef _WALL_HEAD
#define _WALL_HEAD
#include<iostream>
using namespace std;
class Wall
{
public:
enum{
ROW = 26,
COL = 26
};
//初始化墙壁
void initWall();
//画出墙壁
void drawWall();
//根据索引设置二维数组的内容
void setWall(int x,int y, char c);
//根据索引获取当前位置的符号
char getWall(int x,int y);
private:
char gameArray[ROW][COL];
};
#endif
wall.cpp
/********** wall.cpp ************/
#include "wall.h"
void Wall::initWall()
{
for(int i = 0;i < ROW; i++)
{
for(int j = 0;j < COL; j++)
{
//放墙壁
if(i == 0 || j == 0 || i == ROW -1 || j == COL -1)
{
gameArray[i][j] = '*';
}
else
{
gameArray[i][j] = ' ';
}
}
}
}
void Wall::drawWall()
{
for(int i = 0;i < ROW;i++)
{
for(int j = 0;j < COL;j++)
{
cout<< gameArray[i][j]<<" ";
}
if(i == 5)
{
cout<<"create by zt";
}
if(i == 6)
{
cout<<"a: left";
}
if(i == 7)
{
cout<<"d: right";
}
if(i == 8)
{
cout<<"w: up";
}
if(i == 9)
{
cout<<"s: down";
}
cout<<endl;
}
}
void Wall::setWall(int x,int y,char c)
{
gameArray[x][y] = c;
}
char Wall::getWall(int x,int y)
{
return gameArray[x][y];
}
snake.h
/********** snake.h ************/
#include<iostream>
//#include "wall.h"
#include "food.h"
using namespace std;
class Snake
{
public:
enum {
UP = 'w',
DOWN = 's',
LEFT = 'a',
RIGHT = 'd'
};
//Snake();
Snake(Wall& tempWall, Food& food);
void initSnake();
//销毁节点
void destroyPoint();
//添加节点
void addPoint(int x,int y);
//删除节点
void deletePoint();
//移动操作,返回值代表移动是否成功
bool move(char key);
private:
struct Point
{
//数据域
int x;
int y;
//指针域
Point *next;
};
Point *pHead;
Point* pTail;
//这里使用的是引用,顾名思义,只有之前存在
//才能够进行引用,那么源砸在哪?需要从构造函数中传递进来
Wall& wall;
Food& food;
bool isRool;//是否是个环,蛇头紧挨着蛇尾
};
snake.cpp
/********** snake.cpp ************/
#include "snake.h"
void Snake::destroyPoint()
{
//Point* pCur = pHead;
//while(pHead != NULL)
//{
// pCur = pHead->next;
// delete pHead;
// pHead = pCur;
//}
Point* pCur = pTail;
while(pTail != NULL)
{
pCur = pTail->next;
delete pTail;
pTail = pCur;
}
}
void Snake::initSnake()
{
destroyPoint();
addPoint(5,3);
addPoint(5,4);
addPoint(5,5);
cout<<"添加节点了";
}
//Snake::Snake()
//{
// pHead = NULL;
// wall = NULL;
//}
Snake::Snake(Wall& tempWall,Food& tempFood):wall(tempWall),food(tempFood)
{
pHead = NULL;
pTail = NULL;
isRool = false;
}
void Snake::addPoint(int x,int y)
{
//创建新节点
Point* newPoint = new Point;
newPoint->x = x;
newPoint->y = y;
newPoint->next = NULL;
//如果原来头不为空,改为身子
if(pHead != NULL)
{
wall.setWall(pHead->x,pHead->y,'=');
pHead->next = newPoint;
pHead = newPoint;
wall.setWall(pHead->x,pHead->y,'@');
//cout<<x<<y<<"@"<<endl;
}
else
{
//cout<<"为空了\n";
pHead = newPoint;
wall.setWall(pHead->x,pHead->y,'@');
pTail = pHead;
}
}
void Snake::deletePoint()
{
if(pTail == NULL)
return;
Point* pCur = pTail;
pTail = pTail->next;
wall.setWall(pCur->x,pCur->y,' ');
delete pCur;
}
bool Snake::move(char key){
int x = pHead->x;
int y = pHead->y;
switch(key)
{
case UP:
x--;
break;
case DOWN:
x++;
break;
case LEFT:
y--;
break;
case RIGHT:
y++;
break;
default:
return false;
}
if(pTail->x == x && pTail->y == y)
{//碰到尾巴,循环
isRool = true;
}
else
{
//判断用户到达的位置是否成功
if(wall.getWall(x,y) == '*' || wall.getWall(x,y) == '=')
{
cout<<"Game OVRE"<<endl;
return false;
}
}
//移动成功 分两种
//吃到食物 没有吃到食物
if(wall.getWall(x,y) == '#')
{
addPoint(x,y);
//重新设置食物
food.setFood();
}
else//吃到和未吃到食物的重要区别是未吃到食物的时候需要删除尾部节点
{
addPoint(x,y);
deletePoint();
if(isRool == true)
{
wall.setWall(x,y,'@');
}
}
return true;
}
game.cpp
/********** game.cpp ************/
#include "snake.h"
#include<ctime>
//#include<conio.h>
#include<ncurses.h>//用于接收用户输入
//#include<Windows.h>//提供sleep函数
#include<unistd.h>//sleep in unix
#include <sys/ioctl.h>
#include <termios.h>
bool kbhit()
{
termios term;
tcgetattr(0, &term);
termios term2 = term;
term2.c_lflag &= ~ICANON;
tcsetattr(0, TCSANOW, &term2);
int byteswaiting;
ioctl(0, FIONREAD, &byteswaiting);
tcsetattr(0, TCSANOW, &term);
return byteswaiting > 0;
}
int main(){
//添加随机种子
srand((unsigned int)time(NULL));
bool isDead = false;
Wall wall;
//Food food;
wall.initWall();
Food food(wall);
Snake snake(wall,food);
snake.initSnake();
//snake.deletePoint();
//wall.setWall(5,6,'=');
//wall.setWall(5,7,'@');
//Food food(wall);
food.setFood();
//snake.move('w');
//snake.move('w');
//snake.move('a');
wall.drawWall();
//cout<<wall.getWall(0,0)<<endl;
//cout<<wall.getWall(5,5)<<endl;
//cout<<wall.getWall(5,6)<<endl;
//cout<<wall.getWall(1,1)<<endl;
char preKey = ' ';
while(!isDead)
{
//接收用户输入
//char key = getchar();
char key;
cin>>key;
if(preKey == ' ' && key == snake.LEFT)
continue;
//char key = getchar();
//cout<<"key="<<key<<endl;
do
{
if(key == snake.UP || key == snake.DOWN || key == snake.LEFT || key == snake.RIGHT)
{
if((key == snake.LEFT && preKey == snake.RIGHT) || (key == snake.RIGHT && preKey == snake.LEFT) || (key == snake.UP && preKey == snake.DOWN) || (key == snake.DOWN && preKey == snake.UP))
{
key = preKey;
}
preKey = key;
if(snake.move(key) == true)
{
//移动成功 代码
system("cls");
wall.drawWall();
sleep(1);
}
else
{
isDead = true;
break;
}
}
else
{
key = preKey;//强制将错误按键设为上一次的按键
}
}while(!kbhit());
//cout<<key<<endl;
//char key = wgetch();
}
//system("exit");
return 0;
}