Converting a noughts and crosses game onto an 4 x 4 grid - python

I keep on running into list index errors within my sub routine that decides when there is a winner and I'm not sure what to do, I a not fussed with finding the diagonal winning option though, If more info is needed just ask. Here is my original code that was on the 3 x 3 grid:
Board = [[0, 0, 0, 0],
[0, 0, 0, 0],
[0, 0, 0, 0],
[0, 0, 0, 0]]
def CheckXOr0HasWon(Board):
XOrOHasWon = False
for Column in range(1,4):
if (Board[Column][1] == Board[Column][2]) and (Board[Column][2] == Board[Column][3]) and
(Board[Column][2] != ' '):
XOrOHasWon = True
for Row in range(1,4):
if (Board[1][Row] == Board[2][Row]) and (Board[2][Row] == Board[3][Row]) and (Board[2][Row] != ' '):
XOrOHasWon = True
if (Board[1][1] == Board[2][2]) and (Board[2][2] == Board[3][3]) and (Board[2][2] != ' '):
XOrOHasWon = True
if (Board[3][1] == Board[2][2]) and (Board[2][2] == Board[1][3]) and (Board[2][2] != ' '):
XOrOHasWon = True
return XOrOHasWon
And here is the what i have done for the 4 x 4 grid:
Board = [[0, 0, 0, 0],
[0, 0, 0, 0],
[0, 0, 0, 0],
[0, 0, 0, 0]]
def CheckXOr0HasWon(Board):
XOrOHasWon = False
for Column in range(1,5):
if (Board[Column][1] == Board[Column][2]) and (Board[Column][2] == Board[Column][3]) and
(Board[Column][3] == Board[Column][4]) and (Board[Column][2][3] != ' '):
XOrOHasWon = True
for Row in range(1,5):
if (Board[1][Row] == Board[2][Row]) and (Board[2][Row] == Board[3][Row]) and (Board[3][Row] == Board[4][Row]) and (Board[2][3][Row] != ' '):
XOrOHasWon = True
if (Board[1][1] == Board[2][2]) and (Board[2][2] == Board[3][3]) and (Board[2][2] != ' '):
XOrOHasWon = True
if (Board[3][1] == Board[2][2]) and (Board[2][2] == Board[1][3]) and (Board[2][2] != ' '):
XOrOHasWon = True
return XOrOHasWon

Related

Is there a way that I can parse a numpy array and see if there is a certain value? [duplicate]

This question already has answers here:
Use a.any() or a.all()
(7 answers)
Closed 6 months ago.
I have a numpy array that I am using in order to store the position of checkers on a checker board. I am currently writing the logic in order to detect whether the player has won depending on if there are any enemy pieces on the board. Code is included, any help is appreciated. I guess I have to write more, the one sides checkers are stored as 1 and the other sides checkers is stored as 2. I want to see if there is any way to see if there are any ones left in the array or if there are any twos in the array, and exit the loop afterwards
# poop code :)
import numpy as np
# initial board state
positionOfCheckers = np.array([
[0, 2, 0, 2, 0, 2, 0, 2],
[2, 0, 2, 0, 2, 0, 2, 0],
[0, 2, 0, 2, 0, 2, 0, 2],
[0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0],
[1, 0, 1, 0, 1, 0, 1, 0],
[0, 1, 0, 1, 0, 1, 0, 1],
[1, 0, 1, 0, 1, 0, 1, 0]])
# prints current checkerboard
def printCheckerBoard(position_of_checkers):
posArrayX = 0
posArrayY = 0
checkerBoard = ' 0 1 2 3 4 5 6 7\n0'
for x in range(64):
currentPiece = position_of_checkers[posArrayY, posArrayX]
if currentPiece == 1:
checkerBoard = checkerBoard + " O "
elif currentPiece == 2:
checkerBoard = checkerBoard + " o "
else:
checkerBoard = checkerBoard + " "
if posArrayX == 7:
posArrayX = 0
posArrayY += 1
checkerBoard = checkerBoard + '\n' + str(posArrayY)
else:
posArrayX += 1
return checkerBoard
# take move input and logic uppercase
def tmialu():
movePieceX = int(input('Input X Value of Piece'))
movePieceY = int(input('Input Y Value of Piece'))
movePlaceX = int(input('Input X Value of Destination'))
movePlaceY = int(input('Input Y Value of Destination'))
# if piece is on square
if positionOfCheckers[movePieceY, movePieceX] == 1:
# if target square is empty
if positionOfCheckers[movePlaceY, movePlaceX] == 0:
# making sure that you are moving up and left
if movePieceX - movePlaceX == 1 & movePieceY - movePlaceY == 1:
print('cond satisfied')
positionOfCheckers[movePieceY, movePieceX] = 0
positionOfCheckers[movePlaceY, movePlaceX] = 1
# making sure that you are moving up and right
elif movePlaceX - movePieceX == 1 & movePieceY - movePlaceY == 1:
print('cond satisfied')
positionOfCheckers[movePieceY, movePieceX] = 0
positionOfCheckers[movePlaceY, movePlaceX] = 1
# else if the target piece is holding an enemy piece
elif positionOfCheckers[movePlaceY, movePlaceX] == 2:
# making sure its moving in a legal direction, up and left
if movePieceX - movePlaceX == 1 & movePieceY - movePlaceY == 1:
if positionOfCheckers[movePlaceY - 1, movePlaceX - 1] == 0:
print('cond satisfied')
positionOfCheckers[movePieceY, movePieceX] = 0
positionOfCheckers[movePlaceY, movePlaceX] = 0
positionOfCheckers[movePlaceY - 1, movePlaceX - 1] = 1
# making sure its moving in a legal direction, up and right
elif movePlaceX - movePieceX == 1 & movePieceY - movePlaceY == 1:
if positionOfCheckers[movePlaceY - 1, movePlaceX + 1] == 0:
print('cond satisfied')
positionOfCheckers[movePieceY, movePieceX] = 0
positionOfCheckers[movePlaceY, movePlaceX] = 0
positionOfCheckers[movePlaceY - 1, movePlaceX + 1] = 1
return positionOfCheckers
# take input and logic lowercase
def tmiall():
movePieceX = int(input('Input X Value of Piece'))
movePieceY = int(input('Input Y Value of Piece'))
movePlaceX = int(input('Input X Value of Destination'))
movePlaceY = int(input('Input Y Value of Destination'))
# if piece is on square
if positionOfCheckers[movePieceY, movePieceX] == 2:
# if target square is empty
if positionOfCheckers[movePlaceY, movePlaceX] == 0:
# making sure that you are moving down and left
if movePieceX - movePlaceX == 1 & movePlaceY - movePieceY == 1:
print('cond satisfied')
positionOfCheckers[movePieceY, movePieceX] = 0
positionOfCheckers[movePlaceY, movePlaceX] = 2
# making sure that you are moving down and right
elif movePlaceX - movePieceX == 1 & movePlaceY - movePieceY == 1:
print('cond satisfied')
positionOfCheckers[movePieceY, movePieceX] = 0
positionOfCheckers[movePlaceY, movePlaceX] = 2
# else if the target piece is holding an enemy piece
elif positionOfCheckers[movePlaceY, movePlaceX] == 1:
# making sure its moving in a legal direction, up and left
if movePieceX - movePlaceX == 1 & movePlaceY - movePieceY == 1:
if positionOfCheckers[movePlaceY + 1, movePlaceX - 1] == 0:
print('cond satisfied')
positionOfCheckers[movePieceY, movePieceX] = 0
positionOfCheckers[movePlaceY, movePlaceX] = 0
positionOfCheckers[movePlaceY + 1, movePlaceX - 1] = 2
# making sure it's moving in a legal direction, up and right
elif movePlaceX - movePieceX == 1 & movePlaceY - movePieceY == 1:
if positionOfCheckers[movePlaceY + 1, movePlaceX + 1] == 0:
print('cond satisfied')
positionOfCheckers[movePieceY, movePieceX] = 0
positionOfCheckers[movePlaceY, movePlaceX] = 0
positionOfCheckers[movePlaceY + 1, movePlaceX + 1] = 2
return positionOfCheckers
while True:
tmialu()
print(printCheckerBoard())
tmiall()
print(printCheckerBoard())
You can just use the in operator to check.
1 in positionOfCheckers # True if there is a single 1 in array
2 in positionOfCheckers # True if there is a single 2 in array
You can do 2 in positionOfCheckers and this will return true if there is a 2 in the array, otherwise it will return false.

IndexError: Creating two lists from a text file

I cannot figure why when I run my code I get an IndexError saying my list is out of range. I run into the error at “ if x[1] == "strongly agree": “. I’ve went through my code many times and I don’t know how to fix..
Here is my code(not including import):
firstList = [0, 0, 0, 0, 0]
secondList = [0, 0, 0, 0, 0]
with open("surveyData.txt", 'r') as f:
answers = f.read().split('\n')
for x in answers:
x = x.split(',')
if x[0] == "very happy":
firstList[0] += 1
elif x[0] == "happy":
firstList[1] += 1
elif x[0] == "neutral":
firstList[2] += 1
elif x[0] == "unhappy":
firstList[3] += 1
else:
firstList[4] += 1
if x[1] == "strongly agree":
secondList[0] += 1
elif x[1] == "agree":
secondList[1] += 1
elif x[1] == "neutral":
secondList[2] += 1
elif x[1] == "disagree":
secondList[3] += 1
else:
secondList[4] += 1
def showHistogram(dataList, bars):
plt.bars(bars, dataList)
plt.show()
question1_freq = ['very happy', ' happy', 'neutral', 'unhappy', 'very unhappy']
showHistogram(firstList, question1_freq)
question2_freq = ['strongly agree', 'agree', 'neutral', 'disagree', 'strongly disagree']
showHistogram(secondList, question2_freq)
Sample text file:
unhappy,strongly agree
very unhappy,strongly agree
happy,agree
neutral,strongly agree
happy,agree
very unhappy,strongly agree
neutral,strongly agree
very happy,disagree
Just change the below line and rest seems ok
answers = f.read().splitlines()

A* algorithm can't find the goal in Python

I'm still new to Python and this my first ever question on stackoverflow and I've been having trouble for a week to implement an A* algorithm.
The code I've got finds a goal with a straight wall but as you will see, as soon as I extend the wall below the start point and it has to go backwards or around it, it starts looping forever.
I've been banging my head against the wall trying to fix it and how to implement a raise code so it stops looping. Any help will be very much appreciated.
My code:
class Node:
"""A node class for A* Pathfinding"""
def __init__(self, parent=None, position=None):
self.parent = parent
self.position = position
self.g = 0
self.h = 0
self.f = 0
def __eq__(self, other):
return self.position == other.position
def astar(maze, start, end):
"""Returns a list of tuples as a path from the given start to the given end in the given maze"""
# Create start and end node
start_node = Node(None, start)
start_node.g = start_node.h = start_node.f = 0
end_node = Node(None, end)
end_node.g = end_node.h = end_node.f = 0
# Initialize both open and closed list
open_list = []
closed_list = []
# Add the start node
open_list.append(start_node)
# Loop until you find the end
while len(open_list) > 0:
# Get the current node
current_node = open_list[0]
current_index = 0
for index, item in enumerate(open_list):
if item.f < current_node.f:
current_node = item
current_index = index
# Pop current off open list, add to closed list
open_list.pop(current_index)
closed_list.append(current_node)
# Found the goal
if current_node == end_node:
path = []
current = current_node
while current is not None:
path.append(current.position)
current = current.parent
return path[::-1] # Return reversed path
# Generate children
children = []
for new_position in [(0, -1), (0, 1), (-1, 0), (1, 0), (-1, -1), (-1, 1), (1, -1), (1, 1)]: # Adjacent squares
# Get node position
node_position = (current_node.position[0] + new_position[0], current_node.position[1] + new_position[1])
# Make sure within range
if node_position[0] > (len(maze) - 1) or node_position[0] < 0 or node_position[1] > (
len(maze[len(maze) - 1]) - 1) or node_position[1] < 0:
continue
# Make sure walkable terrain
if maze[node_position[0]][node_position[1]] != 0:
print("node -", node_position[0],node_position[1], "is blocked")
continue
# Create new node
new_node = Node(current_node, node_position)
# Append
children.append(new_node)
# Loop through children
for child in children:
# Child is on the closed list
for closed_child in closed_list:
if child == closed_child:
continue
# Create the f, g, and h values
child.g = current_node.g + 1
child.h = ((child.position[0] - end_node.position[0]) ** 2) + (
(child.position[1] - end_node.position[1]) ** 2)
child.f = child.g + child.h
# Child is already in the open list
for open_node in open_list:
if child == open_node and child.g > open_node.g:
continue
# Add the child to the open list
open_list.append(child)
def main():
maze = [[0, 0, 0, 0, 1, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 1, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 1, 0, 0, 0, 0, 0],
[0, 0, 1, 1, 1, 1, 1, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 1, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 1, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 1, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0]]
start = (0, 0)
end = (1, 8)
path = astar(maze, start, end)
print(path)
main()
You have these two pieces:
# Child is on the closed list
for closed_child in closed_list:
if child == closed_child:
continue
# Child is already in the open list
for open_node in open_list:
if child == open_node and child.g > open_node.g:
continue
The continue will continue the inner for loop. Consequently, it does not have any effect. You are rather looking for something like this:
# Child is on the closed list
is_in_closed = False
for closed_child in closed_list:
if child == closed_child:
is_in_closed = True
break
if is_in_closed:
continue
# Child is already in the open list
is_in_open = False
for open_node in open_list:
if child == open_node and child.g > open_node.g:
is_in_open = True
break
if is_in_open:
continue
Two more comments:
Your distance measure only counts the number of steps. Therefore, a diagonal is as expensive as a horizontal / vertical step. You might want to change this and get the actual length or an approximation of it to find the truly shortest path.
Your heuristic is the squared distance to the target. This is not an admissible heuristic because it over-estimates the actual cost to the target. As a result, you might not find the correct shortest path. For your cost function (number of steps), a better and admissible heuristic would be max(child.position[0] - end_node.position[0], child.position[1] - end_node.position[1]) (you need at least this number of steps to get to the target).

How to choose a good Python list data structure to store every possible Tic Tac Toe game

I am working on a python project where I generate every possible tic-tac-toe game, and then draw conclusions, based on those games (ie. what is the best first move, in order to win the most games). I have a function to generate a possible game, then append two arrays with that game, one if the game is winning, and one for every single game. When I append the arrays, and print the last element in those arrays, I get the game that was just generated. However, once the function finished, and I check the arrays, they are all filled with multiples of the same element. My code is below:
print("running...")
allGames = []
winningGames = []
winningFirstMoves = [0] * 9
wins = {
"top horizontal": 0,
"middle horizontal": 0,
"bottom horizontal": 0,
"left vertical": 0,
"middle vertical": 0,
"right vertical": 0,
"backward diagonal": 0,
"forward diagonal": 0
}
def checkFirstMove():
print("checking winning first moves...")
global winningGames
global winningFirstMoves
for game in winningGames:
print(game) #this line is only here to test, I know it slows it down
for move in range(len(game)):
if (game[move][1] == 1):
winningFirstMoves[move] += 1
def checkWin(gameToCheck):
if (gameToCheck[0][0] == gameToCheck[1][0] == gameToCheck[2][0] and gameToCheck[0][0] != 10):
wins["top horizontal"] += 1
return "top horizontal"
elif (gameToCheck[3][0] == gameToCheck[4][0] == gameToCheck[5][0] and gameToCheck[3][0] != 10):
wins["middle horizontal"] += 1
return "middle horizontal"
elif (gameToCheck[6][0] == gameToCheck[7][0] == gameToCheck[8][0] and gameToCheck[6][0] != 10):
wins["bottom horizontal"] += 1
return "bottom horizontal"
elif (gameToCheck[0][0] == gameToCheck[3][0] == gameToCheck[6][0] and gameToCheck[0][0] != 10):
wins["left vertical"] += 1
return "left vertical"
elif (gameToCheck[1][0] == gameToCheck[4][0] == gameToCheck[7][0] and gameToCheck[1][0] != 10):
wins["middle vertical"] += 1
return "middle vertical"
elif (gameToCheck[2][0] == gameToCheck[5][0] == gameToCheck[8][0] and gameToCheck[2][0] != 10):
wins["right vertical"] += 1
return "right vertical"
elif (gameToCheck[0][0] == gameToCheck[4][0] == gameToCheck[8][0] and gameToCheck[0][0] != 10):
wins["backward diagonal"] += 1
return "backward diagonal"
elif (gameToCheck[2][0] == gameToCheck[4][0] == gameToCheck[6][0] and gameToCheck[2][0] != 10):
wins["forward diagonal"] += 1
return "forward diagonal"
else: return False
def cleanGame(gameToClean, moveNumber):
for j in range(9):
if (gameToClean[j][1] >= moveNumber):
gameToClean[j] = [None, 0]
def generateGames():
global allGames
global winningGames
currentGame= [[None, 0], [None, 0], [None, 0], [None, 0], [None, 0], [None, 0], [None, 0], [None, 0], [None, 0]]
for a in range(9):
if (a == 0):
print("generating games.", end="")
elif (a == 8):
print(".")
else:
print(".", end="")
cleanGame(currentGame, 1)
currentGame[a] = [1, 1]
for b in range(9):
cleanGame(currentGame, 2)
if (currentGame[b] == [None, 0]):
currentGame[b] = [0, 2]
for c in range(9):
cleanGame(currentGame, 3)
if (currentGame[c] == [None, 0]):
currentGame[c] = [1, 3]
for d in range(9):
cleanGame(currentGame, 4)
if (currentGame[d] == [None, 0]):
currentGame[d] = [0, 4]
for e in range(9):
cleanGame(currentGame, 5)
if (currentGame[e] == [None, 0]):
currentGame[e] = [1, 5]
if (checkWin(currentGame) != False):
winningGames.append(currentGame)
allGames.append(currentGame)
else:
for f in range(9):
cleanGame(currentGame, 6)
if (currentGame[f] == [None, 0]):
currentGame[f] = [0, 6]
if (checkWin(currentGame) != False):
winningGames.append(currentGame)
allGames.append(currentGame)
else:
for g in range(9):
cleanGame(currentGame, 7)
if (currentGame[g] == [None, 0]):
currentGame[g] = [1, 7]
if (checkWin(currentGame) != False):
winningGames.append(currentGame)
allGames.append(currentGame)
else:
for h in range(9):
cleanGame(currentGame, 8)
if (currentGame[h] == [None, 0]):
currentGame[h] = [0, 8]
if (checkWin(currentGame) != False):
winningGames.append(currentGame)
allGames.append(currentGame)
else:
for i in range(9):
cleanGame(currentGame, 9)
if (currentGame[i] == [None, 0]):
currentGame[i] = [1, 9]
allGames.append(currentGame)
if (checkWin(currentGame) != False):
winningGames.append(currentGame)
generateGames()
print("Number of Possible Games:", len(allGames))
print("Number of Winning Games:", len(winningGames))
checkFirstMove()
print(winningFirstMoves)
print("completed...")
A normal game would look something like this:
[[1, 1], [0, 2], [None, 0], [1, 3], [0, 4], [0, 6], [1, 7], [None, 0], [1, 5]]
However after the function completes, the arrays are filled with:
[[None, 0], [None, 0], [None, 0], [None, 0], [None, 0], [None, 0], [None, 0], [None, 0], [1, 1]]
How can I fix this?
Idea:
I changed the format of the data which stores the game information to a tuple which consists of two elements:
The first element is a list which contains the sequence of player moves. We don't need to store which player is at which position because the order is always the same: first player, then second player, then first player again, and so on. So every odd element index is a move from the first player, every even element index from the second player. The board is indexed from left to right and top to bottom:
[0][1][2]
[3][4][5]
[6][7][8]
Example for some first 4 moves:
[0, 2, 8, 4]
Assuming X is the first player and O is the second player:
[X][ ][ ] [X][ ][O] [X][ ][O] [X][ ][O]
[ ][ ][ ] -> [ ][ ][ ] -> [ ][ ][ ] -> [ ][O][ ]
[ ][ ][ ] [ ][ ][ ] [ ][ ][X] [ ][ ][X]
The second element is the game outcome encoded as an integer: 0 for draw, 1 for first player win, 2 for second player win.
Example:
Again, assuming X is the first player and O is the second player. Examples:
[X][O][X]
([0, 1, 2, 3, 4, 5, 6], 1) -> [O][X][O] -> First player won
[X][ ][ ]
[X][O][X]
([0, 1, 2, 3, 8, 7, 6, 4], 2) -> [O][O][ ] -> Second player won
[X][O][X]
[X][O][X]
([0, 1, 3, 8, 2, 6, 7, 4, 5], 0) -> [X][O][X] -> Draw
[O][X][O]
Implementation:
def draw_board(board):
template = ("[{}]" * 3 + "\n") * 3
print(template.format(*board))
def has_winner(sequence):
board = [" "] * 9
for n, move in enumerate(sequence):
board[move] = "X" if n % 2 == 0 else "O"
#draw_board(board)
tests = [
board[0] == board[1] == board[2] != " ",
board[3] == board[4] == board[5] != " ",
board[6] == board[7] == board[8] != " ",
board[0] == board[3] == board[6] != " ",
board[1] == board[4] == board[7] != " ",
board[2] == board[5] == board[8] != " ",
board[0] == board[4] == board[8] != " ",
board[2] == board[4] == board[6] != " ",
]
return any(tests)
def no_moves_left(sequence):
return len(sequence) == 9
def generate_games(sequence):
if has_winner(sequence):
winner = 2 - len(sequence) % 2
return [(sequence, winner)]
if no_moves_left(sequence):
return [(sequence, 0)]
games = []
open_spaces = [i for i in range(9) if i not in sequence]
for new_move in open_spaces:
new_sequence = sequence.copy()
new_sequence.append(new_move)
new_games = generate_games(new_sequence)
games.extend(new_games)
return games
games = generate_games([])
This implementation is definitely not fully optimized! However, I think it's fast enough while still maintaining a simple code structure.
Minimal statistics:
statistics = [[0] * 9 for _ in range(3)]
for sequence, outcome in games:
statistics[outcome][sequence[0]] += 1
print(*statistics, sep="\n")
Output:
[5184, 5184, 5184, 5184, 4608, 5184, 5184, 5184, 5184]
[14652, 14232, 14652, 14232, 15648, 14232, 14652, 14232, 14652]
[7896, 10176, 7896, 10176, 5616, 10176, 7896, 10176, 7896]
Plotting:
import matplotlib.pyplot as plt
import numpy as np
colors = "#6bc86b", "#5a9bd3", "#ed7d33"
labels = "Draw", "First player wins", "Second player wins"
explode = 0.05, 0.05, 0.05
data = list(map(sum, statistics))
plt.pie(data, colors=colors, labels=labels, explode=explode,
autopct="%1.1f%%", shadow=True)
plt.axis("equal")
plt.title("Outcome for all {} possible Tic-tac-toe games".format(sum(data)))
plt.show()
plt.close()
colors = "#6bc86b", "#5a9bd3", "#ed7d33"
labels = "Draw", "Win", "Lose"
width = 0.3
for i, (data, color, label) in enumerate(zip(statistics, colors, labels)):
index = [j + i * width for j in range(9)]
plt.bar(index, data, width, color=color, label=label)
plt.xlabel("Space of the first move")
plt.ylabel("Number of games")
plt.title("Outcome depending on first player's first move")
plt.xticks([i + width for i in range(9)])
plt.gca().set_xticklabels(map(str, range(9)))
plt.legend()
plt.tight_layout()
plt.show()
plt.close()
Output:

Check if Player X or Player Y has won function/module. Tic Tac Toe

Hello ! I have a question guys.
I was writing my first serious python training project because I'm beginner but I encountered a problem that stops me from further development of my program.
I don't have idea how can I write function/module in my class that check if player X or player Y has won. I tried on so many different ways but it seems to not work. I know that the my code is looking awful. Thank you for your time spent.
import sys
class Tic_tac_toe():
def __init__(self):
self.board = {'top-L': ' ', 'top-M': ' ', 'top-R': ' ',
'mid-L': ' ', 'mid-M': ' ', 'mid-R': ' ',
'low-L': ' ', 'low-M': ' ', 'low-R': ' '}
self.move_X = None
self.move_0 = None
self.WINNING_MOVE = None
self.loop = None
self.nameX = None
self.nameO = None
self.choice = None
def welcome(self):
try:
print("Welcome ! :)\n\nWho is PLAYER X ? :")
self.nameX = input()
print("\nWho is PLAYER O ? :")
self.nameO = input()
print("\nHello {} and {}, ready to play? (Y/N) :".format(self.nameX.title(), self.nameO.title()))
self.choice = input()
if self.choice.title() == 'N' or '\n':
sys.exit()
print('\n{} is PLAYER X.\n{} is PLAYER Y.'.format(self.nameX.title(),self.nameO.title()))
except ValueError:
print('\nTry again:\n')
def printBoard(self):
print()
print(self.board['top-L'] + '|' + self.board['top-M'] + '|' + self.board['top-R'])
print('-+-+-')
print(self.board['mid-L'] + '|' + self.board['mid-M'] + '|' + self.board['mid-R'])
print('-+-+-')
print(self.board['low-L'] + '|' + self.board['low-M'] + '|' + self.board['low-R'])
print()
def moves_X(self):
try:
self.move_X = int(input("Player X :\nChoose field (1,9) : "))
self.write_on_boardX()
self.printBoard()
except ValueError:
print("\nYOU DIDN'T ENTER NUMBER !\n")
def moves_O(self):
try:
self.move_O = int(input("Player O :\nChoose field (1,9) : "))
self.write_on_boardO()
self.printBoard()
except ValueError:
print("\nYOU DIDN'T ENTER NUMBER!\n")
def mix_XO(self):
self.loop = 0
for x in range(1,10):
if self.loop % 2 == 0:
self.moves_X()
self.loop += 1
elif self.loop % 2 == 1:
self.moves_O()
self.loop += 1
def write_on_boardX(self):
if self.move_X == 1:
self.board['top-L'] = 'X'
elif self.move_X == 2:
self.board['top-M'] = 'X'
elif self.move_X == 3:
self.board['top-R'] = 'X'
elif self.move_X == 4:
self.board['mid-L'] = 'X'
elif self.move_X == 5:
self.board['mid-M'] = 'X'
elif self.move_X == 6:
self.board['mid-R'] = 'X'
elif self.move_X == 7:
self.board['low-L'] = 'X'
elif self.move_X == 8:
self.board['low-M'] = 'X'
elif self.move_X == 9:
self.board['low-R'] = 'X'
def write_on_boardO(self):
if self.move_O == 1:
self.board['top-L'] = 'O'
elif self.move_O == 2:
self.board['top-M'] = 'O'
elif self.move_O == 3:
self.board['top-R'] = 'O'
elif self.move_O == 4:
self.board['mid-L'] = 'O'
elif self.move_O == 5:
self.board['mid-M'] = 'O'
elif self.move_O == 6:
self.board['mid-R'] = 'O'
elif self.move_O == 7:
self.board['low-L'] = 'O'
elif self.move_O == 8:
self.board['low-M'] = 'O'
elif self.move_O == 9:
self.board['low-R'] = '0'
def winning_movesX(self):
pass
def main():
app = Tic_tac_toe()
app.welcome()
app.printBoard()
app.mix_XO()
main()
One way to achieve this is to first create a map of all the possible winning 'lines' and then see if the elements on that line are all the same, by creating a set and checking it contains only 1 item (X or O). For example:
lines = [
['top-L','top-M','top-R'],
['top-L', 'mid-L', 'low-L']
... etc ...
]
for line in lines:
if len(set(self.board[x] for x in line])) == 1:
print("Winner:", self.board[line[0]])
Different Approach might be easier...
A simpler way would be to use a 3x3 matrix, e.g. with:
0 as a default value
-1 for player 1
+1 for player 2
You can then calculate the sum of the rows/columns/diagonals. With -3 as a player 1 win, +3 as a player 2 win. For example by using numpy:
>>> import numpy as np
>>> np.zeros((3, 3), dtype=int)
array([[0, 0, 0],
[0, 0, 0],
[0, 0, 0]])
=> self.board = np.zeros((3,3), dtype=int)
and a win check would roughly look like:
d1,d2 = 0,0 #used to calculate sum of diagonal
for i in range(3):
#check row
if sum(self.board[i, :]) in (3,-3):
self.win = True
#check column
elif sum(self.board[:, i]) in (3,-3):
self.win = True
#check diagonal
d1 += self.board[i, i] #diagonal from top left corner to bottom right corner
d2 += self.board[i, 2-i] #diagonal from top right corner to bottom left corner
elif d1 in (3,-3) or d2 in (-3,3):
self.win = True
Note: You know which player has won since you know who's turn it was last.
Well, and since you seem to be rather new to python here a quick overview on how to access elements of an array:
>>> board = np.zeros((3,3), dtype=int)
>>> board[0][1] = 3
>>> board
array([[0, 3, 0],
[0, 0, 0],
[0, 0, 0]])
And in case you keep this board:
"""
[1] | [2] | [3]
-----------------
[4] | [5] | [6]
-----------------
[7] | [8] | [9]
"""
you could use the integer division // and the modulo function % instead of all the elif statements to determine what field/position on the board the user meant:
position = int(input("Choose position:"))
row = (position-1)//3
column = (position-1)%3
self.board[row][column] = 1 #or -1
P.S.:
If you want to implement a "player vs. computer" later on, you might change the value -1 to -3 to get unique sum values. (-1 +1 +0 = 0 +0 +0)

Categories

Resources