25 files changed

+798
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,136 @@
1+
import Constants
2+
from Cell import Cell
3+
4+
5+
class Board:
6+
'''
7+
Class that represents the game board
8+
'''
9+
10+
def __init__(self, width, height):
11+
'''
12+
The board's constructor
13+
:param width: int > 4
14+
:param height: int > 4
15+
'''
16+
self.__height = height
17+
self.__width = width
18+
self.board = self.createBoard()
19+
20+
def createBoard(self):
21+
'''
22+
Function that creates an empty game board
23+
:return: matrix of cell
24+
'''
25+
board = []
26+
for x in range(self.__height):
27+
board.append([])
28+
for y in range(self.__width):
29+
board[x].append(Cell(Constants.EMPTY, x, y))
30+
return board
31+
32+
@property
33+
def height(self):
34+
return self.__height
35+
36+
@property
37+
def width(self):
38+
return self.__width
39+
40+
def isBoardFull(self, board):
41+
'''
42+
43+
:param board: matrix of cells
44+
:return: True if there are no empty spaces anywhere on the board.
45+
'''
46+
for x in range(board.height):
47+
for y in range(board.width):
48+
if board.board[x][y].entity == Constants.EMPTY:
49+
return False
50+
return True
51+
52+
def __str__(self):
53+
'''
54+
55+
:return: string thate represents the game board
56+
'''
57+
b = "\033[93m "
58+
for x in range(self.width):
59+
b += str(x + 1) + " "
60+
b += "\033[0m\n"
61+
for row in self.board:
62+
for y in row:
63+
b += str(y) + " "
64+
b += "\n"
65+
return b
66+
67+
def getLowestPoint(self, column):
68+
'''
69+
:param column: int
70+
:return: the row number of the lowest empty row in the given column.
71+
'''
72+
for y in range(self.height - 1, -1, -1):
73+
if self.board[y][column].entity == Constants.EMPTY:
74+
return y
75+
return -1
76+
77+
def isValidMove(self, column):
78+
'''
79+
:param column: int
80+
:return: True if the column is valid or not
81+
'''
82+
if column < 0 or column >= self.width or self.board[0][column].entity != Constants.EMPTY:
83+
return False
84+
return True
85+
86+
def move(self, column, entity):
87+
'''
88+
:param column: int
89+
:param entity: oneOf("human", "computer")
90+
'''
91+
if self.isValidMove(column):
92+
self.board[self.getLowestPoint(column)][column].entity = entity
93+
else:
94+
raise ValueError("Error: Column is full")
95+
96+
def isWinner(self, entity):
97+
'''
98+
Check if the given entity is a winner or not
99+
:param entity: oneOf("computer", "human")
100+
:return: True if winner, false otherwise
101+
'''
102+
# checks the horizontal possibilities
103+
for x in range(self.height):
104+
for y in range(self.width - 3):
105+
if self.board[x][y].entity == entity and \
106+
self.board[x][y + 1].entity == entity and \
107+
self.board[x][y + 2].entity == entity and \
108+
self.board[x][
109+
y + 3].entity == entity:
110+
return True
111+
# checks vertical possibilities
112+
for x in range(self.height - 3):
113+
for y in range(self.width):
114+
if self.board[x][y].entity == entity and self.board[x + 1][y].entity == entity and self.board[x + 2][
115+
y].entity == entity and \
116+
self.board[x + 3][
117+
y].entity == entity:
118+
return True
119+
120+
# checks the / diagonal possibilities
121+
for x in range(self.height - 3):
122+
for y in range(self.width - 3):
123+
if self.board[x][y].entity == entity and self.board[x + 1][y + 1].entity == entity and \
124+
self.board[x + 2][
125+
y + 2].entity == entity and self.board[x + 3][
126+
y + 3].entity == entity:
127+
return True
128+
# checks the / diagonal possibilities
129+
for x in range(self.height - 3):
130+
for y in range(3, self.width):
131+
if self.board[x][y].entity == entity and self.board[x + 1][y - 1].entity == entity and \
132+
self.board[x + 2][
133+
y - 2].entity == entity and self.board[x + 3][
134+
y - 3].entity == entity:
135+
return True
136+
return False
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
import Constants
2+
3+
4+
class Cell:
5+
'''
6+
A class used for describing one point of the board game
7+
Its main role is to describe whether an point is used by the computer or by the player
8+
'''
9+
10+
def __init__(self, entity, x, y):
11+
'''
12+
13+
:param entity: oneOf("human", "computer")
14+
:param x: the x coordinate
15+
:param y: the y coordinate
16+
'''
17+
self.__entity = entity
18+
self.__x = x
19+
self.__y = y
20+
21+
@property
22+
def x(self):
23+
return self.__x
24+
25+
@property
26+
def y(self):
27+
return self.__y
28+
29+
@property
30+
def entity(self):
31+
return self.__entity
32+
33+
@entity.setter
34+
def entity(self, enity):
35+
self.__entity = enity
36+
37+
def __repr__(self):
38+
return '(' + str(self.__x) + ',' + str(self.y) + ')'
39+
40+
def __str__(self):
41+
'''
42+
Used for representing the cells in the console UI
43+
:return: string
44+
'''
45+
if self.entity == Constants.COMPUTER:
46+
return "\033[1;91m⚫" + "\033[0;0m"
47+
elif self.entity == Constants.HUMAN:
48+
return "\033[93m⚫" + "\033[0;0m"
49+
else:
50+
return "⚪"
51+
52+
def __eq__(self, other):
53+
return self.entity == other.entity and self.x == other.x and self.y == other.y
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
import Constants
2+
from Board import Board
3+
from Console import Console
4+
from GUI import GUI
5+
from GameManager import GameManager
6+
7+
8+
class Config:
9+
'''
10+
Reads the configs settings from the given file and changes the game properties
11+
'''
12+
13+
def __init__(self, config):
14+
'''
15+
The class constructor
16+
:param config: the file name
17+
'''
18+
self.__config = config
19+
self.__settings = {}
20+
21+
def readSettings(self):
22+
'''
23+
Reads the settings from the given file
24+
'''
25+
print(self.__config)
26+
with open(self.__config, "r") as f:
27+
lines = f.read().split("\n")
28+
settings = {}
29+
for line in lines:
30+
setting = line.split("=")
31+
if len(setting) > 1:
32+
self.__settings[setting[0].strip()] = setting[1].strip()
33+
34+
def config(self):
35+
'''
36+
:return: The game settings
37+
'''
38+
ui = None
39+
oponent = None
40+
board = Board(int(self.__settings['width']), int(self.__settings['height']))
41+
gm = GameManager(board, int(self.__settings['difficulty']))
42+
if self.__settings['ui'] == Constants.CONSOLE:
43+
ui = Console(gm)
44+
if self.__settings['ui'] == Constants.GUI:
45+
ui = GUI(gm)
46+
return ui
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
import random
2+
3+
import Constants
4+
5+
6+
class Console:
7+
'''
8+
UI cli
9+
'''
10+
11+
def __init__(self, gm):
12+
self.__gm = gm
13+
self._exit = False
14+
15+
def __addPoint(self):
16+
pass
17+
18+
def __printBoard(self):
19+
print(self.__gm.boardToString())
20+
21+
def __printSubmenu(self, listOfOptions):
22+
'''
23+
Prints a submenu from a dictioary
24+
:param listOfOptions: dictionary of form {key:(function, message)}
25+
'''
26+
for option in listOfOptions:
27+
print(listOfOptions[option][1])
28+
print("0.Exit")
29+
30+
def __move(self):
31+
while True:
32+
column = input("What column do you choose?(-1 to exit the game)\n")
33+
if column.strip() == "-1":
34+
self._exit = True
35+
break
36+
try:
37+
38+
self.__gm.move(column, "human")
39+
break
40+
except ValueError as e:
41+
print("\033[1;91m" + str(e) + "\033[0m")
42+
continue
43+
44+
def run(self):
45+
if random.randint(0, 1) == 0:
46+
turn = Constants.COMPUTER
47+
else:
48+
turn = Constants.HUMAN
49+
while True and not self._exit:
50+
self.__printBoard()
51+
if turn == Constants.HUMAN:
52+
# Human player's turn.
53+
self.__move()
54+
# If the player is winning we end the game and display the message
55+
if self.__gm.checkWinner(Constants.HUMAN):
56+
print("\033[93mYou win! Hooray! ☻")
57+
self.__printBoard()
58+
break
59+
turn = Constants.COMPUTER # switch to other player's turn
60+
else:
61+
pass
62+
print("\033[93mYour's oponent turn")
63+
print(self.__gm.computerMove())
64+
turn = Constants.HUMAN
65+
# If the computer is winning we end the game and display the message
66+
if self.__gm.checkWinner(Constants.COMPUTER):
67+
print("\033[1;91mYou lost! ☹ ")
68+
self.__printBoard()
69+
break
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
# Constants used for managing the game data
2+
3+
EMPTY = None
4+
COMPUTER = 'computer'
5+
HUMAN = 'human'
6+
CONSOLE = 'console'
7+
GUI = 'gui'
8+
CELLSIZE = 50
9+
WHEIGHT = 720
10+
WWIDTH = 1080
11+
MARGINX = 20
12+
MARGINY = 20
13+
BLUE = (0, 39, 6)
14+
WHITE = (255, 255, 255)
15+
BG = BLUE
16+
TCOLOR = WHITE
17+
RED = 'red'
18+
BLACK = "BLACK"

0 commit comments

Comments
 (0)