
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?
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 vielePygoscelis 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
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 hat geschrieben:ok das ist doch dann"call bei Referenz" oder?
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
Ich finde man hat hier einen recht schlechten Überblick,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 geschriebengrausam
Code: Alles auswählen
from collections import namedtuple
from itertools import cycle
Position = namedtuple('Position', 'square_name, index')
class Board(object):
def __init__(self):
self.squares = dict(
(name, 9 * [None]) for name in ('inner', 'mid', 'outer')
)
def set_piece(self, position, color):
square = self.squares[position.square_name]
if square[position.index]:
raise OccupiedError
square[position.index] = color
def move_piece(self, old_pos, new_pos, color):
if not self.is_valid_move(old_pos, new_pos, color):
raise InvalidMoveError
self.squares[old_pos.square_name][old_pos.index] = None
self.squares[new_pos.square_name][new_pos.index] = color
class Player(object):
def __init__(self, name, color):
self.name = name
self.color = color
self.pieces_to_set = 9
def play(self, board):
# Hier in abgeleiteter Klasse Spielzug über GUI erfragen
# oder Spielzug durch KI ermitteln basierend auf board.squares
if has_lost:
raise GameLost
if self.pieces_to_set:
board.set_piece(position, self.color)
self.pieces_to_set -= 1
else:
board.move_piece(old_pos, new_pos, self.color)
def play_game(player1, player2):
board = Board()
player_cycle = cycle([player1, player2])
for player in player_cycle:
try:
player.play(board)
except GameLost:
winner = next(player_cycle)
return winner
def main():
player1 = ask_player()
player2 = ask_player()
winner = play_game(player1, player2)
print(winner.name, 'hat das Spiel gewonnen!')
Zudem Mogeln: Das macht doch erst wirklich Sinn wenn man das Spiel über Netzwerk spielt oder?snafu hat geschrieben: Rein theoretisch könnte man das Spielbrett noch irgendwie vor "unsachgemäßen" Änderungen seitens des Spieler-Codes (auch Schummeln/Mogeln genannt) schützen. Aber das würde ich erstmal weg lassen, da die Klasse ja nur intern verwendet wird und der Endanwender keinen Einfluss darauf hat. Das würde erst dann eine Rolle spielen, wenn man einen abgeleiteten Spieler sozusagen im Rahmen eines Plugin-Systems erlaubt.
Was haltet ihr generell von den gezeigten Ansätzen? Sind sie gut nachvollziehbar? Würdet ihr bestimmte Dinge anders lösen...?
Code: Alles auswählen
def move_allowed(old_pos, new_pos):
if old_pos.square == new_pos.square:
wenn old_pos.index == new_pos.index-1 oder +1
#dabei muss natürlich der Sprung zw. 1 und 8 berücksichtigt werden
return True #oder was sollte man hier zurückgeben?
else:
if old_pos.index % 2 and new_pos.index == old_pos.index:
if quadrate_angrenzend(old_pos, new_pos):
return True
Code: Alles auswählen
"""
The board:
0-----------1-----------2
| | |
| 0-------1-------2 |
| | | | |
| | 0---1---2 | |
| | | | | |
7---7---7 3---3---3
| | | | | |
| | 6---5---4 | |
| | | | |
| 6-------5-------4 |
| | |
6-----------5-----------4
"""
from collections import namedtuple
SQUARE_NAMES = ['inner', 'mid', 'outer']
NUM_SQUARE_FIELDS = 8
class Position(namedtuple('Position', 'square_name, index')):
def __new__(cls, square_name, index):
square_name = square_name.lower()
if square_name not in SQUARE_NAMES:
raise ValueError('Invalid square name')
if not 0 <= index < NUM_SQUARE_FIELDS:
raise ValueError('Invalid field index')
return super().__new__(cls, square_name, index)
def is_valid_move(old_pos, new_pos):
if old_pos == new_pos:
return False
if old_pos.square_name == new_pos.square_name:
offset = old_pos.index - new_pos.index
return abs(offset) in (1, NUM_SQUARE_FIELDS - 1)
if old_pos.index == new_pos.index:
is_crossing = new_pos.index % 2 != 0
square_names = (old_pos.square_name, new_pos.square_name)
return is_crossing and 'mid' in square_names
return False