【问题标题】:What data structure should I use for a snake game?我应该为蛇游戏使用什么数据结构?
【发布时间】:2009-12-22 09:58:51
【问题描述】:

我有一些学校作业,我必须在 Delphi 中制作一个蛇游戏,就像诺基亚的游戏一样。我想知道哪种解决方案是最好的。我希望我的蛇是一个类,而主体是一个点数组(父类)或点的链接列表。什么是最好的?数组还是链表?

【问题讨论】:

  • 我一直很喜欢关于 SO 的家庭作业问题。很想知道什么学校和班级。 . ..

标签: delphi data-structures


【解决方案1】:

一个简单的解决方案是制作一个数组[horizo​​ntal][vertical]类型,这样屏幕上的每个坐标都有一个项目。每种类型都可以是蛇方向、食物、毒药、墙或空。这意味着你只需要记住蛇的头尾位置,以及食物和毒药的数量,数组描述了屏幕的样子。

这消除了处理蛇元素的麻烦,并且可以轻松地在屏幕上放置新的食物或毒物,确保您不会将其放入已经被占用的地方。

当需要移除蛇的尾部元素时,使用direction:=array[tailx,taily];获取尾部的方向然后设置数组[tailx,taily]:=empty。之后,根据方向更新tai​​lx和taily。就是这样。

【讨论】:

    【解决方案2】:

    链接列表更好。 (每个节点都可以指向前一个节点和下一个节点)将节点添加到链表的末尾更容易。

    如果您使用数组,则需要调整其大小或将其初始化为最大可能的蛇形长度以开始,这可能会浪费内存。

    更新 本文讨论 Delph 中的指针,甚至提出了一个简单的 Node 定义delphi article

    【讨论】:

    • 因为这是家庭作业,任何使用指针的练习都会很有帮助。
    • @skamradt 建议您将此作为另一个问题提出。你没有指定什么语言。我通常不使用 Pascal (Delphi) 编写代码,但我认为与 C++ 不同的是,它隐藏了指针的使用
    • @Andrew,您仍然可以在 Delphi 中使用指针。它们不是隐藏的,只是隐含在类实例中。
    • @skamradt - 很有趣 - 添加了可能有帮助的文章的链接。 Delphi 比我想象的更通用(我通常用 C# 或 Java 编写代码,C++ 正在成为一个更遥远的记忆)。
    • Pascal(以及 Delphi)一直支持指针。我记得在 1984 年写过链表!
    【解决方案3】:

    我为我的 Snake 实现使用了不同的东西。这个想法是你存储

    1. 蛇头的位置
    2. 蛇的长度
    3. 蛇头的方向
    4. “弯曲”对象数组,其中弯曲由方向(左或右)和偏移量组成(例如,当蛇的第三个位置有左弯曲时,(左,3))

    这是非常有效的,而不是像简单数组那样愚蠢的解决方案,并且可以很容易地用来绘制“更漂亮”的蛇,例如圆角。

    【讨论】:

    • 队列怎么这么笨?这显然是一个数据结构,如果你想创建圆角,你可以在你的渲染部分做到这一点,游戏逻辑可以保持愚蠢。
    【解决方案4】:

    这里有一些不错的起点……因为我不想做你的功课:

    Pseudo Code for Snake Game to get an Idea

    Thread with a german example...maybe this code helps you

    如果您在编程过程中出现错误,请随时提出新问题。

    【讨论】:

    • 我不想让任何人做我的功课..我只是想要关于数组或链表的建议..
    【解决方案5】:

    在 Delphi 中,我会使用 TQueue,女巫是在 Contnrs 单元中定义的。 您可以将新坐标“推入”其中(蛇头),当达到最大蛇尺寸时,您只需调用“pop”即可释放蛇尾。

    lp := new(PPoint);
    lp^.X := x;
    lp^.X := y;
    
    Body.Push(lp);    
    
    if Body.count > iSnakeLength then
      Dispose(Body.Pop); // Free the last TCoord that is pop'ed.
    

    然后,您需要做的就是绘制 TObjectQueue 中的内容。要访问 TQueue 的列表,您必须公开属性 List...为此,只需像这样定义您的蛇体类;

      TSnakeBody = class(TObjectQueue)
      public
        property List;  //Expose the list
      end;
    

    【讨论】:

    • 从队列中弹出会删除 head 元素,而不是尾部。在什么版本的蛇游戏中,蛇有最大长度?它应该继续增长——这就是游戏的挑战。如果您需要获取队列的内部内容,那么队列不是正确的数据结构。请改用普通列表。另外,我不确定 New 的语法是否有效。
    • 队列是先进先出 (FIFO) 数据结构,而堆栈是后进先出 (LIFO)删除项目。
    • 使用 Delphi 的 TQueue(不是 TStack),弹出删除输入的第一个数据。所以你推动头部,你弹出尾巴......在我的蛇版本中,你必须和蛇一起吃东西才能让它长大。绘制蛇需要获取队列的内部内容。
    【解决方案6】:

    我有一个非常古老的涡轮帕斯卡蛇程序。它使用一个数组作为主体。

    const MaxBodyLength = 100;
    type
      TSnake = record
        Dir : (nord,sud,est,oest);
        Head : tpoint;
        BodyLength : integer;
        Body : array[1..MaxBodyLength] of tPoint;
        Tail : tpoint;
      end;    
    var
      Snake : TSnake;
      Fruit : tPoint;
    

    以及移动蛇的代码......

    procedure Slither;
    var i : integer;
        npos,lpos : tPoint;
        hasEaten:boolean;
    begin
      npos:=Snake.Head;
      lpos:=Snake.Tail;
      case Snake.dir of
        East  : inc(npos.x);
        West  : dec(npos.x);
        South : inc(npos.y);
        North : dec(npos.y);
      end;
      hasEaten:=(npos.x=fruit.x) and (npos.y=fruit.y);
      if hasEaten then 
        inc(Snake.BodyLength)
      else
        Snake.Tail:=Snake.Body[Snake.BodyLength];
    
      for i:=Snake.BodyLength downto 2 do
        Snake.Body[i]:=Snake.Body[i-1];
      Snake.Body[1]:=Snake.Head; 
    
      if not hasEaten then
        Snake.Head:=npos;
    
      writeP(idHead,Snake.Head);  
      writeP(idBody,Snake.Body[1]); 
    
      if not hasEaten then 
       begin
        writeP(idTail,Snake.Tail); 
        writeP(idResidual,lPos); 
       end;
      if hasEaten then 
        NewFruit;
    end;
    

    【讨论】:

    • 我很确定那不是 Turbo Pascal。记录的数组长度是由记录的成员定义的吗?这是不允许的。记录的大小在编译时固定。您不能增加 BodyLength 字段并让数组变长。
    【解决方案7】:

    您可以使用circular buffer。详细说明:

    得到一个足够大的数组来容纳最大的蛇。建立两个指针,一个指向头部,一个指向尾部。

    在开始时,尾部将在 #1 单元格中,头部在 #3 号单元格中。随着蛇的移动,将头部指针向右移动并写入新坐标。然后,如果没有吃的食物,也将尾部指针向右移动。如果任何一个指针试图超出数组的最右端,则将它们包装到开头。

    【讨论】:

      猜你喜欢
      • 2011-12-12
      • 1970-01-01
      • 2011-06-25
      • 1970-01-01
      • 1970-01-01
      • 2011-10-24
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多