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

来源:互联网 发布:思维江硬 知乎 编辑:程序博客网 时间:2024/06/05 02:05

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


我定义了3个类.

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

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

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


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

#ifndef __GREEDYSNAKE_H_#define __GREEDYSNAKE_H_#define MAXLENGTH 200#define MAXMAPWIDTH 200#define MAXMAPHEIGHT 200enum 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 << "■";elsecout << "□";}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;}


以下是游戏界面.

.


个人感觉控制类的实现还不是太好, 也希望大家能指出

0 0
原创粉丝点击