源码网商城,靠谱的源码在线交易网站 我的订单 购物车 帮助

源码网商城

mingw编译的windows命令行贪吃蛇示例

  • 时间:2020-09-03 11:07 编辑: 来源: 阅读:
  • 扫一扫,手机访问
摘要:mingw编译的windows命令行贪吃蛇示例
主线程:维护游戏逻辑,刷新画面。 后台线程:监听按键(getch) 暂时只支持Windows下的MinGW编译,本来用MinGW编译是想写成Linux下也能运行的。结果Linux下面没有直接提供getch()函数(Windows下的<conio.h>有)。 管他呢!纯属娱乐~ 编译要加-lpthread snake_cmd.cpp
[u]复制代码[/u] 代码如下:
#include <limits.h> // for INT_MAX #include <stdio.h> #include <string.h> #include <stdarg.h> #include <pthread.h> #include <list> #include <stack> #include <vector> #include <algorithm> #ifdef WIN32  #include <windows.h>  #include <conio.h> // for console I/O  #define sleep(x) Sleep(1000 * (x))  #define msleep(x) Sleep(x)  #define CLEAR_TERM system("CLS"); #else  #include <unistd.h>  #define msleep(x) usleep(1000 * (x))  #define CLEAR_TERM system("clear"); #endif namespace game { // using namespace std; ///////////////////////////////////////////////////////////////////////////// // for debug #ifdef DEBUG struct Logger {  FILE* out;  Logger(FILE *pf) : out(pf) {}  void operator()(const char *format, ...) {   va_list args;   va_start(args, format);   vfprintf(out, format, args);   va_end(args);  } }; Logger outLogger(stdout); Logger errLogger(stderr); #define log outLogger #define err errLogger // void logger(const char *format, ...) // {  // va_list args;  // va_start(args, format);  // vprintf(format, args);  // va_end(args); // } #else #define logger(fmt, ...) fmt #define log logger #define err logger #endif // #define log logger // #define log outLogger ///////////////////////////////////////////////////////////////////////////// // key values: #define K_SPACE 32 #define K_ESC 27 #define K_W   119 #define K_S   115 #define K_A   97 #define K_D   100 // up, down, left, right Pressed 1 key Return 2 value #define K_DIR   224  // ignore this #define K_UP    72 #define K_DOWN  80 #define K_LEFT  75 #define K_RIGHT 77 // common constants: #ifndef DELAY #define GAME_CYCLE_MS 1000 #else #define GAME_CYCLE_MS DELAY #endif #define MAX_BODY_LEN  128 #define MAX_FOOD_NUM  8 #define WIDTH  64 #define HEIGHT 24 // char constants: #define CH_BORDER '#' #define CH_BLANK  ' ' #define CH_SNAKE  '*' #define CH_SNAKEH '@' #define CH_SNAKET '+' #define CH_FOOD   '$' #define CH_MINE   '#' ///////////////////////////////////////////////////////////////////////////// enum Direction {  UNKNOW, UP, DOWN, LEFT, RIGHT }; struct Point {  int x;  int y;  Point() : x(0), y(0) {}  Point(int xx, int yy) : x(xx), y(yy) {}  bool operator==(const Point &rhs) const {   return x == rhs.x && y == rhs.y;  }  Point& operator+=(const Point &rhs) {   x += rhs.x;   y += rhs.y;   return *this;  }  Point operator+(const Point &rhs) const {   Point res(rhs);   res.x += x;   res.y += y;   return res;  } #ifdef DEBUG  void show() {   log("Point_%p:(%d, %d)\n", this, x, y);  } #endif }; ///////////////////////////////////////////////////////////////////////////// /* dimension:  0---x+  |  y  + */ Point operator+(const Point &point, const Direction &dir) {  Point pt(point);  switch(dir) {   case UP:    pt.y--; break;   case DOWN:    pt.y++; break;   case LEFT:    pt.x--; break;   case RIGHT:    pt.x++; break;   default:    err("ERROR: Point + Direction Error!\n");    break;  }  return pt; } ///////////////////////////////////////////////////////////////////////////// class Snake {  typedef std::vector<Point> body_type;  typedef body_type::iterator body_iter;  typedef body_type::const_iterator body_citer;  Direction dir;  // 前进方向  // Point body[MAX_BODY_LEN]; // 身体位置  body_type body; // 身体位置 public:  Snake(): dir(UNKNOW) {}  Snake(Direction d) : dir(d) {}  void setDir(Direction dir) {   this->dir = dir;  }  void setHead(Point p) {   log("setHead...\n");   // p.show();   if(body.size() == 0) {    body.insert(body.begin(), p);   }  }  int length() const { return body.size(); }  Point getNode(int ino) const { return body[ino]; }  Point getHead() const {   return *body.begin();  }  Point nextHead() const {   return getHead() + dir;  }  bool isOnBody(Point pt) const {   for( body_citer it = body.begin(); it != body.end(); ++it ) {    if( *it == pt ) return true;   }   return false;  }  bool checkDir(Direction newDir) const {   if( dir == UP    && newDir == DOWN    || dir == DOWN  && newDir == UP      || dir == LEFT  && newDir == RIGHT    || dir == RIGHT && newDir == LEFT)    return false;   return true;  }  bool selfCollision() const {   Point h = getHead(); // next time head position   // if( length() > 1 && isOnBody(h) ) return true;   body_citer it = body.begin();   for( ++it; it != body.end(); ++it ) {    if( *it == h ) return true;   }   return false;  }  bool changeDir(Direction newDir) {   if( checkDir(newDir) ) {    setDir(newDir);    return true;   }   else {    return false;   }  }  void move() {   if( ! selfCollision() ) {    Point nh = nextHead();    body.insert(body.begin(), nh);    body.erase(body.end());   }   else {    err("ERROR: move failed! direction incorrect!\n");   }  }  void growth() {   Point nh = nextHead();   body.insert(body.begin(), nh);  }  // void putTo(Point axis) {   // for(body_iter it=body.begin(); it!=body.end(); ++it) {    // *it += axis;   // }  // } #ifdef DEBUG  void show() {   log("Snake_%p:\n", this);   log("{\n");   log("  dir: %d,\n", dir);   log("  body: [");   for(body_citer it = body.begin(); it != body.end(); ++it) {    log("(%d, %d), ", it->x, it->y);   }   log("]\n}\n");  } #endif }; struct PlayGround {  int width;  int height;  bool border;  PlayGround() : width(0), height(0), border(true) {}  PlayGround(int w, int h, bool b) : width(w), height(h), border(b) {  }  // x -- width,  y -- height  bool inArea(int x, int y) {   if( border ) {    if( x < 1 || x >= width-1  ) return false;    if( y < 1 || y >= height-1 ) return false;   }   else { // no border    if( x < 0 || x >= width  ) return false;    if( y < 0 || y >= height ) return false;      }   return true;  }  bool inArea(Point p) { return inArea(p.x, p.y); } #ifdef DEBUG  void show() {   log("PlayGround_%p:\n", this);   log("{\n");   log(" width: %d,\n", width);   log(" height: %d,\n", height);   log(" border: %d,\n", border);   log("}\n");  } #endif  }; enum GameState {  GS_UNKNOW,  GS_START,  GS_PAUSE,  GS_OVER,  GS_EXIT }; class Game {  Snake *snake;  PlayGround *ground;  char buffer[HEIGHT][WIDTH+2];  int  foodCount;  Point *foodBuffer[MAX_FOOD_NUM];  int time;  GameState state;  std::stack<GameState> gsStack; public:  Game() : snake(new Snake(RIGHT)),   ground(new PlayGround(WIDTH, HEIGHT, true)), foodCount(0) { init(); }  ~Game() {   if(ground) delete ground;   if(snake) delete snake;  }  void setState(GameState gs) { state = gs; }  GameState getState() const { return state; }  void pause() {   if( state != GS_PAUSE ) {    state = GS_PAUSE;    gsStack.push(state);    log("state: %d, statck.size(): %d\n", state, gsStack.size());   }   else {    state = gsStack.top();    gsStack.pop();   }  }  void init() {   memset(buffer, 0, sizeof(buffer));     memset(foodBuffer, 0, sizeof(foodBuffer));   Point ph(2, ground->height/3); // init head pos   snake->setHead(ph);   time = 0;  }  void syncGround() { // ground => buffer   for(int x=0; x<ground->width; x++) {    for(int y=0; y<ground->height; y++) {     if( ground->border     && ( y == 0 || y == HEIGHT-1       || x == 0 || x == WIDTH-1  )     ){      buffer[y][x] = CH_BORDER;     }     else buffer[y][x] = CH_BLANK;    }   }  }  void syncSnake() { // snake => buffer   Point head = snake->getNode(0);   buffer[head.y][head.x] = CH_SNAKEH;   for(int i=1; i<snake->length()-1; i++) {    Point p = snake->getNode(i);    buffer[p.y][p.x] = CH_SNAKE;   }   if(snake->length() > 1) {    Point tail = snake->getNode(snake->length()-1);    buffer[tail.y][tail.x] = CH_SNAKET;   }  }  void syncFood() { // foodBuffer => buffer   for(int i=0; i<MAX_FOOD_NUM; i++) {    Point *p = foodBuffer[i];    if(NULL != p) {     buffer[p->y][p->x] = CH_FOOD;    }   }  }  void draw() { // buffer => console     // 0. clear last buffer   memset(buffer, 0, sizeof(buffer));   // 1. sync PlayGround   syncGround();   // 2. sync Snake   syncSnake();   // 3. draw food   syncFood();   // 4. draw to console   for(int i=0; i<HEIGHT; i++) {    puts(buffer[i]);   }  }  bool checkPos(Point p) const {   // check for border   if( ! ground->inArea(p) ) return false;   // check for snake   if( snake->isOnBody(p) ) return false;   // check for foods   for(int i=0; i<MAX_FOOD_NUM; i++) {    if(NULL != foodBuffer[i] && p == *foodBuffer[i]) {     return false;    }   }   return true;  }  void genFood() { // gen food => foodBuffer   log("Food generate...\n");   if( foodCount < MAX_FOOD_NUM ) {    int x, y;    do {     x = rand() % WIDTH;     y = rand() % HEIGHT;    }while( ! checkPos(Point(x, y)) );    for(int i=0; i<MAX_FOOD_NUM; i++) {     if( NULL == foodBuffer[i] ) {      foodBuffer[i] = new Point(x, y);      break;     }    }    foodCount++;    // foodInfo();   }  }  void update() { // move snake once   ++time;   Point nh = snake->nextHead();   // check for eating food   bool willEat = false;   int  foodidx = -1;   for(int i=0; i<MAX_FOOD_NUM; i++) {    if(foodBuffer[i] && *foodBuffer[i] == nh ) {     willEat = true;     foodidx = i;     break;    }   }   if( willEat ) { // snake growth and food delete.    snake->growth();    // food delete.    delete foodBuffer[foodidx];    foodBuffer[foodidx] = NULL;    foodCount--;    // new food.    genFood();   }   else snake->move();   // check for wall collision   if( ground->border ) {    if( nh.x == 0 || nh.x == WIDTH-1     || nh.y == 0 || nh.y == HEIGHT-1 ) {     state = GS_OVER;    }   }   else {    log("UNDEFINE...");    exit(-1);   }   // check for slef colision   if( snake->selfCollision() ) {    state = GS_OVER;    return;   }  }  void snakeTrun(Direction d) {   snake->changeDir(d);  }  void info() {   printf("Greedy Snake! length: %d  time:%d\n", snake->length(), time);  } #ifdef DEBUG  void foodInfo() {   log("foodInfo: {\n");   log(" foodCount: %d,\n", foodCount);   log(" foodBuffer: [");   for(int i=0; i<MAX_FOOD_NUM; i++) {    Point *p = foodBuffer[i];    if( p ) log("(%d, %d)", p->x, p->y);    else log("null");    log("%s", i != MAX_FOOD_NUM-1 ? ", " : "");   }   log("]\n}\n");  }  void show() {   snake->show();   ground->show();   log("buffer:\n");  #if 0   for(int i=0; i<HEIGHT; i++) {    for(int j=0; j<WIDTH; j++) {     log("X ", buffer[i][j]);    }    log("\n");   }  #endif  } #endif }; ///////////////////////////////////////////////////////////////////////////// volatile int keyPressed = INT_MAX;  // 按键缓冲(只记录一次) volatile bool isDirKey = false; Game *pGame = NULL; pthread_t keyLisener; pthread_mutex_t keyBufferLock; void* keyListenFun(void *args) {  while(1) {   keyPressed = getch(); // getch will bolck this thread.   // log("Pressed: %d\n", keyPressed);  }  return NULL; } void init() {  pGame = new Game();  // srand( time(NULL) );  pthread_mutex_init(&keyBufferLock, NULL);   pthread_create(&keyLisener, NULL, keyListenFun, NULL); // 创建按键侦听线程 } void cleanup() {  pthread_cancel(keyLisener);  pthread_mutex_destroy(&keyBufferLock);  delete pGame; } }; ///////////////////////////////////////////////////////////////////////////// int main(int argc, char *argv[]) {  using namespace game;  init();  // pGame->show();  for(int i=0; i<MAX_FOOD_NUM-1; i++)   pGame->genFood();  pGame->draw();  while(1) {   if( GS_PAUSE != pGame->getState() ) {    CLEAR_TERM    switch(keyPressed) {     case K_SPACE: pGame->setState(GS_PAUSE); break;     case K_UP:     case K_W: pGame->snakeTrun(UP); break;     case K_DOWN:     case K_S: pGame->snakeTrun(DOWN); break;     case K_LEFT:     case K_A: pGame->snakeTrun(LEFT); break;     case K_RIGHT:     case K_D: pGame->snakeTrun(RIGHT); break;     case K_ESC: pGame->setState(GS_EXIT); break;    }    pGame->info();    pGame->update();    pGame->draw();   }   else {    switch(keyPressed) {     case K_SPACE: pGame->setState(GS_START); break;     case K_ESC: pGame->setState(GS_EXIT); break;    }   }   if( pGame->getState() == GS_OVER ) {    puts("game over!");    break;   }   else if( pGame->getState() == GS_EXIT ) {    puts("exit!");    break;   }   keyPressed = INT_MAX;   msleep(GAME_CYCLE_MS);  }  cleanup();  return 0; }
Makefile
[u]复制代码[/u] 代码如下:
debug: snake_cmd.cpp  g++ snake_cmd.cpp -lpthread -DDEBUG -DDELAY=1000 -g -Wall release: snake_cmd.cpp  g++ snake_cmd.cpp -lpthread -o snake -DDELAY=1000
  • 全部评论(0)
联系客服
客服电话:
400-000-3129
微信版

扫一扫进微信版
返回顶部