您的位置:首页 > 编程语言 > C语言/C++

贪吃蛇C++源码,使用面向对象方式编写

2015-03-18 12:59 573 查看
网上好多贪吃蛇的源码,不过大部分都是用C面向过程的.自己用面向对象写了一个贪吃蛇,不足之处还请大家见谅.

我定义了3个类.

地图类:包括地图的抽象数组, 地图里面包含一个食物的坐标.用户可以自定义地图的起始坐标和宽度高度.

蛇类: 类中有蛇的出生长度,所属地图,方向,是否存活. 蛇可以吃掉食物,左右上下移动,死亡.

控制类: 记录分数,并操纵蛇移动,控制游戏进度暂停/结束.

"GreedySnake.h" //包含了蛇类和地图类.

#ifndef __GREEDYSNAKE_H_
#define __GREEDYSNAKE_H_

#define MAXLENGTH 200
#define MAXMAPWIDTH 200
#define MAXMAPHEIGHT 200

enum Direction{ LEFT = 'a', RIGHT = 'd', UP = 'w', DOWN = 's' };

struct Point
{
int x, y;
};

void setWindowSize(int lines, int cols);		//设置窗口大小
void gotoXY(int x, int y);		//光标跳转到指定位置
void setColor(int colorId);		//设置输出颜色
bool isOverlap(Point &p1, Point &p2); //判断两个坐标是否重叠

class Map
{
private:
bool _mapObj[MAXMAPWIDTH][MAXMAPHEIGHT];	//地图数组模型
Point _mapStartingCoord,	//地图起始坐标
_food;	//食物坐标
int _mapWidth,	//地图宽度
_mapHeight;	//地图高度
public:
Map(const int x, const int y, const int width, const int height);	//绘制地图
void refreshFood();	//刷新食物
int getWidth()const { return _mapWidth; }
int getHeight()const { return _mapHeight; }
Point getMapStartingCoord()const { return _mapStartingCoord; }
Point getFoodCoord()const { return _food; }
~Map(){}
};

class Snake
{
private:
Map *_belongs;		//所属地图
Direction _direction;	//方向
int _length;		//长度
bool _isLife;	//是否存活
public:
Snake(Map *map, int defaultLenth);
bool eatFood();
void draw()const;
void moveUp();
void moveDown();
void moveLeft();
void moveRight();
void dead();
Map * getBelongsMap()const{ return _belongs; }
int getLength()const { return _length; }
bool isLife()const { return _isLife; }
~Snake();
int _x[MAXLENGTH], _y[MAXLENGTH];

};

#endif


实现代码 "GreedySnake.cpp" 该文件中还包含了几个画图操作必要的函数

#include "GreedySnake.h"
#include <Windows.h>
#include <cstdlib>
#include <cmath>
#include <iostream>
#include <ctime>
using std::cout; using std::endl;

int i, j;

void setWindowSize(int cols, int lines)		//设置窗口大小
{
char cmd[30];
sprintf_s(cmd, "mode con cols=%d lines=%d", cols * 2, lines);
system(cmd);
}

void gotoXY(const int x, const int y)		//光标跳转到指定位置
{
COORD point;
point.X = 2 * x;
point.Y = y;
SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), point);
}

void gotoXY(const Point &p)		//光标跳转到指定位置
{
COORD point;
point.X = 2 * p.x;
point.Y = p.y;
SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), point);
}

void setColor(int colorId)		//设置输出颜色
{
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), colorId);
}

Map::Map(const int x, const int y, const int width, const int height)
{
_mapStartingCoord.x = x;
_mapStartingCoord.y = y;
_mapWidth = width + 2;
_mapHeight = height + 2;
memset(_mapObj, 0, sizeof(_mapObj));

for (i = 1; i <= width; ++i)		//初始化抽象地图数组
{
for (j = 1; j <= height; ++j)
_mapObj[i][j] = 1;
}

gotoXY(x, y);
setColor(11);
for (i = 0; i != _mapWidth; ++i)		//根据抽象地图数组把地图画出来
{
for (j = 0; j != _mapHeight; ++j)
{
if (_mapObj[i][j])
cout << "■";
else
cout << "□";
}
cout << endl;
}

refreshFood();
}

void Map::refreshFood()			//刷新食物
{
_food.x = rand() % (_mapWidth - 2) + 1 + _mapStartingCoord.x;
_food.y = rand() % (_mapHeight - 2) + 1 + _mapStartingCoord.y;
gotoXY(_food.x, _food.y);
setColor(12);
cout << "●" << endl;
}

Snake::Snake(Map *map, int defaultLenth)
{
_belongs = map;
_isLife = true;
_direction = DOWN;
_x[0] = _belongs->getWidth() / 2 + _belongs->getMapStartingCoord().x;	//蛇出现在地图最中央
_y[0] = _belongs->getHeight() / 2 + _belongs->getMapStartingCoord().y;
_length = defaultLenth;
int i;
for (i = 1; i != _length; ++i)
{
_x[i] = _x[0];
_y[i] = _y[i - 1] - 1;
}
draw();
}

bool Snake::eatFood()
{
if (_x[0] == _belongs->getFoodCoord().x && _y[0] == _belongs->getFoodCoord().y)		//判断是否吃到食物
{
_x[_length] = _x[_length - 1];		//先让新增加的蛇屁股坐标等与进食前的蛇屁股,移动后会自动刷新
_y[_length] = _y[_length - 1];
++_length;
_belongs->refreshFood();
return true;
}
return false;
}

void Snake::draw()const
{
setColor(14);
for (int i = 0; i < _length; ++i)
{
gotoXY(_x[i], _y[i]);
cout << "★" << endl;
}
}

void Snake::moveUp()
{
gotoXY(_x[_length - 1], _y[_length - 1]);
setColor(11);
cout << "■";
for (i = _length - 1; i != 0; --i)
{
_x[i] = _x[i - 1];
_y[i] = _y[i - 1];
}
_y[0] -= 1;
draw();
}

void Snake::moveDown()
{
gotoXY(_x[_length - 1], _y[_length - 1]);
setColor(11);
cout << "■";
for (i = _length - 1; i != 0; --i)	//蛇的移动算法, 让后一节的坐标等于前一节的坐标
{
_x[i] = _x[i - 1];
_y[i] = _y[i - 1];
}
_y[0] += 1;
draw();
}

void Snake::moveLeft()
{
gotoXY(_x[_length - 1], _y[_length - 1]);
setColor(11);
cout << "■";
for (i = _length - 1; i != 0; --i)
{
_x[i] = _x[i - 1];
_y[i] = _y[i - 1];
}
_x[0] -= 1;
draw();
}

void Snake::moveRight()
{
gotoXY(_x[_length - 1], _y[_length - 1]);
setColor(11);
cout << "■";
for (i = _length - 1; i != 0; --i)
{
_x[i] = _x[i - 1];
_y[i] = _y[i - 1];
}
_x[0] += 1;
draw();
}

void Snake::dead()
{
if (_x[0] <= _belongs->getMapStartingCoord().x		//判断是否碰到地图边框
|| _x[0] >= _belongs->getWidth() + _belongs->getMapStartingCoord().x - 1
|| _y[0] <= _belongs->getMapStartingCoord().y
|| _y[0] >= _belongs->getHeight() + _belongs->getMapStartingCoord().y - 1)
_isLife = false;

for (i = 3; i <= _length - 1; ++i)		//判断是否碰到自己,从第4节开始算,因为头肯定碰不到第2/3节
{
if (_x[0] == _x[i] && _y[0] == _y[i])
_isLife = false;
}
}


控制类头文件 "Controller.h"

#ifndef __CONTROLLER_H_
#define __CONTROLLER_H_
#include "GreedySnake.h"

class Controller
{
private:
Snake *_snake;	//要控制的蛇
char _dir;		//存储方向键
int _gameSpeed;	//游戏速度
int _score;	//分数
public:
Controller(Snake *s, int speed = 200, char dir = 'q') :_snake(s), _gameSpeed(speed), _dir(dir), _score(0){ }
void start();		//开始游戏
void pause();		//暂停
void stop();		//停止
void showScore();	//显示分数
~Controller(){}
};

#endif


控制类实现代码 "Controller.cpp"

#include "Controller.h"
#include <conio.h>
#include <Windows.h>
#include <iostream>
using std::cout;

void Controller::start()
{
char key = '\0';
showScore();
while (1)
{
if (_snake->isLife())
{
if (_kbhit())
{
gotoXY(0, _snake->getBelongsMap()->getHeight() + 2);
_dir = _getche();
}
switch (_dir)
{
case UP:
if (key != DOWN)	//判断是否朝相反方向移动,下同
{
_snake->moveUp();
key = _dir;
}
else
_snake->moveDown(); break;
case DOWN:
if (key != UP)
{
_snake->moveDown();
key = _dir;
}
else
_snake->moveUp(); break;
case LEFT:
if (key != RIGHT)
{
_snake->moveLeft();
key = _dir;
}
else
_snake->moveRight(); break;
case RIGHT:
if (key != LEFT)
{
_snake->moveRight();
key = _dir;
}
else
_snake->moveLeft(); break;
case 8: pause(); break;	//空格键暂停
default:break;
}
_snake->dead();
Sleep(_gameSpeed);
if (_snake->eatFood())
{
++_score;
showScore();
}
}
else
{
stop();
break;
}
}
}

void Controller::pause()
{
while (1)
{
if (_kbhit())
{
gotoXY(0, _snake->getBelongsMap()->getHeight() + 2);
_dir = _getche();
}
if (_dir == 8)
start();
}
}

void Controller::stop()
{
int x = _snake->getBelongsMap()->getWidth() / 2;
int y = _snake->getBelongsMap()->getHeight() / 2;
gotoXY(x, y);
setColor(30);
cout << "game over!";
Sleep(3000);
}

void Controller::showScore()
{
gotoXY(3, 1);
setColor(14);
cout << _score;
}


最后是 "main.cpp"

/* GreedySnake by ian*/

#include "GreedySnake.h"
#include "Controller.h"
#include <cmath>
#include <iostream>
#include <ctime>

void initWindow(int windowWidth, int windowHeight)
{
setWindowSize(windowWidth, windowHeight);
gotoXY(windowWidth / 2 - 3, 0);
setColor(23);
std::cout << "Greedy Snake" << std::endl;
setColor(90);
std::cout << "Score:" << std::endl;
gotoXY(windowHeight - 7, 1);
std::cout << "by ian." << std::endl;
}

int main()
{
srand((unsigned)time(0));

initWindow(28, 30);
Map *map = new Map(0,2,25, 25);
Snake *snake = new Snake(map, 3);
Controller c(snake);
c.start();
delete map;
}


以下是游戏界面.

.


个人感觉控制类的实现还不是太好, 也希望大家能指出
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: