#pydesw: Programmierung eines Brettspiels

Du hast eine Idee für ein Projekt?

Welches Brettspiel soll programmiert werden?

Umfrage endete am Montag 20. Februar 2017, 16:25

Mühle
6
75%
Dame
2
25%
etwas anderes (bitte im Thread vorschlagen)
0
Keine Stimmen
 
Insgesamt abgegebene Stimmen: 8
Benutzeravatar
snafu
User
Beiträge: 6731
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

BlackJack hat geschrieben:@snafu: Was neueres als Python 3.3 bekomme ich hier nicht installiert.
Naja, das ist ja schonmal was. Gut möglich, dass das Spiel auch unter Python 3.3 laufen wird oder dass nur geringe Anpassungen nötig sind. Über die könnte man sich, sofern sie tatsächlich auftreten, bestimmt noch einigen. :)
BlackJack

@Pygoscelis papua: Die meisten Einsteiger werden wahrscheinlich Python 3 verwenden, so insgesamt würde ich mich diese Aussage nicht trauen zu machen.

Und doch, Python >3.3 selber zu kompilieren ist bei mir schwer. Ich habe ja den Punkt beschrieben ab dem ich aufgegeben habe. Eine Abhängigkeit die ich mir nicht selbst kompilieren möchte, wäre beispielsweise OpenSSL. Da habe ich eine ”alte” Version, aber mit den entsprechenden Sicherheitsupdates, aber Python lässt sich dagegen nicht kompilieren. Für Tkinter müsste ich Tk neu kompilieren und dem war dann mein X-Server zu alt. Wenn ich den Rattenschwanz anschaue der da dran hängt beim neu kompilieren, immer in der Hoffnung das dadurch am System und den Anwendungen irgendwas nicht mehr läuft, könnte ich mir auch die Zeit nehmen das System komplett neu aufzusetzen. Das hat aber sein EOL noch nicht erreicht und ist näher an den Rechnern für die ich ernsthaft programmiere, also will ich da jetzt noch keine Zeit drauf verwenden.

Selbst mit der 3.3 hätte ich dann ja immer noch ein Problem mit Qt wenn das 5 sein sollte. Qt5 zu kompilieren würde mir nämlich auch zu viel Aufwand sein. :-)

Na egal, ich bin ja auch nicht die Zielgruppe für das Projekt.

Zu den Klassen: Wenn das die Logik ist, dann brauchen `Crossroad`-Exemplare keine Position in der GUI.
Benutzeravatar
snafu
User
Beiträge: 6731
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

Wegen dem Qt 4/5 Thema habe ich mir noch keine Gedanken gemacht. Ich fänd's schön, wenn du dabei wärst, BlackJack. Ich für meinen Teil könnte mich auch gut mit Qt 4 anfreunden, weil ich mir nicht vorstellen kann, dass Qt 5 etwas mitbringt, das wir unbedingt benötigen.

Ansonsten haben wir ja viel GUI und Spiellogik in der Planung drin. Das müsste normalerweise alles auch von Python 3.3 unterstützt werden. Es klang bei dir erst so, als wolltest du zwingend bei Python 2.7 bleiben. Da sind die Unterschiede ja nun doch etwas größer. Dass du dein System lieber stabil halten möchtest anstatt den "heißesten Scheiss" drauf zu haben, ist dein gutes Recht und das kann ich auch nachvollziehen - gerade bei Linux.

Ich finde, dass wir uns an den exakten Versionen unserer Abhängigkeiten in der jetzigen Projektphase noch nicht aufhängen sollten. Es ist gut, dies mal besprochen zu haben, aber ich denke schon, dass sich hier ein Kompromiss finden lässt. Wie gesagt: Wenn der kleinste gemeinsame Nenner zumindest Python 3 ist, kann ich gut damit leben. Sofern man irgendwann das fertige Projekt überarbeiten möchte (z.B. das Spiel als mobile App), könnte man ja wieder neu über die geforderten Versionen nachdenken, da Qt 5 in dem Punkt deutliche Stärken gegenüber seinem Vorgänger hat. Soweit meine Meinung zu dem Thema...
Pygoscelis papua
User
Beiträge: 206
Registriert: Freitag 13. März 2015, 18:36

ok hier ein paar Änderungen:
piece-> hängt von crossing ab
- color
- crossroad_id
- __init__(pos, crossroad_id)

crossing -> hängt von game ab
- neighbours (horizontal/vertical)
- content #(piece/None)
- id

player -> hängt von game ab
- name
- color
- num_pieces_placed
- play(game??? :K )

game
- players
- move_piece(from_crossing, to_crossing) -> Mill -> True/False?
- remove_piece(crossing)
- crossings
- has_won(player) -> True/False
- place_piece(pos) -> Mill? -> True/False?
- turn
- get_removeable_pieces() -> list
- turn_end()
- is_protected(crossroad) -> True/False #mill
Ähnlich verhält es sich mit get_removable_pieces() in der Game-Klasse. Wird das wirklich benötigt? Oder hast du dabei so eine Art visuelle Hilfestellung für den Spieler im Hinterkopf?
Ja ich hatte da so eine Hilfestellung im Hinterkopf :) sollte das dann eher in das Gui?

Wie würde player.play auf das spiel zugreifen? (wird das spiel einfach als parameter übergeben wie angedeutet? )
Bei dem kreuzungs-modell habe ich mir einfach vorgestellt, das es nicht so kompliziert ist. Ich habe mir das ganze eher als Netz gedacht und dann muss man einfach nur den Kreuzungen Nachbarn zuordnen, das klang für mich am einfachsten ...
import this
hidden python features

JAVA = Just Another Vulnerability Announcement :D
BlackJack

@Pygoscelis papua: Die IDs sind noch drin. Objekte haben ganz automatisch schon selbst eine Identität, man kann Objekte eindeutig voneinander unterscheiden. Zumindest solange man die Vergleichsoperatoren für den Datentyp nicht anders definiert sogar auf ganz triviale Weise, denn dann ist ein Objekt immer nur gleich sich selbst und nicht gleich einem anderem Objekt [1]_, selbst wenn das die gleichen Werte/den gleichen Zustand besitzt. Und wenn man die Vergleiche doch anders definiert, kann man die Identität immer noch in Form einer Zahl mit der `id()`-Funktion ermitteln und ``is`` oder ``is not`` verwenden um zu ermitteln ob es sich bei gleichen Objekten auch tatsächlich um das selbe Objekt handelt. Wenn man das braucht.

.. [1] Stimmt nur solange man nicht einen Datentyp mit pathologischen Implementierungen von den Vergleichsoperationen hat. :-)
Pygoscelis papua
User
Beiträge: 206
Registriert: Freitag 13. März 2015, 18:36

ok denk dir die id einfach weg. :)
Und zu player.play hat da jemand eine Antwort für mich? Ist einfach game übergeben ok? Sonst müsste man ja verbotener weise global verwenden oder?
import this
hidden python features

JAVA = Just Another Vulnerability Announcement :D
Benutzeravatar
snafu
User
Beiträge: 6731
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

Ein Spieler könnte bereits bei seiner Erzeugung das Spiel, zu dem er gehört, übergeben bekommen. Die Rückgabe seiner play()-Methode wäre dabei der nächste Spielzug. Was hältst du von diesem Ansatz?
Pygoscelis papua
User
Beiträge: 206
Registriert: Freitag 13. März 2015, 18:36

ok das ist doch dann"call bei Referenz" oder?
import this
hidden python features

JAVA = Just Another Vulnerability Announcement :D
BlackJack

@Pygoscelis papua: Nein.
Benutzeravatar
Kebap
User
Beiträge: 686
Registriert: Dienstag 15. November 2011, 14:20
Wohnort: Dortmund

Pygoscelis papua hat geschrieben: Wie kann man hier eigentlich einen Anhang anfügen?
Hier ist das Klassendiagramm, es muss aber noch verbessert werden:

...

Ich hoffe ihr habt noch viele Verbesserungsvorschläge :D
Klar kannst du ein Bild erstellen und hier hochladen, oder du benutzt direkt ein Tool, um Klassendiagramme online zu erstellen/teilen/verbessern, da gibt es sehr viele :mrgreen:
MorgenGrauen: 1 Welt, 8 Rassen, 13 Gilden, >250 Abenteuer, >5000 Waffen & Rüstungen,
>7000 NPC, >16000 Räume, >200 freiwillige Programmierer, nur Text, viel Spaß, seit 1992.
Benutzeravatar
snafu
User
Beiträge: 6731
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

Pygoscelis papua hat geschrieben:ok das ist doch dann"call bei Referenz" oder?
Call by Reference ist etwas ganz anderes. Ich dachte es mir so, dass die play()-Methode ein namedtuple liefert mit den Angaben "from" (bzw "from_") und "to". Ein noch nicht gesetzter Stein hätte keine Angabe bzw den Standardwert None für das from-Attribut. Diese Rückgabe könnte vom Aufrufer (also dem Spiel) entsprechend verarbeitet werden. Im Falle eines ungültigen Zuges erfolgt eine Rückmeldung durch das Spiel per Exception, die von der GUI visuell dargestellt wird. Der Spieler ist dann weiterhin an der Reihe und play() müsste erneut aufgerufen werden.
Pygoscelis papua
User
Beiträge: 206
Registriert: Freitag 13. März 2015, 18:36

Ich meine wenn man am Anfang dem Spieler das Spiel übergibt,
dann wird ja wohl nicht das Spiel in dem Spieler gespeichert, sondern eher sozusagen ein "Zeiger", da wenn man es verändert (in einer Methode von Spieler), wird das Spiel, dass übergeben wurde ja auch z.B bei einem 2. Spieler geändert, dem das Spiel auch übergeben wurde oder?
Wie wird das Spiel denn sonst angesprochen, als über einen "Zeiger", wenn es nicht im Spieler gespeichert ist?
Das Call ist hier natürlich nicht wirklich angebracht, da es keine Funktion ist ...
@Kebap die Frage was nicht ob sondern wie ... :(
import this
hidden python features

JAVA = Just Another Vulnerability Announcement :D
BlackJack

@Pygoscelis papua: Du bewegst Dich da auf der Ebene der Implementierung. Egal welchen Wert Du übergibst oder an ein Attribut bindest, es handelt sich bei Python immer um das selbe Objekt. Python kopiert bei Aufrufen und Zuweisung niemals Objekte/Werte. Das Aufrufmodell kann man als „call by object sharing“ bezeichnen. Namen und Attribute stehen in Python nicht für Speicher(adressen) wo man Werte ”rein tut”. Der Speicher gehört zum Wert/Objekt.
Benutzeravatar
snafu
User
Beiträge: 6731
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

Die Übergabe des Spiels war eine erste Idee. Eigentlich muss nur das Spielfeld übergeben werden. Als Rückgabe dann wie gesagt ein Spielzug. Hierdurch müsste die play() Methode nichts vom Spiel wissen, sondern nur das Spielfeld mit seiner aktuellen Stellung auslesen können.

Denkbar wäre auch, einen GuiPlayer und einen KIPlayer von der Player Klasse abzuleiten, die als Schnittstelle nur Farbe, Name und die play() Methode haben.
Pygoscelis papua
User
Beiträge: 206
Registriert: Freitag 13. März 2015, 18:36

@snafu: Könntest du das Diagramm vielleicht deinen Vorstellungen entsprechend ändern?
Ich habe jetzt dafür nicht so viel Zeit und außerdem weiß ich nicht wie du dir das genau vorstellst :)
import this
hidden python features

JAVA = Just Another Vulnerability Announcement :D
Benutzeravatar
snafu
User
Beiträge: 6731
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

Ich fänd es erstmal ganz gut, wenn sich noch ein paar weitere Leute an der Skizzierung des Projekts beteiligen könnten. Bisher läuft das ja nur zwischen uns beiden ab.
sebastian0202
User
Beiträge: 168
Registriert: Montag 9. Mai 2016, 09:14
Wohnort: Berlin

Ich versuche es mal. Es ist glaube zu viel des Guten und vermutlich wieder so viel vermischt..
Ich habe es halb als Pseudo Python Code geschrieben :lol: grausam

Code: Alles auswählen


class Feld(feldtyp):
    feldtyp=feldtyp
    besitzer = 'Spiel'
    
    def besetzt():
        wenn besitzer != 'Spiel':
            return True
        return False
    
    def setze(spielername):
        besitzer=spielername
    
    def typ():
        return feldtyp
    
    def leere():
        besitzer='Spiel'
    
    def besitzer():
        return besitzer

class Rechteck():
    # beginnen oben-links, enden unten-rechts
    acht_felder = [Feld('Ecke'), Feld('Kreuzung'), ... , Feld('Ecke')]
    
    def besetzt(feldnummer):
        return acht_felder[feldnummer].besetzt()
    
    def setze_besitzer(feldnummer, spielername):
        acht_felder[feldnummer].setze(spielername)
    
    def loesche_besitzer(feldnummer):
        acht_felder[feldnummer].leere()
    
    def hole_besitzer(feldnummer):
        return acht_felder[feldnummer].besitzer()

class Spiellogik():
    spielfeld = { 
        'außen': Rechteck(),
        'mittig': Rechteck(),
        'innen': Rechteck()
    }
    
    selbiges_rechteck = ([1,2,3], [6,7,8], [1,4,6], [3,5,7])
    ungleiches_rechteck = ([2,2,2], [4,4,4], [5,5,5], [7,7,7])
        
    def ist_muehle(info):
        rechteck, nummer = unpack(info)
        
        fuer muehle in selbiges_rechteck:
            wenn nummer in muehle: 
                besitzer = set()
                fuer nummer in muehle:
                    besitzer.add(ermittle_spielstein_besitzer(rechteck, nummer))
                if len(besitzer) == 1:
                    return True
        
        fuer muehle in ungleiches_rechteck:
            wenn nummer in muehle:
                besitzer = set()
                for rechteck in ('außen', 'mittig', 'innen')
                    besitzer.add(ermittle_spielstein_besitzer(rechteck, nummer))
                if len(besitzer) == 1:
                    return True

        return False
    
    def ermittle_spielstein_besitzer(rechteck, nummer):
        return spielfeld[rechteck].hole_besitzer(nummer)


class Spielfeld(Spiellogik):
    
    def setze_spielstein(spielstein, nach, spielername):
        wenn spielfeld[nach['rechteck']].besetzt(nach['nummer']):
            return False
        ansonsten
            wenn spielstein.ist_gesetzt():
                info = spielstein.hole_information()
                spielfeld[info['rechteck']].loesche_besitzer(info['nummer'])
            spielfeld[nach['rechteck']].setze_besitzer(nach['nummer'], spielername)
            return True
    
    def loesche_feld(spielstein):
        info = spielstein.hole_information()
        wenn ist_muehle(info): return False
        ansonsten:
            spielfeld[info['rechteck']].loesche_besitzer(info['nummer'])
            spielstein.toete()
            return True

    def analysiere(info):
        wenn ist_muehle(info): return True
        ansonsten: return False


class Spielstein():
    gesetzt = False
    lebendig = True
    info = ['position':None, 'rechteck':None]
    
    def hole_information():
        return info
    
    def ist_gesetzt():
        return gesetzt

    def toete():
        lebendig = False


class Auswahl():
    nach = [rechteckID, feldID]
    def hole_rechteck(gui):
    def spielstein_waehlen(gui):
        return auswahl aus der gui


class Spieler():
    spielsteine = [8*spielstein()]
    spielername = 
    gui = Auswahl() (emit Funktion spaeter?)
    letzer_zug = None

    def zug(spielfeld):
        spielsteingesetzt = False
        solange bis spielsteingesetzt: 
            spielstein = gui.spielstein_waehlen()
            spielsteingesetzt = spielfeld.setze_spielstein(spielstein, gui.nach, spielername)
        
        letzer_zug = spielstein.hole_information()
    
    def anzahl_lebendiger_spielsteine():
        anzahl = 0
        fuer stein in spielstein:
            wenn stein.lebendig:
                anzahl + 1
        return anzahl

class Spiel():
    spieler = [Spieler(), Spieler()]
    spielfeld = Spielfeld()
    generiere_schicke_grafik()
    
    def mache_zug(spieler_am_zug):
        spieler[spieler_am_zug].zug(spielfeld)

    def werte_zug_aus(spieler_am_zug):
        info = spieler_am_zug.letzer_zug()
        darf_stein_loeschen = spielfeld.analysiere(info)
        
        wenn darf_stein_loeschen:
            spielstein = spieler_am_zug.gui.spielstein_waehlen()
            solange wie nicht wahr: 
                spielfeld.loesche_feld(spielstein)
    
    def spiel_vorbei():
        fuer gamer in spieler:
            wenn spieler.anzahl_lebendiger_spielsteine() == 0:
                return True
        return False

    def update():
        solange True:
            spieler_am_zug = spieler[0]
            spieler = spieler[::-1]
            mache_zug(spieler_am_zug)
            werte_zug_aus(spieler_am_zug)

            wenn spiel_vorbei(): break

Pygoscelis papua
User
Beiträge: 206
Registriert: Freitag 13. März 2015, 18:36

+100 für die Anstrengung und das mitarbeiten an der Ausarbeitung des Spiel-Plans :D
sebastian0202 hat geschrieben:Ich versuche es mal. Es ist glaube zu viel des Guten und vermutlich wieder so viel vermischt..
Ich habe es halb als Pseudo Python Code geschrieben :lol: grausam
Ich finde man hat hier einen recht schlechten Überblick,
es wäre wirklich übersichtlicher es als Bild darzustellen, ich weiß aber immer noch nicht wie man hier einen Anhang anfügt...
Und ich glaube ein Klassendiagramm soll noch nicht festlegen, wie die einzelnen Funktionen Implementiert werden, was es auch noch einmal
unübersichtlicher macht.
Ich finde es dennoch gut, dass du neues zu dem Diagramm beigetragen hast, ich habe nur jetzt nicht die Zeit alles genau durch zuschauen bzw. zu durchschauen.
Wenn es möglich wäre das als Bild irgendwie Darzustellen wäre es echt cool, vieleicht kann das bild einfach auf GitHub hochgeladen werden (in eine fork
von der repo zur Vorstellung des Projekts?) und dann hier verlinkt werden?
import this
hidden python features

JAVA = Just Another Vulnerability Announcement :D
Benutzeravatar
snafu
User
Beiträge: 6731
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

Schonmal auf die Idee gekommen, dass man auch einfach einen Link zum Bild setzen könnte...? ;)

Den Code werde ich gleich mal genauer anschauen und vielleicht später eine überarbeitete Version hier zeigen.
BlackJack

Man könnte sich auch mal Werkzeuge zum erstellen von UML-Diagrammen aus Text anschauen. PlantUML wäre so ein Kandidat. UMLet habe ich auch schon mal verwendet.
Antworten