如何在Linux的命令行中做一个linux c语言贪吃蛇蛇游戏

2387人阅读
一直渴望写一个自己的贪吃蛇游戏,看完国外网友的后发现,自己的能力还是不足以“手写”出这样一个属于自己的程序。这段代码存在上已经3周了,尽管我想等自己完全能够手写出自己的程序,但却还是不想把这篇早该完成的博客留在明年。
这里要用到以管理基于文本的屏幕()
1.各项初始化工作:
void init() {
initscr();//屏幕控制初始化,如果成功,返回一个只想stdscr结构的指针
raw(); //关闭特殊字符的处理
noecho();//关闭输入字符的回显功能
keypad(stdscr, TRUE);
curs_set(0);
nodelay(stdscr, TRUE);
keypad模式:
int keypad(WINDOW *window_ptr, bool keypad_on);
在keypad模式中,curses将接管按键转义序列的处理功能,读键盘操作不仅能够返回用户按下的键,还将返回与逻辑按键相对应的KEY_定义。
2.用结构体表示snack和food:
struct Snack {
int x[100];
int y[100];
struct Food {
3.打印出snack和food:
void draw() {
snack.x[0] = 6;
snack.y[0] = 3;
snack.x[1] = 5;
snack.y[1] = 3;
snack.x[2] = 4;
snack.y[2] = 3;
snack.life = 0;
snack.node = 3;
snack.direction = 4;
food.set = 0;
for (i = 0; i & snack. i++)
mvprintw(snack.y[i], snack.x[i], &*&);
refresh();
timer = time(NULL);
mvprintw()函数:
int myprintw(int y, int x, char *format, ...)在指定的位置打印(x,y)字符串format.
随机生成food:
if (food.set == 0) {
food.X = rand() % 50;
while (food.X == 0 || food.X == 49)
food.X = rand() % 50;
food.Y = rand() % 20;
while (food.Y == 0 || food.Y == 19)
food.Y = rand() % 20;
food.set = 1;
4.打印四面墙
void color() {
start_color();
init_pair(1, COLOR_GREEN, COLOR_RED);
attron(COLOR_PAIR(1));
for (i = 0; i & 50; i++)
mvaddch(0, i, '*');
for (i = 0; i & 20; i++)
mvaddch(i, 0, '*');
for (i = 49; i &= 0; i--)
mvaddch(19, i, '*');
for (i = 19; i &= 0; i--)
mvaddch(i, 49, '*'); //box(stdscr,'*','*');
attroff(COLOR_PAIR(1));
start_color()函数对curses的颜色例程进行初始化
init_pair()函数对准备使用的颜色组合进行初始化
attron()函数在不影响其他属性的前提下启用制定的属性
5.判断前进方向:
void judge() {
if (snack.direction == 1) //up
snack.y[0]--;
else if (snack.direction == 2)//down
snack.y[0]++;
else if (snack.direction == 3)//left
snack.x[0]--;
else //right
snack.x[0]++;
ch = getch();
switch (ch) {
case (KEY_UP):
if (snack.direction == 3 || snack.direction == 4) {
snack.y[0]--;
snack.direction = 1;
} else if (snack.direction == 1)
snack.y[0]--;
snack.y[0]++;
case (KEY_DOWN):
if (snack.direction == 3 || snack.direction == 4) {
snack.y[0]++;
snack.direction = 2;
} else if (snack.direction == 1)
snack.y[0]--;
snack.y[0]++;
case (KEY_LEFT):
if (snack.direction == 1 || snack.direction == 2) {
snack.x[0]--;
snack.direction = 3;
} else if (snack.direction == 3)
snack.x[0]--;
snack.x[0]++;
case (KEY_RIGHT):
if (snack.direction == 1 || snack.direction == 2) {
snack.x[0]++;
snack.direction = 4;
} else if (snack.direction == 3)
snack.x[0]--;
snack.x[0]++;
6.蛇吃到食物
if (snack.x[0] == food.X && snack.y[0] == food.Y) {
food.set = 0;
snack.node++;
score += 10;
for (i = snack.node - 1; i & 0; i--) {
snack.x[i] = snack.x[i - 1];
snack.y[i] = snack.y[i - 1];
7.游戏结束的判断
if ((snack.x[0] == snack.x[i] && snack.y[0] == snack.y[i])
|| snack.x[0] == 0 || snack.y[0] == 0 || snack.x[0] == 49
|| snack.y[0] == 19) {
for (i = 1; i & snack. i++) {
snack.x[i - 1] = snack.x[i];
snack.y[i - 1] = snack.y[i];
snack.y[snack.node - 1] = tem[0];
snack.x[snack.node - 1] = tem[1];
for (i = 0; i & snack. i++)
mvprintw(snack.y[i], snack.x[i], &*&);
mvaddch(food.Y, food.X, '*');
start_attr();
mvprintw(10, 10, &You lose!&);
mvprintw(11, 10, &Do you want again?(y/n)&);
snack.life = 1;
//sleep(1);
完整程序如下:(编译命令:)
#include&curses.h&
#include&stdlib.h&
#include&unistd.h&
#include&time.h&
struct Snack {
int x[100], y[100];
struct Food {
int TIME = 0;
long Time, Time1 = 0, Time2 = 0;
int ptime[100];
int score = 0;
int i, tem[2], k = 0;
void color();
void init();
void draw();
void start_attr();
void output();
void play();
void judge();
int pause_time(int, int *);
void d_e();
int main(int argc, char **argv) {
void d_e() {
int location = 18;
int ch2 = KEY_LEFT, which = 0;
char str[2][5] = { &Easy&, &Hard& };
while (ch2 != '\n') {
switch (ch2) {
case (KEY_LEFT):
if (location != 18) {
location -= 10;
which = 0;
case (KEY_RIGHT):
if (location == 18) {
location += 10;
which = 1;
mvprintw(8, 10, &Please choose the difficulty!&);
mvprintw(10, 23, &^_^&);
mvprintw(12, 18, &Easy&);
mvprintw(12, 28, &Hard&);
attron(A_REVERSE);
mvprintw(12, location, &%s&, str[which]);
attroff(A_REVERSE);
refresh();
ch2 = getch();
/*Time2=time(NULL);
ptime[k]=Time2-Time1;
if (location == 28)
delay.tv_nsec = ;
delay.tv_nsec = ;
int pause_time(int k, int *PTIME) {
int sum = 0;
for (j = 0; j & j++)
sum = sum + ptime[j];
void judge() {
if (snack.direction == 1)
snack.y[0]--;
else if (snack.direction == 2)
snack.y[0]++;
else if (snack.direction == 3)
snack.x[0]--;
snack.x[0]++;
void color() {
start_color();
init_pair(1, COLOR_GREEN, COLOR_RED);
attron(COLOR_PAIR(1));
for (i = 0; i & 50; i++)
mvaddch(0, i, '*');
for (i = 0; i & 20; i++)
mvaddch(i, 0, '*');
for (i = 49; i &= 0; i--)
mvaddch(19, i, '*');
for (i = 19; i &= 0; i--)
mvaddch(i, 49, '*'); //box(stdscr,'*','*');
attroff(COLOR_PAIR(1));
void init() {
initscr();
keypad(stdscr, TRUE);
curs_set(0);
nodelay(stdscr, TRUE);
void draw() {
snack.x[0] = 6;
snack.y[0] = 3;
snack.x[1] = 5;
snack.y[1] = 3;
snack.x[2] = 4;
snack.y[2] = 3;
snack.life = 0;
snack.node = 3;
snack.direction = 4;
food.set = 0;
for (i = 0; i & snack. i++)
mvprintw(snack.y[i], snack.x[i], &*&);
refresh();
timer = time(NULL);
void output() {
mvprintw(20, 0, &Score=%d&, score);
mvprintw(20, 43, &Node=%d&, snack.node);
mvprintw(21, 0, &Time=%ds&, TIME);
attroff(A_REVERSE);
refresh();
void start_attr() {
attron(A_REVERSE);
void play() {
while (1) {
Time = time(NULL);
TIME = Time - timer - pause_time(k, ptime);
if (food.set == 0) {
food.X = rand() % 50;
while (food.X == 0 || food.X == 49)
food.X = rand() % 50;
food.Y = rand() % 20;
while (food.Y == 0 || food.Y == 19)
food.Y = rand() % 20;
food.set = 1;
tem[0] = snack.y[snack.node - 1];
tem[1] = snack.x[snack.node - 1];
for (i = snack.node - 1; i & 0; i--) {
snack.x[i] = snack.x[i - 1];
snack.y[i] = snack.y[i - 1];
int ch = 0;
ch = getch();
switch (ch) {
case (KEY_UP):
if (snack.direction == 3 || snack.direction == 4) {
snack.y[0]--;
snack.direction = 1;
} else if (snack.direction == 1)
snack.y[0]--;
snack.y[0]++;
case (KEY_DOWN):
if (snack.direction == 3 || snack.direction == 4) {
snack.y[0]++;
snack.direction = 2;
} else if (snack.direction == 1)
snack.y[0]--;
snack.y[0]++;
case (KEY_LEFT):
if (snack.direction == 1 || snack.direction == 2) {
snack.x[0]--;
snack.direction = 3;
} else if (snack.direction == 3)
snack.x[0]--;
snack.x[0]++;
case (KEY_RIGHT):
if (snack.direction == 1 || snack.direction == 2) {
snack.x[0]++;
snack.direction = 4;
} else if (snack.direction == 3)
snack.x[0]--;
snack.x[0]++;
Time1 = time(NULL);
for (i = 0; i & snack. i++)
mvprintw(snack.y[i], snack.x[i], &*&);
mvaddch(food.Y, food.X, '*');
start_attr();
mvprintw(9, 10, &Pause!Press 'p' to continue!&);
while (getch() != 'p')
Time2 = time(NULL);
ptime[k] = Time2 - Time1;
Time1 = time(NULL);
for (i = 0; i & snack. i++)
mvprintw(snack.y[i], snack.x[i], &*&);
mvaddch(food.Y, food.X, '*');
start_attr();
mvprintw(10, 22, &Quit!&);
int location = 18;
int ch2 = KEY_LEFT, which = 0;
char str[2][5] = { &No&, &Yes& };
while (ch2 != '\n') {
switch (ch2) {
case (KEY_LEFT):
if (location != 18) {
location -= 10;
which = 0;
case (KEY_RIGHT):
if (location == 18) {
location += 10;
which = 1;
mvprintw(12, 18, &No&);
mvprintw(12, 28, &Yes&);
attron(A_REVERSE);
mvprintw(12, location, &%s&, str[which]);
attroff(A_REVERSE);
refresh();
ch2 = getch();
Time2 = time(NULL);
ptime[k] = Time2 - Time1;
if (location == 18)
for (i = 1; i & snack. i++)
if ((snack.x[0] == snack.x[i] && snack.y[0] == snack.y[i])
|| snack.x[0] == 0 || snack.y[0] == 0 || snack.x[0] == 49
|| snack.y[0] == 19) {
for (i = 1; i & snack. i++) {
snack.x[i - 1] = snack.x[i];
snack.y[i - 1] = snack.y[i];
snack.y[snack.node - 1] = tem[0];
snack.x[snack.node - 1] = tem[1];
for (i = 0; i & snack. i++)
mvprintw(snack.y[i], snack.x[i], &*&);
mvaddch(food.Y, food.X, '*');
start_attr();
mvprintw(10, 10, &You lose!&);
mvprintw(11, 10, &Do you want again?(y/n)&);
snack.life = 1;
//sleep(1);
if (snack.x[0] == food.X && snack.y[0] == food.Y) {
food.set = 0;
snack.node++;
score += 10;
for (i = snack.node - 1; i & 0; i--) {
snack.x[i] = snack.x[i - 1];
snack.y[i] = snack.y[i - 1];
if (snack.life == 0) {
for (i = 0; i & snack. i++)
mvprintw(snack.y[i], snack.x[i], &*&);
//attron(A_INVIS);
mvaddch(food.Y, food.X, '*');
//sleep(1);
//attroff(A_INVIS);
start_attr();
nanosleep(&delay, &dummy); //sleep(2);
while (ch1 = getch())
if (ch1 == 'y' || ch1 == 'Y') {
for (i = 0; i & snack. i++)
snack.x[i] = snack.y[i] = -1;
TIME = Time1 = Time2 = k = 0;
score = 0;
snack.life = 0;
} else if (ch1 == 'n' || ch1 == 'N') {
附一张程序运行图:
------------------------------------------------------------------------------------------------------------------------------
本文还需完善。
参考知识库
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:1503924次
积分:13508
积分:13508
排名:第790名
原创:326篇
转载:126篇
评论:375条
(3)(7)(1)(1)(7)(3)(4)(6)(1)(2)(3)(1)(5)(4)(8)(6)(2)(4)(1)(6)(11)(11)(15)(15)(16)(18)(29)(13)(29)(23)(19)(27)(16)(21)(23)(11)(9)(22)(20)(5)(1)(4)(1)(10)(9)linux字符界面下贪吃蛇游戏制作
 一、视频游戏如何做
  (1)空间:游戏必须在计算机屏幕的特定位置画影像。程序如何控制视频显示?
  (2)时间:影像以不同的速度在屏幕上移动。以一个特定的时间间隔改变位置。程序是如何获知时间并且在特定的时间安排事情的发生?
  (3)中断:程序在屏幕上平滑移动的物体,用户可以在任何时刻产生输入。程序是如何响应中断的?
  (4)同时做几件事:游戏必须在保持几个物体移动的同时还要响应中断。程序是如何同时做多件事情而不被弄得晕头转向的?
  二、操作系统面临着类似的问题
  操作系统同样要面对这4个问题。内核将程序载入内存空间并维护每个程序在内存中所处的位置。在内核的调度下,程序以时间片间隔的方式运行,同时,内核也在特定的时刻运行特定的内部任务。内核必须在很短的时间内响应用户和外设在任何时刻的输入。同时做几件事需要一些技巧。内核是如何保证数据的有序和规整的?
  上面的都是那本书上说的,个人觉得讲的很好,看完这本后再看那本Linux圣经《Unix环境高级编程》或许更好些。回归正题吧,主要介绍一下设计一个终端下的贪吃蛇游戏所实现的功能以及所需要的几个条件和一些函数。
  本贪吃蛇实现的功能是通过吃食物来增长自己的长度,可以利用按键 'f' 实现加速和 's' 键实现减速, 'q'
键退出,方向键控制方向,蛇要是碰到自己的身体或者碰到墙或者吃到一定数量,那么游戏就结束。功能还是挺简单的吧,下面就介绍下各个步骤的设计:
  1.首先要使用终端图形库curses.h文件,由于不是C标准库,一般电脑不会自带,需要自行下载安装,ubuntu下可以这么下载&&sudo
apt-get install libncurses5-dev
&已经替换成ncurses.h 即 new
curses.h的意思,完全兼容curses。介绍下此游戏需要用到的常见的几个curses函数。
基本curse函数
初始化curses库和tty
关闭curses并重置tty
刷新屏幕显示
mvaddch(y,x,c)
在坐标(y,x)处显示字符c
mvaddstr(y,x,str)
在坐标(y,x)处显示字符串str
开启输入立即响应
输入不回显到屏幕
curs_set(0)
使光标不可见
开启图形显示模式
keypad(stdscr, true)
开启小键盘方向键输入捕捉支持
更详细的可以
&man ncurses &
  2.介绍完ncurses图形库,接下来进行屏幕绘图,我初始化屏幕效果图见下图所示:先是外围边框,然后是蛇“@”和食物“*”。
废话不多说,上代码吧。
首先是头文件
snake.h的代码:由于在纯文本模式下编程以及本人英语水平有限,可能有的注释比较别扭。
接下来是初始化界面图形的子函数:
  3.接下来就是蛇的移动问题,这个是核心部分以及最困难的设计部分了,我采用的是蛇用双向链表的结构来构造出来,分别有一个head
和tail指针,用来添加和删除元素。这里若要实现移动的话(未碰到食物前),就是在链表的头部(head的下一个)插入一个新元素,记录下此时的坐标,用mvaddch(y,x,c)函数添加蛇的图形'@',与此同时,在链表尾部(tail的前一个)删除一个节点,同时这里的坐标用mvaddch(y,x,
' ')添加了' '空白字符,实现删除效果,最后加上refresh().
这样就可以看到蛇在“移动”了。当然,要是碰到食物的话,尾部节点处就不用删除,达到增长长度的效果。
  那么,接下来的问题是:如何触发蛇的移动呢?如何实现均匀移动以及通过按键 ‘f’ 或 's'
改变运动速度呢?这里我采用的是信号计时中断调用的函数 &signal(SIGALRM,
Snake_Move) 和
间隔计数器来实现,通过产生相同间隔的时间片段来不断地调用Snake_Move()函数来执行相应的功能。加减速的功能是通过设定其他变量ttm,
ttg来实现再此基本计数器上面再次分频的效果来加减速,ttm, ttg 越大,减速越明显,反之则相反效果。
&具体的间隔计数器的函数设计见下:(参考了以上所提书本上的函数)
  蛇的移动的函数代码如下:
主要函数的实现就是这些,以下贴上完整的源代码供大家参考,或者去这里下载:
  通过本程序可以加强自己对信号间隔计数器的理解,以及终端图形编程的理解和了解设计的此类游戏的一般思路,也实现了我大一学习C语言所想要实现的想法。本人第一次在CSDN上面把自己的一些编程想法写的比较详细,不足之处还请指出,共同讨论。
  参考资料:《Unix/Linux编程实践教程》 &
&(美)Bruce Molay 著 &
& & 杨宗源 & 黄海涛
& & 清华大学出版社
&curses库的使用
&贪吃蛇双链表模型
以上网友发言只代表其个人观点,不代表新浪网的观点或立场。mingw编译的windows命令行贪吃蛇示例
字体:[ ] 类型:转载 时间:
这篇文章主要介绍了mingw编译的windows命令行贪吃蛇示例,需要的朋友可以参考下
主线程:维护游戏逻辑,刷新画面。后台线程:监听按键(getch)
暂时只支持Windows下的MinGW编译,本来用MinGW编译是想写成Linux下也能运行的。结果Linux下面没有直接提供getch()函数(Windows下的&conio.h&有)。
管他呢!纯属娱乐~
编译要加-lpthread
snake_cmd.cpp
代码如下:#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 {///////////////////////////////////////////////////////////////////////////////// for debug#ifdef DEBUGstruct Logger {&FILE*&Logger(FILE *pf) : out(pf) {}&void operator()(const char *format, ...) {&&va_&&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_&// 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{&&&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 *&}&Point operator+(const Point &rhs) const {&&Point res(rhs);&&res.x +=&&res.y +=&&&}#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--;&&case DOWN:&&&pt.y++;&&case LEFT:&&&pt.x--;&&case RIGHT:&&&pt.x++;&&default:&&&err("ERROR: Point + Direction Error!\n");&&&&}&}
/////////////////////////////////////////////////////////////////////////////class Snake{&typedef std::vector&Point& body_&typedef body_type::iterator body_&typedef body_type::const_iterator body_
&D& // 前进方向&// Point body[MAX_BODY_LEN]; // 身体位置&body_ // 身体位置public:
&Snake(): dir(UNKNOW) {}&Snake(Direction d) : dir(d) {}&void setDir(Direction dir) {&&this-&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() +&}&bool isOnBody(Point pt) const {&&for( body_citer it = body.begin(); it != body.end(); ++it ) {&&&if( *it == pt )&&}&&&}&bool checkDir(Direction newDir) const {&&if( dir == UP&&& && newDir == DOWN&& ||&dir == DOWN& && newDir == UP&& && || dir == LEFT& && newDir == RIGHT && || dir == RIGHT && newDir == LEFT) &&&&&&}
&bool selfCollision() const {&&Point h = getHead(); // next time head position&&// if( length() & 1 && isOnBody(h) )&&body_citer it = body.begin();&&for( ++ it != body.end(); ++it ) {&&&if( *it == h )&&}&&&}&bool changeDir(Direction newDir) {&&if( checkDir(newDir) ) {&&&setDir(newDir);&&&&&}&&else {&&&&&}&}&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 +=&&// }&// }#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 {&&&&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& )&&&if( y & 1 || y &= height-1 )&&}&&else { // no border&&&if( x & 0 || x &= width& )&&&if( y & 0 || y &= height )&&&&&}&&&}&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 *&PlayGround *&char buffer[HEIGHT][WIDTH+2];&int& foodC&Point *foodBuffer[MAX_FOOD_NUM];&&GameS&std::stack&GameState& gsSpublic:&Game() : snake(new Snake(RIGHT)),&&ground(new PlayGround(WIDTH, HEIGHT, true)), foodCount(0) { init(); }&~Game() { &&if(ground) &&if(snake)&}&void setState(GameState gs) { state = }&GameState getState() const { }&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-& x++) {&&&for(int y=0; y&ground-& 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) )&&// check for snake&&if( snake-&isOnBody(p) )&&// check for foods&&for(int i=0; i&MAX_FOOD_NUM; i++) { &&&if(NULL != foodBuffer[i] && p == *foodBuffer[i]) {&&&&&&&}&&}&&&}&void genFood() { // gen food =& foodBuffer&&log("Food generate...\n");&&if( foodCount & MAX_FOOD_NUM ) {&&&int x,&&&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);&&&&&&&&&}&&&}&&&foodCount++;&&&// foodInfo();&&}&}&void update() { // move snake once&&++&&Point nh = snake-&nextHead();&&// check for eating food&&bool willEat =&&int& foodidx = -1;&&for(int i=0; i&MAX_FOOD_NUM; i++) {&&&if(foodBuffer[i] && *foodBuffer[i] == nh ) {&&&&willEat =&&&&foodidx =&&&&&&&}&&}&&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;&&&&&}&}
&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("%02X ", buffer[i][j]);&&&}&&&log("\n");&&}&#endif&}#endif};
/////////////////////////////////////////////////////////////////////////////volatile int keyPressed = INT_MAX;& // 按键缓冲(只记录一次)volatile bool isDirKey =Game *pGame = NULL;
pthread_t keyLpthread_mutex_t keyBufferL
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 pG}
/////////////////////////////////////////////////////////////////////////////int main(int argc, char *argv[]){&&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);&&&&case K_UP:&&&&case K_W: pGame-&snakeTrun(UP);&&&&case K_DOWN:&&&&case K_S: pGame-&snakeTrun(DOWN);&&&&case K_LEFT:&&&&case K_A: pGame-&snakeTrun(LEFT);&&&&case K_RIGHT:&&&&case K_D: pGame-&snakeTrun(RIGHT);&&&&case K_ESC: pGame-&setState(GS_EXIT);&&&}&&&pGame-&info();&&&pGame-&update();&&&pGame-&draw();&&}&&else {&&&switch(keyPressed) {&&&&case K_SPACE: pGame-&setState(GS_START);&&&&case K_ESC: pGame-&setState(GS_EXIT);&&&}&&}&&if( pGame-&getState() == GS_OVER ) {&&&puts("game over!");&&&&&}&&else if( pGame-&getState() == GS_EXIT ) {&&&puts("exit!");&&&&&}&&keyPressed = INT_MAX;&&msleep(GAME_CYCLE_MS);&}&cleanup();&return 0;}
代码如下:debug: snake_cmd.cpp&g++ snake_cmd.cpp -lpthread -DDEBUG -DDELAY=1000 -g -Wallrelease: snake_cmd.cpp&g++ snake_cmd.cpp -lpthread -o snake -DDELAY=1000
您可能感兴趣的文章:
大家感兴趣的内容
12345678910
最近更新的内容
常用在线小工具}

我要回帖

更多关于 linux 贪吃蛇 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信