AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Thema durchsuchen
Ansicht
Themen-Optionen

zweidimensionale Arrays

Ein Thema von Mo53 · begonnen am 10. Jun 2021 · letzter Beitrag vom 14. Jun 2021
Antwort Antwort
Michael II

Registriert seit: 1. Dez 2012
Ort: CH BE Eriswil
772 Beiträge
 
Delphi 11 Alexandria
 
#1

AW: zweidimensionale Arrays

  Alt 11. Jun 2021, 20:49
Ich habe ein kleines Problem und zwar das falls eine Bombe eingetragen werden soll einfach nichts geschieht.
Sieht vielleicht jemand von euch wo der Fehler ist, der Debugger hilft mir da auch nicht weiter.
Der Debugger hilft da schon sehr weiter.
Setze einen Breakpoint am Ende von readInput.
Starte das Programm. Wähle Spalte und Zeile und setze mit B eine Bombe.
Der Debugger hält nun am Ende von readInput an.
Jetzt kannst du weiter steppen mit Funktionstaste F8 und siehst, was passiert. (Deine Funktion readInput gibt offenbar false zurück.)

Nebenbei:
eingabeX := upcase(eingabeX);
macht dort wo's steht immer noch gleich wenig Sinn; siehe #10 und #13. Tipp: Beim Kompilieren werden dir Warnungen angezeigt. Lies diese... Bei dieser Zeile steht zum Beispiel:
W1036 Variable 'eingabeX' ist möglicherweise nicht initialisiert worden.
Und das stimmt auch : eingabeX hat in dieser Zeile noch keinen definierten Wert. Erst NACH dem Einlesen mittels readln(eingabeX); macht upcase() Sinn. Nach readln(eingabeY) und auch bei ...z solltest du wieder upcase() nutzen oder aber so:

TIPP: Anstatt upcase() zu nutzen kannst du im case 'X' und 'x' angeben:

Delphi-Quellcode:
  case eingabeX of
    'X', 'x' : cancel := TRUE;
    '1'..'7': begin
                  gueltig := TRUE;
                  x := StrToInt(eingabeX);
              end;

Soweit ich mich erinnere soll gemäss Aufgabenstellung dein Spielfeld auch grösser oder kleiner als 7x7 sein dürfen. Wen dem so ist: In deinem Programm sollte nur hier
Delphi-Quellcode:
const
  FIELDSIZE : Byte = 7;
die Zahl 7 stehen. Suche via IDE nach 7 und ersetze... - Was passiert bei deinen case Abfragen, wenn der Wert FELDSIZE zweistellig ist? (In der Aufgabenstellung wird zur Validierung der Eingabe val(..) empfohlen.)



Viel Spass.
Michael Gasser

Geändert von Michael II (11. Jun 2021 um 23:39 Uhr)
  Mit Zitat antworten Zitat
Mo53

Registriert seit: 16. Mai 2021
59 Beiträge
 
Delphi 10.3 Rio
 
#2

AW: zweidimensionale Arrays

  Alt 12. Jun 2021, 10:33
Da kommt durchgehend nicht verfügbarer Wert für readInput raus
  Mit Zitat antworten Zitat
Michael II

Registriert seit: 1. Dez 2012
Ort: CH BE Eriswil
772 Beiträge
 
Delphi 11 Alexandria
 
#3

AW: zweidimensionale Arrays

  Alt 12. Jun 2021, 12:44
Da kommt durchgehend nicht verfügbarer Wert für readInput raus
Ja ich hab's gesehen. Wenn ich readInput auswerten will, dann will Delphi den Funktionswert berechnen und erwartet deshalb Parameter... (wenn ich mich nicht voll täusche, dann war das bei viel früheren Versionen nicht so - vielleicht ist auch irgend eine "doofe" Einstellung der Grund...).

Aber: Den Funktionswert solltest du auch in "Result" finden.


Tipp: Du kannst den Funktionswert auch immer als Result := <wert> zurückgeben. Also so:

Delphi-Quellcode:
function readInput(var x, y: TSize; var cancel, bomb: Boolean): Boolean;
...
...
   Result := ...
end;
Michael Gasser

Geändert von Michael II (12. Jun 2021 um 12:46 Uhr)
  Mit Zitat antworten Zitat
Mo53

Registriert seit: 16. Mai 2021
59 Beiträge
 
Delphi 10.3 Rio
 
#4

AW: zweidimensionale Arrays

  Alt 12. Jun 2021, 14:33
Ich hab das mit Result nie wirklich verstanden, ist das eine Funktion ?
Bei mir sagt er dann undeklarierter Bezeichner "Result".
  Mit Zitat antworten Zitat
Delphi.Narium

Registriert seit: 27. Nov 2017
2.558 Beiträge
 
Delphi 7 Professional
 
#5

AW: zweidimensionale Arrays

  Alt 12. Jun 2021, 14:42
Beispiel:

Statt
Delphi-Quellcode:
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;
einfach
Delphi-Quellcode:
function isValidCoord(x,y : integer): boolean;
begin
  if ((x <= FIELDSIZE) and (x >= 1)) then
  if ((y <= FIELDSIZE) and (y >= 1)) then
  Result := TRUE
  else Result := FALSE;
end;
Für die Rückgabe eines Funktionsergebnisses kann man dem Funktionsnamen einen Wert zuweisen oder eben statt des Funktionsnamens Result schreiben.

Result ist quasi ein Synonym für den Funktionsnamen.

Funktionsname := Wert; entspricht Result := Wert;
  Mit Zitat antworten Zitat
Michael II

Registriert seit: 1. Dez 2012
Ort: CH BE Eriswil
772 Beiträge
 
Delphi 11 Alexandria
 
#6

AW: zweidimensionale Arrays

  Alt 12. Jun 2021, 17:13
Bei mir sagt er dann undeklarierter Bezeichner "Result".
Hoi mo

genau... wenn du den Wert von Result abfragst, dann zeigt dein Delphi an
E2003 Undeklarierter Bezeichner: 'result'

Das liegt am Compilerschalter $X- ganz oben in deinem Code.
Nimm diesen Schalter raus. Wahrscheinlich wurde diese Übung im 7. Jahrhundert geschrieben und von Generation zu Generation weitergegeben.

Zitat:
Note: The $X directive is provided for backward compatibility. You should not use the {$X-} mode when writing Delphi applications.
Hier findest du Infos dazu:
http://docwiki.embarcadero.com/RADSt...yntax_(Delphi)

Kompiliere dein Programm neu. Setze wieder einen Haltepunkt in readInput. Jetzt wird dir im Fenster "Lokale Variablen" (Menu Ansicht > Debug Fenster > Lokale Variablen) neu auch Result (mit Wert <Wert>) angezeigt. Es ist egal, ob du in deinem Code <Wert> über Result:=<Wert> oder readInput:=<Wert> zugewiesen hast.
Michael Gasser

Geändert von Michael II (12. Jun 2021 um 19:26 Uhr)
  Mit Zitat antworten Zitat
Andreas13

Registriert seit: 14. Okt 2006
Ort: Nürnberg
722 Beiträge
 
Delphi XE5 Professional
 
#7

AW: zweidimensionale Arrays

  Alt 12. Jun 2021, 20:10
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
Grüße, Andreas
Wenn man seinem Nächsten einen steilen Berg hinaufhilft, kommt man selbst dem Gipfel näher. (John C. Cornelius)
  Mit Zitat antworten Zitat
Mo53

Registriert seit: 16. Mai 2021
59 Beiträge
 
Delphi 10.3 Rio
 
#8

AW: zweidimensionale Arrays

  Alt 12. Jun 2021, 23:18
Ich verwende Delphi 10.3

Danke für den Tipp
  Mit Zitat antworten Zitat
Mo53

Registriert seit: 16. Mai 2021
59 Beiträge
 
Delphi 10.3 Rio
 
#9

AW: zweidimensionale Arrays

  Alt 13. Jun 2021, 02:07
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 := ''
      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.

Geändert von Mo53 (13. Jun 2021 um 02:16 Uhr)
  Mit Zitat antworten Zitat
Antwort Antwort


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 14:39 Uhr.
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz