1. 程式人生 > >C語言貪吃蛇Linux版

C語言貪吃蛇Linux版

/* ======================================= */

Update: 20170713

新版貪吃蛇:傳送門

/* ======================================= */
最近閒來無事用C語言寫了個貪吃蛇解解悶, 其實這玩意兒也不難寫, 其一就是如何繪製蛇和背景, 其二就是怎麼把使用者的輸入實現成蛇的轉向. 我這裡使用了curses.h和pthread.h庫, 前者是在Cmdline下繪製圖形, 後者是多執行緒庫.
當蛇撞到邊界或者自己身體裡, 畫面就會停住, 表示遊戲結束, 這時按任意鍵就會回到主選單.
注意,本遊戲在視窗模式下正常執行,全屏可能會有BUG。
Menu


Game1
Game2
編譯:
g++ main.c -lcurses -pthread

#include <iostream>
#include <cstdio>
#include <cstring>
#include <curses.h>//graph lib
#include <unistd.h>//usleep
#include <pthread.h>// mul process
#include <time.h>
#include <cstdlib>
const int DMENU=1;//the manu status
const int DGAME=2;//start game const int MENU_START=1; const int MENU_EXIT=2; const int MENU_ABOUT=3; const int HEAD_LEFT=1; const int HEAD_DOWN=2; const int HEAD_UP=3; const int HEAD_RIGHT=4; using namespace std; struct curPoint { int x, y; }; struct MainSnack { curPoint body[10000] ; int
len, arrowHead, score, dead; }; char StrMenuOption[10][255]; int MenuTotalLine; int MenuChosed; pthread_t Pid; MainSnack Ms; void xcInit();//Initial for the program void msgDeal(int status);//The process to deal key msg void xcDrawMenu(int chose);//Draw the menu void xcDrawAbout();//Draw the about window void initGame();//Initial the variable for the game void *GameProcess(void *arg); int main() { xcInit(); endwin(); return 0; } void *GameProcess(void *arg) { int cnt=0, i, j; curPoint food; clear(); //food.y = rand()%(LINES-1)+1; //food.x = rand()%(COLS-1)+1; food.y = 0; food.x = 0; while(1) { curPoint tmp; if(food.y == 0) { food.y = rand()%(LINES-1)+1; food.x = rand()%(COLS-1)+1; move(food.y, food.x); addch('O'); } box(stdscr, ACS_VLINE, ACS_HLINE); if(cnt==5) { move(Ms.body[Ms.len].y, Ms.body[Ms.len].x); tmp.x=Ms.body[Ms.len].x; tmp.y=Ms.body[Ms.len].y; addch(' '); for(i=Ms.len-1; i>=1; i--) { Ms.body[i+1].x = Ms.body[i].x; Ms.body[i+1].y = Ms.body[i].y; } switch(Ms.arrowHead) { case HEAD_RIGHT: Ms.body[1].x++; break; case HEAD_LEFT: Ms.body[1].x--; break; case HEAD_UP: Ms.body[1].y--; break; case HEAD_DOWN: Ms.body[1].y++; break; } if(Ms.body[1].x == food.x && Ms.body[1].y == food.y) { food.y=0; Ms.len++; } if(Ms.body[1].x == 0 || Ms.body[1].x == COLS-1 || Ms.body[1].y == 0 || Ms.body[1].y == LINES-1) Ms.dead=1; for(i=1; i<=Ms.len; i++) { for(j=i+1; j<=Ms.len; j++) { if(Ms.body[i].x == Ms.body[j].x && Ms.body[i].y == Ms.body[j].y) { Ms.dead=1; i=Ms.len; break; } } } cnt=0; } if(1==Ms.dead) { move(tmp.y, tmp.x); addch('*'); refresh(); return NULL; }else { for(i=1; i<=Ms.len; i++) { move(Ms.body[i].y, Ms.body[i].x); if(1==i) addch('@'); else addch('*'); } refresh(); } cnt++; usleep(15*1000); } } void initGame() { curPoint tmp; tmp.x = COLS/2; tmp.y = LINES/2; Ms.len = 4; for(int i=1; i<=Ms.len; i++) { Ms.body[i].x = tmp.x-(i-1); Ms.body[i].y = tmp.y; } Ms.arrowHead = HEAD_RIGHT; Ms.score = 0; Ms.dead = 0; } void msgDeal(int status) { int ch; while(1) { if(status == DMENU) { ch = getch(); switch(ch) { case KEY_UP: if(MenuChosed > 1) MenuChosed--; break; case KEY_DOWN: if(MenuChosed < MenuTotalLine) MenuChosed++; break; case '\n': switch(MenuChosed) { case MENU_EXIT: return; break; case MENU_ABOUT: clear(); xcDrawAbout(); break; case MENU_START: clear(); initGame(); srand(time(NULL)); pthread_create(&Pid, NULL, GameProcess, NULL); //GameProcess();//mul process msgDeal(DGAME); //getch(); //return; break; } break; } xcDrawMenu(MenuChosed); }else if(status==DGAME) { ch=getch(); if(1==Ms.dead) return; switch(ch) { case KEY_UP: if(Ms.arrowHead!=HEAD_DOWN) Ms.arrowHead=HEAD_UP; break; case KEY_DOWN: if(Ms.arrowHead != HEAD_UP) Ms.arrowHead=HEAD_DOWN; break; case KEY_LEFT: if(Ms.arrowHead != HEAD_RIGHT) Ms.arrowHead=HEAD_LEFT; break; case KEY_RIGHT: if(Ms.arrowHead != HEAD_LEFT) Ms.arrowHead=HEAD_RIGHT; break; } } } } void xcInit() { strcpy(StrMenuOption[1],"Start"); strcpy(StrMenuOption[2],"Exit"); strcpy(StrMenuOption[3],"About"); MenuTotalLine=3; MenuChosed=MENU_START; initscr();//begin curses mode curs_set(0); noecho();//not echo the character that user input keypad(stdscr, TRUE);//accep arrow key xcDrawMenu(MENU_START);//draw the menu msgDeal(DMENU);//like windows msg deal } void xcDrawMenu(int chose) { int i; char info[]="Snack for superxc V0.8 20151210"; clear(); box(stdscr, ACS_VLINE, ACS_HLINE);//draw the border line curPoint tmpPos; tmpPos.y = LINES/2-MenuTotalLine/2; tmpPos.x = COLS/2; move(tmpPos.y/2, tmpPos.x-strlen(info)/2); waddstr(stdscr, info); for(i=1; i<=MenuTotalLine; i++) { if(i==chose) attron(A_REVERSE); move(tmpPos.y+i-1, tmpPos.x-strlen(StrMenuOption[i])/2); waddstr(stdscr, StrMenuOption[i]); if(i==chose) attroff(A_REVERSE); } refresh(); } void xcDrawAbout() { char info[15][255]; box(stdscr, ACS_VLINE, ACS_HLINE); strcpy(info[1], " "); strcpy(info[2], " "); strcpy(info[3], " mmm m m mmmm mmm m mm m m mmm mmm mmm mmmmm "); strcpy(info[4], " # \" # # #\" \"# #\" # #\" \" #m# #\" \" #\" \" #\" \"# # # # "); strcpy(info[5], " \"\"\"m # # # # #\"\"\"\" # m#m # # # # # # # "); strcpy(info[6], " \"mmm\" \"mm\"# ##m#\" \"#mm\" # m\" \"m \"#mm\" # \"#mm\" \"#m#\" # # # "); strcpy(info[7], " # "); strcpy(info[8], " \" "); strcpy(info[9], "Develop by superxc, Copyright 2011-2015."); for(int i=1; i<=9; i++) { move(i, 1); waddstr(stdscr, info[i]); } refresh(); getch(); }