国际象棋决赛:python 中的国王和车对国王
Chess final: king and rook vs king in python
我在 python 中遇到了这个简单的国际象棋代码的一些问题。这是每周作业的一部分;这是我到目前为止得到的:
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())
问题有两个:
- 我的代码虽然不完整,但在棋盘生成部分对我来说似乎是正确的。尽管如此,通常(十分之三)国王彼此相邻,或者车和国王一个放在另一个之上,或者黑国王的随机移动甚至不靠近他的盒子。
- 很多时候,代码保持 运行 并且不会打印任何棋盘;它似乎粘在 Scacchiera 开头的两个
while
上。
注意: F5-ing PC 上的脚本将按以下顺序打印:
两位天王的距离,
棋盘坐标:白王、黑王、车
棋盘上的棋子
黑王新的随机走法坐标
如果我应该添加一些其他信息,请告诉我。
如果发生碰撞,您将更改棋子上的 coord
成员。但是位置也存储在x
和y
中,没有更新。
我建议您在 类 中仅保留 x
和 y
或仅保留 coord
。如果你想花哨一些,你可以保留 coord
并将 x 和 y 变成 properties by using @property
.
您的问题很可能源于对默认参数的错误使用。
简答,这样做:
def __init__(self, coord=None):
coord = coord or rand_pos()
解释:
感谢您的帮助!最后,我删除了国王和车的 类;它们毫无意义,我只需要一本字典,就像这里的代码一样。
这是我经历过的解决方案
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
我在 python 中遇到了这个简单的国际象棋代码的一些问题。这是每周作业的一部分;这是我到目前为止得到的:
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())
问题有两个:
- 我的代码虽然不完整,但在棋盘生成部分对我来说似乎是正确的。尽管如此,通常(十分之三)国王彼此相邻,或者车和国王一个放在另一个之上,或者黑国王的随机移动甚至不靠近他的盒子。
- 很多时候,代码保持 运行 并且不会打印任何棋盘;它似乎粘在 Scacchiera 开头的两个
while
上。
注意: F5-ing PC 上的脚本将按以下顺序打印:
两位天王的距离,
棋盘坐标:白王、黑王、车
棋盘上的棋子
黑王新的随机走法坐标
如果我应该添加一些其他信息,请告诉我。
如果发生碰撞,您将更改棋子上的 coord
成员。但是位置也存储在x
和y
中,没有更新。
我建议您在 类 中仅保留 x
和 y
或仅保留 coord
。如果你想花哨一些,你可以保留 coord
并将 x 和 y 变成 properties by using @property
.
您的问题很可能源于对默认参数的错误使用。
简答,这样做:
def __init__(self, coord=None):
coord = coord or rand_pos()
解释:
感谢您的帮助!最后,我删除了国王和车的 类;它们毫无意义,我只需要一本字典,就像这里的代码一样。
这是我经历过的解决方案
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