From d5b339436e651aa43102c63d9d7f9ddb649175ea Mon Sep 17 00:00:00 2001 From: mnjx Date: Tue, 7 Mar 2023 21:34:21 -1000 Subject: [PATCH] add: variable symbol count needed to win, selecting the position of the new symbol by moving a cursor with arrow keys inside the playfield, press space to place the symbol, when a game ends, the winning symbols will blink a few times; fix: general bugfixes; update: comments --- .gitignore | 3 +- latest/tictactoe-latest.py | 428 +++++++++++----- ...actoe-v2.1.4-new.py => tictactoe-v2.1.4.py | 0 tictactoe-v2.2-new.py | 482 ++++++++++++++++++ 4 files changed, 797 insertions(+), 116 deletions(-) rename tictactoe-v2.1.4-new.py => tictactoe-v2.1.4.py (100%) create mode 100644 tictactoe-v2.2-new.py diff --git a/.gitignore b/.gitignore index c8747bf..5cfec61 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ launch.sh -mark.sh \ No newline at end of file +mark.sh +*.bak \ No newline at end of file diff --git a/latest/tictactoe-latest.py b/latest/tictactoe-latest.py index 4c9a111..946fe7b 100644 --- a/latest/tictactoe-latest.py +++ b/latest/tictactoe-latest.py @@ -1,25 +1,40 @@ +# TODO - __DONE__ variable symbol count needed to win +# - __DONE__ 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, selecting the position of the new symbol by moving a cursor with arrow keys inside the playfield, press return to place the symbol +# 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 +# 3 allow for one player or the other to insert coords by moving with arrow keys and to put the symbol to the selected place by pressing space # 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 +import os, time +from pynput import keyboard +from pynput.keyboard import Key, Listener, KeyCode # these global variables are flags end = 0 turn = 0 error = 0 +# misc. global vars +_size = 0 +winLine = [] +cursorX = cursorY = 0 # setting the default cursor position to the left top corner + # error codes # # 1 - invalid value @@ -27,17 +42,18 @@ error = 0 # 3 - index/position occupied def init(): - global end, turn, pf + global end, turn, pf, name1, name2, symbolCount, cursorX, cursorY, size, _size - # prerequisite 01 -> clear the screen + # 01 -> clear the screen clearScreen() - # prerequisite 02 -> allow a user to determine the size of the playfield + # 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): ")) + _size = size except ValueError: clearScreen() print("Enter a number") @@ -53,10 +69,27 @@ def init(): size = 3 - # prerequisite 03 -> allow a user to enter names of two players + # 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): @@ -65,25 +98,60 @@ def init(): pf.append(temp) temp = [] + # setting the hotkeys for moving with the cursor and putting down symbols + 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") -def inBound(a, b, c, d): - global pf +# detects if a position is inside the playfield +def inBound(x): + global _size - if len(pf) <= a >= 0 or len(pf) <= b >= 0 and len(pf) <= c >= 0 or len(pf) <= d >= 0: + if 0 <= x < _size: return 1 else: return 0 -def gameState(pf, name1, name2): - global error +def blinkPrint(pf, name1, name2): + clearScreen() + print(name1, "(o) vs", name2, "(x)") + for i in range(_size): + for j in range(_size): + if [i, j] in winLine: + print("[ ]", end=" ") + continue + print(f"[{pf[i][j]}]", end=" ") + print("") + time.sleep(0.5) + +def _print(pf, name1, name2, blink = 0): + clearScreen() + if blink == 2: + print("o won!") + elif blink == 3: + print("x won!") + + print(name1, "(o) vs", name2, "(x)") + for i in range(len(pf)): + for j in range(len(pf)): + if cursorX == j and cursorY == i and blink == 0: + print(f"#{pf[i][j]}#", end=" ") + continue + print(f"[{pf[i][j]}]", end=" ") + print("") + if blink == 1: + time.sleep(0.5) + +# prints the current state of the game +def gameState(pf, name1, name2, blink = 0): + global error, cursorX, cursorY if error == 1: print("Invalid value") @@ -94,114 +162,201 @@ def gameState(pf, name1, name2): 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(" ") + if blink == 1: + for i in range(6): + if i % 2 == 0: + blinkPrint(pf, name1, name2) + if i % 2 == 1: + _print(pf, name1, name2, 1) + elif blink == 0: + _print(pf, name1, name2) + elif blink == 2: + _print(pf, name1, name2, 2) + elif blink == 3: + _print(pf, name1, name2, 3) + +# checks whether someone has won def check(pf): + global symbolCount, winLine + + winLine = [] + # horizontal checking # 0 is for when 'o's win and 1 is for when 'x's win + temp = [] o = x = 0 - for i in range(len(pf)): - for j in range(len(pf)): + for i in range(_size): + for j in range(_size): if pf[i][j] == 'o': + temp.append([i, j]) o += 1 - if pf[i][j] == 'x': - x += 1 - if o == 3: + if o == symbolCount: + winLine = temp return 0 - elif x == 3: + if pf[i][j] == ' ' or pf[i][j] == 'x': + temp = [] + o = 0 + if o < symbolCount: + temp = [] + o = 0 + + for i in range(_size): + for j in range(_size): + if pf[i][j] == 'x': + temp.append([i, j]) + x += 1 + if x == symbolCount: + winLine = temp return 1 - if o < 3 or x < 3: - o = x = 0 + if pf[i][j] == ' ' or pf[i][j] == 'o': + temp = [] + x = 0 + if x < symbolCount: + temp = [] + x = 0 # vertical checking + temp = [] + o = x = 0 + for j in range(_size): + for i in range(_size): + if pf[i][j] == 'o': + temp.append([i, j]) + o += 1 + if o == symbolCount: + winLine = temp + return 0 + if pf[i][j] == ' ' or pf[i][j] == 'x': + temp = [] + o = 0 + if o < symbolCount: + temp = [] + o = 0 + + for j in range(_size): + for i in range(_size): + if pf[i][j] == 'x': + temp.append([i, j]) + x += 1 + if x == symbolCount: + winLine = temp + return 1 + if pf[i][j] == ' ' or pf[i][j] == 'o': + temp = [] + x = 0 + if x < symbolCount: + temp = [] + x = 0 + + # diagonal checking + temp = [] 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 == 3: - return 0 - elif x == 3: - return 1 - if o < 3 or x < 3: - o = x = 0 - - # diagonal checking for i in range(len(pf)): for j in range(len(pf)): if pf[i][j] == 'o': - # only 6 possibilities, so the program will try all of them try: - if pf[i-1][j-1] == 'o' and pf[i-2][j-2] == 'o' and inBound(i-1, j-1, i-2, j-2) == 1: - return 0 + if pf[i-1][j-1] == 'o': + for k in range(symbolCount): + if pf[i-k][j-k] == 'o': + temp.append([i-k, j-k]) + o += 1 + else: + temp = [] + o = 0 except IndexError: continue try: - if pf[i-1][j+1] == 'o' and pf[i-2][j+2] == 'o' and inBound(i-1, j+1, i-2, j+2) == 1: - return 0 + if pf[i-1][j+1] == 'o': + for k in range(symbolCount): + if pf[i-k][j+k] == 'o': + temp.append([i-k, j+k]) + o += 1 + else: + temp = [] + o = 0 except IndexError: continue try: - if pf[i+1][j-1] == 'o' and pf[i+2][j-2] == 'o' and inBound(i+1, j-1, i+2, j-2) == 1: - return 0 + if pf[i+1][j-1] == 'o': + for k in range(symbolCount): + if pf[i+k][j-k] == 'o': + temp.append([i+k, j-k]) + o += 1 + else: + temp = [] + o = 0 except IndexError: continue try: - if pf[i+1][j+1] == 'o' and pf[i+2][j+2] == 'o' and inBound(i+1, j+1, i+2, j+2) == 1: - return 0 + if pf[i+1][j+1] == 'o': + for k in range(symbolCount): + if pf[i+k][j+k] == 'o': + temp.append([i+k, j+k]) + o += 1 + else: + temp = [] + o = 0 except IndexError: continue - try: - if pf[i-1][j-1] == 'o' and pf[i+1][j+1] == 'o' and inBound(i-1, j-1, i+1, j+1) == 1: - return 0 - except IndexError: - continue - try: - if pf[i-1][j+1] == 'o' and pf[i+1][j-1] == 'o' and inBound(i-1, j+1, i+1, j-1) == 1: - return 0 - except IndexError: - continue - - for i in range(len(pf)): - for j in range(len(pf)): + if o >= symbolCount: + winLine = temp + return 0 + elif o < symbolCount: + temp = [] + o = 0 + if pf[i][j] == 'x': - # only 6 possibilities, so the program will try all of them try: - if pf[i-1][j-1] == 'x' and pf[i-2][j-2] == 'x' and inBound(i-1, j-1, i-2, j-2) == 1: - return 1 + if pf[i-1][j-1] == 'x': + for k in range(symbolCount): + if pf[i-k][j-k] == 'x': + temp.append([i-k, j-k]) + x += 1 + else: + temp = [] + x = 0 except IndexError: continue try: - if pf[i-1][j+1] == 'x' and pf[i-2][j+2] == 'x' and inBound(i-1, j+1, i-2, j+2) == 1: - return 1 + if pf[i-1][j+1] == 'x': + for k in range(symbolCount): + if pf[i-k][j+k] == 'x': + temp.append([i-k, j+k]) + x += 1 + else: + temp = [] + x = 0 except IndexError: continue try: - if pf[i+1][j-1] == 'x' and pf[i+2][j-2] == 'x' and inBound(i+1, j-1, i+2, j-2) == 1: - return 1 + if pf[i+1][j-1] == 'x': + for k in range(symbolCount): + if pf[i+k][j-k] == 'x': + temp.append([i+k, j-k]) + x += 1 + else: + temp = [] + x = 0 except IndexError: continue try: - if pf[i+1][j+1] == 'x' and pf[i+2][j+2] == 'x' and inBound(i+1, j+1, i+2, j+2) == 1: - return 1 - except IndexError: - continue - try: - if pf[i-1][j-1] == 'x' and pf[i+1][j+1] == 'x' and inBound(i-1, j-1, i+1, j+1) == 1: - return 1 - except IndexError: - continue - try: - if pf[i-1][j+1] == 'x' and pf[i+1][j-1] == 'x' and inBound(i-1, j+1, i+1, j-1) == 1: - return 1 + if pf[i+1][j+1] == 'x': + for k in range(symbolCount): + if pf[i+k][j+k] == 'x': + temp.append([i+k, j+k]) + x += 1 + else: + temp = [] + x = 0 except IndexError: continue + if x >= symbolCount: + winLine = temp + return 1 + elif x < symbolCount: + temp = [] + x = 0 # draw checking # 2 is for when a draw occurs @@ -213,65 +368,107 @@ def check(pf): if count == len(pf)*len(pf): return 2 -def gameRound(pf, name1, name2): - global end, turn, error +def cursorLeft(): + global cursorX, cursorY, pf, name1, name2, error - # step 1 -> clear the screen + if inBound(cursorX-1) == 1 and inBound(cursorY): + cursorX -= 1 + + gameState(pf, name1, name2) + +def cursorRight(): + global cursorX, cursorY, pf, name1, name2, error + + if inBound(cursorX+1) == 1 and inBound(cursorY) == 1: + cursorX += 1 + + gameState(pf, name1, name2) + +def cursorUp(): + global cursorX, cursorY, pf, name1, name2, error + + if inBound(cursorX) == 1 and inBound(cursorY-1) == 1: + cursorY -= 1 + + gameState(pf, name1, name2) + +def cursorDown(): + global cursorX, cursorY, pf, name1, name2, error + + if inBound(cursorX) == 1 and inBound(cursorY+1) == 1: + cursorY += 1 + + gameState(pf, name1, name2) + +def putSymbol(): + global cursorX, cursorY, turn, pf, name1, name2 + + if turn == 0 and pf[cursorY][cursorX] == ' ': + pf[cursorY][cursorX] = 'o' + turn = 1 + elif turn == 1 and pf[cursorY][cursorX] == ' ': + pf[cursorY][cursorX] = 'x' + turn = 0 + clearScreen() + gameState(pf, name1, name2) + +def keys(key): + global listener + + if key == keyboard.Key.left: + cursorLeft() + if key == keyboard.Key.right: + cursorRight() + if key == keyboard.Key.up: + cursorUp() + if key == keyboard.Key.down: + cursorDown() + if key == keyboard.Key.space: + listener.stop() + putSymbol() + +# logic for a round of the game +def gameRound(pf, name1, name2): + global end, turn, error, listener + + # 1 -> clear the screen # # cross-platform (Windows, Unix-like OSs) clearScreen() - # step 2 -> print the current state of the game + # 2 -> print the current state of the game gameState(pf, name1, name2) - # step 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 - - # step 4 -> place an 'o' or an 'x' to the coresponding coords + # 3 -> allow for one player or the other to move with arrow keys and to put the symbol to the selected place by pressing space # # 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 + with keyboard.Listener( + on_press=keys, + supress=True + ) as listener: + listener.join() - # step 5 -> check if the game should end (if someone won) + # 5 -> check if the game should end (if someone won) won = check(pf) if won == 0: - # step 5.1 -> if yes -> end the game + # 5.1 -> if yes -> end the game clearScreen() + gameState(pf, name1, name2, 1) print("o won!") - gameState(pf, name1, name2) + gameState(pf, name1, name2, 2) end = 1 - # step 5.2 -> if no -> jump to step 1 + # 5.2 -> if no -> jump to step 1 if won == 1: clearScreen() + gameState(pf, name1, name2, 1) print("x won!") - gameState(pf, name1, name2) + gameState(pf, name1, name2, 3) end = 1 if won == 2: @@ -280,5 +477,6 @@ def gameRound(pf, name1, name2): gameState(pf, name1, name2) end = 1 +# driver code if __name__ == "__main__": init() \ No newline at end of file diff --git a/tictactoe-v2.1.4-new.py b/tictactoe-v2.1.4.py similarity index 100% rename from tictactoe-v2.1.4-new.py rename to tictactoe-v2.1.4.py diff --git a/tictactoe-v2.2-new.py b/tictactoe-v2.2-new.py new file mode 100644 index 0000000..946fe7b --- /dev/null +++ b/tictactoe-v2.2-new.py @@ -0,0 +1,482 @@ +# TODO - __DONE__ variable symbol count needed to win +# - __DONE__ 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, selecting the position of the new symbol by moving a cursor with arrow keys inside the playfield, press return to place the symbol +# 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 by moving with arrow keys and to put the symbol to the selected place by pressing space +# 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, time +from pynput import keyboard +from pynput.keyboard import Key, Listener, KeyCode + +# these global variables are flags +end = 0 +turn = 0 +error = 0 + +# misc. global vars +_size = 0 +winLine = [] +cursorX = cursorY = 0 # setting the default cursor position to the left top corner + +# error codes +# +# 1 - invalid value +# 2 - invalid index/position +# 3 - index/position occupied + +def init(): + global end, turn, pf, name1, name2, symbolCount, cursorX, cursorY, size, _size + + # 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): ")) + _size = size + 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 = [] + + # setting the hotkeys for moving with the cursor and putting down symbols + + 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(x): + global _size + + if 0 <= x < _size: + return 1 + else: + return 0 + +def blinkPrint(pf, name1, name2): + clearScreen() + print(name1, "(o) vs", name2, "(x)") + for i in range(_size): + for j in range(_size): + if [i, j] in winLine: + print("[ ]", end=" ") + continue + print(f"[{pf[i][j]}]", end=" ") + print("") + time.sleep(0.5) + +def _print(pf, name1, name2, blink = 0): + clearScreen() + if blink == 2: + print("o won!") + elif blink == 3: + print("x won!") + + print(name1, "(o) vs", name2, "(x)") + for i in range(len(pf)): + for j in range(len(pf)): + if cursorX == j and cursorY == i and blink == 0: + print(f"#{pf[i][j]}#", end=" ") + continue + print(f"[{pf[i][j]}]", end=" ") + print("") + if blink == 1: + time.sleep(0.5) + +# prints the current state of the game +def gameState(pf, name1, name2, blink = 0): + global error, cursorX, cursorY + + if error == 1: + print("Invalid value") + error = 0 + if error == 2: + print("Invalid position") + error = 0 + if error == 3: + print("Position occupied") + error = 0 + + if blink == 1: + for i in range(6): + if i % 2 == 0: + blinkPrint(pf, name1, name2) + if i % 2 == 1: + _print(pf, name1, name2, 1) + elif blink == 0: + _print(pf, name1, name2) + elif blink == 2: + _print(pf, name1, name2, 2) + elif blink == 3: + _print(pf, name1, name2, 3) + +# checks whether someone has won +def check(pf): + global symbolCount, winLine + + winLine = [] + + # horizontal checking + # 0 is for when 'o's win and 1 is for when 'x's win + temp = [] + o = x = 0 + for i in range(_size): + for j in range(_size): + if pf[i][j] == 'o': + temp.append([i, j]) + o += 1 + if o == symbolCount: + winLine = temp + return 0 + if pf[i][j] == ' ' or pf[i][j] == 'x': + temp = [] + o = 0 + if o < symbolCount: + temp = [] + o = 0 + + for i in range(_size): + for j in range(_size): + if pf[i][j] == 'x': + temp.append([i, j]) + x += 1 + if x == symbolCount: + winLine = temp + return 1 + if pf[i][j] == ' ' or pf[i][j] == 'o': + temp = [] + x = 0 + if x < symbolCount: + temp = [] + x = 0 + + # vertical checking + temp = [] + o = x = 0 + for j in range(_size): + for i in range(_size): + if pf[i][j] == 'o': + temp.append([i, j]) + o += 1 + if o == symbolCount: + winLine = temp + return 0 + if pf[i][j] == ' ' or pf[i][j] == 'x': + temp = [] + o = 0 + if o < symbolCount: + temp = [] + o = 0 + + for j in range(_size): + for i in range(_size): + if pf[i][j] == 'x': + temp.append([i, j]) + x += 1 + if x == symbolCount: + winLine = temp + return 1 + if pf[i][j] == ' ' or pf[i][j] == 'o': + temp = [] + x = 0 + if x < symbolCount: + temp = [] + x = 0 + + # diagonal checking + temp = [] + 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': + temp.append([i-k, j-k]) + o += 1 + else: + temp = [] + o = 0 + except IndexError: + continue + try: + if pf[i-1][j+1] == 'o': + for k in range(symbolCount): + if pf[i-k][j+k] == 'o': + temp.append([i-k, j+k]) + o += 1 + else: + temp = [] + o = 0 + except IndexError: + continue + try: + if pf[i+1][j-1] == 'o': + for k in range(symbolCount): + if pf[i+k][j-k] == 'o': + temp.append([i+k, j-k]) + o += 1 + else: + temp = [] + o = 0 + except IndexError: + continue + try: + if pf[i+1][j+1] == 'o': + for k in range(symbolCount): + if pf[i+k][j+k] == 'o': + temp.append([i+k, j+k]) + o += 1 + else: + temp = [] + o = 0 + except IndexError: + continue + if o >= symbolCount: + winLine = temp + return 0 + elif o < symbolCount: + temp = [] + 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': + temp.append([i-k, j-k]) + x += 1 + else: + temp = [] + x = 0 + except IndexError: + continue + try: + if pf[i-1][j+1] == 'x': + for k in range(symbolCount): + if pf[i-k][j+k] == 'x': + temp.append([i-k, j+k]) + x += 1 + else: + temp = [] + x = 0 + except IndexError: + continue + try: + if pf[i+1][j-1] == 'x': + for k in range(symbolCount): + if pf[i+k][j-k] == 'x': + temp.append([i+k, j-k]) + x += 1 + else: + temp = [] + x = 0 + except IndexError: + continue + try: + if pf[i+1][j+1] == 'x': + for k in range(symbolCount): + if pf[i+k][j+k] == 'x': + temp.append([i+k, j+k]) + x += 1 + else: + temp = [] + x = 0 + except IndexError: + continue + if x >= symbolCount: + winLine = temp + return 1 + elif x < symbolCount: + temp = [] + 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 + +def cursorLeft(): + global cursorX, cursorY, pf, name1, name2, error + + if inBound(cursorX-1) == 1 and inBound(cursorY): + cursorX -= 1 + + gameState(pf, name1, name2) + +def cursorRight(): + global cursorX, cursorY, pf, name1, name2, error + + if inBound(cursorX+1) == 1 and inBound(cursorY) == 1: + cursorX += 1 + + gameState(pf, name1, name2) + +def cursorUp(): + global cursorX, cursorY, pf, name1, name2, error + + if inBound(cursorX) == 1 and inBound(cursorY-1) == 1: + cursorY -= 1 + + gameState(pf, name1, name2) + +def cursorDown(): + global cursorX, cursorY, pf, name1, name2, error + + if inBound(cursorX) == 1 and inBound(cursorY+1) == 1: + cursorY += 1 + + gameState(pf, name1, name2) + +def putSymbol(): + global cursorX, cursorY, turn, pf, name1, name2 + + if turn == 0 and pf[cursorY][cursorX] == ' ': + pf[cursorY][cursorX] = 'o' + turn = 1 + elif turn == 1 and pf[cursorY][cursorX] == ' ': + pf[cursorY][cursorX] = 'x' + turn = 0 + clearScreen() + gameState(pf, name1, name2) + +def keys(key): + global listener + + if key == keyboard.Key.left: + cursorLeft() + if key == keyboard.Key.right: + cursorRight() + if key == keyboard.Key.up: + cursorUp() + if key == keyboard.Key.down: + cursorDown() + if key == keyboard.Key.space: + listener.stop() + putSymbol() + +# logic for a round of the game +def gameRound(pf, name1, name2): + global end, turn, error, listener + + # 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 move with arrow keys and to put the symbol to the selected place by pressing space + # + # 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 + with keyboard.Listener( + on_press=keys, + supress=True + ) as listener: + listener.join() + + # 5 -> check if the game should end (if someone won) + won = check(pf) + + if won == 0: + # 5.1 -> if yes -> end the game + clearScreen() + gameState(pf, name1, name2, 1) + print("o won!") + gameState(pf, name1, name2, 2) + end = 1 + # 5.2 -> if no -> jump to step 1 + + if won == 1: + clearScreen() + gameState(pf, name1, name2, 1) + print("x won!") + gameState(pf, name1, name2, 3) + end = 1 + + if won == 2: + clearScreen() + print("Draw!") + gameState(pf, name1, name2) + end = 1 + +# driver code +if __name__ == "__main__": + init() \ No newline at end of file