Linux 贪吃蛇游戏 -C语言(本人的第一篇博文)

一、Ncurses库简介:

1、curses是一个在Linux/Unix下广泛应用的图形函数库, 作用是可以在终端内绘制简单的图形用户界面。

2、Nurses库头文件:#include <curses.h>

      编译时要链接    -lcurses

3、本程序中使用的函数 :

#include <curses.h>

1)initscr();             初始化屏幕,启动curses模式

2)getch();              获取一个字符      例:  int c = getch();

3)endwin();           退出curses模式

4)move(0,0);         锁定光标在(0:0)

5)refresh();            刷新界面

6)noecho();           不显示按键符号

7)rand();                生成随即数

8)在Ncurses中使用功能键必须调用:key(stdscr,1);

stdscr:激活功能键

1:是否激活,1:是

#include <unistd.h>

1)sleep();               时间函数(秒)

2)usleep();             时间函数(微秒)

二、贪吃蛇地图规划:

       贪吃蛇竖直方向上的边界:“|”

       贪吃蛇水平方向上的边界:“--”

        贪吃蛇身体:[ ]

        贪吃蛇食物:##

        地图边界:行x列     18x25

        三、Linux线程

               1)头文件: #include <pthread.h>

               定义一个线程:

                pthread_t th;

                ret = pthread_create(&th,NULL,thread,&arg);

               &th : 线程描述符

               thread :线程要执行的东西

         注:Linux编译时可以链接多个库

             例如:gcc snake.c -lcurses -lpthread

  附完整程序,可直接在Linux中运行,程序中有注释。

 

/*
 *    贪吃蛇游戏:(个别程序会被覆盖)
 *             1、贪吃蛇地图:snake_map.c
 *                            地图边界:行x列   20x25
 *             2、贪吃蛇身体1:snake_body.c
 *                            静态的获得一个身体     
 *             3、贪吃蛇身体2:snake_body2.c
 *                            静态的获得三个身体      
 *             4、贪吃蛇身体3:snake_body3.c
 *                            动态的创建贪吃蛇的身体       
 *             5、贪吃蛇方向:snake_dire.c
 *                            贪吃蛇向右移动(按一次动一次)   
 *             6、贪吃蛇撞墙:snake_dire2.c
 *                            贪吃蛇撞墙之后,游戏初始化
 *             7、贪吃蛇自由行走:snake_dire3.c
 *                            无需按键,自己向右游走
 *             8、贪吃蛇四个方向自由行走:snake_dire4.c
 *                            按下按键蛇根据按键方向自由行走
 *             9、贪吃蛇行走问题:snake_dire5.c 
 *                            绝对值方式解决贪吃蛇不合理走为问题
 *             10、贪吃蛇吃食物:snake_food.c
 *                            贪吃蛇通过吃食物变长
 *             11、贪吃蛇食物随机出现:snake_food2.c
 *                            贪吃蛇通过吃食物变长(控制食物不会超出地图边界并且地图内一直有食物存在)
 *             12、贪吃蛇要咬死自己:snake_food3.c
 *                            当蛇头与蛇尾重合时,游戏重新开始
 *             13、贪吃蛇的开始界面:snake_start_screen.c
*/


#include <curses.h>
#include <malloc.h>
#include <unistd.h>
#include <pthread.h>
#include <stdlib.h>

#define UP    1
#define DOWN  -1
#define RIGHT 2
#define LEFT  -2


/*
*       函数声明部分:
*/
void InitNcurses();
void snakeMap();
int TravSnakeBody();
void snakebody();
void Addsnake();
void Initsnake();
void Deletsnake();
void movesnake();
void *refreshSnake();
void *changeDire();
void turn(int direction);
void Initfood();
int hasfood(int line,int list);
int ifsnakedie();


/*
 * 结构体
 */
struct Snake
     {
	 int line;     //行
	 int list;     //列
	 struct Snake *next;
     };

/*
 * 创建贪吃蛇的身体:(创建链表头和尾)
 *                   行一致,列加1
 */
struct Snake *head = NULL;
struct Snake *tail = NULL; 
struct Snake food;
int key;
int dire;      //方向

/*
      初始化Ncurses函数:
*/
void InitNcurses()
   {
       initscr();
       keypad(stdscr,1);
       noecho();    //不显示按键的符号
   }
/*
      贪吃蛇地图:
                  四角的坐标:(行:列)
		            左上:(1:1)   右上:(1:24)
			    左下:(18,1)   右下: (18:24)
*/
void snakeMap()
   {
        int line;    //行
        int list;    //列
        for(line=0;line<20;line++)    
	  {
               if(line==0 || line==19)   //--打印
		{
	           for(list=0;list<25;list++)
		     {
	                 printw("--");
		     }
		}
	       else
	          {
	            for(list=0;list<26;list++)   //  ||打印及游戏界面
		      {
	                  if(list==0 || list==25)
	                   {
		               printw("|");
		           }
		          else
		             {
			        if(TravSnakeBody(line,list))
				 {
			               printw("[]");
				 }
				else if(hasfood(line,list))
				      {
					  printw("##");
				      }
				else{
		                        printw("  ");
				    }
		             }
		      }
		  }
	       printw("\n");
	  }
	printw("Key num:%d\n",key);
	printw("Food line:%d\n",food.line);
	printw("Food list:%d\n",food.list);

   }
/*
 *       遍历蛇身体:
 */
int TravSnakeBody(int line,int list) 
   {
	struct Snake *point;
	point = head;
	while(point != NULL)
	    {
	       if(point->line==line && point->list==list)
		{
		       return 1;
		}
	        point = point->next;
	    }
	return 0;
   }
/*
 *       创建贪吃蛇的身体:
 *                        刷新贪吃蛇地图
 */
void snakebody()
   {
        struct Snake *point;
        point = head;
        while(point->next != NULL)
            {
                move(0,0);
                snakeMap();
                point = point->next;
            }
   }

/*
 *         初始化贪吃蛇:
 *                     作用:用尾插法创建一个链表
 * */
void Initsnake()    //初始化贪吃蛇
    {
        struct Snake *point;
	dire = RIGHT;
	while(head != NULL)
	    {
		 point = head;
		 head = head->next;
		 free(point);
	    }
	Initfood();
	head = (struct Snake *)malloc(sizeof(struct Snake));
	head->line = 1;
	head->list = 1;
	head->next = NULL;
	tail = head;
	Addsnake();
	Addsnake();
    }

/*
 *            增加贪吃蛇长度:
 *                         作用:为链表增加节点(每调用一次增加一个节点)
 */ 
void Addsnake()
   {
        struct Snake *new_snake = NULL;
        new_snake = (struct Snake *)malloc(sizeof(struct Snake));
	switch(dire)
	     {
	          case UP:{
		              new_snake->line = tail->line - 1;
                              new_snake->list = tail->list;
			  }break;
	          case DOWN:{
			      new_snake->line = tail->line + 1;
                              new_snake->list = tail->list;
			    }break;
	          case RIGHT:{
			      new_snake->line = tail->line;
                              new_snake->list = tail->list + 1;
			     }break;
		  case LEFT:{
			      new_snake->line = tail->line;
                              new_snake->list = tail->list - 1;
			    }break;
	     }
	tail->next = new_snake;
	tail = new_snake;
   }

/*
 *          删除链表一个节点(删除头节点)
 */
void Deletsnake()
   {
	struct Snake *point;
	point = head;
       	head = head->next;
        free(point);
   }

/*
 *        贪吃蛇的移动函数
 */
void movesnake()
   {
	         Addsnake();
		 if(hasfood(tail->line,tail->list))
		  {
			 Initfood();
		  }
		 else
		    {
			 Deletsnake();
		    }
                 if(ifsnakedie())
                  {
                     Initsnake();
                  }
   }

/*
 *        转换函数:
 *               用绝对值方法解决蛇走位不合理的问题                                                                             */
void turn(int direction)
   {
	if(abs(dire) != abs( direction))
       	 {
              dire = direction;
	 }
   }

/*
 *         贪吃蛇按键:(方向选择)
 *                   实现贪吃蛇的上下左右移动
*/
void  *changeDire()
   {
	  while(1)
              {
                  key = getch();
                  switch(key)
                       {
                            case KEY_UP:
                               {
				    turn(UP);
                               }break;
                            case KEY_DOWN:
                               {
				    turn(DOWN);
                               }break;
                            case KEY_LEFT:
                               {
                                    turn(LEFT);
                               }break;
                            case KEY_RIGHT:
                               {
				    turn(RIGHT);
                               }break;
                       }
             }
   }

/*
 *      刷新游戏界面
 */
void *refreshSnake()
   {
     while(1)
         {
             move(0,0);
             movesnake();
             snakeMap();
             usleep(100000);
             refresh();    //刷新
	 }
   }
/*
 *       贪吃蛇食物:
 *                  食物:#
 */
void Initfood()
   {
       //xrand();是一个函数(随即生成一个数)
       int x;
       int y;
       x = rand()%20;     //地图中食物的坐标
       y = rand()%20;
       while(x==0 || y==0)
        {
             x = rand()%20; 
	     y = rand()%20;
	}
       food.line = x;
       food.list = y;
   }
/*
 *        确定贪吃蛇食物的位置
 */
int hasfood(int line,int list)
   {
        if(food.line == line && food.list == list)
	 {
              return 1;
	 }       
	return 0;
   }
/*
 *     贪吃蛇复位(游戏重新开始)
 *             贪吃蛇头与贪吃蛇尾巴重合时,游戏冲重新开始。
 */
int ifsnakedie()
  {
       struct Snake *point;
       point = head;
       if(tail->line==0 || tail->line==19|| tail->list==0 || tail->list == 25)     //设置贪吃蛇撞墙参数
        {
		return 1;
	}
       while(point->next != NULL)
           {
		if(point->line == tail->line && point->list == tail->list)
		 {
		      return 1;
		 }
	        point = point->next;
	   }
       return 0;
  }


int main()
  {
     pthread_t th1;
     pthread_t th2;
   
     InitNcurses();
     snakeMap();
     Initsnake();
     snakebody();
     pthread_create(&th1,NULL,refreshSnake,NULL);
     pthread_create(&th2,NULL,changeDire,NULL);


     while(1);  //主线程(防止程序退出)
     getch();   //防止程序退出
     endwin();
       return 0;
  }

  • 5
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值