Delphi-PRAXiS
Seite 3 von 4     123 4      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Algorithmen, Datenstrukturen und Klassendesign (https://www.delphipraxis.net/78-algorithmen-datenstrukturen-und-klassendesign/)
-   -   zweidimensionale Arrays (https://www.delphipraxis.net/208109-zweidimensionale-arrays.html)

Andreas13 12. Jun 2021 20:10

AW: zweidimensionale Arrays
 
Zitat:

Zitat von Mo53 (Beitrag 1491030)
Ich hab das mit Result nie wirklich verstanden, ist das eine Funktion ?
Bei mir sagt er dann undeklarierter Bezeichner "Result".

Welche Delphi-Version verwendest Du? Du kannst & solltest diese in Deinem Profil eintragen: Das vermeidet u.U. dumme Fragen von uns... :)
Gruß, Andreas

Mo53 12. Jun 2021 23:18

AW: zweidimensionale Arrays
 
Ich verwende Delphi 10.3

Danke für den Tipp:-D

Mo53 13. Jun 2021 02:07

AW: zweidimensionale Arrays
 
Ich habe das jetzt soweit, jedoch stürzt er ab wenn er eine Bombe findet, sieht jemand von euch warum ?

Delphi-Quellcode:
{$APPTYPE CONSOLE}
{$R+,Q+,X-}

uses
  System.SysUtils,
  Windows;

const
  FIELDSIZE: Byte = 7;

type
  TSize = 1 .. 7;
  TSTATE = (leer, Bombe);
  TDIR = (Nord, NordOst, Ost, SüdOst, Süd, SüdWest, West, NordWest);
  TFIELD = array [TSize, TSize] of TSTATE;
  TVISIBLE = array [TSize, TSize] of Boolean;

const
  OFFSET_X: array [TDIR] of integer = (0, 1, 1, 1, 0, -1, -1, -1);
  OFFSET_Y: array [TDIR] of integer = (1, 1, 0, -1, -1, -1, 0, 1);

  // Setzt die Ausgabeposition der Konsole auf die angegebene Koordinate.
  // @param
  // x,y - zu setzende Position in der Konsole an 0/0 = oben links
procedure setConsolePosition(x, y: Byte);
var
  coord: _COORD;
begin
  coord.x := x;
  coord.y := y;
  if SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), coord) then;
end;

// Setzt die Textfarbe der Konsole
// @param
// color - zu setzender Farbwert
procedure setTextColor(color: word);
begin
  if SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), color) then
end;

// Initialisiert das Feld leer und das Sichbarkeitsfeld mit 'false'
// Setzt in gerundet 10% aller Zellen eine Bombe
// @param
// field - Feld, welches initialisiert wird
// visible - zu setzendes Sichtbarkeitsfeld
procedure initField(var field: TFIELD; var visible: TVISIBLE);
var
  x, y, r, s: integer;
begin
  for x := 1 to FIELDSIZE do
  begin
    for y := 1 to FIELDSIZE do
    begin
      visible[x, y] := FALSE;
      field[x, y] := leer;
    end;
  end;
  r := (FIELDSIZE * FIELDSIZE) div 10;
  s := (FIELDSIZE * FIELDSIZE) mod 10;
  if s >= 5 then
    inc(r);
  // Bomben platzieren
  randomize;
  while r > 0 do
  begin
    x := Random(FIELDSIZE) + 1; // Random liefert einen Wert 0..(FIELDSIZE - 1)
    y := Random(FIELDSIZE) + 1;
    if field[x, y] = leer then
    begin
      field[x, y] := Bombe;
      Dec(r);
    end;
  end;
end;

// Prüft, ob eine Koordinate gültig ist
// @param
// x,y - zu überprüfende Koordinatenwerte
// @out
// Überprüfung ob Koordinate im Bereich des Spielfeldes liegt
// @return
// true, wenn Koordinaten gültig sind
function isValidCoord(x, y: integer): Boolean;
begin
  if ((x <= FIELDSIZE) and (x >= 1)) then
    if ((y <= FIELDSIZE) and (y >= 1)) then
      isValidCoord := TRUE
    else
      isValidCoord := FALSE;
end;

// Zeigt an, wie viele Bomben sich auf den Nachbarzellen, der übergebenen
// Koordinate befinden
// @param
// field - Spielfeld, welches geprüft wird
// x,y - Koordinaten
// @out
// Bestimmung der Nachbarzellen
// @return
// byte-Wert, wie viele Bomben in den Nachbarzellen existieren
function countBombs(field: TFIELD; x, y: TSize): Byte;
var
  dir: TDIR;
  xNachbar, yNachbar: integer;
  n: Byte;
begin
  n := 0;
  for dir := low(TDIR) to high(TDIR) do
  begin
    xNachbar := x + OFFSET_X[dir];
    yNachbar := y + OFFSET_Y[dir];
    if field[xNachbar, yNachbar] = Bombe then
      inc(n);
  end;
  countBombs := n;
end;

// Textausgabe des Spielfeldes in der Konsole
// @param
// field - Spielfeld, welches ausgegeben werden soll
// visible - augedeckte Zellen
procedure printField(field: TFIELD; visible: TVISIBLE);
var
  x, y: TSize;
  s: string;
  n, i, j: integer;

begin
  setConsolePosition(0, 0);
  for i := 0 to 10 do
  begin
    for j := 0 to 150 do
    begin
      write(' ');
    end;
    writeln;
  end;

  setConsolePosition(0, 0);
  for x := low(TSize) to high(TSize) do
  begin
    for y := low(TSize) to high(TSize) do
    begin
      if not visible[x, y] then
        s := '&#9619;'
      else if visible[x, y] and (field[x, y] = Bombe) then
        s := 'ð'
      else
      begin
        n := countBombs(field, x, y);
        if n = 0 then
          s := ' '
        else
          s := IntToStr(n);
      end;
      write(s, ' ');
    end;
    writeln;
  end;
end;

// liest vom Benutzer Spalte und Zeile ein und prüft diese. Außerdem wird der
// Benutzer gefragt ob die gewählte Zelle aufgedeckt oder als Bombe markiert
// oder das Programm mit der Eingabe von x beendet werden soll
// @param
// x,y - x- und y-Koordinate des Spielfeldes
// cancel - soll das Spiel verlassen werden?
// bomb - soll eine Bombe markiert werden?
// @out
//
// @return
function readInput(var x, y: TSize; var cancel, bomb: Boolean): Boolean;
var
  gueltig: Boolean;
  eingabeX, eingabeY, eingabeZ: char;
  visible: TVISIBLE;
begin
  gueltig := FALSE;
  cancel := FALSE;
  readInput := gueltig or cancel or bomb;

  writeln;
  writeln('Bitte eine Zeile von 1 bis 7 eingeben oder ''X'' für Abbruch: ');
  readln(eingabeX);
  eingabeX := upcase(eingabeX);
  // repeat
  case eingabeX of
    'X':
      begin
        cancel := TRUE;
        readInput := TRUE;
      end;
    '1' .. '7':
      begin
        gueltig := TRUE;
        x := StrToInt(eingabeX);
      end;

  else
    readInput := FALSE;
  end;
  // until readInput(x,y,cancel,bomb):= TRUE;

  if not cancel and gueltig then
  begin
    gueltig := FALSE;
    writeln('Bitte eine Spalte von 1 bis 7 eingeben oder ''X'' für Abbruch: ');
    readln(eingabeY);
    eingabeY := upcase(eingabeY);
    case eingabeY of
      'X':
        begin
          cancel := TRUE;
          readInput := TRUE;
        end;
      '1' .. '7':
        begin
          gueltig := TRUE;
          y := StrToInt(eingabeY);
        end
    else
      readInput := FALSE;
    end;
  end;

  if not cancel and gueltig and isValidCoord(x, y) then
  begin

    writeln('Bitte ein ''B'' eingeben, wenn dort eine Bombe markiert werden ' +
      'soll, leer lassen zum Aufdecken oder ''X'' für Abbruch: ');
    readln(eingabeZ);
    eingabeZ := upcase(eingabeZ);
    case eingabeZ of
      'B':
        bomb := TRUE;
      'X':
        begin
          cancel := TRUE;
          readInput := TRUE;
        end

    else
      begin
        readInput := FALSE;
        visible[x, y] := TRUE;
      end;

    end;
    visible[x, y] := TRUE;

  end;

end;

// Prüft, ob das gesamte Spielfeld mit Ausnahme der Bomben aufgedeckt ist
// @param
// field - Spielfeld, in dem geprüft werden soll
// visible -Sichtbarkeit der Zellen
// @out
//
// @return
// true, wenn alle Zellen außer die Bomben aufgedeckt sind
function isFieldSolved(field: TFIELD; visible: TVISIBLE): Boolean;
var
  x, y: TSize;
  z, b: integer;
begin
  z := 0;
  b := 0;
  for x := 1 to FIELDSIZE do
    for y := 1 to FIELDSIZE do
    begin
      if visible[x, y] then
        inc(z);
      if field[x, y] = Bombe then
        inc(b);
    end;
  isFieldSolved := z = FIELDSIZE * FIELDSIZE - b;
end;
// -------------------------------------------------------------------------------

var
  field: TFIELD;
  visible: TVISIBLE;
  cancel, bomb: Boolean;
  x, y: TSize;
  dir: TDIR;
  xNachbar, yNachbar: integer;
  gueltig: Boolean;

begin
  initField(field, visible);
  repeat
    while not cancel do
    begin
      repeat
        printField(field, visible);
        cancel := readInput(x, y, cancel, bomb);
      visible[x, y] := TRUE;
      until gueltig = TRUE;

      if cancel then
      begin
        writeln('Ende');
        readln;
      end
      else
        // weitere Zellen werden aufgedeckt, wenn in keiner Nachbarzelle eine Bombe ist
        if countBombs(field, x, y) = 0 then
          for dir := low(TDIR) to high(TDIR) do
          begin
            xNachbar := x + OFFSET_X[dir];
            yNachbar := y + OFFSET_Y[dir];
            visible[xNachbar, yNachbar] := TRUE;
          end;

      // wenn eine Bombe aufgedeckt wird
      if ((field[x, y] = Bombe) and visible[x, y]) then
      begin
        writeln('PENG!!!');
        cancel := TRUE;
      end;

    end;

  until isFieldSolved(field, visible) or cancel;
  writeln('Tschüss! Bis zum nächsten Mal');
  readln;

end.

zeras 13. Jun 2021 06:48

AW: zweidimensionale Arrays
 
Zitat:

Zitat von Mo53 (Beitrag 1491036)
Ich habe das jetzt soweit, jedoch stürzt er ab wenn er eine Bombe findet, sieht jemand von euch warum ?

Dann stelle dich doch mit dem Debugger an den Beginn der Funktion, wo er die Bombe findet und steppe weiter. Dann wirst du die Zeile finden, wo der Crash passiert.
Vielleicht kommst du da selber drauf oder postest hier erneut.

haentschman 13. Jun 2021 09:21

AW: zweidimensionale Arrays
 
Zitat:

Dann stelle dich doch mit dem Debugger an den Beginn der Funktion
Debugger Tutorial: https://www.delphipraxis.net/41047-t...ortgeschr.html
...alles Andere ist geraten. :wink:

Mo53 13. Jun 2021 12:15

AW: zweidimensionale Arrays
 
Zitat:

Zitat von haentschman (Beitrag 1491041)
Zitat:

Dann stelle dich doch mit dem Debugger an den Beginn der Funktion
Debugger Tutorial: https://www.delphipraxis.net/41047-t...ortgeschr.html
...alles Andere ist geraten. :wink:

ist das auch aktuell mit delphi 10.3 ?

haentschman 13. Jun 2021 12:33

AW: zweidimensionale Arrays
 
Zitat:

ist das auch aktuell mit delphi 10.3 ?
Ja. Sinngemäß schon seit D1 (imho). :wink:

Mo53 14. Jun 2021 01:10

AW: zweidimensionale Arrays
 
Mein Programm steht jetzt mittlerweile fast, jedoch habe ich zwei Probleme an denen ich fast verzweifel, zum einen sieht das Programm nach der zweiten Abfrage jedes Zeichen als gültig und deckt sofort auf ohne überhaupt die dritte Abfrage auszuführen, zum anderen markiert das Programm das ausgewählte Feld nicht mit einer Bombe sobald ich auf b drücke, sondern deckt sofort auf. Ich wäre echt über jede Hilfe dankbar.

Mo53 14. Jun 2021 01:12

AW: zweidimensionale Arrays
 
Delphi-Quellcode:
{$APPTYPE CONSOLE}
{$R+,Q+,X-}

uses
  System.SysUtils,
  Windows;

const
  FIELDSIZE: Byte = 7;

type
  TSize = 1 .. 7;
  TSTATE = (leer, Bombe);
  TDIR = (Nord, NordOst, Ost, SüdOst, Süd, SüdWest, West, NordWest);
  TFIELD = array [TSize, TSize] of TSTATE;
  TVISIBLE = array [TSize, TSize] of Boolean;

const
  OFFSET_X: array [TDIR] of integer = (0, 1, 1, 1, 0, -1, -1, -1);
  OFFSET_Y: array [TDIR] of integer = (1, 1, 0, -1, -1, -1, 0, 1);

  // Setzt die Ausgabeposition der Konsole auf die angegebene Koordinate.
  // @param
  // x,y - zu setzende Position in der Konsole an 0/0 = oben links
procedure setConsolePosition(x, y: Byte);
var
  coord: _COORD;
begin
  coord.x := x;
  coord.y := y;
  if SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), coord) then;
end;

// Setzt die Textfarbe der Konsole
// @param
// color - zu setzender Farbwert
procedure setTextColor(color: word);
begin
  if SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), color) then
end;

// Initialisiert das Feld leer und das Sichbarkeitsfeld mit 'false'
// Setzt in gerundet 10% aller Zellen eine Bombe
// @param
// field - Feld, welches initialisiert wird
// visible - zu setzendes Sichtbarkeitsfeld
procedure initField(var field: TFIELD; var visible: TVISIBLE);
var
  x, y, r, s: integer;
begin
  for x := 1 to FIELDSIZE do
  begin
    for y := 1 to FIELDSIZE do
    begin
      visible[x, y] := FALSE;
      field[x, y] := leer;
    end;
  end;
  r := (FIELDSIZE * FIELDSIZE) div 10;
  s := (FIELDSIZE * FIELDSIZE) mod 10;
  if s >= 5 then
    inc(r);
  // Bomben platzieren
  randomize;
  while r > 0 do
  begin
    x := Random(FIELDSIZE) + 1; // Random liefert einen Wert 0..(FIELDSIZE - 1)
    y := Random(FIELDSIZE) + 1;
    if field[x, y] = leer then
    begin
      field[x, y] := Bombe;
      Dec(r);
    end;
  end;
end;

// Prüft, ob eine Koordinate gültig ist
// @param
// x,y - zu überprüfende Koordinatenwerte
// @out
// Überprüfung ob Koordinate im Bereich des Spielfeldes liegt
// @return
// true, wenn Koordinaten gültig sind
function isValidCoord(x, y: integer): Boolean;
begin
  if ((x <= FIELDSIZE) and (x >= 1)) then
    if ((y <= FIELDSIZE) and (y >= 1)) then
      isValidCoord := TRUE
    else
      isValidCoord := FALSE;
end;

// Zeigt an, wie viele Bomben sich auf den Nachbarzellen, der übergebenen
// Koordinate befinden
// @param
// field - Spielfeld, welches geprüft wird
// x,y - Koordinaten
// @out
// Bestimmung der Nachbarzellen
// @return
// byte-Wert, wie viele Bomben in den Nachbarzellen existieren
function countBombs(field: TFIELD; x, y: TSize): Byte;
var
  dir: TDIR;
  xNachbar, yNachbar: integer;
  n: Byte;
begin
  n := 0;
  for dir := low(TDIR) to high(TDIR) do
  begin
    xNachbar := x + OFFSET_X[dir];
    yNachbar := y + OFFSET_Y[dir];
    if ((xNachbar > 0) and (xNachbar < 8) and (yNachbar > 0) and (yNachbar < 8))
    then

      if field[xNachbar, yNachbar] = Bombe then
        inc(n);
  end;
  countBombs := n;
end;

// Textausgabe des Spielfeldes in der Konsole
// @param
// field - Spielfeld, welches ausgegeben werden soll
// visible - augedeckte Zellen
procedure printField(field: TFIELD; visible: TVISIBLE);
var
  x, y: TSize;
  s: string;
  n, i, j: integer;

begin
  setConsolePosition(0, 0);
  for i := 0 to 10 do
  begin
    for j := 0 to 150 do
    begin
      write(' ');
    end;
    writeln;
  end;

  setConsolePosition(0, 0);
  for x := low(TSize) to high(TSize) do
  begin
    for y := low(TSize) to high(TSize) do
    begin
      if not visible[x, y] then
      begin
        setTextColor(7);
        s := '&#9619;'
      end
      else if not visible[x, y] and (field[x, y] = Bombe) then
        s := 'ð'
      else
      begin
        n := countBombs(field, x, y);
        case n of
          0:
            s := ' ';
          1:
            begin
              setTextColor(9);
              s := '1';
            end;
          2:
            begin
              setTextColor(2);
              s := '2';
            end;
          3:
            begin
              setTextColor(12);
              s := '3';
            end;
          4:
            begin
              setTextColor(1);
              s := '4';
            end;
          5:
            begin
              setTextColor(4);
              s := '5';
            end;
          6:
            begin
              setTextColor(3);
              s := '6';
            end;
          7:
            begin
              setTextColor(15);
              s := '7';
            end;
        end;
      end;
      write(s, ' ');
    end;
    writeln;
  end;
end;

// liest vom Benutzer Spalte und Zeile ein und prüft diese. Außerdem wird der
// Benutzer gefragt ob die gewählte Zelle aufgedeckt oder als Bombe markiert
// oder das Programm mit der Eingabe von x beendet werden soll
// @param
// x,y - x- und y-Koordinate des Spielfeldes
// cancel - soll das Spiel verlassen werden?
// bomb - soll eine Bombe markiert werden?
// @out
//
// @return
function readInput(var x, y: TSize; var cancel, bomb: Boolean): Boolean;
var
  gueltig: Boolean;
  eingabeX, eingabeY, eingabeZ: char;
  visible: TVISIBLE;
  field: TFIELD;
begin
  gueltig := FALSE;
  cancel := FALSE;
  readInput := gueltig or cancel or bomb;

  writeln;
  writeln('Bitte eine Zeile von 1 bis 7 eingeben oder ''X'' für Abbruch: ');
  readln(eingabeX);
  eingabeX := upcase(eingabeX);
  case eingabeX of
    'X':
      begin
        cancel := TRUE;
        readInput := TRUE;
      end;
    '1' .. '7':
      begin
        gueltig := TRUE;
        x := StrToInt(eingabeX);
      end;

  else
    readInput := FALSE;
  end;

  if not cancel and gueltig then
  begin
    gueltig := FALSE;
    writeln('Bitte eine Spalte von 1 bis 7 eingeben oder ''X'' für Abbruch: ');
    readln(eingabeY);
    eingabeY := upcase(eingabeY);
    case eingabeY of
      'X':
        begin
          cancel := TRUE;
          readInput := TRUE;
        end;
      '1' .. '7':
        begin
          gueltig := TRUE;
          y := StrToInt(eingabeY);
        end
    else
      readInput := FALSE;
    end;
  end;

  if not cancel and gueltig and isValidCoord(x, y) then
  begin
    writeln('Bitte ein ''B'' eingeben, wenn dort eine Bombe markiert werden ' +
      'soll, leer lassen zum Aufdecken oder ''X'' für Abbruch: ');
    readln(eingabeZ);
    eingabeZ := upcase(eingabeZ);
    case eingabeZ of
      'B':
        begin
          if ((field[x, y] = Bombe) and visible[x, y]) then
          begin
            bomb := TRUE;
            if field[x, y] = Bombe then
              visible[x, y] := FALSE;
            cancel := TRUE;
            writeln('PENG!!!');
          end;

        end;

      'X':
        begin
          readInput := TRUE;
          cancel := TRUE;
        end
    else
      begin
        readInput := FALSE;
        visible[x, y] := TRUE;
      end;
    end;
    visible[x, y] := TRUE;
  end;
end;

// Prüft, ob das gesamte Spielfeld mit Ausnahme der Bomben aufgedeckt ist
// @param
// field - Spielfeld, in dem geprüft werden soll
// visible -Sichtbarkeit der Zellen
// @out
//
// @return
// true, wenn alle Zellen außer die Bomben aufgedeckt sind
function isFieldSolved(field: TFIELD; visible: TVISIBLE): Boolean;
var
  x, y: TSize;
  z, b: integer;
begin
  z := 0;
  b := 0;
  for x := 1 to FIELDSIZE do
    for y := 1 to FIELDSIZE do
    begin
      if visible[x, y] then
        inc(z);
      if field[x, y] = Bombe then
        inc(b);
    end;
  isFieldSolved := z = FIELDSIZE * FIELDSIZE - b;
end;
// -------------------------------------------------------------------------------

var
  field: TFIELD;
  visible: TVISIBLE;
  cancel, bomb, gueltig: Boolean;
  x, y: TSize;
  dir: TDIR;
  xNachbar, yNachbar: integer;

begin
  gueltig := FALSE;
  initField(field, visible);
  repeat
    while not cancel do
    begin
      repeat
        printField(field, visible);
        setTextColor(15);
        cancel := readInput(x, y, cancel, bomb);
        visible[x, y] := TRUE;
        // weitere Zellen werden aufgedeckt, wenn in keiner Nachbarzelle eine Bombe ist
        if countBombs(field, x, y) = 0 then
          for dir := low(TDIR) to high(TDIR) do
          begin
            xNachbar := x + OFFSET_X[dir];
            yNachbar := y + OFFSET_Y[dir];
            if ((xNachbar > 0) and (xNachbar < 8) and (yNachbar > 0) and
              (yNachbar < 8)) then
              visible[xNachbar, yNachbar] := TRUE;
          end;
      until gueltig or cancel;

      if cancel then
      begin
        writeln('Ende');
        readln;
      end



      // wenn eine Bombe aufgedeckt wird

    end;
  until isFieldSolved(field, visible) or cancel;
  writeln('Tschüss! Bis zum nächsten Mal');
  readln;

end.

hoika 14. Jun 2021 05:01

AW: zweidimensionale Arrays
 
Hallo,
was sagt denn der Debugger?


Alle Zeitangaben in WEZ +1. Es ist jetzt 02:46 Uhr.
Seite 3 von 4     123 4      

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