免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 99950 | 回复: 87

[算法] [原创]贡献一个unix的贪吃蛇小游戏 [复制链接]

论坛徽章:
0
发表于 2008-06-25 13:16 |显示全部楼层
许久没来,贡献一个原创小程序,是unix下用终端控制字符实现的贪吃蛇小游戏,供大家一乐。

  1. /***snake.c***/
  2. #include <stdio.h>
  3. #include <malloc.h>
  4. #include <sys/time.h>
  5. #include <sys/types.h>
  6. #include <sys/select.h>
  7. #include <termio.h>
  8. #include <fcntl.h>

  9. #define SNAKE_INITX 5
  10. #define SNAKE_INITY 5
  11. #define SNAKE_SHAPE '*'
  12. #define SNAKE_INITLEN 8

  13. #define WIN_X1 1
  14. #define WIN_X2 80
  15. #define WIN_Y1 1
  16. #define WIN_Y2 24

  17. #define MAX_LEVEL 20
  18. #define MAX_INTER 200000
  19. #define MIN_INTER 0
  20. #define MAX_RICH 10
  21. #define DEVRATE 5
  22. #define OVER "Game Over!!!"

  23. struct stNode
  24. {
  25.         int x;
  26.         int y;
  27.         char shape;
  28.         struct stNode *next;
  29. };

  30. struct stFood
  31. {
  32.         int x;
  33.         int y;
  34. };

  35. struct stNode *gpstHead,*gpstTail;
  36. struct stFood gastFood[MAX_RICH];
  37. int giLevel=1;
  38. int giRich=1;
  39. int giScore=0;
  40. int giLen=0;

  41. void settty(int iFlag)
  42. {
  43.         int fd;
  44.         struct termio stTerm;

  45.         if((fd = open(ttyname(1),O_RDWR))==-1)        return;
  46.         if(iFlag == 1)
  47.         {
  48.                 ioctl(fd,TCGETA,&stTerm);
  49.                 stTerm.c_lflag &= ~ICANON;
  50.                 stTerm.c_lflag &= ~ECHO;
  51.                 stTerm.c_cc[4] = 1;
  52.                 stTerm.c_cc[5] = 0;
  53.                 stTerm.c_iflag &= ~ISTRIP;
  54.                 stTerm.c_cflag |= CS8;
  55.                 stTerm.c_cflag &= ~PARENB;
  56.                 ioctl(fd,TCSETA,&stTerm);
  57.         }
  58.         else
  59.         {
  60.                 ioctl(fd,TCGETA,&stTerm);
  61.                 stTerm.c_lflag |= ICANON;
  62.                 stTerm.c_lflag |= ECHO;
  63.                 stTerm.c_cc[4] = 4;
  64.                 stTerm.c_cc[5] = 5;
  65.                 stTerm.c_iflag &= ~ISTRIP;
  66.                 stTerm.c_cflag |= CS8;
  67.                 stTerm.c_cflag &= ~PARENB;
  68.                 ioctl(fd,TCSETA,&stTerm);
  69.         }
  70.         close(fd);
  71. }

  72. void vDrawOneNode(struct stNode *pstNode,int iFlag)
  73. {
  74.         printf("\033[%dm\033[40;%dm\033[%d;%d;H%c",
  75.                 iFlag,iFlag*3+30,pstNode->y,pstNode->x,pstNode->shape);
  76.         fflush(stdout);
  77. }

  78. void vDrawOneFood(int x,int y)
  79. {
  80.         printf("\033[1m\033[40;36m\033[%d;%d;H%c",y,x,'@');
  81.         fflush(stdout);
  82. }

  83. int iGetDir(int iOriDir)
  84. {
  85.         fd_set rset;
  86.         struct        timeval        hTmo;
  87.         int iRet,iFlag=0;
  88.         char cCh;

  89.         FD_ZERO(&rset);
  90.         FD_SET(0,&rset);
  91.         hTmo.tv_sec=0;
  92.         hTmo.tv_usec=MAX_INTER-(MAX_INTER-MIN_INTER)/MAX_LEVEL*giLevel;

  93.         iRet=select(1,&rset,NULL,NULL,&hTmo);
  94.         if(iRet<=0)
  95.         {
  96.                 return(iOriDir);
  97.         }
  98.         for(;;)
  99.         {
  100.                 cCh=getchar();
  101.                 if(cCh != -1)
  102.                 {
  103.                         switch(cCh)
  104.                         {         
  105.                         case 27  :
  106.                         case 91  :
  107.                                 iFlag++;
  108.                                 break;
  109.                         case 65  ://UP
  110.                         case 66 ://DOWN
  111.                         case 67  ://RIGHT
  112.                         case 68 ://LEFT
  113.                         if(iFlag==2)
  114.                                 return((!((cCh-0x41)^iOriDir^1))^(cCh-0x41));
  115.                         default  :
  116.                                 return(iOriDir);
  117.                         }
  118.                 }
  119.         }
  120. }
  121. void vInitScreen()
  122. {
  123.         settty(1);
  124.         printf("\033[?25l\033[2J");
  125. }

  126. void vRestoreScreen()
  127. {
  128.         printf("\033[24;1H\033[1m\033[40;34m\033[?25h");
  129.         settty(0);
  130. }

  131. void vDrawScope()
  132. {
  133.         int i,j;
  134.        
  135.         for(j=WIN_Y1;j<=WIN_Y2;j+=WIN_Y2-WIN_Y1)
  136.         {
  137.                 printf("\033[%d;%dH+",j,WIN_X1);
  138.                 for(i=WIN_X1+1;i<WIN_X2;i++)
  139.                         printf("-");
  140.                 printf("+");
  141.         }
  142.         for(i=WIN_Y1+1;i<WIN_Y2;i++)
  143.                 printf("\033[%d;%dH|%*c|\n",i,WIN_X1,WIN_X2-WIN_X1-1,' ');
  144. }

  145. void vCreateSnake()
  146. {
  147.         struct stNode *pstNew;
  148.         int i;

  149.         gpstHead=(struct stNode*)malloc(sizeof(struct stNode));
  150.         gpstHead->x=SNAKE_INITX;       
  151.         gpstHead->y=SNAKE_INITY;
  152.         gpstHead->shape=SNAKE_SHAPE;
  153.         gpstHead->next=NULL;
  154.         vDrawOneNode(gpstHead,1);
  155.         gpstTail=gpstHead;
  156.         for(i=1;i<SNAKE_INITLEN;i++)
  157.         {
  158.                 pstNew=(struct stNode*)malloc(sizeof(struct stNode));
  159.                 pstNew->x=gpstHead->x+1;       
  160.                 pstNew->y=gpstHead->y;
  161.                 pstNew->shape=SNAKE_SHAPE;
  162.                 pstNew->next=NULL;
  163.                 vDrawOneNode(pstNew,1);
  164.                 gpstHead->next=pstNew;
  165.                 gpstHead=pstNew;
  166.         }
  167.         return;
  168. }

  169. void vKillSnake()
  170. {
  171.         struct stNode *pstNode;

  172.         for(pstNode=gpstTail;gpstTail!=NULL;)
  173.         {
  174.                 gpstTail=pstNode->next;
  175.                 free(pstNode);
  176.                 pstNode=gpstTail;
  177.         }
  178. }

  179. void vGenFood(int iIdx)
  180. {
  181.         struct stNode *pstNode;
  182.         int i,iFound=0;
  183.        
  184.         for(;!iFound;)
  185.         {
  186.                 iFound=1;
  187.                 gastFood[iIdx].x=rand()%(WIN_X2-WIN_X1-1)+WIN_X1+1;
  188.                 gastFood[iIdx].y=rand()%(WIN_Y2-WIN_Y1-1)+WIN_Y1+1;
  189.                 for(i=0;i<giRich;i++)
  190.                 {
  191.                         if(i!=iIdx && gastFood[iIdx].x==gastFood[i].x &&
  192.                                 gastFood[iIdx].y==gastFood[i].y)
  193.                         {
  194.                                 iFound=0;
  195.                                 break;
  196.                         }
  197.                 }
  198.                 if(!iFound) continue;
  199.                 for(pstNode=gpstTail;pstNode!=NULL;pstNode=pstNode->next)
  200.                 {
  201.                         if(gastFood[iIdx].x==pstNode->x &&
  202.                                 gastFood[iIdx].y==pstNode->y)
  203.                         {
  204.                                 iFound=0;
  205.                                 break;
  206.                         }
  207.                 }
  208.                 if(!iFound) continue;
  209.         }
  210.         vDrawOneFood(gastFood[iIdx].x,gastFood[iIdx].y);
  211. }

  212. void vInitFood()
  213. {
  214.         int i;
  215.        
  216.         srand(getpid());
  217.         for(i=0;i<giRich;i++)        vGenFood(i);
  218. }
  219.        
  220. int iIsValid(int x,int y)
  221. {
  222.         struct stNode *pstNode;

  223.         if(x<=WIN_X1 || x>=WIN_X2 || y<=WIN_Y1 || y>=WIN_Y2)
  224.                 return(0);
  225.         pstNode=gpstTail;
  226.         for(;pstNode!=NULL;)
  227.         {
  228.                 if(x==pstNode->x && y==pstNode->y)
  229.                         return(0);
  230.                 pstNode=pstNode->next;
  231.         }
  232.         return(1);
  233. }

  234. int iEat(int x,int y)
  235. {
  236.         int i,j;
  237.        
  238.         for(i=0;i<giRich;i++)
  239.         {
  240.                 if(x==gastFood[i].x && y==gastFood[i].y)
  241.                 {
  242.                         vGenFood(i);
  243.                         giScore+=giLevel*10;
  244.                         giLen++;
  245.                         if(giLevel<MAX_LEVEL)
  246.                                 if(giLen%DEVRATE==0)
  247.                                         giLevel++;
  248.                         return(1);
  249.                 }
  250.         }
  251.         return(0);
  252. }
  253. main()
  254. {
  255.         int iDir=2,iNextX,iNextY;
  256.         struct stNode *pstNew;
  257.         char sPrompt[80];
  258.        
  259.         vInitScreen();
  260.         vDrawScope();
  261.         vCreateSnake();
  262.         vInitFood();
  263.         for(;;)
  264.         {
  265.                 iDir=iGetDir(iDir);
  266.                 iNextX=gpstHead->x+(iDir>>1)*(5-(iDir<<1));
  267.                 iNextY=gpstHead->y-(!(iDir>>1))*(1-(iDir<<1));
  268.                 if(!iIsValid(iNextX,iNextY))
  269.                 {
  270.                         printf("\033[%d;%dH\033[1m\033[40;34m%s\033[0m",
  271.                                 WIN_Y2-1,(WIN_X1+WIN_X2)/2-strlen(OVER)/2,OVER);
  272.                         break;
  273.                 }
  274.                 pstNew=(struct stNode*)malloc(sizeof(struct stNode));
  275.                 pstNew->x=iNextX;
  276.                 pstNew->y=iNextY;
  277.                 pstNew->shape=SNAKE_SHAPE;
  278.                 pstNew->next=NULL;
  279.                 gpstHead->next=pstNew;
  280.                 gpstHead=pstNew;
  281.                 vDrawOneNode(gpstHead,1);
  282.                 if(!iEat(iNextX,iNextY))
  283.                 {
  284.                         vDrawOneNode(gpstHead,1);
  285.                         vDrawOneNode(gpstTail,0);
  286.                         pstNew=gpstTail;
  287.                         gpstTail=pstNew->next;
  288.                         free(pstNew);
  289.                 }
  290.                 sprintf(sPrompt,"Score:%7d Level:%2d",giScore,giLevel);
  291.                 printf("\033[%d;%dH\033[1m\033[40;34m%s\033[0m",
  292.                         WIN_Y2,(WIN_X1+WIN_X2)/2-strlen(sPrompt)/2,sPrompt);
  293.         }
  294.         vKillSnake();
  295.         vRestoreScreen();
  296. }
复制代码

编译方法:
AIX下:cc -qcpluscmt -o snake snake.c
sco unix下:cc -o snake snake.c

[ 本帖最后由 forest077 于 2008-6-25 13:23 编辑 ]

论坛徽章:
0
发表于 2008-06-25 13:20 |显示全部楼层
代码写得很漂亮,支持,友情帮顶!

论坛徽章:
0
发表于 2008-06-25 13:33 |显示全部楼层
gcc加了-Wall选项之后出现了N多警告,主要是一些头文件没加进去;
另外,不知道搂主是在什么环境下跑这个程序的,我的机器跑了之后没看到什么。

论坛徽章:
0
发表于 2008-06-25 13:37 |显示全部楼层

回复 #3 LinuxKen 的帖子

我在AIX下开发的。 sco下虽然没试过,但是以我的经验,跑起来应该没问题。

论坛徽章:
0
发表于 2008-06-25 14:10 |显示全部楼层
跑了就看到个界面, 看不到蛇和豆子, 一会就 GAME OVER了

论坛徽章:
0
发表于 2008-06-25 14:14 |显示全部楼层
我还记得刚来CU时看到LZ在shell版发的shell学习体会~~

论坛徽章:
0
发表于 2008-06-25 14:40 |显示全部楼层

回复 #5 204tian 的帖子

你在什么环境下的?linux下我不敢保证可以运行。

论坛徽章:
0
发表于 2008-06-25 14:42 |显示全部楼层

回复 #6 converse 的帖子

哈哈,多谢,你还记得呀

论坛徽章:
0
发表于 2008-06-25 14:45 |显示全部楼层
可惜我这边找不到linux环境,要不然可以试试

论坛徽章:
0
发表于 2008-06-25 15:11 |显示全部楼层
Segmentation fault (core dumped)

在AIX下。。。
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP