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:
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国王在蟒蛇