Schach in Python - kleines Problem

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
raiminator
User
Beiträge: 31
Registriert: Dienstag 1. Mai 2012, 08:06

Moin,
Python programmiere ich noch nicht so lange, habe aber schon erfahrungen mit Java und PHP. (also auch OOP)
Jetzt programmiere ich gerade ein Schach-Spiel.
Es besitzt die Klassen "gameField" (komplettes Spielfeld), das als Attribut eine zweidimensionale liste mit dann insgesamt 64 "Feldern" besitzt.
Hier mal der Code (nur teilweise):

Code: Alles auswählen

class gameField:
    Main = [[]]
    isReady = False
    def __init__(self):
        F1 = self.Main
        I = 0
        while I < 8:
            I1 = chr(I+65)
            J = 0
            self.Main.append([])
            while J < 8:
                color = (I + J - 1)/2 == (I + J - 1.0)/2
                f = field(color, I, J)
                self.Main[I].append(f)
                # hier wird das richtige ausgegeben, aber anscheinend nicht richtig in der Liste gespeichert...
                print 'Das Feld',I1,J,'hat die Farbe',f.color,'und die Figur',f.figureColor,'/',f.figure
                J += 1
            I += 1
        print 'Spielfeld wurde generiert'
        isReady = True
    
    def getField(self, i, j):
        if not(self.isReady):
            f = field(False, 0, 0)
            f.deleteFigure()
            return f
        return self.Main[i][j]
    
    def getFigure(self, i, j):
        f = self.getField(i, j)
        return f.getFigure()
    
    def setFigure(self, i, j, color, figure):
        self.getField(i, j).setFigure(color, figure)
        
    def deleteFigure(self, i, j):
        self.getField(i, j).deleteFigure()

class field:
    I = 0
    J = 0
    color = False
    figureColor = False
    figure = 0
    def __init__(self, inpColor, I, J):
        color = inpColor
        # Feld aufbauen
        ###############
        
            # Weiß
        if (J == 1):
            self.figure = 1; self.figureColor = True; return
        if (I == 1 or I == 6) and J == 0:
            self.figure = 2; self.figureColor = True; return
        if (I == 2 or I == 5) and J == 0:
            self.figure = 3; self.figureColor = True; return
        if (I == 0 or I == 7) and J == 0:
            self.figure = 4; self.figureColor = True; return
        if I == 3 and J == 0:
            self.figure = 5; self.figureColor = True; return
        if I == 4 and J == 0:
            self.figure = 6; self.figureColor = True; return
        
            # Schwarz
        if (J == 6):
            self.figure = 1; self.figureColor = False; return
        if (I == 1 or I == 6) and J == 7:
            self.figure = 2; self.figureColor = False; return
        if (I == 2 or I == 5) and J == 7:
            self.figure = 3; self.figureColor = False; return
        if (I == 0 or I == 7) and J == 7:
            self.figure = 4; self.figureColor = False; return
        if I == 3 and J == 7:
            self.figure = 5; self.figureColor = False; return
        if I == 4 and J == 7:
            self.figure = 6; self.figureColor = False; return

            # Leer
        self.figure = 0; self.figureColor = False
        
    
    def setFigure(self, inpColor, inpFigureID):
        self.figureColor = inpColor
        self.figure = inpFigureID
    def deleteFigure(self):
        self.figure = 0
        self.figureColor = False
    def getFigure(self):
        return [self.figureColor, self.figure]
    
Der Konstruktor von gameField soll mit der doppelten while-Schleife die Felder automatisch generieren und errechnet die Hintergrundfarbe (schwarz/weiß) anhand der Koordinaten. Wenn ich zum Test im Konstruktor ausgeben lasse Welche Figur nun generiert wurde (im Konstruktor von "field"), wird mir auch das richtige ausgeben, Bsp auf D1 steht die weiße Dame, auf C7 ein schwarzer Bauer. Außerhalb der Klassen wird eine Instanz von gameField erzeugt und in der globalen Variable F gespeichert. Wenn ich aber im Rahmenprogramm auch testen will, ob die Figuren richtig generiert wurden, wird mir immer ausgegeben dass das komplette Feld leer ist.
Rahmenprogramm:

Code: Alles auswählen

# Rahmenprogramm
# Globals
global F
F = gameField()

# Bsp. A1 eingeben, Ausgabe sollte sein:  "Das Feld A1 ( 0 / 0 ) hat die Farbe Weiß und die Figur 4" (0/0 sind koordinaten, 4 steht für Turm
inp = raw_input('Feld testen: ')
X = ord(inp[0])-65
Y = int(inp[1])-1
[col, fig] = F.getFigure(X, Y)

if col:
    color = 'Weiß'
else:
    color = 'Schwarz'
print 'Das Feld',inp,'(',X,'/',Y,'hat die Farbe',color,'und die Figur',fig
# Spielschleife

deets

Oh mann. Da gibt's ne Menge zu zu sagen. Hast du mal vorher ein Python-Tutorial durchgearbeitet?

Zuerstmal das wichtigste:

- in Python werden Instanzattribute so wie dein "Main" nicht auf Klassen-Ebene deklariert - das waere so, als ob du in Java "static" davorschreiben wuerdest. Stattdessen im __init__ ein "self.Main = []" machen. So wie du das machst ist das ganz bestimmt nicht, was du willst - denn dann haetten alle gameFields ein gemeinsames Brett..

- Python arbeitet viel mit Iteration. Und selbst in PHP und Java benutzt man "for", nicht while. Deine Schleife zum Aufbau des Feldes koennte man zb so schreiben:

Code: Alles auswählen

for j in xrange(1, 9):
     for i, i_name in enumerate("ABCDEFGH", 1):
- du solltest dir mal PEP8 anschaun was Namenskonventionen und andere Stilfragen angeht: http://www.python.org/dev/peps/pep-0008/

- diesen ganzen "isReady"-Kram kannst du dir sparen - du baust doch alles schon im __init__ auf, wenn dein Code also auf die Instanz zugreift, ist alles schon fertig. Und daran liegt auch dein Problem: du setzt "isReady" auf True - nicht "self.isReady".
raiminator
User
Beiträge: 31
Registriert: Dienstag 1. Mai 2012, 08:06

danke erstmal!
Das mit dem isReady hab ich eig. auch nur zum Test gemacht, war mir klar dass das unnötig ist.
Muss ich die attribute garnicht deklarieren sondern im Konstruktor einfach nur den Wert zuweisen?
Und was genau bedeutet for i, i_name in enumerate("ABCDEFGH", 1)? bis jetzt kannte ich in python nur for-Schleifen wie z.B. for i in range(10)..

EDIT: habe jetzt das mit den Attributen geändert und es klappt, danke!
deets

@raiminator

google ist dein freund - schau halt mal in der python-doku nach, was enumerate macht.
Benutzeravatar
wuf
User
Beiträge: 1529
Registriert: Sonntag 8. Juni 2003, 09:50

Hi raiminator

Willkommen in unserem Forum. Hier noch etwas basierend auf 'deets' Grundidee:

Code: Alles auswählen

#!/usr/bin/python
# -*- coding: utf-8 -*-

class Field(object):
    
    def __init__(self):
        
        self.figure = None
        
class ChessPlaneModel(object):

    xcoords = "abcdefgh"
    ycoords = "87654321"
    
    def __init__(self):
        
        self.fields = list()
        
        for y, ycoord in enumerate(self.ycoords, 1):
            self.row_list = list()
            for x, xcoord in enumerate(self.xcoords, 1):
                self.row_list.append(Field())
            self.fields.append(self.row_list)

    def __getitem__(self, coords):
        """Liest Spielfeld-Attribute"""
        x, y = self.get_xy(coords)
                
        return self.fields[y][x]

    def __setitem__(self, coords, value):
        """Setzt Spielfeld-Attribute"""
        x, y = self.get_xy(coords)
        self.fields[y][x] = value

    def get_xy(self, coords):
        xcoord, ycoord = coords
        x = self.xcoords.index(xcoord)
        y = self.ycoords.index(ycoord)
        
        return x, y
        
#--- MODUL-TEST ---------------------------------------------------------------#
if __name__ == "__main__":

    chess_model = ChessPlaneModel()
    
    # Setze die Dame auf Feld a8
    chess_model['a8'].figure = "Queen"
    # Was ist auf Feld a8
    print chess_model['a8'].figure
    # Was ist auf Feld b8
    print chess_model['b8'].figure
Da gibt es natürlich noch etliche andere Ansätze. Noch viel Spass beim Studium der Python Tutorials.

Gruß wuf :wink:
Take it easy Mates!
Antworten