Einzelnen Beitrag anzeigen

Benutzerbild von negaH
negaH

Registriert seit: 25. Jun 2003
Ort: Thüringen
2.950 Beiträge
 
#47

Re: Sieger-Prüfung "Vier gewinnt"

  Alt 29. Jun 2004, 16:01
Und da du die Variable "gewonnen := true" von einem Test zum nächsten Test erneut setzt, kann man mit deinem Code nur gewinnen wenn in der letzten Diagonalen 4 Steine hat. Doll dat.

Schau dir noch mal meine obigen Source ganz genau an, und vergleiche mal den Assembler-Code den der Compiler erzeugt. Kurzer PASCAL Code muß nicht immer auch effizienteren Machinencode bedeuten.

Zb. sucht deine Routine von x-3 nach x+3 also insgesammt maximal 7 Positionen ab um 4 in einer horz. Line zu messen. Meine Routine sucht von X ausgehend solange nach links und rechts wie auch gleiche Steine dort sitzen. Statt also bei 1 roten Stein im Board denoch 7 Überprüfungen zu machen, benötigt diese Routine 1 Lins + 1 Rechts um festzustellen das es KEINE 4 Steine gleicher Farbe sind.

Wichtig ist dabei immer eines zu bedenken: baut man später eine KI für 4-gewinnt dann ist nämlich diese Zugauswertung die wichtigste Funktion. Sie muß dann so effizient wie möglich gecodet werden.

Klar, über velinkte Gamepositionen könnte man diese Auswertung weit effizienter gestalten, allerdings erhöht sich dann jedesmal der Aufwand des Einfügens eines Steines. Im Falle der Verlinkung sähe der Code etwa so aus:

Delphi-Quellcode:

type
  PGamePos = ^TGamePos;
  TGamePos = packed record
    Stone: Integer;
    Link: array[0..7] of PGamePos;
  end;
  
var
  Game: array[0..6, 0..5] of TGamePos;

const
  StoneInRow = 4;

(*
  Verlinkung -> TGamePos.Link[0..7]
 
  1 2 3
  0 X 4
  7 6 5

  Die diagonalen Verlinkungen in Richtung 1,3,5,7 die in ihrer Verlinkungskette NICHT mindestens 4 Positionen
  enthalten werden alle auf NIL gesetzt.
*)


function Move(X: Integer; Player: Integer): Boolean;

  function DoCount(Pos: PGamePos; Idx, Player: Integer): Boolean;

    function DoCountLink(Pos: PGamePos; Idx, Player: Integer): Integer;
    begin
      Result := 0;
      repeat
        Pos := Pos.Link[Idx];
        if (Pos = nil) or (Pos.Stone <> Player) then Break;
        Inc(Result);
      until Result >= StoneInRow;
    end;

  begin
    Result := DoCountLink(Pos, Idx, Player);
    if Result < StoneInRow then Inc(Result, DoCountLink(Pos, Idx +4, Player));
    Result := Result >= StoneInRow;
  end;

var
  P: PGamePos;
begin
  P := @Game[X];
  while (P.Stone = Empty) and (P.Link[6] <> nil) do P := P.Link[6];
  P.Stone := Player;
  Result := DoCount(P, 0, Player) or DoCount(P, 1, Player) or DoCount(P, 2, Player) or DoCount(P, 3, Player);
end;
So, das ist aber nun kürzer und effizienter. Es verbleibt nur der EINMALIGE Aufbau der Verlinkungen in Game[].

Gruß Hagen
  Mit Zitat antworten Zitat