Какую структуру данных я должен использовать для игры со змеями? - PullRequest
8 голосов
/ 22 декабря 2009

У меня есть домашнее задание для моей школы, и я должен сделать игру со змеями, как у Nokia, в Delphi. Интересно, какое решение лучше. Я хочу, чтобы моя змея была классом, а тело - массивом точек (родительский класс) или связанным списком точек. Что лучше? Массив или связанный список?

Ответы [ 7 ]

8 голосов
/ 22 декабря 2009

Простое решение - создать массив [горизонтальный] [вертикальный] типа, чтобы на каждой координате на экране был один элемент. Каждый тип может быть змеиным направлением, пищей, ядом, стеной или пустым. Это означает, что вам нужно запомнить только положение головы и хвоста змеи, а также количество пищи и ядов, а массив описывает, как выглядит экран.

Это избавляет от хлопот, связанных с элементами змеи, и позволяет легко размещать на экране новые продукты питания или отравляющие предметы, гарантируя, что вы не поместите их в место, которое уже занято.

Когда вам нужно удалить хвостовой элемент змеи, определите направление хвоста, используя direction: = array [tailx, taily]; а затем установите массив [tailx, taily]: = пусто. После этого обновите tailx и taily в зависимости от направления. Вот и все.

7 голосов
/ 22 декабря 2009

Связанный список лучше. (Каждый узел может указывать на предыдущий и следующий узел). Добавлять узлы в конец связанного списка проще.

Если вы используете массив, вам нужно либо изменить его размер, либо инициализировать его до максимально возможной длины змеи, чтобы начать с нее, что может быть бесполезным для памяти.

UPDATE Эта статья рассказывает об указателях в Delph и даже предлагает простое определение Node delphi article

2 голосов
/ 17 апреля 2011

Я использовал что-то другое для моей реализации Snake. Идея в том, что вы храните

  1. расположение головы змеи
  2. длина змеи
  3. направление головы змеи
  4. массив объектов "изгиба", где изгиб состоит из направления (влево или вправо) и смещения (например, (влево, 3), когда имеется изгиб влево в третьей позиции змеи)

Это довольно эффективно, а не глупое решение, как простой массив, и его можно легко использовать для рисования "причудливых" змей, например. с закругленными углами.

2 голосов
/ 22 декабря 2009

В 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;
2 голосов
/ 22 декабря 2009

Вот несколько хороших отправных точек для вас ... так как я не хочу делать вашу домашнюю работу:

Псевдокод для игры со змеями, чтобы получить идею

Нить с немецким примером ... может быть, этот код поможет вам

Если в процессе программирования возникают ошибки, не стесняйтесь открывать новый вопрос.

0 голосов
/ 19 января 2012

Вы можете использовать круговой буфер . Для уточнения:

Получить массив, достаточно большой, чтобы вместить максимум змеи. Установите два указателя, один для головы, один для хвоста.

Сначала хвост находился в клетке № 1, а голова - в клетке № 3. Когда змея движется, переместите указатель головы вправо и запишите новую координату. Затем, если пищи нет, переместите указатель хвоста также вправо. Если один из указателей пытается выйти за пределы правого конца массива, перенесите их в начало.

0 голосов
/ 22 декабря 2009

У меня есть очень старая программа Turbopascal Snake. Он использует массив для тела.

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;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...