Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Multimedia (https://www.delphipraxis.net/16-multimedia/)
-   -   Delphi [Snake-Spiel] - brauche eure Hilfe (https://www.delphipraxis.net/140199-%5Bsnake-spiel%5D-brauche-eure-hilfe.html)

oxmox. 13. Sep 2009 12:41


[Snake-Spiel] - brauche eure Hilfe
 
Liste der Anhänge anzeigen (Anzahl: 1)
Hallo erstmal ^^

ich bräuchte mal eure Hilfe.
Für die Schule muss ich ein beliebiges Programm schreiben.
Als Projekt, dacht ich mir eignet sich ein simples Spiel, wie 'Snake'.

Das Spiel läuft zwar, aber gelegendlich wird folgende Fehlermeldungen angezeigt (Zugriffsverletzung)
http://img5.imagebanana.com/view/fdz...rror.snake.JPG
Das Programm besteht aus 2 Formen.
Die 2. Form is einfach nur für den Highscore.
Ist aber denk ich hier unwichtig, deshalb post ich hier nur die erste Form, sprich die Main-Form.

Nachdem ich den Highscore eingebaut hatte, tauchten die Fehlermeldungen erst auf.
Auch das, wenn man sich selbst beist, wird das Spiel beendet, funktioniert nicht mehr.
Keine Ahnung an was das liegen könnte ^^

Auch stört mich, dass das schwarze Spielfeld "ausradiert" wird, wenn man z.B. mit der 2.ten Form drübergeht.

Ich hoffe ihr habt paar Tips, da das Programm auch nicht wirklich sauber programmiert ist, denke ich.

Ich hänge die Project files, als Dateianhang noch an.
Hier ist der Code, der ersten Form.

Danke schonmal :D


Delphi-Quellcode:

unit Snake1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, ExtCtrls, StdCtrls, MMSystem, inifiles, ComCtrls, Buttons, highscore2;

const
  farben: Array [0..3] of TColor = (clBlack, clLime, clRed, clBlue);
  raster = 10; //10 Pixel = 1 Feld
  breite = 24; //0 bis 24 -> 25 * 10(Raster) = Breite von 250 Pixeln
  hoehe = 24; // ''

type
  TForm1 = class(TForm)
    PaintBox1: TPaintBox;
    Button1: TButton;
    Button2: TButton;
    Button3: TButton;
    Button4: TButton;
    Button5: TButton;
    Timer1: TTimer;
    Button6: TButton;
    Label1: TLabel;
    Image1: TImage;
    GroupBox1: TGroupBox;
    CheckBox1: TCheckBox;
    Label2: TLabel;
    Image2: TImage;
    Label3: TLabel;
    BitBtn1: TBitBtn;
    Label4: TLabel;
    GroupBox2: TGroupBox;
    BitBtn2: TBitBtn;
    BitBtn4: TBitBtn;
    Label5: TLabel;
    BitBtn3: TBitBtn;
    GroupBox3: TGroupBox;
    GroupBox4: TGroupBox;
    Label9: TLabel;
    Label6: TLabel;
    procedure Button1Click(Sender: TObject);
    procedure Timer1Timer(Sender: TObject);
    procedure Button2Click(Sender: TObject);
    procedure Button3Click(Sender: TObject);
    procedure Button4Click(Sender: TObject);
    procedure Button5Click(Sender: TObject);
    procedure FormCreate(Sender: TObject);
    procedure Button6Click(Sender: TObject);
    procedure FormKeyDown(Sender: TObject; var Key: Word;
      Shift: TShiftState);
    procedure BitBtn1Click(Sender: TObject);
    procedure FormShow(Sender: TObject);
    procedure BitBtn2Click(Sender: TObject);
    procedure BitBtn4Click(Sender: TObject);
    procedure BitBtn3Click(Sender: TObject);
  private
    { Private-Deklarationen }
    //Privater Bereich für Prozeduren die für kein anderes Objekt
    //aufgerufen werden und nicht außerhalb der Form benötigt werden.
    map: Array [0..breite] of Array [0..hoehe] of Integer;
    kopf, richtung, futter: TPoint;
    laenge, punkte: Integer;
    ende: Boolean;
    procedure buttons_freigeben(status: Boolean);
    procedure spiel_ende;
    procedure neues_futter;
    procedure spielfeld;
    procedure schlange;
  public
    { Public-Deklarationen }
  end;
 
var
  Form1: TForm1;

implementation

{$R *.dfm}

type zaehlertyp = array [1..1] of integer;
var einmaligercountdown: zaehlertyp;

procedure InIniSchreiben (Filename, Section, Key, Value: string);
var ini: Tinifile;
begin
  ini:= tinifile.Create(Filename);
  try
    ini.WriteString(section, key, value);
  finally
    ini.Free;
  end;
end;

function InIniLesen (Filename, Section, Key: string):string;
var ini: Tinifile;
begin
  ini:= tinifile.Create(Filename);
  try
    result:= ini.ReadString(section, key, '');
  finally
    ini.Free;
  end;
end;

procedure Delay (const Milliseconds: DWord);
var FirstTickCount: DWord;
begin
  FirstTickCount:= GetTickCount;
  while ((GetTickCount - FirstTickCount) < Milliseconds) do
    begin
      Application.ProcessMessages;
      Sleep(0);
    end;
end;

procedure TForm1.spiel_ende;
begin
  ende:= True;
  Timer1.Enabled:= False;
  buttons_freigeben(False);
  Button1.Enabled:= True;
  button6.Enabled:= false;
end;

procedure TForm1.neues_futter;
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 TForm1.spielfeld;
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[1];
         0: col:= farben[0];
      else
        col:= farben[2];
      end;
      PaintBox1.Canvas.Brush.Color:=col;
      PaintBox1.Canvas.FillRect(Rect(i*raster, j*raster, (i+1)*raster, (j+1)*raster));
    end;
end;

procedure TForm1.schlange;
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]);
  Inc(kopf.X, richtung.X);
  Inc(kopf.Y, richtung.Y);
  if checkbox1.Checked= true then
    begin
      if (kopf.X < 0) then
        Kopf.X:= kopf.X + Breite + 1;
      if Kopf.Y < 0 then
        Kopf.Y:= kopf.Y + Hoehe + 1;
      if Kopf.X > Breite then
        Kopf.X:= Kopf.x - Breite - 1;
      if Kopf.Y > Hoehe then
        Kopf.Y:= Kopf.Y - Hoehe - 1;
    end
  else
    if (kopf.X < 0) or (kopf.X > breite) or (kopf.Y < 0) or (kopf.Y > hoehe) then
      begin
        spiel_ende;
        checkbox1.Enabled:= true;
        if label1.Caption > label5.Caption then
          begin
            form1.Enabled:= false;
            form2.Label3.Caption:= inttostr(punkte-1);
            form2.Show;
          end
        else
          showmessage('Spiel beendet' + #10#13 + 'Du hast den Rand berührt');
  if (map[kopf.X, kopf.Y]>0) and (not ende) then
      begin
        spiel_ende;
        checkbox1.Enabled:= true;
        if label1.Caption > label5.Caption then
          begin
            form1.Enabled:= false;
            form2.Label3.Caption:= inttostr(punkte-1);
            form2.Show;
          end
        else
          showmessage('Spiel beendet' + #10#13 + 'Du hadt dich selbst gebissen');
        end;
      end;
  if (kopf.X = futter.X) and (kopf.Y = futter.Y) then
    begin
      Inc(laenge);
      neues_futter;
      label1.Caption:= inttostr(punkte);
      inc(punkte);
    end;
  map[kopf.X, kopf.Y] := laenge;
end;

procedure TForm1.Button1Click(Sender: TObject);
var i, j, zaehler: Integer;
begin
  inc(einmaligercountdown[1]);
  label1.Caption:= '0';
  punkte:= 1;
  zaehler:= 3;
  spielfeld;
  label3.Visible:= true;
  if einmaligercountdown[1]= 1 then
    begin
      while zaehler > 0 do
        begin
          dec(zaehler);
          delay(1000);
          label3.Caption:= inttostr(zaehler);
        end;
    end;
  Button1.Enabled := False;
  button6.Enabled:= true;
  checkbox1.Enabled:= false;
  for i:=0 to breite do
    for j:=0 to hoehe do
      map[i, j] := 0;
  kopf:= Point(1, 1);
  laenge:= 5;
  richtung := Point(0, 1);
  map[kopf.X, kopf.Y]:= laenge;
  neues_futter;
  buttons_freigeben(True);
  ende:= False;
  Timer1.Enabled := True;
end;

procedure TForm1.Timer1Timer(Sender: TObject);
begin
  schlange;
  if not ende then
    spielfeld;
end;

procedure TForm1.FormShow(Sender: TObject);
var filename: string;
begin
  filename:= extractfilepath(application.ExeName)+'Highscore.ini';
  if fileexists(filename) then
    begin
      label4.Caption:= InIniLesen(Filename,'Highscore','var1') + ' : ';
      label5.Caption:= InIniLesen(Filename,'Highscore','var2') + ' Punkte';
    end
  else
    begin
      InIniSchreiben(Filename, 'Highscore','var1','keiner');
      InIniSchreiben(Filename, 'Highscore','var2','0');
      label4.Caption:= InIniLesen(Filename,'Highscore','var1') + ' : ';
      label5.Caption:= InIniLesen(Filename,'Highscore','var2') + ' Punkte';
    end;
end;

end.

DeddyH 13. Sep 2009 12:45

Re: [Snake-Spiel] - brauche eure Hilfe
 
Hallo und Willkommen in der DP :dp:,

beschränk den Code doch bitte auf das Wesentliche, zumindest ich habe keine Lust, mir den jetzt komplett anzuschauen. Und zum "Radieren": Zeichenoperationen schreibt man im Allgemeinen ins OnPaint-Ereignis der entsprechenden Komponente (Form, Paintbox, etc.), dann tritt dieser Effekt auch nicht auf.

oxmox. 13. Sep 2009 14:12

Re: [Snake-Spiel] - brauche eure Hilfe
 
ok, hab ich gemacht.

oxmox. 14. Sep 2009 17:13

Re: [Snake-Spiel] - brauche eure Hilfe
 
Zitat:

Zitat von DeddyH
Zeichenoperationen schreibt man im Allgemeinen ins OnPaint-Ereignis der entsprechenden Komponente (Form, Paintbox, etc.), dann tritt dieser Effekt auch nicht auf.

ok, aber wie wird diese Prozedur dann auch aufgerufen?

Delphi-Quellcode:
procedure TForm1.PaintBox1Paint(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[1];
         0: col:= farben[0];
      else
        col:= farben[2];
      end;
      PaintBox1.Canvas.Brush.Color:=col;
      PaintBox1.Canvas.FillRect(Rect(i*raster, j*raster, (i+1)*raster, (j+1)*raster));
    end;
end;
mit if button1.click hat es nicht funktioniert

DeddyH 14. Sep 2009 17:18

Re: [Snake-Spiel] - brauche eure Hilfe
 
Das Paint wird automatisch aufgerufen, wenn das Control neu gezeichnet werden muss (etwa weil man ein anderes Fenster darübergezogen hat). Wenn Du es von Hand anstoßen willst, kannst Du Paintbox.Repaint aufrufen.

oxmox. 14. Sep 2009 17:31

Re: [Snake-Spiel] - brauche eure Hilfe
 
danke, klappt super!
nur das Bild flackert ziemlich, da das Bild dauernd refresht oder neu gezeichnet werden muss.
sodass die schlange sich bewegt.

Delphi-Quellcode:
procedure TForm1.Timer1Timer(Sender: TObject);
begin
  schlange;
 if not ende then
   paintbox1.repaint;
   //paintbox1.Refresh;
end;

LDericher 20. Sep 2009 00:56

Re: [Snake-Spiel] - brauche eure Hilfe
 
Delphi-Quellcode:
DoubleBuffered:=true;
ist deine Lösung ;)

edit: delphi-tags^^

edit#2: Setz die Zeile in OnCreate deiner Form^^

oxmox. 20. Sep 2009 13:02

Re: [Snake-Spiel] - brauche eure Hilfe
 
Liste der Anhänge anzeigen (Anzahl: 1)
danke für die Antworten.

Ich hab jetzt alles wieder übeareitet.
Nun funktioniert auch alles, außer 2 Dinge.

1. gelegentlich taucht plätzlich folgende Fehlermeldung auf:
http://img5.imagebanana.com/view/wyq...rror.snake.JPG

2. der Highscore funktioniert nicht immer ^^
hier eine kurze erklärung, wie der Highscore in meinem Programm funktionieren soll.
---
wenn das Programm gestartet wird, wird ein .ini Datei estellt, falls diese noch nicht vorhanden ist.
in die .ini Datei wird die Punktzahl '0' reingeschreiben, die dann in ein label-feld in der Form abgespeichert wird.
wenn man das Spiel beendet, bzw verloren hat, wird die aktuell erreichte Punktzahl mit der aus diesem label-feld verglichen.
wenn die gerade erreichte Punktzahl größer, als die im label (in der ini datei) ist, dann wird die 2. Form geladen, inder
man dann seinen Namen einträgt und dieser dann, mit der erreichten Punnktzahl in die ini datei geschreiben wird.

hier mal der Code:

Delphi-Quellcode:

procedure InIniSchreiben (Filename, Section, Key, Value: string);
var ini: Tinifile;
begin
  ini:= tinifile.Create(Filename);
  try
    ini.WriteString(section, key, value);
  finally
    ini.Free;
  end;
end;

function InIniLesen (Filename, Section, Key: string):string;
var ini: Tinifile;
begin
  ini:= tinifile.Create(Filename);
  try
    result:= ini.ReadString(section, key, '');
  finally
    ini.Free;
  end;
end;

procedure Delay (const Milliseconds: DWord);
var FirstTickCount: DWord;
begin
  FirstTickCount:= GetTickCount;
  while ((GetTickCount - FirstTickCount) < Milliseconds) do
    begin
      Application.ProcessMessages;
      Sleep(0);
    end;
end;

procedure TForm1.spiel_ende;
begin
  ende:= True;
  Timer1.Enabled:= False;
  buttons_freigeben(False);
  Button1.Enabled:= True;
  button6.Enabled:= false;
end;

procedure TForm1.schlange;
var i, j: Integer;
    filename: string;
begin
  for i:= 0 to breite do
    for j:= 0 to hoehe do
      if map[i, j] > 0 then
        Dec(map[i, j]);
  Inc(kopf.X, richtung.X);
  Inc(kopf.Y, richtung.Y);
  if checkbox1.Checked= true then
    begin
      if (kopf.X < 0) then
        Kopf.X:= kopf.X + Breite + 1;
      if Kopf.Y < 0 then
        Kopf.Y:= kopf.Y + Hoehe + 1;
      if Kopf.X > Breite then
        Kopf.X:= Kopf.x - Breite - 1;
      if Kopf.Y > Hoehe then
        Kopf.Y:= Kopf.Y - Hoehe - 1;
    end
  else
    if (kopf.X < 0) or (kopf.X > breite) or (kopf.Y < 0) or (kopf.Y > hoehe) then
      begin
        spiel_ende;
        showmessage('Spiel beendet' + #10#13 + 'Sie haben den Rand berührt');
        checkbox1.Enabled:= true;
        if label10.Caption > label17.Caption then
          begin
            form2.Label3.Caption:= inttostr(punkte-1);
            form2.Show;
          end;
      end;
    if (map[kopf.X, kopf.Y]>0) and (not ende) then
      begin
        spiel_ende;
        showmessage('Spiel beendet' + #10#13 + 'Sie haben sich selbst gebissen');
        checkbox1.Enabled:= true;
        if label10.Caption > label17.Caption then
          begin
            form2.Label3.Caption:= inttostr(punkte-1);
            form2.Show;
          end;
  end;
2. Form:

Delphi-Quellcode:

procedure InIniSchreiben (Filename, Section, Key, Value: string);
var ini: Tinifile;
begin
  ini:= tinifile.Create(Filename);
  try
    ini.WriteString(section, key, value);
  finally
    ini.Free;
  end;
end;

function InIniLesen (Filename, Section, Key: string):string;
var ini: Tinifile;
begin
  ini:= tinifile.Create(Filename);
  try
    result:= ini.ReadString(section, key, '');
  finally
    ini.Free;
  end;
end;

procedure TForm2.Button1Click(Sender: TObject);
var filename: string;
begin
  filename:= extractfilepath(application.ExeName)+'Highscore.ini';
  InIniSchreiben(Filename, 'Highscore','var1',edit1.Text);
  InIniSchreiben(Filename, 'Highscore','var2',label3.Caption);
  if fileexists(filename) then
    begin
      form1.label15.Caption:= InIniLesen(Filename,'Highscore','var1');
      form1.label17.Caption:= InIniLesen(Filename,'Highscore','var2');
    end;
end;
Danke schonmal.

Klaus01 20. Sep 2009 13:20

Re: [Snake-Spiel] - brauche eure Hilfe
 
Zitat:

Zitat von oxmox.
1. gelegentlich taucht plätzlich folgende Fehlermeldung auf:
http://img5.imagebanana.com/view/wyq...rror.snake.JPG

2. der Highscore funktioniert nicht immer ^^

Hallo,

zu 1. kannst Du gelegentlich eingrenzen,
tritt der Fehler bei einer bestimmten Aktion auf?

zu 2. "funktioniert nicht immer" ist eine recht bescheidene
Fehlerbeschreibung. Was passiert wenn der Highscore nicht richtig funktioniert?
Wann funktioniert er nicht richtig?
Gibt es einen Zusammenhang zu Punkt 1?

Grüße
Klaus

oxmox. 20. Sep 2009 14:53

Re: [Snake-Spiel] - brauche eure Hilfe
 
Zitat:

Zitat von Klaus01

Hallo,

zu 1. kannst Du gelegentlich eingrenzen,
tritt der Fehler bei einer bestimmten Aktion auf?

zu 2. "funktioniert nicht immer" ist eine recht bescheidene
Fehlerbeschreibung. Was passiert wenn der Highscore nicht richtig funktioniert?
Wann funktioniert er nicht richtig?
Gibt es einen Zusammenhang zu Punkt 1?

Grüße
Klaus

^^
zu 1.
wenn man das Spiel verloren hat und erneut auf Start klickt, um ein neues Spiel zu starten, taucht der Fehler MANCHMAL auf.

zu 2.
mit "der Highscore funktioniert nicht richtig" mein ich, dass die 2. Form nicht gezeigt wird und auch nichts in die .ini Datei
geschreiben wird, wenn ein neuer Highscore aufgestellt wird ^^
aber das ist auch, wie beim 1. Problem nur manchmal der Fall :confused:
wenn man die .ini Datei manuell löscht, funktionierts auch wieder, aber nur solange bis man das Programm schließt.

mfg


Alle Zeitangaben in WEZ +1. Es ist jetzt 02:05 Uhr.

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz