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

本文转载

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

#include <stdio.h>

#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
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值