检查蛇是不是在游戏中撞到自己[关闭]

Posted

技术标签:

【中文标题】检查蛇是不是在游戏中撞到自己[关闭]【英文标题】:Check if the Snake bangs into itself in game [closed]检查蛇是否在游戏中撞到自己[关闭] 【发布时间】:2011-08-05 14:57:22 【问题描述】:

我正在使用 OpenGL 和 GLFW 用 C++ 编写 Snake。我正在尝试实现一个游戏退出的功能,当蛇头撞到它的身体时。 这是我编写的 Snake 类的 move() 和 CrashCheck() 函数。 x_pos 是一个浮点数组,存储了蛇身的一段 x_coordinate。 y_pos 与 y_coordinate 相同。 length 是蛇的身体节段数,当蛇吃东西时会增加(尚未实现)。 x_speed 和 y_speed 存储沿轴的段的速度。蛇永远不能同时沿着两个轴移动;另外,float MAX_S = 0.00075;。我也包含了我的 draw() 函数。而Fix_Snake_x 和Fix_Snake_y 是重新对齐蛇的片段的函数(因为它们不断分离并对游戏造成严重破坏)。我知道这是纠正问题的愚蠢方法,因此如果您可以在 move() 函数中提出修复建议,那将很有帮助。

void draw(float win_aspect)
  
    for(int a = 0; a < length; a++)
      
        Fix_Snake_y();
        glBegin(GL_QUADS);
        glColor3f(1.0,0.0,0.0);
        glVertex2f(x_pos[a],y_pos[a]);
        glVertex2f((x_pos[a]+0.05),y_pos[a]);
        glVertex2f((x_pos[a]+0.05),y_pos[a]-0.05);
        glVertex2f(x_pos[a],y_pos[a] - 0.05);
        glEnd();
        Fix_Snake_x();
      
   

void move()
  
      for(int a = length ; a >= 0; a--)
        
          if(a > 0)
            
              if(x_pos[a] >= x_pos[a-1] && x_speed[a] < 0)
                
                  x_pos[a] += -MAX_S;
                  Fix_Snake_y();
                  Fix_Snake_x();
                  if(x_pos[a] <= x_pos[a - 1])
                  
                     x_speed [a] = 0;
                     if(y_pos[a] <= y_pos[a-1])
                     
                          y_speed[a] = MAX_S;
                     
                     else
                     
                           y_speed[a] = -MAX_S;
                     
                   
                
              if(x_pos[a] <= x_pos[a-1] && x_speed[a] > 0)
                
                  x_pos[a] += MAX_S;
                  Fix_Snake_y();
                  Fix_Snake_x();
                  if(x_pos[a] >= x_pos[a - 1])
                    
                      x_speed [a] = 0;
                      if(y_pos[a] <= y_pos[a-1])
                       
                          y_speed[a] = MAX_S;
                       
                      else
                        
                          y_speed[a] = -MAX_S;
                        
                    
                
              if(y_pos[a] <= y_pos[a-1] && y_speed[a] > 0)
                
                  y_pos[a] += MAX_S;
                  Fix_Snake_y();
                  Fix_Snake_x();
                  if(y_pos[a] >= y_pos[a-1])
                    
                      y_speed[a] = 0;
                      if(x_pos[a] >= x_pos[a-1])
                        
                          x_speed[a] = -MAX_S;
                        
                      if(x_pos[a] <= x_pos[a-1])
                        
                          x_speed[a] = MAX_S;
                        
                    
                
              if(y_pos[a] >= y_pos[a-1] && y_speed[a] < 0)
                
                  y_pos[a] += -MAX_S;
                  Fix_Snake_y();
                  Fix_Snake_x();
                  if(y_pos[a] <= y_pos[a-1])
                    
                      y_speed[a] = 0;
                      if(x_pos[a] >= x_pos[a-1])
                        
                          x_speed[a] = -MAX_S;
                        
                      if(x_pos[a] <= x_pos[a-1])
                        
                          x_speed[a] = MAX_S;
                        
                    
                
        


          if(a == 0)
                
                  x_pos[0] += x_speed[0];
                  y_pos[0] += y_speed[0];
                  Fix_Snake_y();
                  Fix_Snake_x();
                
             CrashCheck();
            
      
      void CrashCheck()
      
        for(int a = 1; a < length; a++)
          
            if(y_speed[0] > 0 && y_speed[a] == 0)
              
                if(x_pos[0] < x_pos[a] && x_pos[0] < x_pos[a] + 0.05)
                  
                    if(y_pos[0] < y_pos[a] && y_pos[0] > y_pos[a] - 0.05)
                      
                        exit(0);
                      
                  
              
            else if(y_speed[0] < 0 && y_speed[a] == 0)
              
                if(x_pos[0] > x_pos[a] && x_pos[0] < x_pos[a] + 0.05)
                  
                    if(y_pos[0] < y_pos[a] && y_pos[0] > y_pos[a] - 0.05)
                      
                        exit(0);
                      
                  
              
          
      
void Fix_Snake_x()
  
    for(int a = 1; a<length; a++)
      
        if(a > 0)
          
            if(x_pos[a] <= x_pos[a-1] - 0.05)
              
                x_pos[a] = x_pos[a-1] - 0.05;
              
            if(x_pos[a] >= x_pos[a -1] + 0.05)
              
                x_pos[a] = x_pos[a-1] + 0.05;
              
          
      
  
  void Fix_Snake_y()
  
    for(int a = 1; a < length; a++)
          
            if(a > 0)
              
                if(y_pos[a] <= y_pos[a-1] - 0.05)
                  
                    y_pos[a] = y_pos[a-1] - 0.05;
                  
                if(y_pos[a] >= y_pos[a-1] + 0.05)
                  
                    y_pos[a] = y_pos[a-1] + 0.05;
                  
              
          
  

编辑: 新的移动功能

for(int a = 0; a < length; a++)
        
            if(a > 0)
              
                if(x_speed[a] < 0 && x_pos[a] >= x_pos[a-1])
                  
                    x_pos[a] += x_speed[a];
                    if(x_pos[a] == x_pos[a-1])
                      
                        y_speed[a] = y_speed[a-1];
                        x_speed[a] = 0;
                        continue;
                      
                  
                if(x_speed[a] > 0 && x_pos[a] <= x_pos[a-1])
                  
                    x_pos[a] += x_speed[a];
                    if(x_pos[a] == x_pos[a-1])
                      
                        y_speed[a] = y_speed[a-1];
                        x_speed[a] = 0;
                        continue;
                      
                  
                if(y_speed[a] > 0 && y_pos[a] <= y_pos[a-1])
                  
                    y_pos[a] += y_speed[a];
                    if(y_pos[a] == y_pos[a-1])
                      
                        x_speed[a] = x_speed[a-1];
                        y_speed[a] = 0;
                      
                  
                if(y_speed[a] < 0 && y_pos[a] >= y_pos[a-1])
                  
                    y_pos[a] += y_speed[a];
                    if(y_pos[a] == y_pos[a-1])
                      
                        x_speed[a] = x_speed[a-1];
                        y_speed[a] = 0;
                      
                  
              
            else
              
                x_pos[0] += x_speed[0];
                y_pos[0] += y_speed[0];
              
        

导致了一些问题。蛇打破它有太多的同时转弯。只有前两个方块保持运动

【问题讨论】:

你的问题是,“我的代码中导致蛇的身体分离的问题在哪里?” 属于 gamedev.stackexchange.com 【参考方案1】:

如果我是你,我会存储一个std::set,其中包含蛇无法到达的所有无效坐标。这将包括:

“游乐场”的边界 障碍 蛇的身体

然后对于蛇的每一次移动,考虑到 x/y 速度,我首先尝试将 InsertLocation 转换为 CInvalidPlaces,如果返回 true 然后我可以走到那里,如果 false 然后蛇即将撞墙,边界或它自己的身体,“游戏”可以结束。这是代码:

#include <set>
using namespace std;

typedef pair<int,int> tInvalidLocation;

struct ltSeCmp

    bool operator()(tInvalidLocation s1, tInvalidLocation s2) const
    
        if (s1.first == s2.first) return s1.second > s2.second;
        return s1.first > s2.first;
    
;

typedef set<tInvalidLocation, ltSeCmp> tInvalidLocations;

class CInvalidPlaces

private:
    tInvalidLocations mInvalid; //this set will hold all the invalid locations for the snake to go to
public:
    bool InsertLocation(tInvalidLocation iLoc)
    
        if (mInvalid.find(iLoc) != mInvalid.end()) return false;    //check if the location is already in the set
        //we survived.. it's safe to go there :)
        mInvalid.insert(iLoc);
        return true;
    
    bool RemoveLocation(tInvalidLocation iLoc)
    
        if (mInvalid.find(iLoc)== mInvalid.end()) return false;
        mInvalid.insert(iLoc);
        return true;
    
;

你还需要做的是:

最初添加边距、所有障碍物和蛇的所有位置,就像它们从蛇开始的位置一样 修改移动例程,这样当蛇移动时,它也必须使用RemoveLocationCInvalidPlaces中移除它的尾巴 在实现蛇的“放大”后,您还必须向CInvalidPlaces 添加额外的段。

如果需要,您可以在以下位置找到有关 stl::set 的更多信息:

SGI CPP.com

HTH,日本

【讨论】:

【参考方案2】:

我强烈建议您使用动态容器来保存蛇身体的坐标。这允许您获取蛇新位置的坐标并在容器中搜索坐标。如果找到该点,则蛇已经撞到自己了。

同样,您可以为墙和块以及其他不属于棋盘的实体的点提供容器。

另一种方法是使用网格数据结构(或矩阵),并在其中放置代表蛇体和其他障碍物的值。

【讨论】:

容器是动态的。它存储蛇体的当前位置。搜索方法是个好主意,但问题是搜索精确坐标永远不会给出精确匹配。也许我应该尝试匹配块中心的坐标? @viraj,您无法获得完全匹配的主要问题是您没有分离模型和视图。如果你使用网格,蛇要么在里面,要么不在。浮点坐标应该只用于显示蛇,而不是用于游戏逻辑。这也有助于解决分离问题。 @viraj:网格不应该有浮点值。标准化为某个整数值。正如 Karl 所说,您需要一些将网格映射(绘制)到屏幕上的功能。 @Thomas Matthews 我也应该使用整数坐标来移动蛇,对吧? @viraj:从历史上看,蛇在网格上移动。网格有一个整数(非浮点)行数和列数。蛇的头部和其他身体部分各占一个细胞。直到你得到所有的算法工作,将显示视为一个正方形网格。可能是质量较差的图形;但在所有算法正常工作后,这些都可以改进。

以上是关于检查蛇是不是在游戏中撞到自己[关闭]的主要内容,如果未能解决你的问题,请参考以下文章

课后作业-结对编程项目总结

C语言课程设计,贪吃蛇应该怎么做?

结对-贪吃蛇游戏-结对项目总结

结对总结

c语言 贪吃蛇 程序

如何在蛇游戏中改变方向[关闭]