added files

This commit is contained in:
locker98 2024-10-07 19:32:29 -04:00
parent c69f4e2713
commit 50b61cd32b
9 changed files with 322 additions and 0 deletions

5
Readme.md Normal file
View File

@ -0,0 +1,5 @@
# Pygame Checkers
This is a Checkers game programmed in python using the pygame library. This program will be perfect for training a deeplearning ai on how to play checkers.
# Credits
This code is based on the code from https://github.com/Btsan/CheckersBot and the video explaining how it works https://www.youtube.com/playlist?list=PLzMcBGfZo4-lkJr3sqpikNyVzbNZLRiT3 . Check out his code and videos.

0
__init__.py Normal file
View File

BIN
assets/crown.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

0
checkers/__init__.py Normal file
View File

150
checkers/board.py Normal file
View File

@ -0,0 +1,150 @@
import pygame
from .constants import BLACK, ROWS, RED, SQUARE_SIZE, COLS, WHITE
from .piece import Piece
class Board:
def __init__(self):
self.board = []
self.red_left = self.white_left = 12
self.red_kings = self.white_kings = 0
self.create_board()
def draw_squares(self, win):
win.fill(BLACK)
for row in range(ROWS):
for col in range(row % 2, COLS, 2):
pygame.draw.rect(win, RED, (row*SQUARE_SIZE, col *SQUARE_SIZE, SQUARE_SIZE, SQUARE_SIZE))
def move(self, piece, row, col):
self.board[piece.row][piece.col], self.board[row][col] = self.board[row][col], self.board[piece.row][piece.col]
piece.move(row, col)
if row == ROWS - 1 or row == 0:
piece.make_king()
if piece.color == WHITE:
self.white_kings += 1
else:
self.red_kings += 1
def get_piece(self, row, col):
return self.board[row][col]
def create_board(self):
for row in range(ROWS):
self.board.append([])
for col in range(COLS):
if col % 2 == ((row + 1) % 2):
if row < 3:
self.board[row].append(Piece(row, col, WHITE))
elif row > 4:
self.board[row].append(Piece(row, col, RED))
else:
self.board[row].append(0)
else:
self.board[row].append(0)
def draw(self, win):
self.draw_squares(win)
for row in range(ROWS):
for col in range(COLS):
piece = self.board[row][col]
if piece != 0:
piece.draw(win)
def remove(self, pieces):
for piece in pieces:
self.board[piece.row][piece.col] = 0
if piece != 0:
if piece.color == RED:
self.red_left -= 1
else:
self.white_left -= 1
def winner(self):
if self.red_left <= 0:
return WHITE
elif self.white_left <= 0:
return RED
return None
def get_valid_moves(self, piece):
moves = {}
left = piece.col - 1
right = piece.col + 1
row = piece.row
if piece.color == RED or piece.king:
moves.update(self._traverse_left(row -1, max(row-3, -1), -1, piece.color, left))
moves.update(self._traverse_right(row -1, max(row-3, -1), -1, piece.color, right))
if piece.color == WHITE or piece.king:
moves.update(self._traverse_left(row +1, min(row+3, ROWS), 1, piece.color, left))
moves.update(self._traverse_right(row +1, min(row+3, ROWS), 1, piece.color, right))
return moves
def _traverse_left(self, start, stop, step, color, left, skipped=[]):
moves = {}
last = []
for r in range(start, stop, step):
if left < 0:
break
current = self.board[r][left]
if current == 0:
if skipped and not last:
break
elif skipped:
moves[(r, left)] = last + skipped
else:
moves[(r, left)] = last
if last:
if step == -1:
row = max(r-3, 0)
else:
row = min(r+3, ROWS)
moves.update(self._traverse_left(r+step, row, step, color, left-1,skipped=last))
moves.update(self._traverse_right(r+step, row, step, color, left+1,skipped=last))
break
elif current.color == color:
break
else:
last = [current]
left -= 1
return moves
def _traverse_right(self, start, stop, step, color, right, skipped=[]):
moves = {}
last = []
for r in range(start, stop, step):
if right >= COLS:
break
current = self.board[r][right]
if current == 0:
if skipped and not last:
break
elif skipped:
moves[(r,right)] = last + skipped
else:
moves[(r, right)] = last
if last:
if step == -1:
row = max(r-3, 0)
else:
row = min(r+3, ROWS)
moves.update(self._traverse_left(r+step, row, step, color, right-1,skipped=last))
moves.update(self._traverse_right(r+step, row, step, color, right+1,skipped=last))
break
elif current.color == color:
break
else:
last = [current]
right += 1
return moves

14
checkers/constants.py Normal file
View File

@ -0,0 +1,14 @@
import pygame
WIDTH, HEIGHT = 800, 800
ROWS, COLS = 8, 8
SQUARE_SIZE = WIDTH//COLS
# rgb
RED = (255, 0, 0)
WHITE = (255, 255, 255)
BLACK = (0, 0, 0)
BLUE = (0, 0, 255)
GREY = (128,128,128)
CROWN = pygame.transform.scale(pygame.image.load('assets/crown.png'), (44, 25))

73
checkers/game.py Normal file
View File

@ -0,0 +1,73 @@
import pygame
from .constants import RED, WHITE, BLUE, SQUARE_SIZE
from checkers.board import Board
class Game:
def __init__(self, win):
self._init()
self.win = win
def _init(self):
self.selected = None
self.board = Board()
self.turn = RED
self.valid_moves = {}
self.row = -1
self.col = -1
def update(self):
self.board.draw(self.win)
self.draw_valid_moves(self.row, self.col)
pygame.display.update()
def winner(self):
return self.board.winner()
def reset(self):
self._init()
def select(self, row, col):
if self.selected:
result = self._move(row, col)
if not result:
self.selected = None
self.select(row, col)
piece = self.board.get_piece(row, col)
if piece != 0 and piece.color == self.turn:
self.selected = piece
self.valid_moves = self.board.get_valid_moves(piece)
self.row = row
self.col = col
return True
self.row = -1
self.col = -1
return False
def _move(self, row, col):
row = row
col = col
piece = self.board.get_piece(row, col)
if self.selected and piece == 0 and (row, col) in self.valid_moves:
self.board.move(self.selected, row, col)
skipped = self.valid_moves[(row, col)]
if skipped:
self.board.remove(skipped)
self.change_turn()
else:
return False
return True
def draw_valid_moves(self, row, col):
pygame.draw.circle(self.win, BLUE, (col * SQUARE_SIZE + SQUARE_SIZE//2, row * SQUARE_SIZE + SQUARE_SIZE//2), 15)
def change_turn(self):
self.valid_moves = {}
if self.turn == RED:
self.turn = WHITE
else:
self.turn = RED

39
checkers/piece.py Normal file
View File

@ -0,0 +1,39 @@
from .constants import RED, WHITE, SQUARE_SIZE, GREY, CROWN
import pygame
class Piece:
PADDING = 15
OUTLINE = 2
def __init__(self, row, col, color):
self.row = row
self.col = col
self.color = color
self.king = False
self.x = 0
self.y = 0
self.calc_pos()
def calc_pos(self):
self.x = SQUARE_SIZE * self.col + SQUARE_SIZE // 2
self.y = SQUARE_SIZE * self.row + SQUARE_SIZE // 2
def make_king(self):
self.king = True
def draw(self, win):
radius = SQUARE_SIZE//2 - self.PADDING
pygame.draw.circle(win, GREY, (self.x, self.y), radius + self.OUTLINE)
pygame.draw.circle(win, self.color, (self.x, self.y), radius)
if self.king:
win.blit(CROWN, (self.x - CROWN.get_width()//2, self.y - CROWN.get_height()//2))
def move(self, row, col):
self.row = row
self.col = col
self.calc_pos()
def __repr__(self):
return f'Piece({self.x}, {self.y}, {self.color})'

41
main.py Normal file
View File

@ -0,0 +1,41 @@
import pygame
from checkers.constants import WIDTH, HEIGHT, SQUARE_SIZE, RED, BLUE
from checkers.game import Game
FPS = 60
WIN = pygame.display.set_mode((WIDTH, HEIGHT))
pygame.display.set_caption('Checkers')
def get_row_col_from_mouse(pos):
x, y = pos
row = y // SQUARE_SIZE
col = x // SQUARE_SIZE
return row, col
def main():
run = True
clock = pygame.time.Clock()
game = Game(WIN)
while run:
clock.tick(FPS)
if game.winner() != None:
print(game.winner())
run = False
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
if event.type == pygame.MOUSEBUTTONDOWN:
pos = pygame.mouse.get_pos()
row, col = get_row_col_from_mouse(pos)
game.select(row, col)
game.update()
pygame.quit()
main()