我应该使用什么数据结构进行蛇游戏?

时间:2009-12-22 09:58:52

标签: delphi data-structures

我为学校做了一些功课,我必须在德尔福做一个像诺基亚一样的蛇游戏。我想知道哪种解决方案是最好的。我希望我的蛇是一个类,主体是一个点数组(父类)或点链接列表。什么是最好的?数组或链表?

7 个答案:

答案 0 :(得分:8)

一个简单的解决方案是创建一个类型的数组[水平] [垂直],这样屏幕上的每个坐标都有一个项目。每种类型都可以是蛇方向,食物,毒药,墙壁或空洞。这意味着你只需要记住蛇的头部和尾部位置,以及食物和毒药的数量,并且阵列描述了屏幕的样子。

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

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

答案 1 :(得分:7)

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

如果你使用一个数组,你需要调整它的大小或者将它初始化为最大可能的蛇长度,这可能会浪费在内存上。

<强>更新 本文讨论Delph中的指针,甚至建议一个简单的节点定义delphi article

答案 2 :(得分:2)

以下是一些很好的起点...因为我不想做你的作业:

Pseudo Code for Snake Game to get an Idea

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

如果在编程过程中出现错误,请随时打开一个新问题。

答案 3 :(得分:2)

在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,你必须公开属性List ...要做到这一点,只需像那样定义你的蛇体类;

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

答案 4 :(得分:2)

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

  1. 蛇头的位置
  2. 蛇的长度
  3. 蛇头的方向
  4. 一组“弯曲”物体,其中弯曲由方向(左或右)和偏移组成(例如(左,3),当蛇的第三个位置有左弯时)
  5. 这非常有效,不是像简单阵列那样愚蠢的解决方案,而且可以很容易地用来绘制“发烧的”蛇,例如:圆角。

答案 5 :(得分:0)

我有一个非常古老的turbopascal蛇计划。它为身体使用一个数组。

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;

答案 6 :(得分:0)

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

获得一个足够大的阵列来容纳最大的蛇。建立两个指针,一个用于头部,一个用于尾部。

开始时,尾部将位于单元格#1中,单元格位于单元格#3中。当蛇移动时,将头指针移动到右侧并写入新坐标。然后,如果没有食用,也可以将尾指针移到右边。如果其中一个指针试图超出数组的最右端,请将它们包装到开头。