贪吃蛇C++源码,使用面向对象方式编写
2015-03-18 12:59
573 查看
网上好多贪吃蛇的源码,不过大部分都是用C面向过程的.自己用面向对象写了一个贪吃蛇,不足之处还请大家见谅.
我定义了3个类.
地图类:包括地图的抽象数组, 地图里面包含一个食物的坐标.用户可以自定义地图的起始坐标和宽度高度.
蛇类: 类中有蛇的出生长度,所属地图,方向,是否存活. 蛇可以吃掉食物,左右上下移动,死亡.
控制类: 记录分数,并操纵蛇移动,控制游戏进度暂停/结束.
"GreedySnake.h" //包含了蛇类和地图类.
实现代码 "GreedySnake.cpp" 该文件中还包含了几个画图操作必要的函数
控制类头文件 "Controller.h"
控制类实现代码 "Controller.cpp"
最后是 "main.cpp"
以下是游戏界面.
.
个人感觉控制类的实现还不是太好, 也希望大家能指出
我定义了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; }
以下是游戏界面.
.
个人感觉控制类的实现还不是太好, 也希望大家能指出
相关文章推荐
- 一个使用面向对象方式编写的简单游戏框架
- Silverlight实用窍门系列:22.Silverlight使用WebService调用C++,Delphi编写的DLL文件【实例源码下载】
- Silverlight实用窍门系列:22.Silverlight使用WebService调用C++,Delphi编写的DLL文件【实例源码下载】
- Lua和C++交互 学习记录之九:在Lua中以面向对象的方式使用C++注册的类
- 跨平台C++开源码的两种经常使用编译方式
- SpringMVC 中文件上传 MultipartResolver两种使用方式及简单源码分析
- 使用tf库:编写tf广播器(C++)
- 使用纯文本方式编写软件设计文档
- 使用C/C++编写Python扩展库
- 使用Xcode阅读Makefile管理的C/C++项目源码(支持调试,符号跳转,自动补全)
- Qt5 C++源码中使用中文的简单步骤
- C++使用OLE高速读写EXCEL的源码
- c++模版声明定义及使用方式
- 求两个正整数的最大公约数 使用c++ class编写
- 一元二次方程求解 使用c++ class编写
- kiss-rpc IDL协议编写和使用方式
- 【C++】利用Visual Studio 2008编写C++,Visual Studio 2008的基本使用
- java 使用面向对象方式实现录入学生信息,取出成绩最大值、最小值、平均值、对其进行排序
- C++ 项目中直接使用JsonCpp源码文件
- Android ConstraintLayout详解-使用可视化的方式来编写界面