Skip to content

Commit

Permalink
force jumps
Browse files Browse the repository at this point in the history
  • Loading branch information
MihajloMilojevic committed May 21, 2024
1 parent d2c6cfd commit 380f154
Show file tree
Hide file tree
Showing 17 changed files with 282 additions and 19 deletions.
215 changes: 215 additions & 0 deletions Checkers.aip

Large diffs are not rendered by default.

Binary file modified Checkers.msi
Binary file not shown.
9 changes: 7 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,11 @@

## Description

Project for playing checkers. App supports two game modes: Single Player (player vs bot) or two players (player vs player). This project was created as project for algorithms and data structures, subject in II semestar on Faculty of tehnical science in Novi Sad using minimax algorithm with alpha-beta pruning with changing depth.
Project for playing checkers. App supports two game modes: Single Player (player vs bot) or two players (player vs player) and with or without fourcing jumps. This project was created as project for algorithms and data structures, subject in II semestar on Faculty of tehnical science in Novi Sad using minimax algorithm with alpha-beta pruning with changing depth.

## Features

App allows users to player against bot or another player.
App allows users to player against bot or another player with or without forcing jumps.

Game has intutive UI that show user available moves for selected piece by marking places where piece can move with blue dot and marking jumps with green dots. Current player is marked with cyan outline.

Expand Down Expand Up @@ -51,3 +51,8 @@ This project is licensed under the MIT License - see the LICENSE file for detail
<img src="./screenshots/game_over.PNG" alt="game over window">
<caption ><i>Game over window</i></caption>
</figure>

<figure style="display: flex; flex-direction: column; gap: 10px; align-items: center; justify-content: center">
<img src="./screenshots/force_jump.PNG" alt="force jump">
<caption ><i>Forcing jumps</i></caption>
</figure>
Binary file modified assets/checkers.ico
Binary file not shown.
Binary file modified assets/checkers.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
18 changes: 18 additions & 0 deletions assets/design.ui
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,24 @@ border-radus: 15px;
<set>Qt::AlignCenter</set>
</property>
</widget>
<widget class="QCheckBox" name="force_jump_cb">
<property name="geometry">
<rect>
<x>50</x>
<y>300</y>
<width>301</width>
<height>41</height>
</rect>
</property>
<property name="font">
<font>
<pointsize>14</pointsize>
</font>
</property>
<property name="text">
<string>Force Jump?</string>
</property>
</widget>
</widget>
<resources/>
<connections/>
Expand Down
Binary file modified checkers.exe
Binary file not shown.
Binary file added screenshots/force_jump.PNG
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified screenshots/game_over.PNG
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified screenshots/start.PNG
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified src/__pycache__/app.cpython-311.pyc
Binary file not shown.
Binary file modified src/__pycache__/game.cpython-311.pyc
Binary file not shown.
Binary file modified src/__pycache__/get_path.cpython-311.pyc
Binary file not shown.
Binary file modified src/__pycache__/state.cpython-311.pyc
Binary file not shown.
20 changes: 14 additions & 6 deletions src/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,12 @@ def __init__(self) -> None:
self.setVisible(True)

def play(self):
self.setVisible(False)
force = self.force_jump_cb.isChecked()
if self.one_player_rb.isChecked():
State.game = Checkers(Checkers.SINGLE_PLAYER)
State.game = Checkers(Checkers.SINGLE_PLAYER, force)
else:
State.game = Checkers(Checkers.TWO_PLAYERS)
State.game = Checkers(Checkers.TWO_PLAYERS, force)
self.setVisible(False)
State.game.run(self.onEnd, self.onClose)

def onEnd(self, game: Any):
Expand Down Expand Up @@ -58,20 +59,26 @@ def setupUi(self):
self.label.setAlignment(QtCore.Qt.AlignCenter)
self.label.setObjectName("label")
self.one_player_rb = QtWidgets.QRadioButton(self)
self.one_player_rb.setGeometry(QtCore.QRect(50, 250, 200, 50))
self.one_player_rb.setGeometry(QtCore.QRect(50, 220, 200, 50))
font = QtGui.QFont()
font.setPointSize(14)
self.one_player_rb.setFont(font)
self.one_player_rb.setObjectName("one_player_rb")
self.two_players_rb = QtWidgets.QRadioButton(self)
self.two_players_rb.setGeometry(QtCore.QRect(280, 250, 200, 50))
self.two_players_rb.setGeometry(QtCore.QRect(280, 220, 200, 50))
font = QtGui.QFont()
font.setPointSize(14)
self.two_players_rb.setFont(font)
self.two_players_rb.setChecked(True)
self.two_players_rb.setObjectName("two_players_rb")
self.play_btn = QtWidgets.QPushButton(self)
self.play_btn.setGeometry(QtCore.QRect(160, 350, 171, 61))
self.force_jump_cb = QtWidgets.QCheckBox(self)
self.force_jump_cb.setGeometry(QtCore.QRect(50, 280, 301, 41))
font = QtGui.QFont()
font.setPointSize(14)
self.force_jump_cb.setFont(font)
self.force_jump_cb.setObjectName("force_jump_cb")
font = QtGui.QFont()
font.setPointSize(16)
self.play_btn.setFont(font)
Expand All @@ -83,13 +90,14 @@ def setupUi(self):
font = QtGui.QFont()
font.setPointSize(20)
self.winner_label.setFont(font)
self.winner_label.setText("Select Mode")
self.winner_label.setAlignment(QtCore.Qt.AlignCenter)
self.winner_label.setObjectName("winner_label")

self.setWindowTitle("Checkers")
self.label.setText("CHECKERSSSSS")
self.winner_label.setText("Select Mode")
self.one_player_rb.setText("One Player")
self.two_players_rb.setText("Two Players")
self.force_jump_cb.setText("Force Jump?")
self.play_btn.setText("PLAY")

5 changes: 3 additions & 2 deletions src/game.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,16 +11,17 @@
class Checkers:
SINGLE_PLAYER = 1
TWO_PLAYERS = 2
def __init__(self, mode) -> None:
def __init__(self, mode, force_jump = False) -> None:
pg.init()
pg.display.set_caption("Checkers")
icon = pg.image.load(Constants.ICON_PATH)
pg.display.set_icon(icon)
self.screen = pg.display.set_mode((Constants.CELL_COUNT * Constants.CELL_SIZE, Constants.CELL_COUNT * Constants.CELL_SIZE))
self.board = Board(self.screen)
self.state = GameState(self.screen)
self.state = GameState(self.screen, force_jump)
self.mode = mode
self.bot_move = False
# self.force_jump = force_jump
#print(self.state)

def run(self, onEnd, onClose):
Expand Down
34 changes: 25 additions & 9 deletions src/state.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
from src.cache import moves

class GameState:
def __init__(self, screen):
def __init__(self, screen, force_jump = False):
self.screen = screen
self.winner = None
self.player = Player()
Expand All @@ -33,6 +33,8 @@ def __init__(self, screen):
self.current_player_moves = {(5, 0): {(4, 1, None)}, (5, 2): {(4, 1, None), (4, 3, None)}, (5, 4): {(4, 3, None), (4, 5, None)}, (5, 6): {(4, 5, None), (4, 7, None)}}
self.history = History(self)
self.heuristic = self.calucalte_heuristic()
self.force_jump = force_jump




Expand Down Expand Up @@ -320,16 +322,30 @@ def calculacte_moves(self):
else:
positions = self.black_positions
self.current_player_moves = {}
all_moves = {}
only_jumps = {}
for position in positions:
row, col = position
moves = calucate_moves(self, row, col)
row, col = position
if not self.force_jump or len(only_jumps) == 0:
moves = calucate_moves(self, row, col)
else:
moves = []
jumps = calcuate_jumps(self, row, col)
#print(f"Moves: {moves}, jumps: {jumps} for {position}")
moves_for_position = set()
for move in moves:
moves_for_position.add((move[0], move[1], None))

all_moves_for_position = set()
only_jumps_for_position = set()
for jump_cell, path in jumps.items():
moves_for_position.add((jump_cell[0], jump_cell[1], tuple(path)))
if len(moves_for_position) > 0:
all_moves_for_position.add((jump_cell[0], jump_cell[1], tuple(path)))
only_jumps_for_position.add((jump_cell[0], jump_cell[1], tuple(path)))
if len(only_jumps_for_position) > 0:
only_jumps[position] = only_jumps_for_position
for move in moves:
all_moves_for_position.add((move[0], move[1], None))
if len(all_moves_for_position) > 0:
#print(f"Calulated moves: {moves_for_position} for position: {position}")
self.current_player_moves[position] = moves_for_position
all_moves[position] = all_moves_for_position
if len(only_jumps) > 0 and self.force_jump:
self.current_player_moves = only_jumps
else:
self.current_player_moves = all_moves

0 comments on commit 380f154

Please sign in to comment.