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


^_^一个小游戏,贪吃蛇,C语言实现 嘎嘎 在Linux 环境下 编译通过。

//mysnake1.0.c
//编译命令:cc mysnake1.0.c -lcurses -o mysnake1.0
//用方向键控制蛇的方向
#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);
}

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

相关内容