首页 > 其他 > 详细

x01.chess: 国际象棋

时间:2020-05-20 16:35:50      阅读:69      评论:0      收藏:0      [点我收藏+]

忽略王车易位,国际象棋实现起来还是比较简单的,按照行棋路线不断进行即可,遇到边界或棋子则停,兵,王,马只走一步,兵有方向,如此而已。

1.效果图 

                                    技术分享图片

2.代码

技术分享图片
import sys, copy, os, configparser
import tkinter as tk 
from tkinter import messagebox

import utils 
from game.chess.core import Board, R 

sys.path.append(utils.R.CurrentDir)

class MainWindow(tk.Tk):
    def __init__(self):
        super().__init__()
        self.title("x01.chess")
        size = (R.CellNumber+0.5)*R.CellSize
        utils.R.win_center(self, w=size, h=size)

        self.background = lightgrey
        self.foreground = black
        self.menu = tk.Menu(self, bg=self.background, fg=self.foreground)
        utils.R.generate_menus(self, [file, help])
        self.configure(menu=self.menu)

        self.board = Board(self)
        self.board.pack(pady=R.CellSize/4)

    def file_start_game(self):
        self.board.pack_forget()
        self.board = Board(self)
        self.board.pack(pady=R.CellSize/4)

    def help_about(self):
        messagebox.showinfo(x01.chess, 国际象棋程序,版权属于x01(黄雄)所有。)

if __name__ == "__main__":
    w = MainWindow()
    w.mainloop()
main.py
技术分享图片
import tkinter as tk 
import utils
import os
from itertools import count 
from tkinter import messagebox

class R:
    ImgDir = os.path.join(utils.R.CurrentDir, rgame\chess\res)
    CellNumber = 8
    CellSize = 64
    Color1 = #e6a803
    Color2 = #8b8350
    Highlight = #2ef70d

    OrthogalPoses = ((-1, 0), (0, 1), (1, 0), (0, -1))
    DiagonalPoses = ((-1, -1), (-1, 1), (1, -1), (1, 1))
    KnightPoses = ((-2, -1), (-2, 1), (-1, -2), (-1, 2),
                    (1, -2), (1, 2), (2, -1), (2, 1))

    Directions = {
        p: ((1,0), (2,0), (1,1), (1,-1)),
        n: KnightPoses,
        b: DiagonalPoses,
        r: OrthogalPoses,
        q: DiagonalPoses + OrthogalPoses,
        k: DiagonalPoses + OrthogalPoses,

        P: ((-1,0), (-2,0), (-1,1), (-1,-1)),
        N: KnightPoses,
        B: DiagonalPoses,
        R: OrthogalPoses,
        Q: DiagonalPoses + OrthogalPoses,
        K: DiagonalPoses + OrthogalPoses
    }

class Board(tk.Frame):
    def __init__(self, master=None):
        super().__init__(master)
        self.master = master 
        self.cell_size = R.CellSize 
        self.offset = R.CellSize // 2
        self.cell_number = R.CellNumber
        self.color1 = R.Color1 
        self.color2 = R.Color2 
        self.highlight = R.Highlight

        self.canvas = tk.Canvas(self, bg="#999" , width=R.CellNumber*R.CellSize, height=R.CellNumber*R.CellSize)
        self.canvas.pack()

        self.piece_images = {
            r: tk.PhotoImage(file=os.path.join(R.ImgDir, rook_white.png)),
            n: tk.PhotoImage(file=os.path.join(R.ImgDir, knight_white.png)),
            b: tk.PhotoImage(file=os.path.join(R.ImgDir, bishop_white.png)),
            q: tk.PhotoImage(file=os.path.join(R.ImgDir, queen_white.png)),
            k: tk.PhotoImage(file=os.path.join(R.ImgDir, king_white.png)),
            p: tk.PhotoImage(file=os.path.join(R.ImgDir, pawn_white.png)),

            R: tk.PhotoImage(file=os.path.join(R.ImgDir, rook_black.png)),
            N: tk.PhotoImage(file=os.path.join(R.ImgDir, knight_black.png)),
            B: tk.PhotoImage(file=os.path.join(R.ImgDir, bishop_black.png)),
            Q: tk.PhotoImage(file=os.path.join(R.ImgDir, queen_black.png)),
            K: tk.PhotoImage(file=os.path.join(R.ImgDir, king_black.png)),
            P: tk.PhotoImage(file=os.path.join(R.ImgDir, pawn_black.png)),
        }
        self.pieces = []
        self.init_pieces()

        self.current_move = (None, None)
        self.chess_core = ChessCore(self.pieces)
        self.is_black = True 

        self.draw_cells()
        self.draw_pieces()
        self.bind_events()

    def init_pieces(self):
        names = rnbqkbnrppppppppPPPPPPPPRNBQKBNR
        for row in range(8):
            for col in range(8):
                if row == 0 or row==1:
                    self.pieces.append(Piece(row,col,names[row*8+col]))
                elif row == 6 or row==7:
                    self.pieces.append(Piece(row,col,names[(row-4)*8+col]))
                else:
                    self.pieces.append(Piece(row,col,.))

    def draw_pieces(self):
        self.canvas.delete(pieces)
        for p in self.pieces:
            if p.name == .: continue
            self.canvas.create_image(p.col*R.CellSize+self.offset, 
                p.row*R.CellSize+self.offset, image=self.piece_images[p.name], tags=(pieces), anchor=c)

    def bind_events(self):
        self.canvas.bind(<Button-1>, self.click)

    def click(self, e=None):
        dead = self.check_dead()
        if dead[0]: 
            messagebox.showinfo(x01.chess, black king is dead!)
            return
        if dead[1]:
            messagebox.showinfo(x01.chess, white king is dead!)
            return

        self.canvas.delete("highlights")
        r,c = e.y // self.cell_size,  e.x // self.cell_size
        piece = self.chess_core.get_piece((r,c))
        moves = self.chess_core.get_moves(self.is_black)
        highlight_moves = [p[1] for p in moves if piece == p[0]]
        for h in highlight_moves:
            self.draw_highlight(h)
            self.draw_pieces()

        if self.current_move[0]  and self.current_move[1] is None:
            self.current_move = (self.current_move[0], piece)
            if self.current_move[0] and self.current_move[1]:
                moves = self.chess_core.get_moves(self.is_black)
                can_moves = [p[1] for p in moves if self.current_move[0] == p[0]]
                if self.current_move[1] in can_moves:
                    if self.move():
                        self.current_move = (None, None)
                        self.is_black = not self.is_black
                        self.p2q()
                        self.draw_pieces()
        self.current_move = (piece, None)

    def check_dead(self):
        blackdead, whitedead = True, True
        for p in self.pieces:
            if k == p.name: whitedead = False
            if K == p.name: blackdead = False
        return (blackdead, whitedead)

    def p2q(self):
        pieces = self.pieces[:]
        for i, p in enumerate(pieces):
            if p.name == p and p.row == 7:
                self.pieces[i].name = q
            elif p.name == P and p.row == 0:
                self.pieces[i].name = Q

    def move(self):
        org, dest = self.current_move
        org_index = self.get_index(org)
        dest_index = self.get_index(dest)
        if org_index is None or dest_index is None: 
            return  False
        self.pieces[dest_index].name = org.name 
        self.pieces[org_index].name = .
        self.draw_pieces()
        return True 

    def get_index(self, piece):
        for i, p in enumerate(self.pieces):
            if p == piece: return i 
        return None 
        
    def draw_cells(self):
        color = self.color2 
        for row in range(self.cell_number):
            color = self.alternate_color(color)
            for col in range(self.cell_number):
                x1,y1 = self.get_xy(row,col) 
                x2,y2 = x1+self.cell_size, y1+self.cell_size
                self.canvas.create_rectangle(x1,y1,x2,y2,fill=color)
                color = self.alternate_color(color)

    def get_xy(self, row, col):
        x = self.cell_size * col 
        y = self.cell_size * row 
        return (x,y)

    def alternate_color(self, color):
        if color == self.color1:
            return self.color2 
        return self.color1 

    def test(self):
        moves = self.chess_core.get_moves(isblack=False)
        for org,dest in moves:
            print(org, dest)

    def draw_highlight(self, piece):
        # self.canvas.delete(‘highlights‘)
        x1,y1 = self.get_xy(piece.row, piece.col)
        x2,y2 = x1+self.cell_size, y1+self.cell_size
        self.canvas.create_rectangle(x1,y1,x2,y2,fill=R.Highlight, tags=highlights)

class Piece:
    def __init__(self, row, col, name):
        self.row = row 
        self.col = col 
        self.name = name

    def __str__(self):
        return (row={},col={},name={}).format(self.row, self.col, self.name)

    def __eq__(self, other):
        return self.row == other.row and self.col == other.col

class ChessCore:
    def __init__(self, pieces):
        self.pieces = pieces[:]
        self.rotates = []

    def get_piece(self, pos):
        for p in self.pieces:
            if pos == (p.row, p.col):
                return p
        return None 
    
    def get_moves(self, isblack=True):
        # 忽略王车易位
        for p in self.pieces:
            if isblack:
                if p.name.islower() or p.name == .: continue
                for d in R.Directions[p.name]:
                    for i in range(1,8):
                        pos = (p.row + d[0]*i, p.col + d[1]*i)
                        dest = self.get_piece(pos)
                        if not self.valid_pos(pos) or dest.name.isupper():  break
                        if p.name == P and d in ((-1,0), (-2,0)) and dest.name != .: break
                        if p.name == P and d == (-2,0) and (p.row != 6 or self.get_piece((p.row-1,p.col)).name != .): break
                        if p.name == P and d in ((-1,1), (-1,-1)) and dest.name == .: break 
                        yield (p, dest)
                        if p.name in PNK or dest.name.islower(): break 
            else:
                if p.name.isupper() or p.name == .: continue
                for d in R.Directions[p.name]:
                    for i in range(1,9): 
                        pos = (p.row + d[0]*i, p.col + d[1]*i)
                        dest = self.get_piece(pos)
                        if not self.valid_pos(pos) or dest.name.islower():  break
                        if p.name == p and d in ((1,0), (2,0)) and dest.name != .: break
                        if p.name == p and d == (2,0) and (p.row != 1 or self.get_piece((p.row+1,p.col)).name != .): break
                        if p.name == p and d in ((1,1), (1,-1)) and dest.name == .: break 
                        yield (p, dest)
                        if p.name in pnk or dest.name.islower(): break 


    def valid_pos(self, pos):
        if 0 <= pos[0] <= 7 and 0 <= pos[1] <= 7: return True
        return False 


if __name__ == "__main__":
    b = Board()
    b.test()
core.py

3.下载

x01.lab/py/game/chess

x01.chess: 国际象棋

原文:https://www.cnblogs.com/china_x01/p/12924022.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!