Code for How to Make a Checkers Game with Pygame in Python Tutorial


View on Github

Game.py

class Game:	def __init__(self):	self.winner = None	# checks if both colors still has a piece	def check_piece(self, board):	red_piece = 0	black_piece = 0	for y in range(board.board_size):	for x in range(board.board_size):	tile = board.get_tile_from_pos((x, y))	if tile.occupying_piece != None:	if tile.occupying_piece.color == "red":	red_piece += 1	else:	black_piece += 1	return red_piece, black_piece	def is_game_over(self, board):	red_piece, black_piece = self.check_piece(board)	if red_piece == 0 or black_piece == 0:	self.winner = "red" if red_piece > black_piece else "black"	return True	else:	return False	def check_jump(self, board):	piece = None	for tile in board.tile_list:	if tile.occupying_piece != None:	piece = tile.occupying_piece	if len(piece.valid_jumps()) != 0 and board.turn == piece.color:	board.is_jump = True	break	else:	board.is_jump = False	if board.is_jump:	board.selected_piece = piece	board.handle_click(piece.pos)	return board.is_jump	def message(self):	print(f"{self.winner} Wins!!")

Main.py

import pygame from Board import Board from Game import Game pygame.init() class Checkers:	def __init__(self, screen):	self.screen = screen	self.running = True	self.FPS = pygame.time.Clock()	def _draw(self, board):	board.draw(self.screen)	pygame.display.update()	def main(self, window_width, window_height):	board_size = 8	tile_width, tile_height = window_width // board_size, window_height // board_size	board = Board(tile_width, tile_height, board_size)	game = Game()	while self.running:	game.check_jump(board)	for self.event in pygame.event.get():	if self.event.type == pygame.QUIT:	self.running = False	if not game.is_game_over(board):	if self.event.type == pygame.MOUSEBUTTONDOWN:	board.handle_click(self.event.pos)	else:	game.message()	self.running = False	self._draw(board)	self.FPS.tick(60) if __name__ == "__main__":	window_size = (640, 640)	screen = pygame.display.set_mode(window_size)	pygame.display.set_caption("Checkers")	checkers = Checkers(screen)	checkers.main(window_size[0], window_size[1])

Pawn.py

import pygame from Piece import Piece class Pawn(Piece):	def __init__(self, x, y, color, board):	super().__init__(x, y, color, board)	img_path = f'images/{color}-pawn.png'	self.img = pygame.image.load(img_path)	self.img = pygame.transform.scale(self.img, (board.tile_width, board.tile_height))	self.notation = 'p'	def _possible_moves(self):	# (x, y) move for left and right	if self.color == "red":	possible_moves = ((-1, -1), (+1, -1))	else:	possible_moves = ((-1, +1), (+1, +1))	return possible_moves	def valid_moves(self):	tile_moves = []	moves = self._possible_moves()	for move in moves:	tile_pos = (self.x + move[0], self.y + move[-1])	if tile_pos[0] < 0 or tile_pos[0] > 7 or tile_pos[-1] < 0 or tile_pos[-1] > 7:	pass	else:	tile = self.board.get_tile_from_pos(tile_pos)	if tile.occupying_piece == None:	tile_moves.append(tile)	return tile_moves	def valid_jumps(self):	tile_jumps = []	moves = self._possible_moves()	for move in moves:	tile_pos = (self.x + move[0], self.y + move[-1])	if tile_pos[0] < 0 or tile_pos[0] > 7 or tile_pos[-1] < 0 or tile_pos[-1] > 7:	pass	else:	tile = self.board.get_tile_from_pos(tile_pos)	if self.board.turn == self.color:	if tile.occupying_piece != None and tile.occupying_piece.color != self.color:	next_pos = (tile_pos[0] + move[0], tile_pos[-1] + move[-1])	next_tile = self.board.get_tile_from_pos(next_pos)	if next_pos[0] < 0 or next_pos[0] > 7 or next_pos[-1] < 0 or next_pos[-1] > 7:	pass	else:	if next_tile.occupying_piece == None:	tile_jumps.append((next_tile, tile))	return tile_jumps

King.py

import pygame from Piece import Piece class King(Piece):	def __init__(self, x, y, color, board):	super().__init__(x, y, color, board)	img_path = f'images/{color}-king.png'	self.img = pygame.image.load(img_path)	self.img = pygame.transform.scale(self.img, (board.tile_width, board.tile_height))	self.notation = 'k'	def _possible_moves(self):	possible_moves = ((-1, -1), (+1, -1), (-1, +1), (+1, +1))	return possible_moves	def valid_moves(self):	tile_moves = []	moves = self._possible_moves()	for move in moves:	tile_pos = (self.x + move[0], self.y + move[-1])	if tile_pos[0] < 0 or tile_pos[0] > 7 or tile_pos[-1] < 0 or tile_pos[-1] > 7:	pass	else:	tile = self.board.get_tile_from_pos(tile_pos)	if tile.occupying_piece == None:	tile_moves.append(tile)	return tile_moves	def valid_jumps(self):	tile_jumps = []	moves = self._possible_moves()	for move in moves:	tile_pos = (self.x + move[0], self.y + move[-1])	if tile_pos[0] < 0 or tile_pos[0] > 7 or tile_pos[-1] < 0 or tile_pos[-1] > 7:	pass	else:	tile = self.board.get_tile_from_pos(tile_pos)	if self.board.turn == self.color:	if tile.occupying_piece != None and tile.occupying_piece.color != self.color:	next_pos = (tile_pos[0] + move[0], tile_pos[-1] + move[-1])	next_tile = self.board.get_tile_from_pos(next_pos)	if next_pos[0] < 0 or next_pos[0] > 7 or next_pos[-1] < 0 or next_pos[-1] > 7:	pass	else:	if next_tile.occupying_piece == None:	tile_jumps.append((next_tile, tile))	return tile_jumps

Piece.py

import pygame class Piece:	def __init__(self, x, y, color, board):	self.x = x	self.y = y	self.pos = (x, y)	self.board = board	self.color = color	def _move(self, tile):	for i in self.board.tile_list:	i.highlight = False	if tile in self.valid_moves() and not self.board.is_jump:	prev_tile = self.board.get_tile_from_pos(self.pos)	self.pos, self.x, self.y = tile.pos, tile.x, tile.y	prev_tile.occupying_piece = None	tile.occupying_piece = self	self.board.selected_piece = None	self.has_moved = True	# Pawn promotion	if self.notation == 'p':	if self.y == 0 or self.y == 7:	from King import King	tile.occupying_piece = King(	self.x, self.y, self.color, self.board	)	return True	elif self.board.is_jump:	for move in self.valid_jumps():	if tile in move:	prev_tile = self.board.get_tile_from_pos(self.pos)	jumped_piece = move[-1]	self.pos, self.x, self.y = tile.pos, tile.x, tile.y	prev_tile.occupying_piece = None	jumped_piece.occupying_piece = None	tile.occupying_piece = self	self.board.selected_piece = None	self.has_moved = True	# Pawn promotion	if self.notation == 'p':	if self.y == 0 or self.y == 7:	from King import King	tile.occupying_piece = King(	self.x, self.y, self.color, self.board	)	return True	else:	self.board.selected_piece = None	return False

Board.py

import pygame from Tile import Tile from Pawn import Pawn class Board:	def __init__(self,tile_width, tile_height, board_size):	self.tile_width = tile_width	self.tile_height = tile_height	self.board_size = board_size	self.selected_piece = None	self.turn = "black"	self.is_jump = False	self.config = [	['', 'bp', '', 'bp', '', 'bp', '', 'bp'],	['bp', '', 'bp', '', 'bp', '', 'bp', ''],	['', 'bp', '', 'bp', '', 'bp', '', 'bp'],	['', '', '', '', '', '', '', ''],	['', '', '', '', '', '', '', ''],	['rp', '', 'rp', '', 'rp', '', 'rp', ''],	['', 'rp', '', 'rp', '', 'rp', '', 'rp'],	['rp', '', 'rp', '', 'rp', '', 'rp', '']	]	self.tile_list = self._generate_tiles()	self._setup()	def _generate_tiles(self):	output = []	for y in range(self.board_size):	for x in range(self.board_size):	output.append(	Tile(x, y, self.tile_width, self.tile_height)	)	return output	def get_tile_from_pos(self, pos):	for tile in self.tile_list:	if (tile.x, tile.y) == (pos[0], pos[1]):	return tile	def _setup(self):	for y_ind, row in enumerate(self.config):	for x_ind, x in enumerate(row):	tile = self.get_tile_from_pos((x_ind, y_ind))	if x != '':	if x[-1] == 'p':	color = 'red' if x[0] == 'r' else 'black'	tile.occupying_piece = Pawn(x_ind, y_ind, color, self)	def handle_click(self, pos):	x, y = pos[0], pos[-1]	if x >= self.board_size or y >= self.board_size:	x = x // self.tile_width	y = y // self.tile_height	clicked_tile = self.get_tile_from_pos((x, y))	if self.selected_piece is None:	if clicked_tile.occupying_piece is not None:	if clicked_tile.occupying_piece.color == self.turn:	self.selected_piece = clicked_tile.occupying_piece	elif self.selected_piece._move(clicked_tile):	if not self.is_jump:	self.turn = 'red' if self.turn == 'black' else 'black'	else:	if len(clicked_tile.occupying_piece.valid_jumps()) == 0:	self.turn = 'red' if self.turn == 'black' else 'black'	elif clicked_tile.occupying_piece is not None:	if clicked_tile.occupying_piece.color == self.turn:	self.selected_piece = clicked_tile.occupying_piece	def draw(self, display):	if self.selected_piece is not None:	self.get_tile_from_pos(self.selected_piece.pos).highlight = True	if not self.is_jump:	for tile in self.selected_piece.valid_moves():	tile.highlight = True	else:	for tile in self.selected_piece.valid_jumps():	tile[0].highlight = True	for tile in self.tile_list:	tile.draw(display)

Tile.py

import pygame class Tile:	def __init__(self, x, y, tile_width, tile_height):	self.x = x	self.y = y	self.pos = (x, y)	self.tile_width = tile_width	self.tile_height = tile_height	self.abs_x = x * tile_width	self.abs_y = y * tile_height	self.abs_pos = (self.abs_x, self.abs_y)	self.color = 'light' if (x + y) % 2 == 0 else 'dark'	self.draw_color = (220, 189, 194) if self.color == 'light' else (53, 53, 53)	self.highlight_color = (100, 249, 83) if self.color == 'light' else (0, 228, 10)	self.occupying_piece = None	self.coord = self.get_coord()	self.highlight = False	self.rect = pygame.Rect(	self.abs_x,	self.abs_y,	self.tile_width,	self.tile_height	)	def get_coord(self):	columns = 'abcdefgh'	return columns[self.x] + str(self.y + 1)	def draw(self, display):	if self.highlight:	pygame.draw.rect(display, self.highlight_color, self.rect)	else:	pygame.draw.rect(display, self.draw_color, self.rect)	if self.occupying_piece != None:	centering_rect = self.occupying_piece.img.get_rect()	centering_rect.center = self.rect.center	display.blit(self.occupying_piece.img, centering_rect.topleft)