控制台小游戏之贪吃蛇

来源:互联网 发布:java中冒泡排序法代码 编辑:程序博客网 时间:2024/04/29 16:55

贪吃蛇和俄罗斯方块差不多,都是另起一个线程监听键盘输入,然后就是不断刷新。(控制台跳屏的感觉真不爽,感觉要瞎了)


很简单的就一个snake类和一个game类外加辅助的random_food可调用对象类。用枚举变量代表snake当前的行进方向


point_and_dir.h


#ifndef _POINT_AND_DIR_H#define _POINT_AND_DIR_Henum _direction{ _up, _left, _down, _right };class _pt{public:_pt(int x = 0, int y = 0) :_x(x), _y(y){}inline int x()const{ return _x; }inline int y()const{ return _y; }inline void set(int x, int y){ _x = x, _y = y; }bool operator== (const _pt & rhs){if (x() == rhs.x() && y() == rhs.y())return true;return false;}private:int _x;int _y;};#endif


random_food.h


#ifndef _RANDOM_FOOD_H#define _RANDOM_FOOD_H#include<random>#include"point_and_dir.h"struct Random_food{_pt operator()(int h,int w){static std::default_random_engine e;static std::uniform_int_distribution<unsigned> u(0, ~(1<<31));return _pt(u(e) % h, u(e) % w);}};#endif



snake.h


#ifndef _SNAKE_H#define _SNAKE_H#include<list>#include"point_and_dir.h"class Snake{public:Snake(int x = 0, int y = 0) :dir(_right),body(std::list<_pt>(1,_pt(x,y))){}void move();void grow();bool collided();bool setdir(_direction);int length()const{ return body.size(); }_pt bodies(int i){if (i >= length() || i < 0)return _pt(-1,-1);auto it = body.begin();while (i--)++it;return *it;}private:_direction dir;std::list<_pt> body;};#endif


game.h


#ifndef _GAME_H#define _GAME_H#include<mutex>#include"snake.h"class game{public:game(int w = 60, int h = 25) :mtx(),score(0),width(w),height(h),growing(false),food(0, 0),snake(height / 2, width / 2){makefood();}void start();private:void print();void keylistener();void keydown(char);void move();bool setdir(_direction);void makefood();bool crashed();void checkfood();std::mutex mtx;int score;int width;int height;bool growing;_pt food;Snake snake;};#endif


snake.cpp


#include"snake.h"void Snake::move(){grow();body.pop_back();}void Snake::grow(){int x = body.front().x();int y = body.front().y();_pt offset;switch (dir){case_up:offset.set(x - 1, y);break;case  _left:offset.set(x, y - 1);break;case  _down:offset.set(x + 1, y);break;case _right:offset.set(x, y + 1);break;default   :break;}body.push_front(offset);}bool Snake::collided(){int headx = body.front().x();int heady = body.front().y();auto it = body.begin();for (++it; it != body.end(); ++it)if (headx == it->x() && heady == it->y())return true;return false;}bool Snake::setdir(_direction d){if (dir == d || dir == (d + 2) % 4)return false;dir = d;return true;}


game.cpp


#include<conio.h>#include<vector>#include<string>#include<thread>#include<iostream>#include<Windows.h>#include"game.h"#include"random_food.h"void game::print(){system("cls");std::vector<std::string> win(std::vector<std::string>(height, std::string(width * 2, ' ')));std::string s = "●";win[food.x()][food.y() * 2] = s[0];win[food.x()][food.y() * 2 + 1] = s[1];s = "■";for (int i = 1; i != snake.length(); ++i)win[snake.bodies(i).x()][2 * snake.bodies(i).y()] = s[0],win[snake.bodies(i).x()][2 * snake.bodies(i).y() + 1] = s[1];s = "○";win[snake.bodies(0).x()][2 * snake.bodies(0).y()] = s[0];win[snake.bodies(0).x()][2 * snake.bodies(0).y() + 1] = s[1];std::cout << "||";for (int i = 0; i < width * 2; ++i)std::cout << "=";std::cout << "||" <<std::endl;for (int i = 0; i != height; ++i)std::cout << "||" << win[i] << "||" << std::endl;std::cout << "||";for (int i = 0; i < width * 2; ++i)std::cout << "=";std::cout << "||" << std::endl;std::cout << "\t\t\t\t\t\t\tSCORE:" << score << std::endl;}void game::keydown(char c){switch (c){case 'w': if(setdir(_up)) move();break;case 'a': if(setdir(_left))  move();break;case 's': if(setdir(_down))  move();break;case 'd': if(setdir(_right)) move();break;default:break;}}void game::checkfood(){if (snake.bodies(0) == food){++score;growing = true;makefood();}}void game::move(){if (growing){snake.grow();growing = false;}else snake.move();checkfood();}bool game::setdir(_direction dir){return snake.setdir(dir);}void game::makefood(){food = Random_food()(height,width);}bool game::crashed(){if (snake.collided()  ||snake.bodies(0).x() >= height ||snake.bodies(0).x() < 0  ||snake.bodies(0).y() >= width  ||snake.bodies(0).y() < 0)return true;return false;}void game::keylistener(){while (true){char c;c = _getch();mtx.lock();keydown(c);if (crashed())break;print();mtx.unlock();}mtx.unlock();}void game::start(){std::thread t(&game::keylistener, this);t.detach();while (true){if (mtx.try_lock()){move();if (crashed())break;print();mtx.unlock();}Sleep(200);}mtx.unlock();std::cout << "GAME OVER!" << std::endl;}



食用方法:

main.cpp


#include"game.h"int main(){game g(30,20);g.start();return 0;}


0 0
原创粉丝点击