# [Delphi] Snake - wo ist der Fehler?



## minecrawler (28. November 2010)

Ich hab aus Langeweile nen Snake Klon gemacht. Ist natürlich noch nicht ganz fertig, aber die Basissteuerung und so sollte eigentlich schonmal funktionieren. Der Code lässt sich kompilieren, aber sobald ich das Programm starte kommen Fehlermeldungen: "Fehler bei Adresse xy lesen von yxz". Ich vermute, dass er Probleme mit meinen Variablen breite und hoehe hat. Vielleicht sieht jemand, wie man das in Ordnung bringt...


```
unit Unit3;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, cyPaintBox, cyAdvPaintBox, ExtCtrls;

type
  TForm3 = class(TForm)
    cyAdvPaintBox1: TcyAdvPaintBox;
    tmr1: TTimer;
    tmr2: TTimer;
    procedure FormShow(Sender: TObject);
    procedure tmr2Timer(Sender: TObject);
    procedure cyAdvPaintBox1Paint(Sender: TObject);
    procedure FormShortCut(var Msg: TWMKey; var Handled: Boolean);
    procedure tmr1Timer(Sender: TObject);
  private
    { Private-Deklarationen }
  public
    { Public-Deklarationen }
  end;

var
  Form3: TForm3;

implementation

{$R *.dfm}

const farben : array[0..2] of TColor = (clBlack, clWhite,clRed);
      raster : Integer = 8;
var breite : Integer;
    hoehe : Integer;
    map: Array of array of Integer;
    kopf, dir, futter: TPoint;
    _length, points: Integer;
    game : Boolean;

procedure spiel_ende;
begin
  game:=False;
end;

procedure feed;
begin
  futter := Point(Random(breite), Random(hoehe));
  while map[futter.X, futter.Y]<>0 do
    futter := Point(Random(breite), Random(hoehe));
  map[futter.X,futter.Y] := -1;
end;

procedure movesnake;
var
  i, j: Integer;
begin
  for i := 0 to breite do
    for j := 0 to hoehe do
      if map[i, j]>0 then
        Dec(map[i, j]);
  kopf.X:=kopf.X+dir.X;
  kopf.Y:=kopf.Y+dir.Y;
  if (kopf.X<0) or (kopf.X>breite) or (kopf.Y<0) or (kopf.Y>hoehe) then
  begin
    spiel_ende;
    ShowMessage('Sie haben den Rand berührt! F2 für neues Spiel!');
  end;
  if (map[kopf.X, kopf.Y]>0) and (game) then
  begin
    spiel_ende;
    ShowMessage('Sie haben sich selbst gebissen! F2 für neues Spiel!');
  end;
  if (kopf.X=futter.X) and (kopf.Y=futter.Y) then
  begin
    Inc(_length);
    feed;
  end;
  map[kopf.X, kopf.Y] := _length;
end;

procedure TForm3.cyAdvPaintBox1Paint(Sender: TObject);
var i,j : Integer;
    col: TColor;
begin
  for i := 0 to breite do
    for j := 0 to hoehe do
    begin
      case map[i, j] of
        -1: col := farben[2];
         0: col := farben[0];
      else
        col := farben[1];
      end;
      CyAdvPaintBox1.Canvas.Brush.Color:=col;
      CyAdvPaintBox1.Canvas.FillRect(Rect(i*raster, j*raster, (i+1)*raster, (j+1)*raster));
    end;
end;

procedure setstart;
var
  J, I: Integer;
begin
  points:=0;
  _length:=5;
  map[0,0]:=5;
  kopf.X:=1;
  kopf.Y:=1;
  dir.X:=0;
  dir.Y:=1;
  feed;
  Form3.tmr2.Enabled:=True;
end;

procedure TForm3.FormShortCut(var Msg: TWMKey; var Handled: Boolean);
begin
if Msg.CharCode=vk_F2 then setstart;
if Msg.CharCode=VK_ESCAPE then
  begin
    game:=False;
    TerminateProcess(GetCurrentProcess,0);
  end;
end;

procedure TForm3.FormShow(Sender: TObject);
begin
Randomize;
Left:=0;
Top:=0;
cyAdvPaintBox1.Left:=0;
cyAdvPaintBox1.Top:=0;
Width:=Screen.Width;
Height:=Screen.Height;
cyAdvPaintBox1.Width:=Width;
cyAdvPaintBox1.Height:=Height;
breite:=Round((Screen.Width / raster));
hoehe:=Round((Screen.Height / raster));
SetLength(map,breite,hoehe);
setstart;
end;

procedure gamecontrol;
begin
  if GetAsyncKeyState(VK_UP)<>0 then
    if dir.Y<1 then begin dir.Y:=-1; dir.X:=0; end;
  if GetAsyncKeyState(VK_DOWN)<>0 then
    if dir.Y>-1 then begin dir.Y:=1; dir.X:=0; end;
  if GetAsyncKeyState(VK_LEFT)<>0 then
    if dir.X<1 then begin dir.X:=-1; dir.Y:=0; end;
  if GetAsyncKeyState(VK_RIGHT)<>0 then
    if dir.X>-1 then begin dir.X:=1; dir.Y:=0; end;
end;

procedure Main;
begin
  game:=true;
  while game do
    begin
      gamecontrol;
      Form3.cyAdvPaintBox1.Repaint;
      if GetAsyncKeyState(VK_ESCAPE)<>0 then
        begin
          game:=False;
          TerminateProcess(GetCurrentProcess,0);
        end;
    end;
end;

procedure TForm3.tmr1Timer(Sender: TObject);
begin
  if game then
      movesnake;
end;

procedure TForm3.tmr2Timer(Sender: TObject);
begin
Form3.tmr2.Enabled:=False;
ShowMessage('Bereit? Wenn du OK gedrückt hast kannst du das Spiel jederzeit mit ESC beenden!');
Main;
end;

end.
```

Anmerkung: tmr1 auf 500ms und tmr2 auf 10ms.


----------

