linux下怎么编译贪吃蛇,Linux 环境下C语言编译实现贪吃蛇游戏(转载)

本文转载 http://www.linuxidc.com/Linux/2011-08/41375.htm本文可以改进的就是它的链表实现的方式,可以考虑内核的链表实现

#include

#include

<

stdlib.h

>

#include

<

curses.h

>

#include

<

signal.h

>

#include

<

sys

/

time.h

>

#define

NUM 60

struct

direct

//

用来表示方向的

{

int

cx;

int

cy;

};

typedef

struct

node

//

链表的结点

{

int

cx;

int

cy;

struct

node

*

back;

struct

node

*

next;

}node;

void

initGame();

//

初始化游戏

int

setTicker(

int

);

//

设置计时器

void

show();

//

显示整个画面

void

showInformation();

//

显示游戏信息(前两行)

void

showSnake();

//

显示蛇的身体

void

getOrder();

//

从键盘中获取命令

void

over(

int

i);

//

完成游戏结束后的提示信息

void

creatLink();

//

(带头尾结点)双向链表以及它的操作

void

insertNode(

int

x,

int

y);

void

deleteNode();

void

deleteLink();

int

ch;

//

输入的命令

int

hour, minute, second;

//

时分秒

int

length, tTime, level;

//

(蛇的)长度,计时器,(游戏)等级

struct

direct dir, food;

//

蛇的前进方向,食物的位置

node

*

head,

*

tail;

//

链表的头尾结点

int

main()

{

initscr();

initGame();

signal(SIGALRM, show);

getOrder();

endwin();

return

0

;

}

void

initGame()

{

cbreak();

//

把终端的CBREAK模式打开

noecho();

//

关闭回显

curs_set(

0

);

//

把光标置为不可见

keypad(stdscr,

true

);

//

使用用户终端的键盘上的小键盘

srand(time(

0

));

//

设置随机数种子

//

初始化各项数据

hour

=

minute

=

second

=

tTime

=

0

;

length

=

1

;

dir.cx

=

1

;

dir.cy

=

0

;

ch

=

'

A

'

;

food.cx

=

rand()

%

COLS;

food.cy

=

rand()

%

(LINES

-

2

)

+

2

;

creatLink();

setTicker(

20

);

}

//

设置计时器(这个函数是书本上的例子,有改动)

int

setTicker(

int

n_msecs)

{

struct

itimerval new_timeset;

long

n_sec, n_usecs;

n_sec

=

n_msecs

/

1000

;

n_usecs

=

( n_msecs

%

1000

)

*

1000L

;

new_timeset.it_interval.tv_sec

=

n_sec;

new_timeset.it_interval.tv_usec

=

n_usecs;

n_msecs

=

1

;

n_sec

=

n_msecs

/

1000

;

n_usecs

=

( n_msecs

%

1000

)

*

1000L

;

new_timeset.it_value.tv_sec

=

n_sec ;

new_timeset.it_value.tv_usec

=

n_usecs ;

return

setitimer(ITIMER_REAL,

&

new_timeset, NULL);

}

void

showInformation()

{

tTime

++

;

if

(tTime

>=

1000000

)

//

tTime

=

0

;

if

(

1

!=

tTime

%

50

)

return

;

move(

0

,

3

);

//

显示时间

printw(

"

time: %d:%d:%d %c

"

, hour, minute, second);

second

++

;

if

(second

>

NUM)

{

second

=

0

;

minute

++

;

}

if

(minute

>

NUM)

{

minute

=

0

;

hour

++

;

}

//

显示长度,等级

move(

1

,

0

);

int

i;

for

(i

=

0

;i

<

COLS;i

++

)

addstr(

"

-

"

);

move(

0

, COLS

/

2

-

5

);

printw(

"

length: %d

"

, length);

move(

0

, COLS

-

10

);

level

=

length

/

3

+

1

;

printw(

"

level: %d

"

, level);

}

//

蛇的表示是用一个带头尾结点的双向链表来表示的,

//

蛇的每一次前进,都是在链表的头部增加一个节点,在尾部删除一个节点

//

如果蛇吃了一个食物,那就不用删除节点了

void

showSnake()

{

if

(

1

!=

tTime

%

(

30

-

level))

return

;

//

判断蛇的长度有没有改变

bool

lenChange

=

false

;

//

显示食物

move(food.cy, food.cx);

printw(

"

@

"

);

//

如果蛇碰到墙,则游戏结束

if

((COLS

-

1

==

head

->

next

->

cx

&&

1

==

dir.cx)

||

(

0

==

head

->

next

->

cx

&&

-

1

==

dir.cx)

||

(LINES

-

1

==

head

->

next

->

cy

&&

1

==

dir.cy)

||

(

2

==

head

->

next

->

cy

&&

-

1

==

dir.cy))

{

over(

1

);

return

;

}

//

如果蛇头砬到自己的身体,则游戏结束

if

(

'

*

'

==

mvinch(head

->

next

->

cy

+

dir.cy, head

->

next

->

cx

+

dir.cx) )

{

over(

2

);

return

;

}

insertNode(head

->

next

->

cx

+

dir.cx, head

->

next

->

cy

+

dir.cy);

//

蛇吃了一个“食物”

if

(head

->

next

->

cx

==

food.cx

&&

head

->

next

->

cy

==

food.cy)

{

lenChange

=

true

;

length

++

;

//

恭喜你,通关了

if

(length

>=

50

)

{

over(

3

);

return

;

}

//

重新设置食物的位置

food.cx

=

rand()

%

COLS;

food.cy

=

rand()

%

(LINES

-

2

)

+

2

;

}

if

(

!

lenChange)

{

move(tail

->

back

->

cy, tail

->

back

->

cx);

printw(

"

"

);

deleteNode();

}

move(head

->

next

->

cy, head

->

next

->

cx);

printw(

"

*

"

);

}

void

show()

{

signal(SIGALRM, show);

//

设置中断信号

showInformation();

showSnake();

refresh();

//

刷新真实屏幕

}

void

getOrder()

{

//

建立一个死循环,来读取来自键盘的命令

while

(

1

)

{

ch

=

getch();

if

(KEY_LEFT

==

ch)

{

dir.cx

=

-

1

;

dir.cy

=

0

;

}

else

if

(KEY_UP

==

ch)

{

dir.cx

=

0

;

dir.cy

=

-

1

;

}

else

if

(KEY_RIGHT

==

ch)

{

dir.cx

=

1

;

dir.cy

=

0

;

}

else

if

(KEY_DOWN

==

ch)

{

dir.cx

=

0

;

dir.cy

=

1

;

}

setTicker(

20

);

}

}

void

over(

int

i)

{

//

显示结束原因

move(

0

,

0

);

int

j;

for

(j

=

0

;j

<

COLS;j

++

)

addstr(

"

"

);

move(

0

,

2

);

if

(

1

==

i)

addstr(

"

Crash the wall. Game over

"

);

else

if

(

2

==

i)

addstr(

"

Crash itself. Game over

"

);

else

if

(

3

==

i)

addstr(

"

Mission Complete

"

);

setTicker(

0

);

//

关闭计时器

deleteLink();

//

释放链表的空间

}

//

创建一个双向链表

void

creatLink()

{

node

*

temp

=

(node

*

)malloc(

sizeof

(node) );

head

=

(node

*

)malloc(

sizeof

(node) );

tail

=

(node

*

)malloc(

sizeof

(node) );

temp

->

cx

=

5

;

temp

->

cy

=

10

;

head

->

back

=

tail

->

next

=

NULL;

head

->

next

=

temp;

temp

->

next

=

tail;

tail

->

back

=

temp;

temp

->

back

=

head;

}

//

在链表的头部(非头结点)插入一个结点

void

insertNode(

int

x,

int

y)

{

node

*

temp

=

(node

*

)malloc(

sizeof

(node) );

temp

->

cx

=

x;

temp

->

cy

=

y;

temp

->

next

=

head

->

next;

head

->

next

=

temp;

temp

->

back

=

head;

temp

->

next

->

back

=

temp;

}

//

删除链表的(非尾结点的)最后一个结点

void

deleteNode()

{

node

*

temp

=

tail

->

back;

node

*

bTemp

=

temp

->

back;

bTemp

->

next

=

tail;

tail

->

back

=

bTemp;

temp

->

next

=

temp

->

back

=

NULL;

free(temp);

temp

=

NULL;

}

//

删除整个链表

void

deleteLink()

{

while

(head

->

next

!=

tail)

deleteNode();

head

->

next

=

tail

->

back

=

NULL;     free(head);     free(tail); }

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值