Entwickler-Ecke

Open Source Projekte - Einsiedlerspiel


Fiete - Do 08.05.08 18:24
Titel: Einsiedlerspiel
Einsiedlerspiel ist ein altes Brettspiel für einen Spieler.

Gegeben ist ein Spielbrett in Kreuzform mit 33 Mulden, in denen 32 Steine liegen. Die Mulde in der Mitte ist leer. Man muss nacheinander die Steine entfernen, indem man sie in waagerechter oder senkrechter Richtung überspringt. Am Ende muss ein Stein in der Mitte übrigbleiben (Standardspiel).

Ein Sprung besteht darin, einen Spielstein aus einer Mulde zu nehmen, einen daneben liegenden zu überspringen und den springenden Stein in die dahinterliegende Mulde zu platzieren.

Das Spiel heißt auch Solitaire, Steckhalma, Solohalma, Springer, Jumper, Nonnenspiel oder Solitär.
Spielfeld
Ich habe 13 Brett-Varianten implementiert:
die englische Variante(33 Felder) und die französische(37 Felder) sowie einige neue.

Im Ordner Stellungen sind Aufgaben, die selbst gelöst werden können, unter Einstellungen mit der Variante Mensch.

Die Versionen Delphi und Assembler sind zum Berechen von Stellungen.
Ein Zielfeld wird mit der rechten Maustaste gesetzt.

Viel Spaß beim Tüfteln
Fiete

Edit1:
Die neue Version ist da!
Die Menue-Führung ist geändert worden, neu ist das Menue Schablonen. Hierüber können neue Brettformen kreiert werden. Die neue Schablone kann gespeichert werden, gleichzeitig wird dann im Ordner Stellungen ein Unterordner mit dem Namen der Schablone erstellt, jetzt kann gespielt werden.
Wenn die Schablone nicht gespeichert wird muß der Menu-Punkt <Fertig> angeklickt werden, um spielen zu können.

Edit2:
Im Menue <Demo> können Ergebnisse geladen und gespeichert werden.


alzaimar - Do 08.05.08 19:38

Du kannst die Suche drastisch verkürzen, wenn Du dir die Stellungen merkst, die zum Mißerfolg führen und dann die jeweilige um 90/180/270° gedreht Stellung vergleichst. Ist die Stellung in der Liste, kannst Du gleich abbrechen.


Fiete - Mo 12.05.08 10:52

Moin alzaimar,
danke für den Beitrag.

So einfach ist es nicht, die Suchroutine arbeit mit definierten Suchrichtungen, ähnlich einer Suche im Labyrinth.
Die Bretter und Stellungen sind nicht notwendigerweise symmetrisch, s. Beispiele.

Gruß
Fiete

eine neue Version kommt demnächst(verschiedene Brettformen)


Hidden - Mo 12.05.08 12:47

Hi,

Verwendest du einen BruteForce-Algorithmus? Wenn ja, eventuell Hashtabellen.

mfG,


alzaimar - Mo 12.05.08 19:40

Hi Fiete, Das Spielbrett ist doch rotations- und spiegelsymetrisch.
Eine komprimierte Speicherung (Bitvektor) sollte schon recht einfach zu realisieren sein. Beim Eintritt in die rekursive Suchfunktion erstellst Du zunächst die vier Bitvektoren der Stellung (gedreht um 0,90,180,270 Grad) und schaust nach, ob Du schon mal da warst. 33 Mulden = 33 bit = int64, da kannst du mein Integer-Dictionary nehmen. Zur Not einfach umfriesieren (Cardinal-Key => Int64-Key). Da das Teil eh mit einer kleineren Hashtabelle arbeitet, passt das schon.


Fiete - Di 13.05.08 11:38

Moin alzaimar,
ich werde mir mal Gedanken machen.

Gruß
Fiete

meine Prozedur

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:
 PROCEDURE TSoli.MACHZUG(ZUGNR:BYTE);
  VAR RICHTUNG,POSITION,X1,X2:BYTE;
  BEGIN
   INC(AUFRUF);POSITION:=ANFANGSPOSITION-1;
   REPEAT
    INC(POSITION);RICHTUNG:=0;
    IF FELD[POSITION]=BESETZT THEN
     REPEAT
      INC(RICHTUNG);X1:=POSITION+ZUWACHS[RICHTUNG];X2:=X1+ZUWACHS[RICHTUNG];
      IF (FELD[X1]=BESETZT) AND (FELD[X2]=FREI) THEN
       BEGIN
        FELD[POSITION]:=FREI;FELD[X1]:=FREI;FELD[X2]:=BESETZT;
        PROTOKOLL[ZUGNR].ZUG:=POSITION;PROTOKOLL[ZUGNR].RI:=RICHTUNG;
        IF ZUGNR<MA THEN
         BEGIN
          MACHZUG(ZUGNR+1); // Rekursion
          IF NOT ERFOLG THEN
           BEGIN
            FELD[POSITION]:=BESETZT;FELD[X1]:=BESETZT;FELD[X2]:=FREI
           END
         END
        ELSE IF WEITER AND (FELD[ZIEL]<>BESETZT) THEN
              BEGIN
               FELD[POSITION]:=BESETZT;FELD[X1]:=BESETZT;FELD[X2]:=FREI
              END
             ELSE ERFOLG:=TRUE
       END
     UNTIL ERFOLG OR (RICHTUNG=4)
   UNTIL ERFOLG OR (POSITION=ENDPOSITION)
  END;


Hidden - Di 13.05.08 12:56

Hmm kann sein, dass das nur mir so geht aber ich fand das unlesbar :wink: falls es noch wem so geht, habe ich das mal formatiert gepostet.
user profile iconFiete hat folgendes geschrieben:

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:
procedure TSoli.MachZug(ZugNr: Byte);
var 
  Richtung, Position, X1, X2: Byte;
begin
  Inc(Aufruf); 
  Position := Pred(AnfangsPosition);
  repeat
    Inc(Position); 
    Richtung := 0;
    if Feld[Position] = Besetzt then begin
      repeat
        Inc(Richtung);
        X1 := Position + Zuwachs[Richtung]; 
        X2 := X1 + Zuwachs[Richtung];
        if (Feld[X1] = Besetzt) and (Feld[X2] = Frei) then
        begin
          Feld[Position] := Frei; 
          Feld[X1] := Frei; 
          Feld[X2] := Besetzt;
          Protokoll[ZugNr].Zug := Position; 
          Protokoll[ZugNr].Ri := Richtung;
          if ZugNr < Ma then begin
            MachZug(Succ(ZugNr)); // Rekursion
            if not Erfolg then begin
              Feld[Position] := Besetzt; 
              Feld[X1] := Besetzt; 
              Feld[X2] := Frei;
            end;
          end else begin
            if Weiter and (Feld[Ziel] <> Besetzt) then begin
              Feld[Position] := Besetzt; 
              Feld[X1] := Besetzt; 
              Feld[X2] := Frei;
            end;
          end else Erfolg := true
        end;
      until Erfolg or (Richtung = 4);
    end;
  until Erfolg or (Position = EndPosition);
end;


Fiete - Mi 13.05.20 17:23

Moin,
das Menue <Demo> wurde erweitert: <Starten>, <Speichern> und <Laden> sind jetzt möglich.
Gruß Fiete