鱼C论坛

 找回密码
 立即注册
查看: 2712|回复: 7

贪吃蛇源代码

[复制链接]
发表于 2014-2-6 15:22:39 | 显示全部楼层 |阅读模式
10鱼币
求一个用c语言写的能在vc++正常编译的贪吃蛇源代码。想拿来看一下,学习一下。大神别藏起来了哈。

最佳答案

查看完整内容

Linux下代码windows下(最好用trubo c VC行也行麻烦点貌似要装easyx 应为有graphics.h)
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2014-2-6 15:22:40 | 显示全部楼层
Linux下代码
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <curses.h>
  4. #include <signal.h>
  5. #include <sys/time.h>
  6. #define NUM 60

  7. struct direct                //用来表示方向的
  8. {
  9.     int cx;
  10.     int cy;
  11. };
  12. typedef struct node            //链表的结点
  13. {
  14.     int cx;
  15.     int cy;
  16.     struct node *back;
  17.     struct node *next;
  18. }node;

  19. void initGame();            //初始化游戏
  20. int setTicker(int);            //设置计时器
  21. void show();                //显示整个画面
  22. void showInformation();        //显示游戏信息(前两行)
  23. void showSnake();            //显示蛇的身体
  24. void getOrder();            //从键盘中获取命令
  25. void over(int i);            //完成游戏结束后的提示信息

  26. void creatLink();                //(带头尾结点)双向链表以及它的操作
  27. void insertNode(int x, int y);   
  28. void deleteNode();
  29. void deleteLink();

  30. int ch;                                //输入的命令
  31. int hour, minute, second;            //时分秒
  32. int length, tTime, level;            //(蛇的)长度,计时器,(游戏)等级
  33. struct direct dir, food;            //蛇的前进方向,食物的位置
  34. node *head, *tail;                    //链表的头尾结点

  35. int main()
  36. {
  37.     initscr();
  38.     initGame();
  39.     signal(SIGALRM, show);
  40.     getOrder();
  41.     endwin();
  42.     return 0;
  43. }

  44. void initGame()
  45. {
  46.     cbreak();                    //把终端的CBREAK模式打开
  47.     noecho();                    //关闭回显
  48.     curs_set(0);                //把光标置为不可见
  49.     keypad(stdscr, true);        //使用用户终端的键盘上的小键盘
  50.     srand(time(0));                //设置随机数种子
  51.     //初始化各项数据
  52.     hour = minute = second = tTime = 0;
  53.     length = 1;
  54.     dir.cx = 1;
  55.     dir.cy = 0;
  56.     ch = 'A';
  57.     food.cx = rand() % COLS;
  58.     food.cy = rand() % (LINES-2) + 2;
  59.     creatLink();
  60.     setTicker(20);
  61. }

  62. //设置计时器(这个函数是书本上的例子,有改动)
  63. int setTicker(int n_msecs)
  64. {
  65.     struct itimerval new_timeset;
  66.     long    n_sec, n_usecs;

  67.     n_sec = n_msecs / 1000 ;
  68.     n_usecs = ( n_msecs % 1000 ) * 1000L ;
  69.     new_timeset.it_interval.tv_sec  = n_sec;        
  70.     new_timeset.it_interval.tv_usec = n_usecs;      
  71.     n_msecs = 1;
  72.     n_sec = n_msecs / 1000 ;
  73.     n_usecs = ( n_msecs % 1000 ) * 1000L ;
  74.     new_timeset.it_value.tv_sec     = n_sec  ;      
  75.     new_timeset.it_value.tv_usec    = n_usecs ;     
  76.     return setitimer(ITIMER_REAL, &new_timeset, NULL);
  77. }

  78. void showInformation()
  79. {
  80.     tTime++;
  81.     if(tTime >= 1000000)                //
  82.         tTime = 0;
  83.     if(1 != tTime % 50)
  84.         return;
  85.     move(0, 3);   
  86.     //显示时间
  87.     printw("time: %d:%d:%d %c", hour, minute, second);
  88.     second++;
  89.     if(second > NUM)
  90.     {
  91.         second = 0;
  92.         minute++;
  93.     }
  94.     if(minute > NUM)
  95.     {
  96.         minute = 0;
  97.         hour++;
  98.     }
  99.     //显示长度,等级
  100.     move(1, 0);
  101.     int i;
  102.     for(i=0;i<COLS;i++)
  103.         addstr("-");
  104.     move(0, COLS/2-5);
  105.     printw("length: %d", length);
  106.     move(0, COLS-10);
  107.     level = length / 3 + 1;
  108.     printw("level: %d", level);
  109. }

  110. //蛇的表示是用一个带头尾结点的双向链表来表示的,
  111. //蛇的每一次前进,都是在链表的头部增加一个节点,在尾部删除一个节点
  112. //如果蛇吃了一个食物,那就不用删除节点了
  113. void showSnake()
  114. {
  115.     if(1 != tTime % (30-level))
  116.         return;
  117.     //判断蛇的长度有没有改变
  118.     bool lenChange = false;
  119.     //显示食物
  120.     move(food.cy, food.cx);
  121.     printw("@");
  122.     //如果蛇碰到墙,则游戏结束
  123.     if((COLS-1==head->next->cx && 1==dir.cx)
  124.         || (0==head->next->cx && -1==dir.cx)
  125.         || (LINES-1==head->next->cy && 1==dir.cy)
  126.         || (2==head->next->cy && -1==dir.cy))
  127.     {
  128.         over(1);
  129.         return;
  130.     }
  131.     //如果蛇头砬到自己的身体,则游戏结束
  132.     if('*' == mvinch(head->next->cy+dir.cy, head->next->cx+dir.cx) )
  133.     {
  134.         over(2);
  135.         return;
  136.     }
  137.     insertNode(head->next->cx+dir.cx, head->next->cy+dir.cy);
  138.     //蛇吃了一个“食物”
  139.     if(head->next->cx==food.cx && head->next->cy==food.cy)
  140.     {
  141.         lenChange = true;
  142.         length++;
  143.         //恭喜你,通关了
  144.         if(length >= 50)
  145.         {
  146.             over(3);
  147.             return;
  148.         }
  149.         //重新设置食物的位置
  150.         food.cx = rand() % COLS;
  151.         food.cy = rand() % (LINES-2) + 2;
  152.     }
  153.     if(!lenChange)
  154.     {
  155.         move(tail->back->cy, tail->back->cx);
  156.         printw(" ");
  157.         deleteNode();
  158.     }
  159.     move(head->next->cy, head->next->cx);
  160.     printw("*");
  161. }

  162. void show()
  163. {
  164.     signal(SIGALRM, show);        //设置中断信号
  165.     showInformation();
  166.     showSnake();
  167.     refresh();                    //刷新真实屏幕
  168. }

  169. void getOrder()
  170. {
  171.     //建立一个死循环,来读取来自键盘的命令
  172.     while(1)
  173.     {
  174.         ch = getch();
  175.         if(KEY_LEFT == ch)
  176.         {
  177.             dir.cx = -1;
  178.             dir.cy = 0;
  179.         }
  180.         else if(KEY_UP == ch)
  181.         {
  182.             dir.cx = 0;
  183.             dir.cy = -1;
  184.         }
  185.         else if(KEY_RIGHT == ch)
  186.         {
  187.             dir.cx = 1;
  188.             dir.cy = 0;
  189.         }
  190.         else if(KEY_DOWN == ch)
  191.         {
  192.             dir.cx = 0;
  193.             dir.cy = 1;
  194.         }
  195.         setTicker(20);
  196.     }
  197. }

  198. void over(int i)
  199. {
  200.     //显示结束原因
  201.     move(0, 0);
  202.     int j;
  203.     for(j=0;j<COLS;j++)
  204.         addstr(" ");
  205.     move(0, 2);
  206.     if(1 == i)
  207.         addstr("Crash the wall. Game over");
  208.     else if(2 == i)
  209.         addstr("Crash itself. Game over");
  210.     else if(3 == i)
  211.         addstr("Mission Complete");
  212.     setTicker(0);                //关闭计时器
  213.     deleteLink();                //释放链表的空间
  214. }

  215. //创建一个双向链表
  216. void creatLink()
  217. {
  218.     node *temp = (node *)malloc( sizeof(node) );
  219.     head = (node *)malloc( sizeof(node) );
  220.     tail = (node *)malloc( sizeof(node) );
  221.     temp->cx = 5;
  222.     temp->cy = 10;
  223.     head->back = tail->next = NULL;
  224.     head->next = temp;
  225.     temp->next = tail;
  226.     tail->back = temp;
  227.     temp->back = head;
  228. }

  229. //在链表的头部(非头结点)插入一个结点
  230. void insertNode(int x, int y)
  231. {
  232.     node *temp = (node *)malloc( sizeof(node) );
  233.     temp->cx = x;
  234.     temp->cy = y;
  235.     temp->next = head->next;
  236.     head->next = temp;
  237.     temp->back = head;
  238.     temp->next->back = temp;
  239. }

  240. //删除链表的(非尾结点的)最后一个结点
  241. void deleteNode()
  242. {
  243.     node *temp = tail->back;
  244.     node *bTemp = temp->back;
  245.     bTemp->next = tail;
  246.     tail->back = bTemp;
  247.     temp->next = temp->back = NULL;
  248.     free(temp);
  249.     temp = NULL;
  250. }

  251. //删除整个链表
  252. void deleteLink()
  253. {
  254.     while(head->next != tail)
  255.         deleteNode();
  256.     head->next = tail->back = NULL;
  257.     free(head);
  258.     free(tail);
  259. }
复制代码
windows下(最好用trubo c VC行也行麻烦点貌似要装easyx 应为有graphics.h)
  1. #define N 200
  2. #include <graphics.h>
  3. #include <stdlib.h>
  4. #include <dos.h>
  5. #define LEFT 0x4b00
  6. #define RIGHT 0x4d00
  7. #define DOWN 0x5000
  8. #define UP 0x4800
  9. #define ESC 0x011b
  10. int i,key;
  11. int score=0;/*得分*/
  12. int gamespeed=50000;/*游戏速度自己调整*/
  13. struct Food
  14. {
  15.    int x;/*食物的横坐标*/
  16.    int y;/*食物的纵坐标*/
  17.    int yes;/*判断是否要出现食物的变量*/
  18. }food;/*食物的结构体*/
  19. struct Snake
  20. {
  21.    int x[N];
  22.    int y[N];
  23.    int node;/*蛇的节数*/
  24.    int direction;/*蛇移动方向*/
  25.    int life;/* 蛇的生命,0活着,1死亡*/
  26. }snake;
  27. void Init(void);/*图形驱动*/
  28. void Close(void);/*图形结束*/
  29. void DrawK(void);/*开始画面*/
  30. void GameOver(void);/*结束游戏*/
  31. void GamePlay(void);/*玩游戏具体过程*/
  32. void PrScore(void);/*输出成绩*/
  33. /*主函数*/
  34. void main(void)
  35. {
  36.    Init();/*图形驱动*/
  37.    DrawK();/*开始画面*/
  38.    GamePlay();/*玩游戏具体过程*/
  39.    Close();/*图形结束*/
  40. }
  41. /*图形驱动*/
  42. void Init(void)
  43. {
  44.    int gd=DETECT,gm;
  45.    initgraph(&gd,&gm,"c:\\tc");
  46.    cleardevice();
  47. }
  48. /*开始画面,左上角坐标为(50,40),右下角坐标为(610,460)的围墙*/
  49. void DrawK(void)
  50. {
  51. /*setbkcolor(LIGHTGREEN);*/
  52.    setcolor(11);
  53.    setlinestyle(SOLID_LINE,0,THICK_WIDTH);/*设置线型*/
  54.    for(i=50;i<=600;i+=10)/*画围墙*/
  55.    {
  56.       rectangle(i,40,i+10,49); /*上边*/
  57.       rectangle(i,451,i+10,460);/*下边*/
  58.    }
  59.   for(i=40;i<=450;i+=10)
  60.   {
  61.      rectangle(50,i,59,i+10); /*左边*/
  62.      rectangle(601,i,610,i+10);/*右边*/
  63.   }
  64. }
  65. /*玩游戏具体过程*/
  66. void GamePlay(void)
  67. {
  68.    randomize();/*随机数发生器*/
  69.    food.yes=1;/*1表示需要出现新食物,0表示已经存在食物*/
  70.    snake.life=0;/*活着*/
  71.    snake.direction=1;/*方向往右*/
  72.    snake.x[0]=100;snake.y[0]=100;/*蛇头*/
  73.    snake.x[1]=110;snake.y[1]=100;
  74.    snake.node=2;/*节数*/
  75.    PrScore();/*输出得分*/
  76.    while(1)/*可以重复玩游戏,压ESC键结束*/
  77.    {
  78.       while(!kbhit())/*在没有按键的情况下,蛇自己移动身体*/
  79.       {
  80.   if(food.yes==1)/*需要出现新食物*/
  81.   {
  82.       food.x=rand()()%400+60;
  83.       food.y=rand()()%350+60;
  84.       while(food.x%10!=0)/*食物随机出现后必须让食物能够在整格内,这样才可以让蛇吃到*/
  85.   food.x++;
  86.       while(food.y%10!=0)
  87.   food.y++;
  88.   food.yes=0;/*画面上有食物了*/
  89.   }
  90.   if(food.yes==0)/*画面上有食物了就要显示*/
  91.   {
  92.               setcolor(GREEN);
  93.               rectangle(food.x,food.y,food.x+10,food.y-10);
  94.   }
  95.          for(i=snake.node-1;i>0;i--)/*蛇的每个环节往前移动,也就是贪吃蛇的关键算法*/
  96.          {
  97.             snake.x[i]=snake.x[i-1];
  98.      snake.y[i]=snake.y[i-1];
  99.   }
  100.        /*1,2,3,4表示右,左,上,下四个方向,通过这个判断来移动蛇头*/
  101.   switch(snake.direction)
  102.   {
  103.      case 1:snake.x[0]+=10;break;
  104.      case 2: snake.x[0]-=10;break;
  105.      case 3: snake.y[0]-=10;break;
  106.      case 4: snake.y[0]+=10;break;
  107.   }
  108.   for(i=3;i<snake.node;i++)/*从蛇的第四节开始判断是否撞到自己了,因为蛇头为两节,第三节不可能拐过来*/
  109.   {
  110.      if(snake.x[i]==snake.x[0]&&snake.y[i]==snake.y[0])
  111.      {
  112.                GameOver();/*显示失败*/
  113.                snake.life=1;
  114.                break;
  115.      }
  116.         }
  117. if(snake.x[0]<55||snake.x[0]>595||snake.y[0]<55||
  118.     snake.y[0]>455)/*蛇是否撞到墙壁*/
  119. {
  120.      GameOver();/*本次游戏结束*/
  121.      snake.life=1; /*蛇死*/
  122. }
  123. if(snake.life==1)/*以上两种判断以后,如果蛇死就跳出内循环,重新开始*/
  124.            break;
  125. if(snake.x[0]==food.x&&snake.y[0]==food.y)/*吃到食物以后*/
  126. {
  127.            setcolor(0);/*把画面上的食物东西去掉*/
  128.            rectangle(food.x,food.y,food.x+10,food.y-10);
  129.     snake.x[snake.node]=-20;snake.y[snake.node]=-20;
  130.           /*新的一节先放在看不见的位置,下次循环就取前一节的位置*/
  131.     snake.node++;/*蛇的身体长一节*/
  132.     food.yes=1;/*画面上需要出现新的食物*/
  133.     score+=10;
  134.     PrScore();/*输出新得分*/
  135. }
  136. setcolor(4);/*画出蛇*/
  137. for(i=0;i<snake.node;i++)
  138.     rectangle(snake.x[i],snake.y[i],snake.x[i]+10,
  139.                snake.y[i]-10);
  140. delay(gamespeed);
  141. setcolor(0);/*用黑色去除蛇的的最后一节*/
  142. rectangle(snake.x[snake.node-1],snake.y[snake.node-1],
  143. snake.x[snake.node-1]+10,snake.y[snake.node-1]-10);
  144.      }  /*endwhile(!kbhit)*/
  145.     if(snake.life==1)/*如果蛇死就跳出循环*/
  146.         break;
  147.     key=bioskey(0);/*接收按键*/
  148.     if(key==ESC)/*按ESC键退出*/
  149.        break;
  150.     else
  151.        if(key==UP&&snake.direction!=4)
  152. /*判断是否往相反的方向移动*/
  153.    snake.direction=3;
  154.        else
  155.    if(key==RIGHT&&snake.direction!=2)
  156.       snake.direction=1;
  157.    else
  158.       if(key==LEFT&&snake.direction!=1)
  159.   snake.direction=2;
  160.       else
  161.   if(key==DOWN&&snake.direction!=3)
  162.      snake.direction=4;
  163.    }/*endwhile(1)*/
  164. }
  165. /*游戏结束*/
  166. void GameOver(void)
  167. {
  168.     cleardevice();
  169.     PrScore();
  170.    setcolor(RED);
  171.    settextstyle(0,0,4);
  172.    outtextxy(200,200,"GAME OVER");
  173.    getch()();
  174. }
  175. /*输出成绩*/
  176. void PrScore(void)
  177. {   
  178.    char str[10];
  179.    setfillstyle(SOLID_FILL,YELLOW);
  180.    bar(50,15,220,35);
  181.    setcolor(6);
  182.    settextstyle(0,0,2);
  183.    sprintf(str,"score:%d",score);
  184.    outtextxy(55,20,str);
  185. }
  186. /*图形结束*/
  187. void Close(void)
  188. {   
  189.     getch()();
  190.     closegraph();
  191. }
复制代码
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2014-2-6 18:28:46 | 显示全部楼层
还有 我是windows 而且没装trubo c 这到底能不能正常运行 我心里却是没底啊
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2014-2-6 18:42:11 | 显示全部楼层
本帖最后由 andalousie 于 2014-2-6 18:48 编辑
  1. /***********************************************
  2. * File: snake.cpp
  3. * Author: Keith Schwarz (htiek@cs.stanford.edu)
  4. *
  5. * An implementation of the game "Snake" with a
  6. * rudimentary computer AI player.  The computer
  7. * controls a snake that tries to eat as much food
  8. * as possible.  Every time it eats a food pellet,
  9. * its length increases by one.  The snake loses if
  10. * it hits a wall or crashes into itself.
  11. *
  12. * The AI in this program is extremely simple.  The
  13. * snake moves forward, turning with probability 1/5
  14. * at each step.  If the snake's next step will
  15. * certainly hit a wall, it tries to turn.
  16. *
  17. * In order to run this program, you will need to use
  18. * a level file.  A set of sample files are included
  19. * in this directory.
  20. */

  21. #include <iostream>
  22. #include <string>
  23. #include <deque>
  24. #include <vector>
  25. #include <fstream>
  26. #include <cstdlib>
  27. #include <ctime>
  28. using namespace std;

  29. /* Probability of turning at each step. */
  30. const double kTurnRate = 0.2;

  31. /* Time to wait, in seconds, between frames. */
  32. const double kWaitTime = 0.1;

  33. /* Number of food pellets that must be eaten to win. */
  34. const size_t kMaxFood = 20;

  35. /* Constants for the different tile types.  Each level file is
  36. * encoded using these characters.
  37. */
  38. const char kEmptyTile = ' '; // Empty space
  39. const char kWallTile  = '#'; // Wall
  40. const char kFoodTile  = '
  41. ; // Food
  42. const char kSnakeTile = '*'; // Snake start location/current position

  43. /* The string used to clear the display before printing the game board.
  44. * Windows systems should use CLS, Mac OS X or Linux users should use
  45. * clear.
  46. */

  47.   const string kClearCommand = "CLS";

  48. /* A struct encoding a point in a two-dimensional grid. */
  49. struct pointT {
  50.   size_t row, col;

  51.   /* Utility constructor. */
  52.   pointT(size_t row, size_t col) {
  53.     this->row = row;
  54.     this->col = col;
  55.   }

  56.   /* Default constructor sets everything to 0. */
  57.   pointT() {
  58.     row = col = 0;
  59.   }
  60. };

  61. /* A struct containing relevant game information. */
  62. struct gameT {
  63.   vector<string> world; // The playing field.  Each string is
  64.                         // composed of the characters encoding
  65.                         // tiles and represents one row of the
  66.                         // playing field.
  67.   
  68.   size_t numRows, numCols; // Size of the playing field
  69.   
  70.   deque<pointT> snake;  // The snake body.  The head is in the front
  71.                         // of the deque and the tail in the back, so
  72.                         // we can easily advance the snake a step
  73.                         // forward
  74.   
  75.   int dx, dy;           // The snake direction
  76.   
  77.   size_t numEaten;      // How much food we've eaten.
  78. };

  79. /* Reads a line of text from the user. */
  80. string GetLine() {
  81.   string result;
  82.   getline(cin, result);
  83.   return result;
  84. }

  85. /* Returns true with probability probability.  This works by scaling
  86. * down rand() by RAND_MAX so that we have a value in [0, 1) and returning
  87. * whether the value is less than the set probability.
  88. */
  89. bool RandomChance(double probability) {
  90.   return static_cast<double>(rand()) / RAND_MAX < probability;
  91. }

  92. /* Places a piece of food randomly on the board.  This assumes that there
  93. * is some free space remaining.
  94. */
  95. void PlaceFood(gameT& game) {
  96.   while(true) {
  97.     size_t row = rand() % game.numRows;
  98.     size_t col = rand() % game.numCols;
  99.    
  100.     /* If there isn't anything at the specified position, place the food there. */
  101.     if(game.world[row][col] == kEmptyTile) {
  102.       game.world[row][col] = kFoodTile;
  103.       return;
  104.     }
  105.   }
  106. }

  107. /* Clears the display and prints the game board. */
  108. void PrintWorld(gameT& game) {
  109.   /* Use a system call to clear the display. */
  110.   system(kClearCommand.c_str());
  111.   
  112.   /* Print each row. */
  113.   for(size_t i = 0; i < game.world.size(); ++i)
  114.     cout << game.world[i] << endl;
  115.   
  116.   cout << "Food eaten: " << game.numEaten << endl;
  117. }

  118. /* Given an ifstream to a file containing CORRECTLY-FORMATTED world data,
  119. * loads in the world.
  120. *
  121. * The format used is as follows:
  122. * Line 1: numRows numCols
  123. * Line 2: dx dy
  124. * Rest:   World data
  125. *
  126. * We assume that the world is correctly-sized and that there is a single
  127. * '*' character in the world that's the starting point for the snake.
  128. */
  129. void LoadWorld(gameT& game, ifstream& input) {
  130.   /* Read in the number of rows and columns. */
  131.   input >> game.numRows >> game.numCols;
  132.   game.world.resize(game.numRows);

  133.   /* Read in the starting location. */
  134.   input >> game.dx >> game.dy;

  135.   /* Because we're going to be using getline() to read in the world
  136.    * data, we need to make sure that we consume the newline character
  137.    * at the end of the line containing the input data.  We'll use
  138.    * getline() to handle this.  This scans characters until it finds
  139.    * a newline, then consumes it.
  140.    */
  141.   string dummy;
  142.   getline(input, dummy);

  143.   /* Read in the rows. */
  144.   for(size_t row = 0; row < game.numRows; ++row) {
  145.     getline(input, game.world[row]);
  146.    
  147.     /* Check to see if the * character (snake start position)
  148.      * is in this line.  If so, make the snake.
  149.      */
  150.     size_t col = game.world[row].find('*');
  151.     if(col != string::npos)
  152.       game.snake.push_back(pointT(row, col));
  153.   }
  154.   
  155.   /* Set numEaten to zero - this needs to get done somewhere! */
  156.   game.numEaten = 0;
  157. }

  158. /* Helper function which returns whether a point is contained in the game
  159. * grid.
  160. */
  161. bool InWorld(pointT& pt, gameT& game) {
  162.   return pt.col < game.numCols &&
  163.          pt.row < game.numRows;
  164. }

  165. /* Returns whether, if the snake head is at position head, the snake
  166. * has crashed.
  167. */
  168. bool Crashed(pointT head, gameT& game) {
  169.   /* We crashed if the head is out of bounds, on a wall, or on another
  170.    * snake piece.
  171.    */
  172.   return !InWorld(head, game) ||
  173.          game.world[head.row][head.col] == kSnakeTile ||
  174.          game.world[head.row][head.col] == kWallTile;
  175. }

  176. /* Returns the next position occupied by the head if the snake is moving
  177. * in the direction dx, dy.
  178. */
  179. pointT GetNextPosition(gameT& game, int dx, int dy) {
  180.   /* Get the head. */
  181.   pointT nextSpot = game.snake.front();
  182.   
  183.   /* Update it. */
  184.   nextSpot.col += dx;
  185.   nextSpot.row += dy;
  186.   
  187.   return nextSpot;
  188. }

  189. /* Performs AI logic to control the snake.  The behavior is as follows:
  190. * 1. If we aren't going to crash and we don't roll a 1 on a fair die,
  191. *    keep going straight.
  192. * 2. Otherwise, check to see if we can turn left or right.  Then randomly
  193. *    pick one safe choice.
  194. */
  195. void PerformAI(gameT& game) {
  196.   /* Look where we're going to be next step. */
  197.   pointT nextSpot = GetNextPosition(game, game.dx, game.dy);
  198.   
  199.   /* If this crashes us or we just feel like turning, turn. */
  200.   if(Crashed(nextSpot, game) || RandomChance(kTurnRate)) {
  201.     /* Compute what direction we'd be facing if we turned left or
  202.      * right.  From linear algebra we have the following:
  203.      *
  204.      * For a left turn:
  205.      * |x'|   |0 -1||x| --> x' = -y
  206.      * |y'| = |1  0||y| --> y' =  x
  207.      *
  208.      * For a right turn:
  209.      * |x'|   |0  1||x| --> x' =  y
  210.      * |y'| = |-1 0||y| --> y' = -x
  211.      */
  212.     int leftDx = -game.dy;
  213.     int leftDy =  game.dx;
  214.    
  215.     int rightDx =  game.dy;
  216.     int rightDy = -game.dx;
  217.    
  218.     /* Check if turning left or right will cause us to crash. */
  219.     bool canLeft = !Crashed(GetNextPosition(game, leftDx, leftDy), game);
  220.     bool canRight = !Crashed(GetNextPosition(game, rightDx, rightDy), game);
  221.    
  222.     /* Now determine which direction to turn based on what direction
  223.      * we're facing.  If we can choose either direction, pick one
  224.      * randomly.  If we can't turn, don't.
  225.      */
  226.     bool willTurnLeft;
  227.     if(!canLeft && !canRight)
  228.       return;
  229.     else if(canLeft && !canRight)
  230.       willTurnLeft = true;
  231.     else if(!canLeft && canRight)
  232.       willTurnLeft = false;
  233.     else
  234.       willTurnLeft = RandomChance(0.5);
  235.    
  236.     /* Otherwise, based on the direction, turn appropriately. */
  237.     game.dx = willTurnLeft? leftDx : rightDx;
  238.     game.dy = willTurnLeft? leftDy : rightDy;
  239.   }
  240. }

  241. /* Moves the snake one step in its current direction and handles collisions
  242. * and eating food.  Returns true if we didn't crash, false if we did.
  243. */
  244. bool MoveSnake(gameT& game) {
  245.   /* Compute new head. */
  246.   pointT nextHead = GetNextPosition(game, game.dx, game.dy);
  247.   
  248.   /* Check for dead. */
  249.   if(Crashed(nextHead, game))
  250.     return false;

  251.   /* Remember whether we just ate food. */
  252.   bool isFood = (game.world[nextHead.row][nextHead.col] == kFoodTile);

  253.   /* Update the display. */
  254.   game.world[nextHead.row][nextHead.col] = kSnakeTile;
  255.   
  256.   /* Push new head to the front of the deque. */
  257.   game.snake.push_front(nextHead);
  258.   
  259.   /* If we got food, pick a new spot and don't remove the tail.  This
  260.    * causes us to extend by one spot. */
  261.   if(isFood) {
  262.     PlaceFood(game);
  263.     ++game.numEaten;
  264.   }
  265.   else {
  266.     /* Clear the tail and remove it from the snake. */
  267.     game.world[game.snake.back().row][game.snake.back().col] = kEmptyTile;
  268.     game.snake.pop_back();
  269.   }
  270.   
  271.   return true;
  272. }

  273. /* Pauses for a few milliseconds so we can see what's happening.  This is
  274. * implemented using a busy loop, which is less-than-optimal but doesn't
  275. * require platform-specific features.
  276. */
  277. void Pause() {
  278.   clock_t start = clock();
  279.   
  280.   while(static_cast<double>(clock() - start) / CLOCKS_PER_SEC < kWaitTime);
  281. }

  282. /* Prompts the user for a filename, then loads the specified file. */
  283. void InitializeGame(gameT& game) {
  284.   /* Seed the randomizer. */
  285.   srand(static_cast<int>(time(NULL)));
  286.   
  287.   ifstream input;
  288.   while(true) {
  289.     cout << "Enter level file: ";
  290.     input.open(GetLine().c_str());
  291.    
  292.     if(!input.fail()) break;
  293.    
  294.     cout << "Sorry, I can't open that file." << endl;
  295.     input.clear();
  296.   }
  297.   
  298.   LoadWorld(game, input);
  299. }

  300. /* Displays the result of the game. */
  301. void DisplayResult(gameT& game) {
  302.   PrintWorld(game);
  303.   if(game.numEaten == kMaxFood)
  304.     cout << "Yay!  The snake won!" << endl;
  305.   else
  306.     cout << "Oh no!  The snake crashed!" << endl;
  307. }

  308. /* Runs the simulation and displays the result. */
  309. void RunSimulation(gameT& game) {
  310.   /* Keep looping while we haven't eaten too much. */
  311.   while(game.numEaten < kMaxFood) {
  312.     PrintWorld(game);
  313.     PerformAI(game);
  314.    
  315.     /* Move the snake and abort if we crashed. */
  316.     if(!MoveSnake(game))
  317.       break;
  318.     Pause();
  319.   }
  320.   DisplayResult(game);
  321. }

  322. /* The main program.  Initializes the world, then runs the simulation. */
  323. int main() {
  324.   gameT game;
  325.   InitializeGame(game);
  326.   RunSimulation(game);
  327.   return 0;
  328. }
复制代码

想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2014-2-6 19:10:13 | 显示全部楼层
地图格式是
  1. 15 15
  2. 1 0
  3. ###############
  4. #             #
  5. # # # # # # # #
  6. #  $  $    $  #
  7. # # # # # # # #
  8. #  $          #
  9. # # # # # # # #
  10. #      *      #
  11. # # # # # # # #
  12. #          $  #
  13. # # # # # # # #
  14. #  $     $ $  #
  15. # # # # # # # #
  16. #             #
  17. ###############
复制代码
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2014-2-6 22:15:45 | 显示全部楼层
看看而已,初学者
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2014-2-8 20:54:28 | 显示全部楼层
路过看看 = =
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2014-2-10 15:14:55 | 显示全部楼层
不明觉厉啊~~~
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2024-4-25 04:51

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表