Chess final: king and rook vs king in python

I've got some issues with this simple chess code in python. It is part of a weekly assignment; this is what I got so far:

from math import sqrt
from random import randint,shuffle,seed
def rand_pos():
    return [randint(0,7),randint(0,7)]

#first, classes defining the kings and the rook; 
#their only attribute is a randomly generated position on the chessboard. 
#Each of them has its special print method that will be used in the Chessboard (Scacchiera) class.
class W_king:
    def __init__(self,coord=rand_pos()):
        self.coord=coord
        self.x=coord[1]
        self.y=coord[0]
    def __repr__(self):
        return "R"
class B_king:
    def __init__(self,coord=rand_pos()):
        self.coord=coord
        self.x=coord[1]
        self.y=coord[0]
    def __repr__(self):
        return "r"
class Rook:
    def __init__(self,coord=rand_pos()):
        self.coord=coord
        self.x=coord[1]
        self.y=coord[0]
    def __repr__(self):
        return "T"

#the following will be used to calculate the distance between the kings and between a king and the rook; 
#I'll use it in the while statements later in the Scacchiera class to check if the kings are generated too near or stuff
def distance(n1,n2):
    return sqrt(sum((n1.coord[i]-n2.coord[i])**2 for i in [0,1]))

class Scacchiera:
    def __init__(self,w_king=W_king(),b_king=B_king(),rook=Rook(),boxes=[[" " for y in range(8)] for x in range(8)]):
        self.w_king=w_king
        self.b_king=b_king
        self.rook=rook
        self.boxes=boxes
        #here it is: while the two kings are generated too near, 
        #get the black king new coordinates
        while distance(self.b_king,self.w_king)<2:
            self.b_king.coord=[randint(0,7),randint(0,7)]
        #...and, while the white king (or the black king) and the rook have the same coordinates 
        #or the black king is in the rook's sight, 
        #get a new pair of coordinates for the rook:
        while self.w_king.coord==self.rook.coord or self.b_king.coord==self.rook.coord or self.rook.x==self.b_king.x or self.rook.y==self.b_king.y:
            self.rook.coord=[randint(0,7),randint(0,7)]
        print distance(self.b_king,self.w_king) #to check, just for me
        #the function conv switches to the chessboard's coordinates e.g. e4, h5, etc
        print conv(self.w_king.coord),conv(self.b_king.coord),conv(self.rook.coord)
    def __repr__(self):
        #self.boxes is an array of blank spaces " ",
        #and in the right place the kings and the rook are placed
        scacchiera=self.boxes[:]
        scacchiera[self.w_king.x][self.w_king.y]=self.w_king
        scacchiera[self.b_king.x][self.b_king.y]=self.b_king
        scacchiera[self.rook.x][self.rook.y]=self.rook
        return "n".join([str(8-i)+" "+" ".join(str(scacchiera[i][j]) for j in range(8)) for i in range(8)])+"n  "+" ".join([chr(97+k) for k in range(8)])
    def check(self,king):
        #no need for this for now
        return self.rook.x==king.x or self.rook.y==king.y
    def black_legal_moves(self,mossa):
        future_king=B_king([self.b_king.y+mossa[0],self.b_king.x+mossa[1]])
        if distance(self.w_king,future_king)<2 or self.check(future_king):
            return False
        else:
            return True

    def new_mossa_random(self):
        #this method chooses randomly a new position for the black king from the list of adjacent cells 
        #and tests if it's legal with the method above. If it's not, it deletes it from the list and re-tries 
        moves_list=[[self.b_king.y+hor,self.b_king.x+ver] for ver in [-1,0,1] for hor in [-1,0,1] if not hor==ver==0]
        shuffle(moves_list)
        move=moves_list[0]
        #while it's not legal or the coordinates are out of the board:
        while not self.black_legal_moves(move) or not 0<=move[0]<=7 or not 0<=move[1]<=7:
            del moves_list[0]
            if not moves_list:
                return None
            move=moves_list[0]
        return move
def conv(coord):
    return [chr(coord[0]+97),8-coord[1]]

#you just need to run it:
seed()
scacchiera=Scacchiera()
print scacchiera
print conv(scacchiera.new_mossa_random())

The issues are two:

  • My code, though incomplete, seems correct to me in the chessboard generation section. Nonetheless, often (nearly three times out of ten) the kings are next to each other or the rook and a king are placed one over the other, or the random move for the black king isn't even near of his box.
  • Very often, the code keeps running and won't print any chessboard; it seems like it sticks on the two while s at the beginning of Scacchiera.
  • NB : F5-ing the script on your PC will print, in the following order:

  • The distance between the two kings,

  • The coordinates on the chessboard of: the white king, the black king, and then the rook

  • The chessboard with the pieces on the board

  • The coordinates of a new random move for the black king.

  • Let me know if I should add some other info.


    In case of collision, you're changing the coord member on the pieces. But the positions are also stored in x and y , which are not updated.

    I'd suggest that you keep only x and y or only coord in your classes. if you want to get fancy, you could keep coord and make x and y into properties by using @property .


    Your problems most likely stem from an incorrect use of default parameters.

    Short answer, do this:

    def __init__(self, coord=None):
        coord = coord or rand_pos()
    

    Explanation: Common gotcha with Python default args


    Thank you for your help! Finally I removed the classes for the kings and the rook; they were pointless, all I needed was just a dictionary, just like in the code here.

    Here is the solution I went through

    from random import randint,shuffle,choice
    
    
    def rand_pos():
        return [randint(0,7),randint(0,7)]
    
    def dist(n1,n2):
        return (sum([(n1[i]-n2[i])**2 for i in [0,1]]))**(0.5)
    def invconv(coord):
        return [ord(coord[0])-97,8-coord[1]]
    #the core of the game is here; Scacchiera means Checkboard, and it basically generates coordinates
    #for the kings and the rook while they are in illegal positions.
    #then there's a bunch of methods to determine wether a move is legal or not
    #and, just for black, a random move is chosen.
    #finally, all the stuff is gathered in the Partita (=Game) function.
    class Scacchiera:
    def __init__(self,w_king=rand_pos(),b_king=rand_pos(),rook=rand_pos()):
        self.w_king=w_king
        self.b_king=b_king
        self.rook=rook
            while dist(self.b_king,self.w_king)<=1.5:
                self.b_king=rand_pos()
            while self.w_king==self.rook or self.b_king==self.rook or self.rook[0]==self.b_king[0] or self.rook[1]==self.b_king[1]:
                self.rook=rand_pos()
            self.pezzi={"R":self.w_king,"r":self.b_king,"T":self.rook}
            self.mosse=[self.pezzi[item] for item in ["r","R","T"]]
        def __repr__(self):
            griglia=[["." for j in range(8)] for i in range(8)]
            for item in self.pezzi:
                griglia[self.pezzi[item][0]][self.pezzi[item][1]]=item
            return "n".join([str(8-j)+" "+" ".join(str(griglia[i][j]) for i in range(8)) for j in range(8)])+"n  "+" ".join([chr(97+k) for k in range(8)])
    
        def move(self,pezzo,end):
            if not end:
                return
            end=[end[0]-self.pezzi[pezzo][0],end[1]-self.pezzi[pezzo][1]]
            self.pezzi[pezzo][0]+=end[0]
            self.pezzi[pezzo][1]+=end[1]
            if self.pezzi["r"]==self.pezzi["T"]:
                del self.pezzi["T"]
            self.mosse.append(self.pezzi.values())
            return
        def check(self):
            return self.pezzi["T"][0]==self.pezzi["r"][0] or self.pezzi["T"][1]==self.pezzi["r"][1]
    
        def black_legal_move(self,end):
            kings_dist=dist(self.pezzi["R"],end)
            rook_king_dist=dist(self.pezzi["T"],self.pezzi["R"])
            if  kings_dist<=1.5:
                return False
            elif self.pezzi["T"]==end and rook_king_dist>1.5:
                return True
            elif self.pezzi["T"][0]==end[0] or self.pezzi["T"][1]==end[1] or end[0] not in range(8) or end[1] not in range(8):
                return False
            return True
    
        def mosse_legali_b(self):
            moves_list=[[self.pezzi["r"][0]+hor,self.pezzi["r"][1]+ver] for ver in [-1,0,1] for hor in [-1,0,1] if not hor==ver==0]
            shuffle(moves_list)
            elle=[]
            for i in range(len(moves_list)):
                if self.black_legal_move(moves_list[i]):
                    elle.append(moves_list[i])
            if not elle:
                return None
            return elle
    
        def mossa_random_black(self):
            print "Tocca al nero.n"
            end=choice(self.mosse_legali_b())
            if not end:
                return None
            self.move("r",end)
            print self
            return
    
        def scacco_matto(self):
            return self.check() and self.mosse_legali_b()==None
        def stallo(self):
            return self.mosse_legali_b()==None
        def ripetizione(self):
            return 3 in [self.mosse.count(item) for item in self.mosse]
    
        def white_king_lmove(self,beg,end):
            return dist(beg,end)<=1.5 and dist(self.pezzi["r"],end)>1.5 and beg!=end
        def white_rook_lmove(self,beg,end):
            return (beg[0]==end[0] or beg[1]==end[1]) and beg!=end
        def white_legal_move(self,beg,end):
            if self.pezzi["R"]==beg:
                return self.white_king_lmove(beg,end)
            else:
                return self.white_rook_lmove(beg,end)
    
        def mossa_white(self):
            print "n**Tocca al bianco**"
            mossa=raw_input("Inserisci la prossima mossa:n")
            beg=invconv([mossa[0],int(mossa[1])])
            end=invconv([mossa[2],int(mossa[3])])
            if not self.white_legal_move(beg,end):
                print "nMossa non valida."
                return self.mossa_white()
            if self.pezzi["R"]==beg:
                pezzo="R"
            elif self.pezzi["T"]==beg:
                pezzo="T"
            self.move(pezzo,end)
            if self.check():
                print "Scacco!n",self
            else:
                print self      
            return 
    
    链接地址: http://www.djcxy.com/p/84670.html

    上一篇: 国际象棋验证希望移动输入

    下一篇: 国际象棋决赛:国王和白嘴鸦vs国王在蟒蛇