Benutzer:Arbol01/Sokoban

Aus Wikibooks
Symbole:
. Freier Weg
# Wall
o Männchen
m Kiste
x Ort an den eine Kiste geschoben werden Soll

Beispiel eines Levels (sehr einfach)

7;5
4;3
2
#######
#xm...#     
###o###
#...mx#
#######

7;5 betrifft die Größe des Levels. Wenn man beispielsweise den Level in einer Matrix unterbringen will, so ist das sehr Hilfreich. 4;3 sind die Koordinaten, an denen das Männchen startet. 2 Ist die Anzahl der zu verschiebenden Kisten.

Das Programm muß über den Aufbau des Levels nichts wissen. Es muß nur auf bestimmte Ereignisse Reagieren.

Bewegung:
 ###    ###
 .o. -> ..o
 ###    ###

Wenn in Bewegungsrichtung des Männchens ein Punkt liegt (Freier Weg), so müssen . und o nur vertauscht werden, und die Koordinaten des Männchens korrigiert werden.

 ####    ####
 .om. -> ..om
 ####    ####

Steht eine Kiste in Bewegungsrichtung des Männchens, dahinter aber freier Weg, so werden Männchen und Kiste um eine Position verschoben und die Koordinaten des M„nnchens angepasst. Die Koordinaten der Kisten ist unwichtig (kommt später).

 ###                 ###      ####                 ####
 .o# -> Kollision -> .o#      .om# -> Kollision -> .om#
 ###                 ###      ####                 ####

Läuft das Männchen gegen eine Mauer, oder mit einer Kiste gegen eine Mauer, oder gegen zwei Kisten, so passiert nichts.

 ####    ####         ####    ####
 .omx -> ..o*    oder .omx -> ..o.
 ####    ####         ####    ####

Wenn das Männchen eine Kiste an den Zielort schiebt, kann man ein "belegter Zielort" einführen, der dann wie eine Mauer wirkt oder man kann Zielort und Kiste neutralisiern, durch einen freien Weg. Auch kann man Kiste auf Zielort zu einer Mauer werden lassen, oder wenn der Zielort ein Loch ist, das Loch belassen (nur dann darf das Mänchen nicht auf das Loch kommen (weitere Prüfung). Auf jeden Fall muß die Anzahl der Kisten um eins reduziert werden (bei Kistenzahl 0 hat man den Level gewonnen)

Wie aber erkennt das Programm eine Ausweglose Situation, wenn es nichts über den Aufbau des Levels weiß?

Ganz einfach: Es müssen immer 4 Felder des Levels in einem Block zusammen analysiert werden:

 m#   mm  mm   mm  m#
 ##   ##  m#   mm  #m

Das sind alles ausweglose Fälle. Wenn so eine Konstellation vorkommt, ist das Spiel nicht mehr zu schaffen.

Natürlich muß man, wenn man so etwas programmieren will, keine Zeichen verwenden. Sofern das System Graphische Objekte ermöglicht, kann man auch diese verwenden.

Wenn man es richtig macht, kann man die Level aus einer externen Ascii-Datei einlesen. In dem Fall läßt sich die Anzahl und Level leicht vergrößern.


Man kann das Sokoban auch mit neuen Regeln erweitern, wie ich es schon gesehen habe:

> Einbahnstraße (als Beispiel)

 #####    #####
 .o>..  -> ..>o.
 #####    #####


Anmeldungsdatum: 27.09.2003 Beiträge: 312 Wohnort: Giessen

Das, was ich gepostet habe, sind die Überlegungen, die man anstellt, bevor man auch nur eine Zeile Code schreibt. Sie enthalten, wenn vieleicht auch nicht vollständig, die Dinge, die zu beachten sind, um ein Lauffähiges Sokoban zu bekommen.

Es sind noch keine Funktionen oder Module im Programm enthalten. Natürlich kann man möglicherweise nur dann mit dem Posting etwas Anfangen, wenn man das Spiel versteht.

Zum Spiel selbst:

Ein Arbeiter is in einem Raum, in dem sich mehrere Kisten befinden. Jede Kiste muß auf einen Abstellplatz gestellt werden. Nicht auf einen bestimmten Abstellplatz, sondern auf irgend einen (man könnte das als verschärfung einführen, daß bestimmte Kisten auf bestimmte Abstellplätze müssten, aber das wäre vermutlich ein anderes Spiel).

Der Arbeiter kann nicht zwei oder mehr Kisten zusammen verschieben, sondern immer nur eine Kiste zur Zeit. Auch kann er eine Kiste nur schieben, aber nicht ziehen.

Ziel ist es, daß der Arbeiter alle Kisten auf einem Abstellplatz unterbringt (mit möglichst wenig Zügen). Damit wäre der Level beendet. Sollte der Arbeiter die Kisten in eine solche Position verschieben, das man das Spiel nicht mehr gewinnen kann, so muß man den Level neu beginnen (oder aufgeben).

Code:


- Die Anzahl der Kisten muß während eines Level > 0 sein. Erreicht die Anzahl der Kisten = 0, so wurde der Level gewonnen.

- Wenn folgende Viererkonstellationen im Bereich eines Levels auftauchen, ist der Level verloren (Neubeginn)

mm   mm   mm   m#   m#
mm   m#   ##   ##   #.


Das sind, wenn ich es richtig gerechnet habe 33 Konstellationen

- zulässige Bewegungsabläufe:

Code:


o. -> .o
om. -> .om


Das sind alle 8 möglichen Bewegungsabläufe

- Was passiert, wenn eine Kiste auf einen Abstellplatz geschoben wird?

Eine mögliche Lösung ist, das sich Kiste und Abstellplatz auslöschen:

Code:


omx -> .o.


Das hätte den Vorteil, das man, unter der Annahme man realisiert das Ganze in ASCII, sich keinen gedanken Machen muß, was passier, wenn der Arbeiter auf den Abstellplatz kommt. Er dürfte ihn wie eine Mauer einfach nicht betreten. Das widerspricht aber den meisten Sokoban-Umsetzungen.

Eine andere Möglickeit ist ein Symbol für belegten Abtellplatz zu wählen:

Code:


omx -> .oM


Das würde zweierlei nach sich ziehen: Man braucht ein Zeichen, für Den Arbeiter auf einem Abstellplatz, und eine Kiste kann möglicherweise wieder von einem Abstellplatz heruntergeschoben werden.

Code:


ox -> .O
oM. -> .Om


Wenn ich etwas vergessen habe, bitte mitteilen!

BeitragVerfasst am: 13. Okt 2003, 00:16 Titel: Antworten mit Zitat Ich versuche weiter zu machen, aber, da tauchen ein paar Probleme auf, bei der ich Hilfe gebrauchen könnte, aber ich greife vor.

Da es möglich ist, das ein Einzelner Stein an einer Mauer zu einer unlösbaren Situation führen kann, sollte man noch die kritische Mauer einführen. Eine kritische Mauer ist eine Mauer, bei der es nicht möglich ist, die Kiste wegzubekommen, wenn die Kiste erstmal an der Mauer klebt:

Code:


 Kritische Mauer  =
 #=======#
 =.......=
 =.......=
 =.......=
 ####.####
 =.......=
 ##.###.##
 =.......=
 =.......=
 =.......=
 #=======#


Eine Ecke muß nicht unbedingt erst als kritisch gekennzeichnet werden, denn eine Ecke ist immer kritisch. Wenn mann Ecken als kritisch kennzeichnen möchte, ist das aber auch kein Problem. In beiden Fällen ergeben sich mehr Vierergruppen, auch wenn man das Problem der kritischen Mauer mit Zweiergruppen lösen kann/könnte:

Code:


 =    m    =m    m=
 m    =


Wahrscheinlich ist es besser, weterhin in Vierergruppen zu analysieren:

Code:


 ==    #=
  m    #m


So, wenn mir noch etwas einfällt, füge ich es nach.

Ich möchte langsam zur Programmierung kommen. Eigentlich wollte ich verschiedene Programmiersprachen als Beispiele verwenden, bleibe aber doch bei REXX, und füge tcl/tk später nach. Also REXX:

Das folgende Listing bewegt sich fast auf dem Niveau von 'hello world':

Code:


/* Ein Rexx-Programm */
z.1  = "    #####          "
z.2  = "    #...#          "
z.3  = "    #m..#          "
z.4  = "  ###..m##         "
z.5  = "  #..m.m.#         "
z.6  = "###.#.##.#   ######"
z.7  = "#...#.##.#####..xx#"
z.8  = "#.m..m..........xx#"
z.9  = "#####.###.#o##..xx#"
z.10 = "    #.....#########"
z.11 = "    #######        "
/* Ausdehnung des Levels */
x_a = 19
y_a = 11
/* Startposition des Arbeiters */
a_x = 12
a_y =  9
/* Anzahl der zu verschiebenden Kisten */
k   =  6
/* Mit der Anweisung cls wird der Bildschirm gel”scht */
cls
/* Schleife, in der der Level auf den Bildschirm dargestellt wird */
do i = 1 to 11
  say z.i
end


Um nicht den Quellcode mit den Leveln zu belasten, und flexibel zu sein, werden die Level später in eine eigene Datei ausgelagert, aus der sie ausgelesen werden können.

Ein Nachteil des oberen Listing ist es, daß der Level oben links in der Ecke dargestellt wird. Um den Level möglichst mittig darzustellen, und um bei Veränderungen, durch Bewegung, nicht jedesmal kommplett darzustellen, braucht man, jedenfalls in der Textversion, einen Befehl wie gotoxy:

Code:


/* Ein Rexx-Programm */
z.1  = "    #####          "
z.2  = "    #...#          "
z.3  = "    #m..#          "
z.4  = "  ###..m##         "
z.5  = "  #..m.m.#         "
z.6  = "###.#.##.#   ######"
z.7  = "#...#.##.#####..xx#"
z.8  = "#.m..m..........xx#"
z.9  = "#####.###.#o##..xx#"
z.10 = "    #.....#########"
z.11 = "    #######        "
/* Ausdehnung des Levels */
x_a = 19
y_a = 11
/* Operationen, um den Level m”glichst mittig darzustellen */
x_p = (80-x_a)/2
y_p = (25-y_a)/2
/* Startposition des Arbeiters */
a_x = 12
a_y =  9
/* Anzahl der zu verschiebenden Kisten */
k   =  6
/* Mit der Anweisung cls wird der Bildschirm gel”scht */
cls
/* Schleife, in der der Level auf den Bildschirm dargestellt wird */
do i = 1 to 11
  gotoxy(x_p , y_p+i)
  say z.i
end