Autor Beitrag
bf109g.01
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 84



BeitragVerfasst: Do 11.02.10 20:36 
Hallo, ich habe ein Programm geschrieben, mit dem man das bekannte Spiel "Schiffe versenken" zu zweit spielen kann. An einer Stelle passiert allerdings etwas komisches:
Text, den ich in die Prozedur zum Schießen auf das Feld des Gegners reinschreibe, wird einfach ignoriert. Delphi gibt keinen Hinweis, keine Fehlermeldung, sondern liest einfach nicht weiter.
ausblenden volle Höhe Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
58:
59:
60:
61:
62:
63:
64:
65:
66:
67:
68:
69:
70:
71:
72:
73:
74:
75:
76:
77:
78:
79:
80:
81:
82:
83:
84:
85:
86:
{ --- --- Prozedur: Feuern & Versenken --- ---}

procedure TForm6.Feuern;
var vX,vY:integer;
    Typ:string;
    Versenkt,Verloren:boolean;

begin
{1. FEUERN}
  if Spielfeld[strtoint(Form6.EX.text),strtoint(Form6.EY.text)].Treffer=true then
    showmessage('Feld bereits beschossen.')
  else
  begin
  BTreffen.Enabled:=false;
  BWechsel.Enabled:=true;
  // Zugzähler erhöhen}
  inc(Zugzaehler);
  Form6.LZug.caption:='Züge: '+InttoStr(Zugzaehler);

  // Schuss auf Feld
  Spielfeld[strtoint(Form6.EX.text),strtoint(Form6.EY.text)].Treffer:=true;

  showmessage('Schuss auf ('+Form6.EX.text+') | ('+Form6.EY.text+'). Getroffen: '+Spielfeld[strtoint(Form6.EX.text),strtoint(Form6.EY.text)].Typ);

{2. VERSENKEN}

  Typ:=Spielfeld[strtoint(Form6.EX.text),strtoint(Form6.EY.text)].Typ;

  {2.1. Test: Schiff zerstört?}

  // Feld scannen: nach intakten Teilen suchen
  for vX := 1 to 10 do
    for vY := 1 to 10 do
      if Spielfeld[vX,vY].typ=typ then
        if Spielfeld[vX,vY].treffer=false then // intaktes Schiffsteil gefunden
          begin
            Versenkt:=false;  // Schiff schwimmt noch
            if Spielfeld[vX,vY].Typ<>'Wasser' then
              showmessage(Typ+' schwimmt noch...');
            abort;
          end;

  {2.2. Schiff zerstört: Versenken}
  if Versenkt then
    begin
      // Feld scannen: auf 'versenkt' schalten
      for vX := 1 to 10 do
        for vY := 1 to 10 do
         if Spielfeld[vX,vY].typ=typ then
           Spielfeld[vX,vY].versenkt:=true;

      showmessage(Typ+' zerstört.');
    end;

{3. GRAFIK}
// Feld neuladen...

{4. SPIELENDE}

  {4.1 Nach unversenkten Schiffen suchen}
  Verloren:=true;
  // Feld scannen
  for vX := 1 to 10 do
    for vY := 1 to 10 do
      if Spielfeld[vX,vY].typ<>'Wasser' then // Schiff gefunden
        if Spielfeld[vX,vY].versenkt=false then // schwimmendes Schiff gefunden
          begin
            Verloren:=false;  // mind. Schiff schwimmt noch
            abort;
          end;

  {4.2 Kein Schiff mehr übrig: Spielende}
  if Verloren then
    begin
      case Aktiv of
      1: showmessage('Flotte vernichtet. Spieler 1 hat das Spiel gewonnen!');
      2: showmessage('Flotte vernichtet. Spieler 2 hat das Spiel gewonnen!');
      end;

      application.terminate;
    end;

{Jeder beliebige Programmtext, der ab hier steht wird ignoriert}

  end;
end;


Komisch ist dabei, dass nicht nur prozedurintern nachfolgender Text ignoriert wird, sondern auch alles was dem Prozeduraufruf folgt.
Die Nachrichten "Flotte vernichtet blabla" erscheinen noch und application.terminate funktioniert asuch noch, wenn die if-Fallunterscheidung wahr ist.

ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
{ --- Schuss auf Feld --- }
procedure TForm6.BTreffenClick(Sender: TObject);
begin
  Feuern;
  Reload_Grafik; // Wird nicht mehr gelesen. :(
end;


Insgesamt ist das ziemlich nervig und ich habe nicht die leiseste Ahnung, warum das so ist. Bitte schaut mal, ob ihr was findet.
Flamefire
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 1207
Erhaltene Danke: 31

Win 10
Delphi 2009 Pro, C++ (Visual Studio)
BeitragVerfasst: Do 11.02.10 23:52 
Fehler ist dein Abort!
Guck dir mal die Hilfe an, was das macht!

wenn dann meintest du break (schleife verlassen) bzw exit (prozedure verlassen)

ist aber alles NICHT zu epmfehlen und sollte durch entsprechende ifs und variablen ersetzt werden.

Außerdem würde ich das design ändern:
1) Feuern sollte als parameter (x,y:Integer) erhalten, spart konvertierungen und unnötige zugriffe auf die edits
2) Die Doppelschleifen (was auch immer die machen sollen) als extra prozeduren anlegen. also z.b. (function IsVersenkt(x,y,typ):Boolean )
3) Mal die Dopelschleifen angucken. ich glaube die machen nicht, was sie sollen. Oder ist der typ eindeutig? (also keine 2 schiffe haben den gleichen typ?)
bf109g.01 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 84



BeitragVerfasst: Sa 13.02.10 15:37 
user profile iconFlamefire hat folgendes geschrieben Zum zitierten Posting springen:
1) Feuern sollte als parameter (x,y:Integer) erhalten,

1) x,y gleich an Feuern zu übergeben ist eine gute Idee. An welcher stelle muss ich das schreiben? Geht das so?

ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
{ --- Schuss auf Feld --- }
procedure TForm6.BTreffenClick(Sender: TObject);
var x,y:integer;
begin
  x:=Ex.text;
  y:=Ey.text;
  Feuern (x,y:Integer);
  Reload_Grafik; // Wird nicht mehr gelesen. :(
end;


user profile iconFlamefire hat folgendes geschrieben Zum zitierten Posting springen:
3) Mal die Dopelschleifen angucken. ich glaube die machen nicht, was sie sollen. Oder ist der typ eindeutig? (also keine 2 schiffe haben den gleichen typ?)

3) Die Doppelschleifen sind richtig und notwendig, damit das komplette Feld abgescannt wird: 10 x 10 Felder werden so spaltenweise (von oben nach unten) überprüft.
Der Typ ist eindeutig, es gibt jedes Schiff nur 1 mal.

user profile iconFlamefire hat folgendes geschrieben Zum zitierten Posting springen:
wenn dann meintest du break (schleife verlassen) bzw exit (prozedure verlassen)

break kann ich deswegen auch nicht benutzen, weil dadurch nur eine, nämlich die innere Schleife verlassen wird.

user profile iconFlamefire hat folgendes geschrieben Zum zitierten Posting springen:
2) Die Doppelschleifen (was auch immer die machen sollen) als extra prozeduren anlegen. also z.b. (function IsVersenkt(x,y,typ):Boolean )

2) Das Prinzip der Funktion hab ich verstanden. Hab aber im Mom keinen Plan, wie ich die Function schreiben müsste und weiß auch nicht, wie ich die Abrufen soll.
ausblenden Delphi-Quelltext
1:
2:
if function IsVersenkt(x,y,typ)=false
  then
Flamefire
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 1207
Erhaltene Danke: 31

Win 10
Delphi 2009 Pro, C++ (Visual Studio)
BeitragVerfasst: Sa 13.02.10 18:25 
Dann als erstes: Delphi-Tutorials lesen.
Wenn du nicht weißt, was man mit Parametern macht, hat der Rest keinen Sinn ;-)
Nicht böse gemeint, ist aber einfach so.
Alle Infos stehen in meinem Post.
Wenn du weiß, was prozeduren und Funktionen sind, wie und wo man die verwendet, verstehst du auch meinen Post und die Lösung ist klar ;-)
elundril
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 3747
Erhaltene Danke: 123

Windows Vista, Ubuntu
Delphi 7 PE "Codename: Aurora", Eclipse Ganymede
BeitragVerfasst: Sa 13.02.10 20:27 
user profile iconFlamefire hat folgendes geschrieben Zum zitierten Posting springen:
Dann als erstes: Delphi-Tutorials lesen.


Huch, mein Stichwort. :mrgreen: Am bestern sind Christian's Crashkurs und Delphi-Wikibook. ;)

lg elundril

_________________
This Signature-Space is intentionally left blank.
Bei Beschwerden, bitte den Beschwerdebutton (gekennzeichnet mit PN) verwenden.