WinFuture-Forum.de: Sokoban - Programmvorstellung - WinFuture-Forum.de

Zum Inhalt wechseln

Nachrichten zum Thema: Entwicklung
Seite 1 von 1

Sokoban - Programmvorstellung Python 2 u. 3 + Kivy - Win, Lin, Android


#1 Mitglied ist offline   Astorek 

  • Gruppe: aktive Mitglieder
  • Beiträge: 1.145
  • Beigetreten: 28. Juli 07
  • Reputation: 42
  • Geschlecht:Männlich

geschrieben 30. Mai 2017 - 09:17

Hi @ all,

Tjoar, ich bin Fan des Sokoban-Spielprinzips und dachte mir, so ein Spielchen könnte ich mal für Python programmieren^^.

Die Regeln für Sokoban sind schnell erklärt: Der Spieler muss Kisten an vorgegebene Kistenplätze schieben, um das Level zu schaffen. Dabei kann der Spieler nur eine Kiste gleichzeitig schieben und keine ziehen. Ideale Ausgangslage für ein Rätsel- oder Knobelspiel^^.



Screenshots:
Eingefügtes Bild Eingefügtes Bild
Eingefügtes Bild Eingefügtes Bild



Downloadlinks:



Zum Ausführen bringen:
Die EXE-Datei ist unter Windows sofort lauffähig.

Wollt ihr den Quelltext zum Laufen bringen, müsst ihr die main.py mit dem Python-Interpreter ausführen. Die erfoderlichen Kivy-Bindings müssen installiert sein; auf der entsprechenden Kivy-Installations-Seite sind die erforderlichen Schritte gut erklärt. Linux-Nutzer haben eine eigene Installations-Seite. Das Spiel wurde so geschrieben, dass es in den Python-Versionen 2.7 und 3.6 einwandfrei läuft; andere Versionen von Python habe ich nicht getestet.

Theoretisch sollte das Spiel auch auf Macs laufen, mangels Gerät kann ich dazu allerdings nicht sagen^^.

Android-Benutzer haben zwei Möglichkeiten:
  • Möglichkeit 1: Die APK herunterladen und installieren. Allerdings muss in den Android-Einstellungen die "Installation von Apps unbekannter Herkunft" erlaubt werden.
  • Möglichkeit 2: Ihr besorgt euch vom Googles PlayStore den "Kivy Launcher" und entpackt die Quelltext-ZIP-Datei in den Ordner "/sdcard/kivy/". Dann könnt ihr mit dem Kivy Launcher direkt den Quelltext starten.



Steuerung:
  • WASD, Richtungs- oder Nummerntasten: Die Figur bewegen.
  • R: Level neu starten
  • U: Zug rückgängig machen

Unter Android ist auch die Bewegung mittels Wisch-Gesten möglich (unten, oben, links rechts).



Levels:
Die Levels hab ich nicht selbst gebaut, stattdessen gibts einige nette Leute im Internet, die ihre Sokoban-Levels unter eine Lizenz stellen, die die Verwendung in eigene Programme erlaubt (Interessante Nebeninfo dabei: Genau deshalb haben fast alle Sokoban-Apps im Googles PlayStore immer dieselben Levels^^). Für Anfänger sind besonders die Levelsets von einem gewissen David W. Skinner (erste Auswahl im Levelauswahl-Bildschirm) sehr empfehlenswert, da in den meisten seiner Levels nur wenige Züge möglich sind, zur Lösung aber trotzdem "um die Ecke" gedacht werden muss.



Sonstiges:
(Der Abschnitt dürfte nurnoch für Programmierer interessant sein, hier liste ich nurnoch Anekdoten von mir auf, weil ich grad Lust drauf habe^^)

Programmiert wurde das Ganze in Python; als Framework kam Kivy zum Einsatz, was ich hauptsächlich haben wollte, weil man damit auch für Android entwickeln kann^^. Ist aber auch sonst ein nettes Framework, das mit seinen Layout-Managern ein bisschen an Java-GUI-Programmierung erinnert^^.

Programmiertechnisch hab ich versucht, das Ganze ein bisschen zu kapseln. So enthält z.B. die models.py sämtliche Logiken, wie ein Sokoban-Spiel abzulaufen hat. Bevor ich mit Kivy gearbeitet habe, habe ich mir mittels cmdviewer.py eine eigene Text-GUI geschrieben. Das hat den riesigen Vorteil, dass ich damit die ganzen Logik-Geschichten auf Herz und Nieren prüfen konnte und Änderungen auch vergleichsweise schnell in besagte Text-GUI sichtbar wurden. Ereignisprogrammierung ist so ein tolles Konstrukt^^.

Die Kivy-GUI in kivyviewer.py hatte ich anfangs massiv unterschätzt; das Ding hat mehr Quelltextzeilen als die Sokoban-Logiken, generell hab ich mehr Zeit in die GUI gesteckt als ich eigentlich vorhatte. Waren gefühlt sogar mehr als 50% der Zeit, die ich fürs Programmieren des gesamten Projekts brauchte. Am Schluss war ich froh, es endlich fertiggestellt zu haben und konnte es gegen Ende echt nicht mehr sehen^^.



Schlussworte:
Tjoar... Ich wünsche viel Spaß beim Ausprobieren des Spiels, und beim Durchschauen des Quelltextes ;) . Würd mich über Feedback freuen! :)
0

Anzeige



#2 Mitglied ist offline   Ludacris 

  • Gruppe: Moderation
  • Beiträge: 4.666
  • Beigetreten: 28. Mai 06
  • Reputation: 218
  • Geschlecht:Männlich

geschrieben 30. Mai 2017 - 14:45

Was mir schon auf den Screenshots auffällt ist, dass die UI etwas verwirrend ist. Ein Zielfeld sollte doch normal durch einen · gekennzeichnet sein. Sonst kann ich noch nicht viel dazu sagen, ich werds mir am abend mal genauer anschaun. Nachtrag: Brings hier in der Arbeit nicht zum laufen (Ubuntu 16.04) - ich kann Kivy nicht installieren.

Dieser Beitrag wurde von Ludacris bearbeitet: 30. Mai 2017 - 14:56
Änderungsgrund: Nachtrag

0

#3 Mitglied ist offline   Astorek 

  • Gruppe: aktive Mitglieder
  • Beiträge: 1.145
  • Beigetreten: 28. Juli 07
  • Reputation: 42
  • Geschlecht:Männlich

geschrieben 30. Mai 2017 - 15:27

Beitrag anzeigenZitat (Ludacris: 30. Mai 2017 - 14:45)

Nachtrag: Brings hier in der Arbeit nicht zum laufen (Ubuntu 16.04) - ich kann Kivy nicht installieren.
Vielleicht hilft folgendes: Ich musste unter Ubuntu (auch 16.04) folgende Befehle ausführen, bevor ich es zum Laufen brachte:
sudo add-apt-repository ppa:kivy-team/kivy
sudo apt-get update
sudo apt-get install python-kivy  # Alternativ: "python3-kivy" für die Python3-Version


Die Kivy-Pakete aus dem offiziellen Ubuntu-Repository hab ich garnicht erst probiert^^.

Zitat

Was mir schon auf den Screenshots auffällt ist, dass die UI etwas verwirrend ist. Ein Zielfeld sollte doch normal durch einen · gekennzeichnet sein. Sonst kann ich noch nicht viel dazu sagen, ich werds mir am abend mal genauer anschaun.
Erstens schonmal Danke für den Versuch und die Rückmeldung :) . Eigentlich sollten die roten "X"-Felder die Ziele darstellen, es ist mir nie in den Sinn gekommen darin etwas anderes zu sehen^^.
0

#4 Mitglied ist offline   XiLeeN2004 

  • Gruppe: aktive Mitglieder
  • Beiträge: 580
  • Beigetreten: 16. Juni 04
  • Reputation: 50
  • Geschlecht:Männlich
  • Wohnort:Ahrensburg
  • Interessen:Aikidō (Godan), Schwimmen, Motorradfahren ('35er Indian Four, noch von meinem Vater), Dampfmodellbau, Kino

geschrieben 30. Mai 2017 - 23:36

Macht Spaß und süchtig :) Vielen Dank! Wünschen würde ich mir nur, dass sich "Zug rückgängig" nur auf die letze Bewegung einer Kiste beziehen würde und nicht auf jeden einzelnen Schritt der Spielfigur.
Eingefügtes Bild
0

#5 Mitglied ist offline   RalphS 

  • Gruppe: VIP Mitglieder
  • Beiträge: 8.895
  • Beigetreten: 20. Juli 07
  • Reputation: 1.126
  • Geschlecht:Männlich
  • Wohnort:Zuhause
  • Interessen:Ja

geschrieben 31. Mai 2017 - 00:03

Schau grad mal über den Quelltext, weil ich mich gewundert hab, wo die >1MB für *Quellcode* herkommen. :huh:

Aber, die Grafiken. Natürlich. ... Vielleicht eine dumme Frage, aber, wären evtl Vektorgrafiken auch eine Option? Können die als solche angezeigt werden via der Grafikbibliothek? Spart Platz und hat auch den Vorteil, daß das auf allen Auflösungen gut aussieht. Nur so als Gedanke; wenn es nicht einfach umsetzbar ist, kann man das natürlich streichen.

Versuch grad das Objektmodell nachzuvollziehen. Gelingt mir aber grad noch nicht so richtig. Wohl schon bissel spät, muß ich morgen noch mal schauen. Sehe spontan aber keinen Player und auch keine Kisten in der Klassendefinition und sehe aber dafür init_level, was ich spontan für einen Konstruktor halten würde, was es aber offensichtlich nicht ist. :unsure:

Oder denk ich an Python vorbei? Ich sehe 'class' und denke 'aha, objektorientiert'; ist was anderes gemeint? Falls ja, sorry. Oder ich stehe auf dem Schlauch. Ich mein, ist Python. Da steh ich gerne mal auf diesem. :huh:

Ansonsten tät ich die kivyviewer und die models auseinandernehmen nach Klassendefinition, jeweils eine Klasse in eine Datei. Dann muß man nicht überall rumsuchen.


Anyway, danke fürs Bereitstellen, und solange wie es hinterher funktioniert und möglichst gut funktioniert, ist ja auch alles in bester Butter, ob jetzt die Quellcodestruktur zusagt oder nicht. :)
"If you give a man a fish he is hungry again in an hour. If you teach him to catch a fish you do him a good turn."-- Anne Isabella Thackeray Ritchie

Eingefügtes Bild
Eingefügtes Bild
0

#6 Mitglied ist offline   Astorek 

  • Gruppe: aktive Mitglieder
  • Beiträge: 1.145
  • Beigetreten: 28. Juli 07
  • Reputation: 42
  • Geschlecht:Männlich

geschrieben 31. Mai 2017 - 08:27

Beitrag anzeigenZitat (XiLeeN2004: 30. Mai 2017 - 23:36)

Macht Spaß und süchtig :) Vielen Dank! Wünschen würde ich mir nur, dass sich "Zug rückgängig" nur auf die letze Bewegung einer Kiste beziehen würde und nicht auf jeden einzelnen Schritt der Spielfigur.
Schau mal in den Optionen nach, letzte Auswahl ;)


Beitrag anzeigenZitat (RalphS: 31. Mai 2017 - 00:03)

Schau grad mal über den Quelltext, weil ich mich gewundert hab, wo die >1MB für *Quellcode* herkommen. :huh:

Aber, die Grafiken. Natürlich. ... Vielleicht eine dumme Frage, aber, wären evtl Vektorgrafiken auch eine Option? Können die als solche angezeigt werden via der Grafikbibliothek? Spart Platz und hat auch den Vorteil, daß das auf allen Auflösungen gut aussieht. Nur so als Gedanke; wenn es nicht einfach umsetzbar ist, kann man das natürlich streichen.
Wär mal einen Versuch wert, hab allerdings noch nie was mit Vectorgrafiken zu tun gehabt und dementsprechend keine Ahnung, wie das funktioniert^^.

Zitat

Versuch grad das Objektmodell nachzuvollziehen. Gelingt mir aber grad noch nicht so richtig. Wohl schon bissel spät, muß ich morgen noch mal schauen. Sehe spontan aber keinen Player und auch keine Kisten in der Klassendefinition und sehe aber dafür init_level, was ich spontan für einen Konstruktor halten würde, was es aber offensichtlich nicht ist. :unsure:

Oder denk ich an Python vorbei? Ich sehe 'class' und denke 'aha, objektorientiert'; ist was anderes gemeint? Falls ja, sorry. Oder ich stehe auf dem Schlauch. Ich mein, ist Python. Da steh ich gerne mal auf diesem. :huh:
Das Ganze ist zugegeben etwas seltsam aufgebaut^^. Generell ist unter Python die "__init__"-Methode der Konstruktor. Ich erklär mal, wie ich die models.yp generell aufgebaut habe :) :

  • Generell hab ich versucht, mich großteils an MVC zu halten. Grundprinzip: Die Objekte haben verschiedene Methoden, die Attribute ändern und nach dem Ändern ein Event abfeuern. Die Viewers (sowohl cmdviewer.py als auch kivyviewer.py) schnappen sich besagte Events und binden diese an eigene Methoden.

  • Bei den Models gibts die Klasse LevelLoader. Das Ding schnappt sich TXT-Dateien (Methode "load_levelset"), führt Prüfungen durch ob es sich um valide Sokobanlevels handeln und speichert es dann "in einem Rutsch" in einem Dictionary ab. Sortierung des Dictionary: [Levelnummer]=[2D-Array des Levels]. Methode "get_level" gibt dann das entsprechende 2D-Array zurück.

  • Die Klasse SokobanGame ist die eigentliche "Spielklasse". Das Objekt benötigt ein 2D-Array des Spielfelds, auf dem dann das Spiel ablaufen soll. Die Objekte übernimmt quasi die komplette Spiellogik; sie stellt Methoden bereit, um den Spieler gemäß der Sokobanregeln zu bewegen, ggf. Kisten zu verschieben und zu vermelden, ob der Spieler das Level geschafft hat. Bei Leveländerungen (also wenn sich z.B. der Spieler bewegen konnte) werden entsprechende Events abgefeuert, um die Änderungen dem Viewer mitzuteilen.

    Wenn der Spieler das Level geschafft hat, wird das "alte" Objekt nichtmehr benötigt und ein neues "SokobanGame"-Objekt mit dem neuen Level erstellt.

    Speziell wegen der Methode init_level: Technisch ist das kein Konstruktor (ist ja immer die "__init__"-Methode in Python), wird aber "so halb" dafür verwendet. Der Grund ist recht einfach: Wenn ein Objekt angelegt wird, kann man sich bereits dessen Events schnappen. init_level feuert ein paar Events ab, die die Viewer brauchen (z.B. wo sich was befindet; die "set_block"-Events).

    Wenn ich so drüber nachdenke, wars eigentlich eine blöde Idee, dem Objekt bereits beim Erstellen das Level mitzugeben. Sinnvoller wärs gewesen, das erst in der init_level-Methode zu tun^^.

  • Achja: Ich hab überhaupt keine Objekte für Spieler, Kisten usw. erstellt, sondern fummle direkt am 2D-Array herum. Vielleicht sollte ich das auch nochmal überdenken, das Debuggen ist bei sowas nämlich ziemlich nervig gewesen^^.

  • Die nächsten Aufteilungen sind zugegeben noch etwas kurioser, was daran liegt, dass ich nicht wirklich Erfahrung mit OOP in der Praxis habe^^: Die Klasse "ReplaySaver" ist eigentlich selbsterklärend; in "SokobanGame_v2" nutze ich ein Objekt davon, um zusätzliche Replay-Funktionalität zur Verfügung zu stellen. Sowas Ähnliches mache ich auch in "SokobanGame_v3" für den Schrittzähler. Offen gestanden glaube ich kaum, dass das in der Praxis so gemacht wird - es war der Versuch, eine Gottklasse zu vermeiden, was aber irgendwie nicht so ganz gelückt ist^^.

Falls noch was unklar ist, einfach fragen. :)

Zitat

Ansonsten tät ich die kivyviewer und die models auseinandernehmen nach Klassendefinition, jeweils eine Klasse in eine Datei. Dann muß man nicht überall rumsuchen.
Oh ja, das hab ich mir später auch sowas von gedacht. Ich hab noch nie ein OOP-Projekt dieser Größe umgesetzt und weiß jetzt, dass ich das nie wieder so machen werde, für jeden Viewer bloß eine einzige Quelltextdatei zu verwenden^^.


Vielen Dank für euer Feedback! :)

Dieser Beitrag wurde von Astorek bearbeitet: 31. Mai 2017 - 08:28

0

#7 Mitglied ist offline   Ludacris 

  • Gruppe: Moderation
  • Beiträge: 4.666
  • Beigetreten: 28. Mai 06
  • Reputation: 218
  • Geschlecht:Männlich

geschrieben 31. Mai 2017 - 09:02

Beitrag anzeigenZitat (Astorek: 30. Mai 2017 - 15:27)

sudo add-apt-repository ppa:kivy-team/kivy
sudo apt-get update
sudo apt-get install python-kivy  # Alternativ: "python3-kivy" für die Python3-Version





jo hab ich gemacht, entsprechend der Kivy seite, dort stand nix von python3-kivy (daher dachte ich mir erst ja, klar macht sinn, auf die idee hätte ich auch kommen können) aber es geht damit auch nicht - kann aber auch an dem system hier liegen, ich glaub ich hab mir das mit einem versuchten kernel update etwas kaputt gemacht :lol:
0

#8 Mitglied ist offline   RalphS 

  • Gruppe: VIP Mitglieder
  • Beiträge: 8.895
  • Beigetreten: 20. Juli 07
  • Reputation: 1.126
  • Geschlecht:Männlich
  • Wohnort:Zuhause
  • Interessen:Ja

geschrieben 31. Mai 2017 - 11:07

Mh? Kann man das nicht einfach mit nem <pip install> reinholen? :unsure:

Das jetzt auf striktes OO umbiegen zu wollen, ... mh, könnte unter Umständen problematisch werden. Denn auf das Modell setzt ja alles auf. Das Modell muß also zuerst da sein.

Ohne jetzt weiter reingeschaut zu haben wäre ein "okay, wir bauen einen Player und eine Box und ggf noch was anderes und bauen die so trivial, daß die erstmal mit geringen Änderungen im restlichen Quellcode wegkommen", aber ultimativ -denk ich- wäre ein ordentlicher Entwurf und eine vollständige Reimplementierung der sinnvollere Ansatz.

Wenn man nämlich mit Objekten agieren kann, wird plötzlich der Programmablauf *logisch*. Das ist ja auch der Sinn von MVC (unter anderem). Dann steht nicht da
$feld[0][5] += $feld[1][$kiste[7]]


, sondern Player.moveKiste(Kiste k, KISTE::MOVE_UP); was gleich mit berücksichtigen würde, daß Kisten nur unter bestimmten Umständen in bestimmte Richtungen *geschoben* werden können. (Immerhin können sie ja nicht *gezogen* werden.) Anderenfalls hätte ein Kiste.moveUp(2) gereicht, um die Kiste zwei Felder hochzuschieben.

So als Beispiel.

Wo man sich mit gewissem Recht nach dem Sinn von fragen darf.

Vielleicht beim nächsten Projekt, und sei es nur Sokoban 2.0. :)

Dieser Beitrag wurde von RalphS bearbeitet: 31. Mai 2017 - 11:10

"If you give a man a fish he is hungry again in an hour. If you teach him to catch a fish you do him a good turn."-- Anne Isabella Thackeray Ritchie

Eingefügtes Bild
Eingefügtes Bild
1

Thema verteilen:


Seite 1 von 1

1 Besucher lesen dieses Thema
Mitglieder: 0, Gäste: 1, unsichtbare Mitglieder: 0