Python chess project. Any GUI coding recommendations?

beavoid
beavoid used Ask the Experts™
on
Hi
I found this page of 60x60 chess images to use in my uncontestedly invulnerable ;) Python AI development

here

Instead of  trial and error myself, is there an example page with code for a Python Frame of image load, drag and drop? w listeners? like in chess apps? I have pygame ready.
I can see the functions on pygame.org, but I'd love to see it mostly in one screen.

Thanks
Comment
Watch Question

Do more with

Expert Office
EXPERT OFFICE® is a registered trademark of EXPERTS EXCHANGE®
Well nobody replied so far:

Well I never used pygame so I can't help a lot.

First imagine how you want to implement your user interface.
There's many options. Some more elegant, some less elegant, some easier to implement some more difficult.

I suggest here a rather simple one without animation. Lateron you can add animation.

For example you decide, that in order to move a chess piece you:
- have to move your mouse on the chess piece, that you want to move
- you press the button down
    - if you clicked on a field without one of your chess pieces, then nothing will happen)
- then you move the mouse to the target position
- and click again
    - if the target position is empty but invalid,then nothing will happen and you wait for a click on a
      correct target field
    - if you click again on the same position as your start position, then you will 'cancel' the move
    - if the target position is valid, you move the piece to this position.


I'll send you a very simple code snippet lateron.
Ok here my very simple working pygame example.
Please note, that I never used pygame before, so perhaps some things are less elegant than they could be.

Note as well, that Game.run is getting quite long.
I wrote everything in one method, but you should refactor this. Especially if you want to add animation lateron.

First part is just some imports and constant declarations:
#!/usr/bin/env python


import pygame


FIELD_WIDTH = 60 # 60 pixel per field
BOARD_WIDTH = FIELD_WIDTH * 8  # width of board

BOARD_F  = "board.png"
FIGURE_F = "Chess_%s%st60.png"

Open in new window



You need a file containing the image of the board "board.png" and one file for each different figure.
for this demo you just need the files "Chess_kdt60.png"  and "Chess_klt60.png"
I adapted to the naming style of the link you referenced.

Next part declares a class which is a stub for your gaming engine with its chessboard.
class Board:
    """ a fake class for a chess board """
    def __init__(self):
        self.fields = [  [" "]* 8 for i in range(8)]
        self.fields[7][5] = "k"
        self.fields[5][4] = "K"

    def figure_on_field(self, field):
        """ fake functionidication whether field contains a figure, that
            I'm allowed to move
        """
        x, y = field
        return self.fields[y][x] != " "

    def is_valid_move(self, field_from, field_to):
        """ fake function to see if moveis valid
            - field_from must contain a figure
            - field_to must be a neighbour field
        """
        x1, y1 = field_from
        x2, y2 = field_to
        if self.fields[y1][x1] == " ":
            return False  # not empty 
        if field_from == field_to:
            return False
        delta_x = abs(x2-x1)
        if delta_x > 1:
            return False
        delta_y = abs(y2-y1)
        if delta_y > 1:
            return False
        return True

    def move(self, field_from, field_to):
        fields = self.fields
        x1, y1 = field_from
        x2, y2 = field_to
        to_move = fields[y1][x1]
        fields[y1][x1] = " "
        fields[y2][x2] = to_move
    def print(self):
        """ Just for debugging 
            It allows you to see whether
            your non graphical game stays in sync with 
            the bygame board
        """
        print("+-" * 8 + "+")
        for row in self.fields:
            print("|" + "|".join(row) + "|")
            print("+-" * 8 + "+")

Open in new window


I implemented functions to:
- move a figure from one place to another
- to tell me whether the I can move a figure on a certain position on the board
- to tell me whether I can move a figure from one position to another
- a function for debugging, that prints the chess board on the console.

Next part implements the pygame code:
If you press 'q' you willquit the game.
with clicking you can select and move a figure:


class Game:
    def __init__(self):
        """ load images for chess board and chess figures """
        self.board = Board()
        self.background = pygame.image.load(BOARD_F)
        self.figures = {}
        self.screen = None
        self.clock = None

        fields = self.board.fields
        for x in range(8):
            for y in range(8):
                fieldval = fields[y][x]
                if fieldval != " ":
                    color = "l" if fieldval.lower() == fieldval else "d"
                    print("loading %s for %d,%d" % (fieldval, x, y))
                    figure = pygame.image.load(FIGURE_F % (fieldval.lower(), color))
                    self.figures[(x,y)] = figure

    def init_pygame(self):
        """ just initialize the screen and draw it a first time """
        print("init game")
        pygame.init()
        pygame.display.set_caption("My Game")
        pygame.mouse.set_visible(1)
        self.clock = pygame.time.Clock()
        pygame.key.set_repeat(1, 30)
        # load figures (I just load one here)
        self.screen = screen = pygame.display.set_mode((BOARD_WIDTH, BOARD_WIDTH))
        print("created screen", screen)
        self.running = True
        self.draw()

    def draw(self):
        self.screen.blit(self.background, (0, 0))
        for position, figure in self.figures.items():
            x, y = position
            x *= FIELD_WIDTH
            y *= FIELD_WIDTH
            self.screen.blit(figure, (x, y))

        pygame.display.flip()
        self.board.print() # just for debugging

    def run(self):
        self.init_pygame()
        clock = self.clock
        changes = False
        field_from = None 
        board = self.board
        figures = self.figures
        while self.running:
            if changes:
                print("redraw")
                self.draw()
                changes = False
            clock.tick(30)
            for event in pygame.event.get():
                if event.type == pygame.MOUSEBUTTONDOWN:
                    if event.button == 1:
                        x, y = event.pos
                        x //= FIELD_WIDTH
                        y //= FIELD_WIDTH 
                        print("X", x, "Y", y)
                        field = (x, y)
                        if field_from is None:
                            # We just clicked on what we want to move
                            if board.figure_on_field(field):
                                print("clicked on a figure", field)
                                field_from = field
                            else:
                                print("clicked on empty field")
                        elif field == field_from:
                            # we clicked again on the same field.
                            # we cancelled
                            print("unselected figure", field_from) 
                            field_from = None
                        else:
                            if board.is_valid_move(field_from, field):
                                print("move figure from %s to %s" % (field_from, field))
                                board.move(field_from, field)
                                figure = figures.pop(field_from)
                                figures[field] = figure
                                print(sorted(figures.keys()))
                                self.draw()
                                field_from = None
                                
                elif event.type == pygame.KEYDOWN:
                    if event.unicode == 'q':
                        self.running = False

Open in new window



The last parts just starts the game:
if __name__ == "__main__":
    game = Game()
    game.run()

Open in new window

beavoidSelf Employed

Author

Commented:
Thanks!

Do more with

Expert Office
Submit tech questions to Ask the Experts™ at any time to receive solutions, advice, and new ideas from leading industry professionals.

Start 7-Day Free Trial