القائمة الرئيسية

الصفحات

كيفية برمجة لعبة الشطرنج باستخدام Python و Pygame

نشر Pygame، تحويل Python إلى ملف تنفيذي، PyInstaller، ذكاء اصطناعي للشطرنج، AI بسيط، اختيار عشوائي للحركات، تقييم اللوحة (أساسي)، Pygame events، معالجة الأحداث، تفاعل المستخدم، تحديث حالة اللعبة، منطق اللعبة، قواعد الشطرنج، حركة القطع، التحقق من الصحة، أكل القطع، الترقية، التبييت، كش ملك، إزاحة الملك، Pygame display، Pygame surface، تحميل الصور، رسم الأشكال، الخطوط، النصوص، Python، pip، Pygame installation، برمجة ألعاب، تطوير ألعاب Python، Pygame، لعبة الشطرنج، واجهة مستخدم رسومية (GUI)، منطق الشطرنج، الذكاء الاصطناعي للشطرنج (AI)، نشر تطبيقات Pygame، PyInstaller، How-to-code-chess-game-in-Python-Pygame، How to code a chess game using Python and Pygame، برمجة لعبة الشطرنج: pygame-chess، برمجة لعبة الشطرنج باستخدام Python و Pygame، التطبيق عن برمجة لعبة الشطرنج: pygame-chess، برمجة لعبة الشطرنج التفاعلية باستخدام Python و Pygame: دليل شامل، كيفية برمجة لعبة الشطرنج باستخدام Python و Pygame، PyInstaller، برمجة ألعاب، تطوير ألعاب Python، Pygame، لعبة الشطرنج، Pygame installation،




كيفية برمجة لعبة الشطرنج باستخدام Python و Pygame



يُعد تطوير لعبة الشطرنج باستخدام مكتبة Pygame في Python
 مشروعًا تعليميًا وترفيهيًا ممتازًا. يتيح لك هذا المشروع فهم أساسيات تطوير الألعاب، 
وتصميم واجهات المستخدم الرسومية، وتنفيذ منطق اللعبة المعقد، وحتى دمج ذكاء اصطناعي بسيط. 
يقدم هذا المقال دليلًا شاملاً بالخطوات لكل مرحلة، بدءًا من
 تصميم واجهة المستخدم وصولًا إلى نشر تطبيقك القابل للتوزيع.


خطوات  برمجة لعبة الشطرنج باستخدام Python و Pygame


هل تحلم بإنشاء لعبتك التفاعلية الخاصة؟ يعتبر مشروع برمجة لعبة 
الشطرنج باستخدام لغة Python ومكتبة Pygame نقطة انطلاق مثالية لتحقيق هذا الحلم. 
ستغوص في أعماق أساسيات تطوير الألعاب، بدءًا من تصميم واجهة مستخدم جذابة 
ووصولًا إلى تنفيذ قواعد اللعبة المعقدة، وحتى إضافة لمسة من الذكاء الاصطناعي لتحدي اللاعب.
هذا الدليل المفصل سيرافقك خطوة بخطوة في رحلة بناء لعبة الشطرنج الخاصة بك
 لكل مرحلة ليتحول شغفك بالبرمجة إلى لعبة شطرنج كاملة وقابلة للعب.
الخطوات الأساسية لتطوير لعبة الشطرنج:
1. تهيئة بيئة التطوير وتثبيت Pygame:

# التأكد من تثبيت Python
python --version
# تثبيت pip (إذا لم يكن مثبتًا)
# (عادةً ما يأتي مع Python)
# إنشاء بيئة افتراضية (اختياري ولكن موصى به)
python -m venv chess_env
source chess_env/bin/activate  # لنظام Linux/macOS
# chess_env\Scripts\activate  # لنظام Windows
# تثبيت Pygame
pip install pygame
pip show pygame
--

2. تصميم واجهة المستخدم الرسومية (GUI):

* (ملف chess_gui.py):




import pygame

# تهيئة Pygame
pygame.init()

# أبعاد النافذة ولوحة الشطرنج
SQUARE_SIZE = 80
BOARD_SIZE = 8 * SQUARE_SIZE
WIDTH, HEIGHT = BOARD_SIZE, BOARD_SIZE
SCREEN = pygame.display.set_mode((WIDTH, HEIGHT))
pygame.display.set_caption("Pygame Chess")

# ألوان مربعات الشطرنج
LIGHT_SQUARE = (240, 217, 181)
DARK_SQUARE = (181, 136, 99)

# تحميل صور القطع (يجب أن تكون الصور في نفس مجلد المشروع أو تحديد المسار)
pieces_images = {
    'wP': pygame.image.load('assets/wp.png'), 'wR': pygame.image.load('assets/wr.png'),
    'wN': pygame.image.load('assets/wn.png'), 'wB': pygame.image.load('assets/wb.png'),
    'wQ': pygame.image.load('assets/wq.png'), 'wK': pygame.image.load('assets/wk.png'),
    'bP': pygame.image.load('assets/bp.png'), 'bR': pygame.image.load('assets/br.png'),
    'bN': pygame.image.load('assets/bn.png'), 'bB': pygame.image.load('assets/bb.png'),
    'bQ': pygame.image.load('assets/bq.png'), 'bK': pygame.image.load('assets/bk.png')
}

# تغيير حجم الصور لتناسب مربعات الشطرنج
for key in pieces_images:
    pieces_images[key] = pygame.transform.scale(pieces_images[key], (SQUARE_SIZE, SQUARE_SIZE))

def draw_board():
    for row in range(8):
        for col in range(8):
            color = LIGHT_SQUARE if (row + col) % 2 == 0 else DARK_SQUARE
            pygame.draw.rect(SCREEN, color, (col * SQUARE_SIZE, row * SQUARE_SIZE, SQUARE_SIZE, SQUARE_SIZE))

def draw_pieces(board):
    for row in range(8):
        for col in range(8):
            piece = board[row][col]
            if piece:
                SCREEN.blit(pieces_images[piece], (col * SQUARE_SIZE, row * SQUARE_SIZE))

def main_loop():
    # تمثيل مبدئي للوحة الشطرنج (سيتم استبداله بمنطق اللعبة)
    board = [
        ['bR', 'bN', 'bB', 'bQ', 'bK', 'bB', 'bN', 'bR'],
        ['bP', 'bP', 'bP', 'bP', 'bP', 'bP', 'bP', 'bP'],
        ['', '', '', '', '', '', '', ''],
        ['', '', '', '', '', '', '', ''],
        ['', '', '', '', '', '', '', ''],
        ['', '', '', '', '', '', '', ''],
        ['wP', 'wP', 'wP', 'wP', 'wP', 'wP', 'wP', 'wP'],
        ['wR', 'wN', 'wB', 'wQ', 'wK', 'wB', 'wN', 'wR']
    ]

    running = True
    while running:
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                running = False

        draw_board()
        draw_pieces(board)
        pygame.display.flip()

    pygame.quit()

if __name__ == '__main__':
    main_loop()


--

* شرح الكود:

- pygame.init(): تهيئة جميع وحدات Pygame المستوردة.
- pygame.display.set_mode(): إنشاء نافذة العرض.
- pygame.display.set_caption(): تعيين عنوان النافذة.
- LIGHT_SQUARE, DARK_SQUARE: تعريف ألوان مربعات الشطرنج.
- pieces_images: قاموس لتخزين صور قطع الشطرنج المحملة وتغيير حجمها. 
تأكد من وجود مجلد assets في نفس المجلد مع صور القطع بتسميات مثل
 wp.png (بيدق أبيض)، br.png (رخ أسود)، إلخ.
- draw_board(): دالة لرسم لوحة الشطرنج عن طريق رسم مستطيلات ملونة بالتناوب.
- draw_pieces(): دالة لرسم قطع الشطرنج على اللوحة بناءً على تمثيل المصفوفة للوحة.
- main_loop(): الحلقة الرئيسية للعبة التي تعالج الأحداث وترسم الإطار الحالي.
- board: تمثيل مبدئي للوحة الشطرنج كمصفوفة ثنائية الأبعاد.



3. تنفيذ منطق الشطرنج:

* (ملف chess_logic.py):




Python

class ChessLogic:
    def __init__(self):
        self.board = [
            ['bR', 'bN', 'bB', 'bQ', 'bK', 'bB', 'bN', 'bR'],
            ['bP', 'bP', 'bP', 'bP', 'bP', 'bP', 'bP', 'bP'],
            ['', '', '', '', '', '', '', ''],
            ['', '', '', '', '', '', '', ''],
            ['', '', '', '', '', '', '', ''],
            ['', '', '', '', '', '', '', ''],
            ['wP', 'wP', 'wP', 'wP', 'wP', 'wP', 'wP', 'wP'],
            ['wR', 'wN', 'wB', 'wQ', 'wK', 'wB', 'wN', 'wR']
        ]
        self.current_player = 'w'
        self.selected_piece = None
        self.possible_moves = []

    def get_piece(self, row, col):
        return self.board[row][col]

    def is_valid_move(self, start_pos, end_pos):
        # سيتم تنفيذ منطق التحقق من صحة الحركة هنا لكل قطعة
        # يتضمن التحقق من حدود اللوحة، وقواعد حركة القطعة، وعدم وجود قطع صديقة في المربع الهدف
        start_row, start_col = start_pos
        end_row, end_col = end_pos
        piece = self.board[start_row][start_col]
        if not piece or piece[0] != self.current_player:
            return False

        # منطق حركة البيدق
        if piece[1] == 'P':
            direction = -1 if self.current_player == 'w' else 1
            start_row_pawn = 6 if self.current_player == 'w' else 1
            # حركة للأمام بمربع واحد
            if end_col == start_col and self.board[end_row][end_col] == '':
                if end_row == start_row + direction or (start_row == start_row_pawn and end_row == start_row + 2 * direction and self.board[start_row + direction][start_col] == ''):
                    return True
            # أكل قطريًا
            elif abs(end_col - start_col) == 1 and end_row == start_row + direction and self.board[end_row][end_col] != '' and self.board[end_row][end_col][0] != self.current_player:
                return True
        # ... تنفيذ منطق حركة القطع الأخرى (الرخ، الحصان، الفيل، الملكة، الملك) ...
        elif piece[1] == 'R':
            if start_row == end_row:  # حركة أفقية
                step = 1 if end_col > start_col else -1
                for c in range(start_col + step, end_col, step):
                    if self.board[start_row][c] != '':
                        return False
                return self.board[end_row][end_col] == '' or self.board[end_row][end_col][0] != self.current_player
            elif start_col == end_col:  # حركة رأسية
                step = 1 if end_row > start_row else -1
                for r in range(start_row + step, end_row, step):
                    if self.board[r][start_col] != '':
                        return False
                return self.board[end_row][end_col] == '' or self.board[end_row][end_col][0] != self.current_player
        elif piece[1] == 'N':
            possible_knight_moves = [(start_row - 2, start_col - 1), (start_row - 2, start_col + 1),
                                    (start_row - 1, start_col - 2), (start_row - 1, start_col + 2),
                                    (start_row + 1, start_col - 2), (start_row + 1, start_col + 2),
                                    (start_row + 2, start_col - 1), (start_row + 2, start_col + 1)]
            return (end_row, end_col) in possible_knight_moves and \
                   (self.board[end_row][end_col] == '' or self.board[end_row][end_col][0] != self.current_player)
        elif piece[1] == 'B':
            row_diff = abs(end_row - start_row)
            col_diff = abs(end_col - start_col)
            if row_diff != col_diff:
                return False
            row_step = 1 if end_row > start_row else -1
            col_step = 1 if end_col > start_col else -1
            r, c = start_row + row_step, start_col + col_step
            while r != end_row:
                if self.board[r][c] != '':
                    return False
                r += row_step
                c += col_step








 return self.board[end_row][end_col] == '' or self.board[end_row][end_col][0] != self.current_player
        elif piece[1] == 'Q':
            # يمكن للملكة التحرك كالرخ أو الفيل
            rook_move = (start_row == end_row or start_col == end_col)
            bishop_move = (abs(end_row - start_row) == abs(end_col - start_col))
            if rook_move:
                # ... (نسخ ولصق منطق حركة الرخ مع تعديلات طفيفة) ...
                if start_row == end_row:
                    step = 1 if end_col > start_col else -1
                    for c in range(start_col + step, end_col, step):
                        if self.board[start_row][c] != '':
                            return False
                    return self.board[end_row][end_col] == '' or self.board[end_row][end_col][0] != self.current_player
                elif start_col == end_col:
                    step = 1 if end_row > start_row else -1
                    for r in range(start_row + step, end_row, step):
                        if self.board[r][start_col] != '':
                            return False
                    return self.board[end_row][end_col] == '' or self.board[end_row][end_col][0] != self.current_player
            elif bishop_move:
                # ... (نسخ ولصق منطق حركة الفيل) ...
                row_diff = abs(end_row - start_row)
                col_diff = abs(end_col - start_col)
                if row_diff != col_diff:
                    return False
                row_step = 1 if end_row > start_row else -1
                col_step = 1 if end_col > start_col else -1
                r, c = start_row + row_step, start_col + col_step
                while r != end_row:
                    if self.board[r][c] != '':
                        return False
                    r += row_step
                    c += col_step
                return self.board[end_row][end_col] == '' or self.board[end_row][end_col][0] != self.current_player
        elif piece[1] == 'K':
            possible_king_moves = [(start_row - 1, start_col - 1), (start_row - 1, start_col),
                                   (start_row - 1, start_col + 1), (start_row, start_col - 1),
                                   (start_row, start_col + 1), (start_row + 1, start_col - 1),
                                   (start_row + 1, start_col), (start_row + 1, start_col + 1)]
            return (end_row, end_col) in possible_king_moves and \
                   (self.board[end_row][end_col] == '' or self.board[end_row][end_col][0] != self.current_player)

        return False

    def move_piece(self, start_pos, end_pos):
        if self.is_valid_move(start_pos, end_pos):
            start_row, start_col = start_pos
            end_row, end_col = end_pos
            self.board[end_row][end_col] = self.board[start_row][start_col]
            self.board[start_row][start_col] = ''
            self.current_player = 'b' if self.current_player == 'w' else 'w'
            return True
        return False

    def get_possible_moves(self, row, col):
        piece = self.board[row][col]
        if not piece or piece[0] != self.current_player:
            return []
        possible_moves = []
        # ... تنفيذ منطق توليد الحركات الممكنة لكل قطعة ...
        return possible_moves

    # ... تنفيذ وظائف إضافية للتحقق من كش ملك، إزاحة الملك، الترقية، التبييت ...


           
--

* شرح الكود:

- ChessLogic class: يحتوي على منطق اللعبة وحالة اللوحة واللاعب الحالي.
- __init__(): تهيئة اللوحة واللاعب الحالي.
- get_piece(): إرجاع القطعة الموجودة في مربع معين.
- is_valid_move(): (يجب إكمال هذا الجزء بشكل كامل) يتحقق من صحة الحركة
 بناءً على قواعد الشطرنج لكل قطعة. هذا هو الجزء الأكثر تعقيدًا ويتطلب
 تنفيذ دقيق لقواعد حركة كل قطعة (البيدق، الرخ، الحصان، الفيل، الملكة، الملك)
 بالإضافة إلى التحقق من عدم وجود قطع صديقة في المربع الهدف.
- move_piece(): ينفذ الحركة إذا كانت صالحة ويغير دور اللاعب الحالي.
- get_possible_moves(): (يجب إكمال هذا الجزء) يولد قائمة بالحركات الممكنة لقطعة في مربع معين.
- وظائف إضافية مطلوبة: يجب تنفيذ وظائف للتحقق من حالات كش ملك 
(is_king_in_check())، وإزاحة الملك (is_checkmate(), is_stalemate())، والترقية (handle_pawn_promotion())، والتبييت (can_castle(), perform_castling()).

4. ربط واجهة المستخدم بمنطق اللعبة:

* (تعديل chess_gui.py):





Python

import pygame
from chess_logic import ChessLogic

# ... (بقية تهيئة Pygame والمتغيرات من ملف chess_gui.py) ...

def main_loop():
    game = ChessLogic()
    selected_square = None
    running = True
    while running:
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                running = False
            if event.type == pygame.MOUSEBUTTONDOWN:
                col = event.pos[0] // SQUARE_SIZE
                row = event.pos[1] // SQUARE_SIZE
                clicked_square = (row, col)

                if selected_square:
                    if clicked_square in game.get_possible_moves(*selected_square):
                        game.move_piece(selected_square, clicked_square)
                    selected_square = None
                    game.possible_moves = []
                else:
                    piece = game.get_piece(*clicked_square)
                    if piece and piece[0] == game.current_player:
                        selected_square = clicked_square
                        game.possible_moves = game.get_possible_moves(*selected_square)

        draw_board()
        # تظليل المربع المحدد والحركات الممكنة
        if selected_square:
            pygame.draw.rect(SCREEN, (0, 255, 0, 128), (selected_square[1] * SQUARE_SIZE, selected_square[0] * SQUARE_SIZE, SQUARE_SIZE, SQUARE_SIZE))
            for move in game.possible_moves:
                pygame.draw.rect(SCREEN, (0, 0, 255, 128), (move[1] * SQUARE_SIZE, move[0] * SQUARE_SIZE, SQUARE_SIZE, SQUARE_SIZE))
        draw_pieces(game.board)
        pygame.display.flip()

    pygame.quit()

if __name__ == '__main__':
    main_loop()


--

* شرح الكود:

- استيراد ChessLogic من chess_logic.py.
- إنشاء مثيل (game) من ChessLogic.
- selected_square: لتتبع المربع الذي تم النقر عليه لتحديد قطعة.
- عند النقر بالماوس (pygame.MOUSEBUTTONDOWN):
يتم حساب الصف والعمود للمربع الذي تم النقر عليه.


- إذا كان هناك مربع محدد بالفعل (selected_square):
يتم التحقق مما إذا كانت النقرة الحالية تمثل حركة ممكنة للقطعة المحددة.
إذا كانت الحركة صالحة، يتم تنفيذها باستخدام game.move_piece().
يتم إعادة تعيين selected_square و game.possible_moves.
- إذا لم يكن هناك مربع محدد:
يتم الحصول على القطعة الموجودة في المربع الذي تم النقر عليه.
إذا كانت القطعة مملوكة للاعب الحالي، يتم تحديد المربع ويتم الحصول على الحركات الممكنة باستخدام game.get_possible_moves().
يتم رسم تظليل للمربع المحدد والحركات الممكنة على الشاشة.

5. دمج الذكاء الاصطناعي البسيط (اختياري):


* (تعديل chess_logic.py وإضافة AI logic):




Python

import random

class ChessLogic:
    # ... (بقية كود ChessLogic) ...
    def get_opponent_move_random(self):
        possible_opponent_moves = []
        for r in range(8):
            for c in range(8):
                piece = self.board[r][c]
                if piece and piece[0] != self.current_player:
                    moves = self.get_possible_moves(r, c)
                    for move in moves:
                        possible_opponent_moves.append(((r, c), move))
        if possible_opponent_moves:
            return random.choice(possible_opponent_moves)
        return None

    def make_ai_move(self):
        move = self.get_opponent_move_random()
        if move:
            start_pos, end_pos = move
            self.move_piece(start_pos, end_pos)

# تعديل main_loop في chess_gui.py لاستدعاء make_ai_move() بعد حركة اللاعب
def main_loop():
    game = ChessLogic()
    selected_square = None
    running = True
    while running:
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                running = False
            if event.type == pygame.MOUSEBUTTONDOWN:
                # ... (معالجة نقرات اللاعب) ...
                if not selected_square and game.current_player == 'w': # مثال: اللاعب الأبيض
                    piece = game.get_piece(*clicked_square)
                    if piece and piece[0] == game.current_player:
                        selected_square = clicked_square
                        game.possible_moves = game.get_possible_moves(*selected_square)
                elif selected_square:
                    if clicked_square in game.possible_moves:
                        game.move_piece(selected_square, clicked_square)
                        selected_square = None
                        game.possible_moves = []
                        # جعل الكمبيوتر يتحرك بعد حركة اللاعب
                        if game.current_player == 'b': # مثال: الكمبيوتر الأسود
                            pygame.time.delay(500) # تأخير بسيط
                            game.make_ai_move()
                    else:
                        selected_square = None
                        game.possible_moves = []

        draw_board()
        # ... (بقية رسم الواجهة) ...
        pygame.display.flip()

    pygame.quit()


--

* شرح الكود:

- get_opponent_move_random(): دالة بسيطة للذكاء 
الاصطناعي تقوم باختيار حركة عشوائية صالحة للخصم.
- make_ai_move(): تستدعي
 get_opponent_move_random() وتقوم بتنفيذ الحركة.
- يتم تعديل main_loop لاستدعاء 
game.make_ai_move() بعد أن يقوم اللاعب البشري بحركته.

6. نشر التطبيق باستخدام PyInstaller:

* (استخدام سطر الأوامر):

pip install pyinstaller
pyinstaller --onefile chess_gui.py --add-data "assets:assets"
--

* شرح الكود:

- pip install pyinstaller: تثبيت مكتبة PyInstaller.
- pyinstaller --onefile chess_gui.py --add-data "assets:assets":
- --onefile: لإنشاء ملف تنفيذي واحد.
- chess_gui.py: ملف الدخول الرئيسي لتطبيقك.
- --add-data "assets:assets": لتضمين مجلد assets (الذي يحتوي على صور القطع
) داخل الملف التنفيذي. سيتم استخراج المجلد assets إلى مجلد مؤقت 
عند تشغيل التطبيق. يمكنك الوصول إلى مسار المجلد assets باستخدام
 pygame.file.get_config_dir().
- بعد التشغيل: سيتم إنشاء مجلد dist يحتوي على الملف التنفيذي
 (chess_gui أو chess_gui.exe). يمكنك توزيع هذا الملف لتشغيل لعبتك
 على أنظمة أخرى (قد تحتاج إلى اختبار توافقية النظام).

* ملاحظات مهمة:

- إكمال منطق الشطرنج: الجزء الأكثر تحديًا هو تنفيذ وظيفة 
is_valid_move() بشكل كامل ودقيق لجميع قطع الشطرنج، بالإضافة إلى التعامل 
مع الحالات الخاصة مثل الترقية، والتبييت، وكش ملك، وإزاحة الملك.
- الذكاء الاصطناعي المتقدم: لإنشاء ذكاء اصطناعي أقوى، ستحتاج إلى تطبيق
 خوارزميات بحث وتقييم أكثر تعقيدًا (مثل Minimax أو Alpha-Beta Pruning).
- تحسين واجهة المستخدم: يمكنك تحسين واجهة المستخدم بإضافة رسومات متحركة، 
ومؤشرات للحركات الممكنة بشكل أفضل، ومعلومات حول حالة اللعبة (مثل دور اللاعب الحالي).
- التعامل مع الأخطاء: قم بتضمين معالجة للأخطاء المحتملة في تفاعل المستخدم ومنطق اللعبة.

* الخلاصة:

يعد تطوير لعبة الشطرنج باستخدام Pygame مشروعًا مثمرًا يغطي
 جوانب متعددة من تطوير الألعاب. من خلال تصميم واجهة المستخدم، وتنفيذ
 منطق اللعبة، وربط الاثنين معًا، وحتى دمج ذكاء اصطناعي ، يمكنك إنشاء
 لعبة شطرنج تفاعلية كاملة. باستخدام PyInstaller، يمكنك تجميع تطبيقك ليصبح 
قابلاً للتوزيع بسهولة. يتطلب إكمال منطق الشطرنج بشكل صحيح اهتمامًا دقيقًا بقواعد
 اللعبة، ولكن النتيجة النهائية هي تطبيق ممتع وتعليمي. استمر في تطوير وتحسين
 لعبتك بإضافة المزيد من الميزات والذكاء الاصطناعي الأكثر تقدمًا.


جدول المحتويات