• 自制贪吃蛇——会移动的蛇


      上篇地址:http://www.cnblogs.com/chinxi/p/7184063.html

      有了主场景,就要加一条蛇进去看看了。这条“蛇”的功能嘛,要有以下几个:

        1、改变方向

        2、新增一个节点

        3、前进

      首先,是枚举和结构体:

     1 enum Direction
     2 {
     3     EN_DIR_UP = 0,
     4     EN_DIR_DOWN,
     5     EN_DIR_LEFT,
     6     EN_DIR_RIGHT,
     7 };
     8 
     9 struct Coordinate
    10 {
    11     int int_x;
    12     int int_y;
    13 };
    14 
    15 typedef struct Snake_Base
    16 {
    17     Snake_Base* pNext;
    18     char char_icon;              //图标
    19     Coordinate coordinate_cur;   //当前坐标
    20 }SnakeBase;
    21 
    22 typedef struct Snake_Head
    23 {
    24     char char_icon;              //图标
    25     int int_direction;           //前进方向
    26     int int_size;                //当前长度
    27     Coordinate coordinate_cur;   //当前坐标
    28     Snake_Base* pNext;           //下一节   
    29 }SnakeHead;
     1  ///
     2  /// @file    snake.h
     3  /// @author  marrs(chenchengxi993@gmail.com)
     4  /// @date    2017-07-15 09:32:47
     5  ///
     6 
     7 #ifndef __SNAKE_H__
     8 #define __SNAKE_H__
     9 
    10 #include "define.h" 
    11 
    12 namespace marrs{
    13 
    14 class Snake
    15 {
    16     public:
    17         Snake();
    18         ~Snake();
    19 
    20     public:
    21         int init(char char_icon, int int_direction, int int_size, Coordinate coordinate);
    22         int change_direction(int int_direction);    
    23         int add_new_node(Coordinate coordinate_new, char char_icon_new);
    24         int forward();
    25         Snake_Base* get_snake_base();
    26         SnakeHead* get_snake_head();
    27 
    28     private:
    29         SnakeHead _snake;
    30 
    31 };
    32 
    33 }
    34 
    35 #endif

      改变方向其实很简单,改一下字段的值就行了。新增节点的话,如果不考虑场景,那么只要用头插法,向链表中插入一个新元素即可。至于前进,想到了两种植方法:

      其一,“蛇”类中只处理头节点的坐标,其它坐标放在game.cc中处理,把前一个节点的坐标赋值给后一个节点,然后清除最后一个节点的原坐标在场景中的展示。这种方法需要进行多次拷贝,而且要定义多个临时变量,比较麻烦。

      其二,“蛇”类中,如果“蛇”的长度大于1,则先调用一波add_new_node方法,再把最后一个节点删除,并返回这个节点的信息。如果size=1,则new一个节点出来,把头节点的原坐标赋值给它,之后game.cc中,直接清理返回的坐标,再设置头节点新坐标即可。

      实际上,是先想到第一种方法,而且实现了,后来想到了第二种方法,直接就改了。

      1  /// /// @file    snake.cc
      2  /// @author  marrs(chenchengxi993@gmail.com)
      3  /// @date    2017-07-15 11:02:32
      4  ///
      5 
      6 #include <string.h>
      7 #include <iostream>
      8 #include "snake.h"
      9 
     10 namespace marrs{
     11  
     12 Snake::Snake()
     13 {
     14 }
     15 
     16 Snake::~Snake()
     17 {
     18 }
     19 
     20 int Snake::init(char char_icon, int int_direction, int int_size, Coordinate coordinate)
     21 {
     22     _snake.char_icon = char_icon;
     23     _snake.int_direction = int_direction;
     24     _snake.int_size = int_size;
     25     _snake.coordinate_cur = coordinate;
     26     _snake.pNext = NULL;
     27 
     28     if (int_size > 1)
     29     {
     30         for (int int_idx = 0; int_idx < int_size; ++int_idx)
     31         {
     32             //todo add_new_node
     33         }
     34     }
     35     return 0;
     36 
     37 }
     38 
     39 int Snake::change_direction(int int_direction)
     40 {
     41     _snake.int_direction = int_direction;
     42     return int_direction;
     43 }
     44 
     45 int Snake::add_new_node(Coordinate coordinate_new, char char_icon_new)
     46 {
     47     Snake_Base* pNode = new Snake_Base;
     48     memset(pNode, 0, sizeof(Snake_Base));
     49     pNode->coordinate_cur = _snake.coordinate_cur;
     50     pNode->char_icon = _snake.char_icon;
     51 
     52     if (_snake.pNext == NULL)
     53     {
     54         _snake.pNext = pNode;        
     55     }else{
     56         pNode->pNext = _snake.pNext;
     57         _snake.pNext = pNode;
     58     }
     59     
     60     _snake.coordinate_cur = coordinate_new;
     61     _snake.char_icon = char_icon_new;
     62     ++_snake.int_size;
     63 
     64     return 0;
     65 }
     66 
     67 Snake_Base* Snake::forward()
     68 {
     69     Snake_Base* pReturn = NULL;
     70     if(_snake.int_size > 1)
     71     {
     72         add_new_node(_snake.coordinate_cur, _snake.char_icon);        
     73         Snake_Base* pCur = _snake.pNext;
     74         while(pCur->pNext->pNext)
     75         {
     76             pCur = pCur->pNext;
     77         }
     78         pReturn = pCur->pNext;
     79         pCur->pNext = NULL;    
     80 
     81     }
     82     else
     83     {
     84         pReturn = new Snake_Base;
     85         pReturn->coordinate_cur = _snake.coordinate_cur;
     86     }
     87     
     88     switch(_snake.int_direction)
     89     {
     90         case EN_DIR_UP:
     91             _snake.coordinate_cur.int_x -= 1;
     92             break;
     93         case EN_DIR_DOWN:    
     94             _snake.coordinate_cur.int_x += 1;
     95             break;
     96         case EN_DIR_LEFT:    
     97             _snake.coordinate_cur.int_y -= 1;
     98             break;
     99         case EN_DIR_RIGHT:    
    100             _snake.coordinate_cur.int_y += 1;
    101             break;
    102         default:break;
    103 
    104     }
    105     return pReturn;
    106 
    107 }
    108 
    109 Snake_Base* Snake::get_snake_base()
    110 {
    111     return _snake.pNext;
    112 
    113 }
    114 
    115 SnakeHead* Snake::get_snake_head()
    116 {
    117     return &_snake;
    118 
    119 }
    120 }

       然后,根据需要修改了game.h和game.cc

     1  ///
     2  /// @file    game.h
     3  /// @author  marrs(chenchengxi993@gmail.com)
     4  /// @date    2017-07-15 11:42:03
     5  ///
     6 
     7 #ifndef __GAME_H__
     8 #define __GAME_H__
     9 
    10 #include "map.h"
    11 #include "snake.h"
    12 
    13 namespace marrs{
    14 
    15 class Game
    16 {
    17     public:
    18         int init();    
    19         int output_map();    
    20         int refresh_map();
    21         int gen_random_point();
    22         int reset_random_point();
    23         
    24         int forward();
    25         int check_collision();
    26 
    27     private:
    28         Map _map;
    29         Snake _snake;    
    30         Coordinate _random_point;
    31 };
    32  
    33 }
    34 
    35 #endif

      新增了一些方法。 

      1  ///
      2  /// @file    game.cc
      3  /// @author  marrs(chenchengxi993@gmail.com)
      4  /// @date    2017-07-15 18:05:24
      5  ///
      6  
      7 #include <iostream>
      8 #include "game.h"
      9 
     10 namespace marrs{
     11 
     12 int Game::init()
     13 {
     14     Coordinate coordinate = _map.get_map_center_pos();
     15     _snake.init('O', EN_DIR_DOWN, 1, coordinate);    
     16     
     17     MapBase map;
     18     map.char_icon = 'O';
     19     map.int_type = EN_MAP_SNAKE;
     20     _map.set_map_val(coordinate.int_x, coordinate.int_y, map);
     21 
     22     reset_random_point();
     23 
     24     output_map();
     25     return 0;
     26 
     27 }
     28 
     29 int Game::output_map()
     30 {
     31     int int_map_x_size = _map.get_x_size();
     32     int int_map_y_size = _map.get_y_size();
     33 
     34     for (int int_idx = 0; int_idx < int_map_x_size; ++int_idx)
     35     {
     36         for (int int_idy = 0; int_idy < int_map_y_size; ++int_idy)
     37         {
     38             _map.output_map(int_idx, int_idy);
     39         }
     40         cout << endl;
     41     }
     42     return 0;
     43     
     44 }
     45 
     46 int Game::refresh_map()
     47 {
     48     int int_map_y_size = _map.get_y_size();
     49     printf("33[%dA", int_map_y_size);
     50     output_map();
     51     return 0;
     52 
     53 }
     54 
     55 int Game::gen_random_point()
     56 {
     57     while(_random_point.int_x == 0)
     58     {
     59         _random_point.int_x = random(_map.get_x_size());
     60     }
     61     while(_random_point.int_x == 0)
     62     {
     63         _random_point.int_y = random(_map.get_y_size());
     64     }
     65     return 0;
     66     
     67 }
     68 
     69 int Game::reset_random_point()
     70 {
     71     _random_point.int_x = 0;
     72     _random_point.int_y = 0;
     73     return 0;
     74 }
     75 
     76 int Game::forward()
     77 {
     78     int int_ret = check_collision();
     79     if(int_ret)
     80     {
     81         return int_ret;
     82     }
     83 
     84     Snake_Base* snake_tmp = _snake.forward();
     85     
     86     
     87     _map.reset_point(snake_tmp->coordinate_cur.int_x, snake_tmp->coordinate_cur.int_y);
     88     delete snake_tmp;
     89     MapBase map_tmp;
     90     map_tmp.int_type = EN_MAP_SNAKE;
     91     map_tmp.char_icon = _snake.get_snake_head()->char_icon;
     92     _map.set_map_val(_snake.get_snake_head()->coordinate_cur.int_x,
     93                 _snake.get_snake_head()->coordinate_cur.int_y,
     94                 map_tmp);
     95 
     96     return 0;
     97 }
     98 
     99 int Game::check_collision()
    100 {
    101 
    102     return 0;
    103 }
    104 
    105 }

      可以测试一下

     1  ///
     2  /// @file    main.cc
     3  /// @author  marrs(chenchengxi993@gmail.com)
     4  /// @date    2017-07-15 18:20:18
     5  ///
     6  
     7 #include "game.h" 
     8 using namespace marrs;
     9 
    10 int main()
    11 {
    12     Game game;
    13     game.init();
    14     for(int int_idx = 0; int_idx < 5; ++int_idx)
    15     {
    16         game.forward();    
    17         game.refresh_map();
    18         sleep(1);
    19     }
    20     
    21 
    22 
    23 
    24     return 0;
    25 }

      预期的结果,是“OO”向下移动了五个位置,一秒一次。

      执行程序:

      开始

     1 [ccx@ubuntu ~/Retro_Snaker/bin]$>./game.exe 
     2 ++====================================++
     3 ||                                    ||
     4 ||                                    ||
     5 ||                                    ||
     6 ||                                    ||
     7 ||                                    ||
     8 ||                                    ||
     9 ||                                    ||
    10 ||                                    ||
    11 ||                                    ||
    12 ||                  OO                ||
    13 ||                                    ||
    14 ||                                    ||
    15 ||                                    ||
    16 ||                                    ||
    17 ||                                    ||
    18 ||                                    ||
    19 ||                                    ||
    20 ||                                    ||
    21 ++====================================++

      结束

     1 [ccx@ubuntu ~/Retro_Snaker/bin]$>./game.exe 
     2 ++====================================++
     3 ||                                    ||
     4 ||                                    ||
     5 ||                                    ||
     6 ||                                    ||
     7 ||                                    ||
     8 ||                                    ||
     9 ||                                    ||
    10 ||                                    ||
    11 ||                                    ||
    12 ||                                    ||
    13 ||                                    ||
    14 ||                                    ||
    15 ||                                    ||
    16 ||                                    ||
    17 ||                  OO                ||
    18 ||                                    ||
    19 ||                                    ||
    20 ||                                    ||
    21 ++====================================++
    22 [ccx@ubuntu ~/Retro_Snaker/bin]$>

      可以看到,它从第12行,移到了第17行,符合预期。

      未完待续....

      github:https://github.com/ccx19930930/Retro_Snaker

  • 相关阅读:
    4header组件开发
    3组件骨架开发
    2项目目录设计
    1项目相关的一些简介
    21AJax与Comet
    20JSON
    获取特定筛选条件下数据的四分位点
    动态长度字符串的解析拆分问题
    myBase Desktop 7无限免费试用方法
    VBA 将Excel工作簿中所有表格进行一键排版
  • 原文地址:https://www.cnblogs.com/chinxi/p/7185309.html
Copyright © 2020-2023  润新知