国际象棋决赛:Python王与车王对决

2024-09-30 01:25:37 发布

您现在位置: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上。在

NB:F5在电脑上打印脚本时,将按以下顺序打印:

  1. 两个国王之间的距离,

  2. 棋盘上的坐标是:白王,黑王,然后是车

  3. 棋盘上有棋子的棋盘

  4. 一个新的随机移动的坐标。

如果我需要补充一些其他信息,请告诉我。在


Tags: orandtheinselfforreturndef
3条回答

您的问题很可能源于对默认参数的错误使用。在

简而言之,请这样做:

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

说明:Common gotcha with Python default args

如果发生冲突,您将更改片段上的coord成员。但是这些位置也存储在x和{}中,它们不会被更新。在

我建议你在你的类中只保留xy,或者只保留{}。如果你想变得花哨,你可以保留coord并把x和y变成{a1}。在

谢谢你的帮助!最后我删除了kings和rook的类;它们毫无意义,我只需要一本字典,就像这里的代码一样。在

这是我的解决方案

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 

相关问题 更多 >

    热门问题