Files
tictactoe/baks/tictactoe-v2.2-var-sym-count.py.bak
T
2023-03-22 10:35:19 -10:00

323 lines
9.2 KiB
Plaintext

# TODO - __DONE__ variable symbol count needed to win
# - selecting the position of the new symbol by moving a cursor with arrow keys inside the playfield, press return to place the symbol
# - when a game ends, the winning symbols will blink a few times
# add: variable symbol count needed to win
# fix: general bugfixes
# update: comments
# algorithm steps
#
# prerequisites
# 01 clear the screen
# 02 allow a user to determine the size of the playfield
# 03 allow a user to enter names of two players
# 04 allow a user to determine the symbol count needed to win
#
# 1 clear the screen
# 2 print the current state of the game
# 3 allow for one player or the other to insert coords
# 4 place an 'o' or an 'x' to the coresponding coords
# 5 check if the game should end (if someone won)
# 5.1 if yes -> end the game
# 5.2 if no -> jump to step 1
import os, keyboard
# these global variables are flags
end = 0
turn = 0
error = 0
# error codes
#
# 1 - invalid value
# 2 - invalid index/position
# 3 - index/position occupied
def init():
global end, turn, pf, symbolCount
# 01 -> clear the screen
clearScreen()
# 02 -> allow a user to determine the size of the playfield
size = None
F_printOneMoreTime = 0 # variables starting with 'F_' are flags
while size == None:
try:
size = int(input("Size of the playfield (n*n): "))
except ValueError:
clearScreen()
print("Enter a number")
F_printOneMoreTime = 1
continue
if F_printOneMoreTime == 1:
clearScreen()
print("Size of the playfield (n*n):", size)
F_printOneMoreTime = 0
if size <= 2:
clearScreen()
print("Size of the playfield (n*n):", size, "(changed to 3*3)")
size = 3
# 03 -> allow a user to enter names of two players
name1 = input("Name of the first player: ")
name2 = input("Name of the second player: ")
# 04 -> allow a user to determine the symbol count needed to win
symbolCount = None
F_printOneMoreTime = 0
while symbolCount == None:
try:
symbolCount = int(input("Number of symbols inline needed to win: "))
except ValueError:
clearScreen()
print("Enter a number")
F_printOneMoreTime = 1
continue
if F_printOneMoreTime == 1:
clearScreen()
print("Number of symbols inline needed to win:", symbolCount)
F_printOneMoreTime = 0
# creating the playfield
pf = [] # pf is shor for PlayField
temp = []
for i in range(size):
for j in range(size):
temp.append(' ')
pf.append(temp)
temp = []
while end == 0:
gameRound(pf, name1, name2)
# clears the screen
def clearScreen():
if os.name == "posix":
os.system("clear")
if os.name == "nt":
os.system("cls")
# detects if a position is inside the playfield
def inBound(a, b):
global pf
if len(pf) <= a >= 0 or len(pf) <= b >= 0:
return 1
else:
return 0
# prints the current state of the game
def gameState(pf, name1, name2):
global error
if error == 1:
print("Invalid value")
error = 0
if error == 2:
print("Invalid position")
error = 0
if error == 3:
print("Position occupied")
error = 0
print(name1, "(o) vs", name2, "(x)")
for i in range(len(pf)):
for j in range(len(pf)):
print(f"[{pf[i][j]}]", end=" ")
print(" ")
# checks whether someone has won
def check(pf):
global symbolCount
# horizontal checking
# 0 is for when 'o's win and 1 is for when 'x's win
o = x = 0
for i in range(len(pf)):
for j in range(len(pf)):
if pf[i][j] == 'o':
o += 1
if pf[i][j] == 'x':
x += 1
if o == symbolCount:
return 0
elif x == symbolCount:
return 1
if pf[i][j] == ' ':
o = x = 0
if o < symbolCount or x < symbolCount:
o = x = 0
# vertical checking
o = x = 0
for i in range(len(pf)):
for j in range(len(pf)):
if pf[j][i] == 'o':
o += 1
if pf[j][i] == 'x':
x += 1
if o == symbolCount:
return 0
elif x == symbolCount:
return 1
if pf[j][i] == ' ':
o = x = 0
if o < symbolCount or x < symbolCount:
o = x = 0
# diagonal checking
o = x = 0
for i in range(len(pf)):
for j in range(len(pf)):
if pf[i][j] == 'o':
try:
if pf[i-1][j-1] == 'o':
for k in range(symbolCount):
if pf[i-k][j-k] == 'o':
o += 1
except IndexError:
continue
try:
if pf[i-1][j+1] == 'o':
for k in range(symbolCount):
if pf[i-k][j+k] == 'o':
o += 1
except IndexError:
continue
try:
if pf[i+1][j-1] == 'o':
for k in range(symbolCount):
if pf[i+k][j-k] == 'o':
o += 1
except IndexError:
continue
try:
if pf[i+1][j+1] == 'o':
for k in range(symbolCount):
if pf[i+k][j+k] == 'o':
o += 1
except IndexError:
continue
if o >= symbolCount:
return 0
elif o < symbolCount:
o = 0
if pf[i][j] == 'x':
try:
if pf[i-1][j-1] == 'x':
for k in range(symbolCount):
if pf[i-k][j-k] == 'x':
x += 1
except IndexError:
continue
try:
if pf[i-1][j+1] == 'x':
for k in range(symbolCount):
if pf[i-k][j+k] == 'x':
x += 1
except IndexError:
continue
try:
if pf[i+1][j-1] == 'x':
for k in range(symbolCount):
if pf[i+k][j-k] == 'x':
x += 1
except IndexError:
continue
try:
if pf[i+1][j+1] == 'x':
for k in range(symbolCount):
if pf[i+k][j+k] == 'x':
x += 1
except IndexError:
continue
if x >= symbolCount:
return 1
elif x < symbolCount:
x = 0
# draw checking
# 2 is for when a draw occurs
count = 0
for i in range(len(pf)):
for j in range(len(pf)):
if pf[i][j] == 'o' or pf[i][j] == 'x':
count += 1
if count == len(pf)*len(pf):
return 2
# logic for a round of the game
def gameRound(pf, name1, name2):
global end, turn, error
# 1 -> clear the screen
#
# cross-platform (Windows, Unix-like OSs)
clearScreen()
# 2 -> print the current state of the game
gameState(pf, name1, name2)
# 3 -> allow for one player or the other to insert coords
row = column = None
while row == column == None:
try:
row, column = map(int, input().split())
except ValueError:
clearScreen()
error = 1
gameState(pf, name1, name2)
continue
# 4 -> place an 'o' or an 'x' to the coresponding coords
#
# only if there isn't another symbol present and the coords are valid
# the 'o' or 'x' is determined by the turn variable
# - if it is 0, then an 'o' is placed, if it is 1, an 'x' is placed instead
# the rows and columns are marked 1, 2 and 3, not 0, 1 and 2 as the indexes
# for better user experience
if row < 1 or column < 1:
error = 2
try:
if pf[row-1][column-1] != ' ':
error = 3
elif 1 <= row <= len(pf) and 1 <= column <= len(pf) and error == 0:
if turn == 0:
pf[row-1][column-1] = 'o'
turn = 1
elif turn == 1:
pf[row-1][column-1] = 'x'
turn = 0
except IndexError:
error = 2
# 5 -> check if the game should end (if someone won)
won = check(pf)
if won == 0:
# 5.1 -> if yes -> end the game
clearScreen()
print("o won!")
gameState(pf, name1, name2)
end = 1
# 5.2 -> if no -> jump to step 1
if won == 1:
clearScreen()
print("x won!")
gameState(pf, name1, name2)
end = 1
if won == 2:
clearScreen()
print("Draw!")
gameState(pf, name1, name2)
end = 1
# driver code
if __name__ == "__main__":
init()