mit meinem grafischen Lösungsansatz. Die Spiel-
Canvas-Objekten. Die Programmiermethode bei
diesem Prototypen basiert noch nicht auf OOP.
Variante des ganzen Matrix-Spiels. Es kann nat-
ürlich noch mit diversen features erweitert werden.
Code: Alles auswählen
#!/usr/bin/env python
# -*- coding: UTF-8 -*-
""" Skriptname : fwsMatrixGame-05.py
Version : 1.05
Autor : Fritz Wüst
Copyright : wuest59@dial.centralnet.ch
Erstellt : 13.12.2004
Geändert : 15.12.2004
Lizenz : GNU/GPL
Entwicklungs- : OS :SuSE91
Plattform Editor :KWrite
Debugger :Bash-Shell
Sprache :Python 2.3.3
GUI :Tkinter
Funktion : Matrix-Game
** Spielregel **
Die Game-Boxen (Rechtecke mit Ziffern) müssen mit
aufsteigender Nummernfolge horizontal aneinander
gereiht in möglichst kurzer Zeit und mit möglichst
wenig Bewegungen platziert werden. Das Matrix-Feld
unten rechts bleibt am Ende des Spiels leer, so wie
es sich vor einem Spielbeginn präsentiert!
** Verschieben der Game-Boxen **
Durch Anklicken einer der um das leere Matrix-Feld
platzierten Game-Boxen, mit der linken Maustaste,
verschiebt sich diese automatisch aufs leere Matrix-Feld.
Es können auch mehrere Game-Boxen gleichzeitig horizontal
oder vertikal verschoben werden indem eine vom leeren
Matrix-Feld entfernte Game-Box, welche in der gleichen
Reihe bzw. Kolonne liegt, angeklickt wird. Diese Aktion
bewertet das Spiel nur als eine Bewegung.
** Schwierigkeitsgrad **
Kann mit setzen höherer Werte für Variable 'gridsperrow'
erreicht werden.
** Mögliche Matrix-Abmessungen **
Matrixen von 3x3 bis 8x8 sind möglich.
"""
from Tkinter import*
from time import time
from random import shuffle
def GameTimer():
global starttime,runflag
#~~ Timer-Aktualisierungintervall
if runflag == 1 and startflag == 1:
timervalue['text']= ('%5.1f') % (time()-starttime)
platform.after(reptime,GameTimer)
def ChangeBoxEnter(event):
#~~ Ändert Kursor-Symbol von Pfeil in Hand um.
cursor = platform['cursor']
platform['cursor'] = 'hand1'
def ChangeBoxLeave(event):
#~~ Ändert Kursor-Symbol von Hand in Pfeil um.
platform['cursor'] = root['cursor']
def MoveBox(event=None,gamebox=None):
#~~ Verschiebt die selektierte Game-Box
# auf die leere Grid-Box
global movecount,shuffleflag,runflag,startflag,starttime
if not(runflag ^ shuffleflag):
return
if startflag == 0 and event != None:
startflag = 1
starttime = time()
timervalue['text']= ('%d') % (time()-starttime)
butstart['text'] = 'Spiel läuft!'
butstart.update_idletasks()
#~~ Suche die leere Grid-BoxGameTimer()
emptygridbox = FindEmptyGridBox()
#~~ Koordinaten der leeren Grid-Box
x1e,y1e,x2e,y2e = platform.bbox(emptygridbox)
#~~ Koordinaten der aktivierten Game-Box14
x1s,y1s,x2s,y2s = platform.bbox(gamebox)
if y1e == y1s:
#~~ Horizontalverschiebung der Game-Box
if (x1e - x1s) >= 0:
boxlist = list(platform.find_enclosed(x1s,y1s,x1e,y2s))
boxlist.reverse()
for box in boxlist:
if box > gridboxes and box < 2*gridboxes:
#~~ Verschiebe die Game-Box nach rechts
platform.move(box,gridwidth,0)
#~~ Verschiebe die Game-Box Ziffer nach rechts
platform.move(box+gridboxes-1,gridwidth,0)
movecount += 1
if (x1e - x1s) < 0:
boxlist = list(platform.find_enclosed(x2s,y1s,x2e,y2s))
for box in boxlist:
if box > gridboxes and box < 2*gridboxes:
#~~ Verschiebe die Game-Box nach links
platform.move(box,-gridwidth,0)
#~~ Verschiebe die Game-Box Ziffer nach links
platform.move(box+gridboxes-1,-gridwidth,0)
movecount += 1
if x1e == x1s:
#~~ Vertikalverschiebung der Game-Box
if (y1e - y1s) >= 0:
boxlist = list(platform.find_enclosed(x1s,y1s,x2s,y1e))
for box in boxlist:
if box > gridboxes and box < 2*gridboxes:
#~~ Verschiebe die Game-Box nach unten
platform.move(box,0,gridwidth)
#~~ Verschiebe die Game-Box Ziffer nach unten
platform.move(box+gridboxes-1,0,gridwidth)
movecount += 1
if (y1e - y1s) < 0:
boxlist = list(platform.find_enclosed(x1s,y2s,x2s,y2e))
boxlist.reverse()
for box in boxlist:
if box > gridboxes and box < 2*gridboxes:
#~~ Verschiebe die Game-Box nach oben
platform.move(box,0,-gridwidth)
#~~ Verschiebe die Game-Box Ziffer nach oben
platform.move(box+gridboxes-1,0,-gridwidth)
movecount += 1
if shuffleflag == 0:
movevalue['text']= str(movecount)
#~~ Kontrolle ob das Spiel erfolgreich beendet wurde
CheckGame()
def FindEmptyGridBox():
#~~ Finde die unbelegte Grid-Box
for gridbox in xrange(1,gridboxes+1):
#~~ Lade Koordinaten der Grid-Box
x1,y1,x2,y2 = platform.bbox(gridbox)
#~~ Lade die Objektnummern der Canvasobjekte,welche
# sich in der Grid-Box befinden
gridboxstack = platform.find_overlapping(x1,y1,x2,y2)
#~~ Suche der leeren Grid-Box
if len(gridboxstack) == 1:
#~~ Die unbelegte Gridbox wurde gefunden!
# x11,y11,x22,y22 = platform.bbox(gridboxstack[0])
return gridboxstack[0]
def CheckGame():
#~~ Kontrolle ob sich alle Game-Boxen auf den zugehörigen
# Grid-Boxen befinden
global runflag
gamewonflag = 1
for gridbox in xrange(1,gridboxes+1):
x1,y1,x2,y2 = platform.bbox(gridbox)
gridboxstack = platform.find_overlapping(x1,y1,x2,y2)
if len(gridboxstack) == 1:
#~~ Dies war die unbelegte Grid-Box
continue
if gridboxstack[0] != gridboxstack[1]-gridboxes:
#~~ Es liegt eine Falschbelegung vor
gamewonflag = 0
break
if gamewonflag == 1:
runflag = 0
startflag = 0
butstart['text'] = 'Starte neues Spiel'
butstart['fg'] = 'gray40'
butstart.update_idletasks()
wondisplay['fg'] ='salmon2'
print 'Das Matrix-Spiel wurde erfolgreich beendet!'
def RealShuffle(event=None):
#~~ Die Game-Boxen werden wie von Hand durch verschieben gemischt.
# Auf diese Art wird verhindert, dass eine unlösbare Konstellation
# der Game-Boxen entstehen kann
# Die Mischtiefe wird über die Konstante SHUFFLE_DEPTH bestimmt.
global starttime,runflag,movecount,shuffleflag,SHUFFLE_DEPTH,shufftimecnt,TimerObj
global startflag
#~~ Verhindert das klebenbleiben der Startschaltfläche
butstart.update_idletasks()
butstart['text'] = 'Moment ich mische!'
butstart['fg'] = 'red'
#butstart['state'] = DISABLED
wondisplay['fg'] ='gray'
runflag = 0
startflag = 0
shuffleflag = 1
timervalue['text'] = '0'
movevalue['text'] = '0'
root.update_idletasks()
for iteration in xrange(SHUFFLE_DEPTH):
Shuffle()
shuffleflag = 0
runflag = 1
movecount = 0
movevalue['text'] = str(movecount)
butstart['state'] = NORMAL
butstart['text'] = 'Spiel ist bereit!'
butstart['fg'] = 'darkgreen'
butstart.update_idletasks()
def Shuffle():
#~~ Mischprozess
global gridwidth
enclosed = ()
liste = []
neighbours = []
emptygridbox = FindEmptyGridBox()
x11,y11,x22,y22 = platform.bbox(emptygridbox)
enclosed += platform.find_enclosed(x11-gridwidth,y11,x22,y22)
enclosed += platform.find_enclosed(x11,y11-gridwidth,x22,y22)
enclosed += platform.find_enclosed(x11,y11,x22+gridwidth,y22)
enclosed += platform.find_enclosed(x11,y11,x22,y22+gridwidth)
liste = list(enclosed)
liste.sort()
for item in liste:
#~~ Sucht die benachbarten Game-Boxen
# um die leere Gridbox
if item == emptygridbox:
#~~ Objek ist die leere Grid-Box
continue
if item <= gridboxes:
#~~ Objektnummer ist keine Grid-Box
continue
if item >= (2*gridboxes):
#~~ Objektnummer ist keine Grid-Box
continue
neighbours.append(item)
#~~ Mische die gefundenen benachbarten Game-Boxen
shuffle(neighbours)
#~~ Verschiebe eine Game-Box
MoveBox(gamebox=neighbours[0])
#**********************************************
#* Matrix-Game Startup
#**********************************************
if __name__ == "__main__":
root = Tk()
gridsperrow = 5 # Anzahl Spiel-Felder auf einer Reihe min.3 max.8
gridwidth = 80 # Seitenlänge eines Matrix-Feldes (nur gerade Zahlen!)
reptime = 100 # Aktualisierung der Zeitmessung (ms)
SHUFFLE_DEPTH = 800 # Anzahl Iterationen zum durchmischen der Game-Boxen
COLOR_GAMEBOX = 'steelblue3'
COLOR_MAINFRM = 'gray'
COLOR_GAMEFRM = 'darkgreen'
FONT_GAMEBOX = ('Utopia', 30, 'bold')
FONT_VALUE = ('Helvetica', 15, 'normal')
sequence = []
xptr = 0
yptr = 0
movecount = 0
startflag = 0
runflag = 0
shuffleflag = 0
starttime = time()
startflag = 0
#~~ Begrenzt Matrixgrösse
if gridsperrow > 8:
gridsperrow = 8
if gridsperrow < 3:
gridsperrow = 3
gridboxes = gridsperrow * gridsperrow
gameboxwidth = gridwidth-2
root.title('Matrix-Spiel ' + str(gridsperrow) +'x' + str(gridsperrow))
#~~ Liste für Game-Boxen Ziffern#
for number in xrange(1,gridboxes):
sequence.append(number)
#~~ Anzeigerahmen
gameframe = Frame(root,
relief = 'raised',
bd = 6,
bg = COLOR_MAINFRM,
# highlightbackground ='black',
highlightthickness = 1,
)
gameframe.pack(fill=BOTH,expand=YES)
#~~ Rahmen für Daten-Ausgabe
timerframe = Frame(gameframe,
bg = gameframe['bg'],
bd = 2,
)
timerframe.pack(side=TOP,fill=X,padx=5,pady=5)
#~~ Label für die Zeitmessung
timerdisplay = Label(timerframe,
text = 'Zeitmessung (sek): ',
width = 17,
bg = 'gray80',
fg = 'gray40',
font = FONT_VALUE,
anchor = E,
)
timerdisplay.grid(row=0,column=0,pady=4)
#~~ Ausgabe der Zeitmessung
timervalue = Label(timerframe,
text = '0',
width = 8,
bg = 'gray35',
fg = 'white',
font = FONT_VALUE,
)
timervalue.grid(row=0,column=1,pady=4)
#~~ Label für die Anzahl Bewegungen
movedisplay = Label(timerframe,
text ='Bewegungen: ',
width = 17,
bg = 'gray80',
fg = 'gray40',
font = FONT_VALUE,
anchor = E,
)
movedisplay.grid(row=1,column=0,pady=4)
#~~ Ausgabe der Bewegungen
movevalue = Label(timerframe,
text = '0',
width = 8,
bg = 'gray35',
fg = 'white',
font = FONT_VALUE,
)
movevalue.grid(row=1,column=1,pady=4)
#~~ Anzeige für OK
wondisplay = Label(timerframe,
text = 'OK !',
width = 4,
bg = 'gray',
fg = 'salmon2',
font = FONT_GAMEBOX,
anchor = CENTER,
)
wondisplay.grid(row=0,rowspan=2,column=2,sticky='we',padx=10)
#~~ Slogan
sloglabel = Label(gameframe,
bg=gameframe['bg'],
fg='darkgreen',
text='Matrix-Game 1.05\n(powered by Python & Tkinter)',
width=20,
pady=2,
)
sloglabel.pack(side=TOP,fill=X,pady=5)
#~~ Canvas für die Aufnahme der Game-Boxen
platform = Canvas(gameframe,
bg=COLOR_GAMEFRM,
relief='groove',
bd=8,
highlightthickness=0,
)
platform.pack(padx=20,pady=5)
platform['width'] = gridwidth * gridsperrow + 3
platform['height'] = gridwidth * gridsperrow + 3
#~~ Rahmen für Schaltflächen
buttonframe = Frame(gameframe,
bg=gameframe['bg']
)
buttonframe.pack(side=BOTTOM,fill=X,padx=5,pady=8)
butstart = Button(buttonframe,
bg='gray85',
fg='gray40',
text='Starte neues Spiel',
command=RealShuffle,
font=FONT_VALUE,
highlightthickness=0,
width = 20,
cursor = 'hand1',
)
butstart.grid(row=0, column=0, padx=10)
butend = Button(buttonframe,
bg='gray85',
fg='gray40',
text='Beenden',
command=root.quit,
font=FONT_VALUE,
highlightthickness=0,
width = 10,
cursor = 'hand1',
)
butend.grid(row=0, column=1, padx=10)
root.update_idletasks()
#~~ Zentriert das Root-Fenster
width,height,left,top = tuple(map(int,root.winfo_geometry().replace("x","+").split("+")))
xpos = (root.winfo_screenwidth()-width)/2
ypos = (root.winfo_screenheight()-height)/2
root.wm_geometry("+%d+%d" % (xpos,ypos))
root.update_idletasks()
#~~ Erzeuge die fixen Grid-Boxen
gridtab = gridsperrow-1
for index in xrange(gridboxes):
x1 = xptr+10
y1 = yptr+10
gridbox = platform.create_rectangle(x1,
y1,
x1+gameboxwidth,
y1+gameboxwidth,
fill='gray',
stipple='gray25',
)
if index == gridtab:
gridtab += gridsperrow
xptr = 0
yptr += gridwidth
else:
xptr += gridwidth
#~~ Erzeugt die beweglichen Game-Boxen
# Eine Box weniger als die maximale Anzahl Grid-Boxen
for boxobj in platform.find_all():
x1,y1,x2,y2 = platform.bbox(boxobj)
gamebox = platform.create_rectangle(x1+1,
y1+1,
x1+1+gameboxwidth,
y1+1+gameboxwidth,
fill=COLOR_GAMEBOX,
)
platform.tag_bind(gamebox,"<Button-1>",lambda e,obj=gamebox:MoveBox(e,obj))
platform.tag_bind(gamebox,"<Enter>" ,ChangeBoxEnter)
platform.tag_bind(gamebox,"<Leave>" ,ChangeBoxLeave)
if boxobj == gridboxes-1:
break
#~~ Nummeriert die Game-Boxen
for gridobj in xrange(1,gridboxes):
x1,y1,x2,y2 = platform.bbox(gridobj)
numberobj = platform.create_text(x1+(gridwidth/2),
y1+(gridwidth/2),
text=str(gridobj),
font=FONT_GAMEBOX,
fill='white',
)
platform.tag_bind(numberobj,"<Button-1>",lambda e,obj=numberobj-(gridboxes-1):MoveBox(e,obj))
platform.tag_bind(numberobj,"<Enter>" ,ChangeBoxEnter)
platform.tag_bind(numberobj,"<Leave>" ,ChangeBoxLeave)
GameTimer()
root = mainloop()