Skip to content

Instantly share code, notes, and snippets.

Created March 19, 2014 20:38
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save anonymous/9650662 to your computer and use it in GitHub Desktop.
Save anonymous/9650662 to your computer and use it in GitHub Desktop.
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from sys import exit
import controls
import events
import models
import views
def main():
# Die Ganzen Module miteinander bekanntmachen
# und den EventManager durchreichen
evManager = events.EventManager()
viewer = views.CmdViewer(evManager)
controller = controls.CmdController(evManager)
game = models.Game(evManager)
four_in_a_row = controls.CPUSpinner(evManager)
# Als Beobachter brauchen beide Zugriff aufs Spiel
viewer.game = game
controller.game = game
# Im Hauptmenue anfangen und losstarten
evManager.send(events.SetEventState("main menu"))
four_in_a_row.run()
if __name__ == "__main__":
main()
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import events
# Fix fuer Python2-/3-Kompatibilitaet
try:
input = raw_input
except NameError:
pass
# Die Funktion ist ein uebler Hack wegen dem evManager
def check_input(min, max, evManager):
"""Funktion, die den Benutzer nach einer Eingabe fragt.
Es werden min- und max-Werte mitgegeben. Die Funktion verlangt
solange eine Eingabe, bis eine korrekte geliefert wurde.
"""
while True:
keyb_key = None
try:
keyb_key = int(input())
if keyb_key < min or keyb_key > max:
raise ValueError
except (SyntaxError, NameError, EOFError, ValueError):
evManager.send(events.WrongInput())
else:
break
return keyb_key
class CmdController(object):
def __init__(self, evManager):
self.evManager = evManager
self.evManager.register(self)
self.keyb_key = None
def notify(self, event):
if self.evManager.state == "game running":
self.control_game(event)
elif self.evManager.state == "main menu":
self.control_mainmenu(event)
def control_game(self, event):
if isinstance(event, events.Tick):
self.keyb_key = check_input(0, 7, self.evManager)
if self.keyb_key == 0:
self.evManager.send(events.QuitGame())
else:
# -1, um Die Zaehlung Mensch vs. Programmierer
# auszugleichen. Ein Programmierer faengt immer bei 0
# das Zaehlen an ;)
self.evManager.send(
events.RequestDrop(self.game.player, self.keyb_key - 1))
def control_mainmenu(self, event):
#print event
#exit()
if isinstance(event, events.Tick):
self.keyb_key = check_input(1, 2, self.evManager)
if self.keyb_key == 1:
self.evManager.send(events.SetEventState("game running"))
else:
self.evManager.send(events.QuitProgram())
class CPUSpinner(object):
def __init__(self, evManager):
self.evManager = evManager
self.evManager.register(self)
self.running = True
def run(self):
while self.running:
self.evManager.send(events.Tick())
def notify(self, event):
if isinstance(event, events.QuitProgram):
self.running = False
#!/usr/bin/env python
# -*- coding: utf-8 -*-
class EventManager(object):
"""EventManager zum Sammeln von Events.
Mit dem EventManager ist es moeglich, mehrere sog. Listener zu
registrieren (Methode "register"), und ihnen Events zu senden
(Methode "send"). Wenn ein Event gesendet wird, wird an allen
registrierten Listeners die Methode "notify" aufgerufen.
"""
def __init__(self):
self.listener = list()
self.register(self)
self.state = None
def register(self, listener):
"""Registriert einen Listener."""
self.listener.append(listener)
def unregister(self, listener):
"""Deregistriert einen Listener."""
if listener in self.listener:
del self.listener[listener]
def send(self, event):
"""Ruft bei allen Listeners die notify-Methode auf.
Das entsprechende Event wird als Parameter mitgesendet.
"""
for listener in self.listener:
listener.notify(event)
def notify(self, event):
"""Implementierung der notify-Methode.
Jeder Listener, der sich registriert, muss die notify-Methode
implementiert haben.
"""
if isinstance(event, SetEventState):
self.state = event.state
class Event(object): # Superklasse
pass
class SetEventState(Event):
def __init__(self, state):
self.state = state
class Tick(Event):
pass
class RequestDrop(Event):
def __init__(self, player, colnum):
self.player = player # Spielerobjekt
self.colnum = colnum # Spalte als Integer
class DropStone(Event):
def __init__(self, stone, colnum):
self.stone = stone
self.colnum = colnum
class DropNotPossible(Event):
def __init__(self, colnum):
self.colnum = colnum
class SwitchPlayers(Event):
pass
class WrongInput(Event):
pass
class QuitGame(Event):
pass
class QuitProgram(Event):
pass
class GameWon(Event):
def __init__(self, player):
self.player = player
class ReInitialize(Event):
pass
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from sys import exit
import events
class Player(object):
"""Objekt Spieler."""
def __init__(self, name, stone):
self.name = name
self.stone = stone
class Col(object):
"""Repraesentiert eine Spalte eines 4Gewinnt-Spiels."""
def __init__(self, height=6, emptyvalue="."):
"""Erstellt eine Spalte."""
self.reinitialize(height, emptyvalue)
def reinitialize(self, height=None, emptyvalue=None):
if height is not None:
self.height = height
if emptyvalue is not None:
self.emptyvalue = emptyvalue
self.col = [self.emptyvalue for _ in range(self.height)]
def __getitem__(self, key):
return self.col[key]
def __len__(self):
return len(self.col)
def is_drop_possible(self):
"""Prueft, ob ganz oben in der Spalte noch Platz frei ist.
Boolean als Rueckgabewert.
"""
return self.col[-1] == self.emptyvalue
def drop_stone(self, stone):
"""Wirft einen Stein in die Spalte rein.
Kein Rueckgabewert! "stone" sollte ein String mit
maximal einem Buchstaben sein.
Achtung: Keine Pruefung, ob ueberhaupt noch Platz fuer einen
Stein ist! Sonst wird der Stein an hoechster Stelle
ueberschrieben!
"""
# von Aussen nicht sichtbare Methode aufrufen, da niemand
# auf "row" zugreifen darf.
self.__drop_stone(stone, self.height - 1)
def __drop_stone(self, stone, row):
# Wenn der Stein noch nicht ganz unten angekommen ist UND sich
# unterhalb von der aktuellen Position noch Platz befindet,
# koennen wir noch eins nach unten wandern...
if row != 0 and self.col[row-1] == self.emptyvalue:
self.__drop_stone(stone, row-1)
else:
self.col[row] = stone
class Gamefield(object):
"""Repraesentiert das 4Gewinnt-Spielfeld mit seinen Spalten."""
def __init__(self, width=7):
"""Erstellt das Spielfeld"""
self.width = width
self.rows = [Col() for _ in range(self.width)]
def __getitem__(self, key):
return self.rows[key]
def is_drop_possible(self, col):
"""Prueft, ob die Reihe voll ist.
col ist die angesprochene Spalte als Integer.
Boolean als Rueckgabewert."""
return self.rows[col].is_drop_possible()
def drop_stone(self, stone, col):
"""Wirft einen Stein in die Reihe."""
return self.rows[col].drop_stone(stone)
def get_row(self, row):
"""Gibt eine Reihe des Spielfelds zurueck."""
return [col[row] for col in self.rows]
def is_full(self):
"""Prueft, ob das Spielfeld voll ist."""
for col in self.rows:
if col.is_drop_possible():
return True
return False
def reinitialize(self):
"""Setzt das Spielfeld wieder auf Anfang zurueck."""
for col in self.rows:
col.reinitialize()
def is_someone_winner(self):
"""Prueft, ob jemand gewonnen hat."""
# TODO: Alles katastrophal hier. Ich habe keine Ahnung, wie
# ich das alles besser hinbekomme :\
# Senkrechte Pruefung
for col in self.rows:
for i in range(len(col)-3):
if col[i] == col.emptyvalue:
continue
elif col[i] == col[i+1] == col[i+2] == col[i+3]:
return True
# Waagrechte Pruefung...
for i in range(len(self.rows[0])):
row = self.get_row(i)
for j in range(len(row)-3):
if row[j] == self.rows[i].emptyvalue:
continue
elif row[j] == row[j+1] == row[j+2] == row[j+3]:
return True
# Diagonale Pruefung - Das Schlimmste zum Schluss :( ...
if self.__is_diagonal_winner(0, 3, 1):
return True
if self.__is_diagonal_winner(3, 6, -1):
return True
def __is_diagonal_winner(self, start, end, direction):
for i in range(start, end):
row1 = self.get_row(i)
row2 = self.get_row(i+direction)
row3 = self.get_row(i+(direction*2))
row4 = self.get_row(i+(direction*3))
for j in range(len(row1)-3):
if row1[j] == self.rows[0].emptyvalue:
continue
if row1[j] == row2[j+1] == row3[j+2] == row4[j+3]:
return True
return False
class Game(object):
"""Repraesentiert das Spiel."""
def __init__(self, evManager):
self.evManager = evManager
self.evManager.register(self)
self.gamefield = Gamefield()
self.gamefield.game = self
self.player = Player("Programmierer", "X")
self.waiting_player = Player("Dummy-Spieler", "O")
def notify(self, event):
# Spieler fragt, ob er einen Stein werfen darf.
if isinstance(event, events.RequestDrop):
if self.gamefield.is_drop_possible(event.colnum):
self.evManager.send(
events.DropStone(event.player.stone, event.colnum))
if self.gamefield.is_someone_winner():
self.evManager.send(events.GameWon(self.player))
self.evManager.send(events.QuitGame())
self.evManager.send(events.SwitchPlayers())
else:
self.evManager.send(events.DropNotPossible(event.colnum))
elif isinstance(event, events.SwitchPlayers):
self.player, self.waiting_player = self.waiting_player, self.player
elif isinstance(event, events.DropStone):
self.gamefield.drop_stone(event.stone, event.colnum)
elif isinstance(event, events.QuitGame):
self.evManager.send(events.ReInitialize())
self.evManager.send(events.SetEventState("main menu"))
elif isinstance(event, events.ReInitialize):
self.gamefield.reinitialize()
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from sys import stdout
import events
class CmdViewer(object):
def __init__(self, evManager):
self.evManager = evManager
self.evManager.register(self)
def notify(self, event):
if self.evManager.state == "game running":
self.listen_game(event)
elif self.evManager.state == "main menu":
self.listen_mainmenu(event)
def listen_game(self, event):
if isinstance(event, events.Tick):
self.show_gamefield()
print("{} ist an der Reihe!".format(self.game.player.name))
print("1-7 fuer Spalte, 0 fuer Beenden druecken!")
elif isinstance(event, events.DropNotPossible):
print("Sorry {},".format(self.game.player.name))
print("hier kannst du nicht werfen!")
elif isinstance(event, events.WrongInput):
print("Fehlerhafte Eingabe!")
print("versucht es nochmal!")
elif isinstance(event, events.GameWon):
self.show_gamefield()
print("HERZLICHEN GLUECKWUNSCH!")
print("{} hat das Spiel gewonnen!".format(event.player.name))
def show_gamefield(self):
"""Zeigt das Spielfeld an."""
# TODO: Nicht gerade huebsch, die Methode :\
print("")
# Erst die Zeilennummern ausgeben...
for i in range(1, len(self.game.gamefield.rows)+1):
stdout.write(str(i) + " ")
print("")
# ... dann den Rest vom Spielplan
height = self.game.gamefield.rows[0].height
for i in range(height -1, -1, -1):
for j, char in enumerate(self.game.gamefield.get_row(i)):
stdout.write(char)
if j != height:
stdout.write("|")
print("")
def listen_mainmenu(self, event):
if isinstance(event, events.Tick):
print("")
print("Hauptmenue 4gewinnt.py - MVC-Test")
print("---------------------------------")
print("1. Spiel starten")
print("2. Programm beenden")
elif isinstance(event, events.QuitProgram):
print("Vielen Dank fuer die Benutzung des Programms!")
print("Have a nice day! ;o)")
elif isinstance(event, events.WrongInput):
print("Fehlerhafte Eingabe, bitte wiederholen!")
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment