so I was basically was trying to make a multiplayer Tic-Tac-Toe game but then I've been running into this following problems
This is the host side:
Enter row and column numbers to fix spot(row,column): 1,2
- X -
- - -
- - -
This is the guest side:
X - -
- - -
- - -
The problems are:
It did not pass the turn to the guest side.
It displays a false mark
on the grid.
import socket
import threading
HOST = '192.168.1.115'
PORT = 9090
class TicTacToe:
def __init__(self):
self.you = 'O'
self.opponet = 'X'
self.turn = 'X'
self.board = []
self.game_over = False
self.winner = None
self.counter = 0
self.create_board()
def create_board(self):
for i in range(3):
row = []
for j in range(3):
row.append('-')
self.board.append(row)
def show_board(self):
for row in self.board:
for item in row:
print(item, end=" ")
print()
def is_board_filled(self):
for row in self.board:
for item in row:
if item == '-':
return False
return True
def fix_move(self, row, col, player):
if self.game_over:
return
self.counter +=1
self.board[row-1][col-1] = player
self.show_board()
if self.is_player_win(player):
if self.winner == self.you:
print('You win!')
exit()
if self.winner == self.opponet:
print('You lose!')
exit()
else:
if self.counter == 9:
print('Its a draw!')
exit()
def valid_move(self, row, col):
if self.board[row][col] == 'O' or self.board[row][col] == 'X':
return False
return True
def swap_player_turn(self):
self.turn = self.you if self.turn == self.opponet else self.opponet
def handle(self, client):
while not self.game_over:
if self.turn == self.you:
move = input("Enter row and column numbers to fix spot(row,column): ")
place = move.split(',')
if self.valid_move(int(place[0]), int(place[1])):
self.fix_move(int(place[0]), int(place[1]), self.you)
self.turn = self.opponet
client.send(move.encode('utf-8'))
else:
print('Invalid Move!')
else:
data = client.recv(1024)
if not data:
client.close()
break
else:
place = data.decode('utf-8').split(',')
self.fix_move(int(place[0]), int(place[0]), self.opponet)
client.close()
def is_player_win(self, player):
if self.board[0][0] == self.board[0][1] == self.board[0][2] == 'X':
return True
if self.board[1][0] == self.board[1][1] == self.board[1][2] == 'X' or 'O':
return True
if self.board[2][0] == self.board[2][1] == self.board[2][2] == 'X' or 'O':
return True
# etc etc
def host_game(self, host, port):
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.bind((host, port))
server.listen(1)
client, addr = server.accept()
self.you = 'X'
self.opponet = 'O'
threading.Thread(target=self.handle, args=(client,)).start()
server.close()
def connect_to_game(self, host, port):
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect((host, port))
self.you = 'O'
self.opponet = 'X'
threading.Thread(target=self.handle, args=(client,)).start()
game = TicTacToe()
game.host_game(HOST, PORT)
the structure of the code is in a way that you take the source code above and copy it and then generate 2 files, one for the host and another for the guest the difference between them is that you you use the host_game function in the host file and the connect_to_game function in the guest file.
I've tried everything I could , searching in here , googling and nothing
I've also tried to ask ChatGPT but it was worthless
I'll address the immediate two problems:
Use your swap_player_turn() method and place it at the bottom of the while loop in handle so it happens on both host and client after the turn is handled. This will pass the turn correctly.
After asking for input or receiving data, call a common a function to convert to 0-based row/col data, because sometimes you subtract one from row/col, and sometimes you don't. For example:
def parse_move(move):
return [int(n)-1 for n in move.split(',')]
move = input("Enter row and column numbers to fix spot(row,column): ")
row, col = parse_move(move)
...
data = client.recv(1024)
row, col = parse_move(move)
Then use row/col instead of int(place[n]) everywhere. This will fix the false mark.
Other issues are the code isn't complete to determine a win or draw, opponet is misspelled, and (while this slow turn-based code will probably never have the issue) TCP is not a message-based protocol, but the code assumes it is.
A useful debug feature is to make the game able to print its state. For example, add:
def __repr__(self):
return f'TicTacToe(you={self.you!r}, op={self.opponent!r}, turn={self.turn!r})'
Then print(self) at the top of the while loop.
Related
My problem: Python tab closes on "3 1" input.
This code is heavily inspired by Hafeezul Kareem Shaik's tic-tac-toe game on geekflare.
My code:
import random
class TicTacToe:
def __init__(self):
self.board = []
def create_board(self):
for r0w in range(3):
row = []
for c0l in range(3):
row.append('-')
self.board.append(row)
def get_random_first_player(self):
return random.randint(0,1)
def fix_spot(self, row, col, player):
self.board[row][col] = player
def is_player_win(self, player):
win = None
n = len(self.board)
#checking rows
for r0w in range(n):
win = True
for c0l in range(n):
if self.board[r0w][c0l] != player:
win = False
break
if win:
return win
#checking columns
for r0w in range(n):
win = True
for c0l in range(n):
if self.board[c0l][r0w] != player:
win = False
break
if win:
return win
#checking diagonals
win = True
for i in range (n):
if self.board[i][i] != player:
win = False
break
if win:
return win
win = True
for i in range(n):
if self.board[r0w][n - 1 - r0w] != player:
win = False
break
if win:
return win
return False
for row in self.board:
for item in row:
if item == '-':
return False
return True
def is_board_filled(self):
for row in self.board:
for item in row:
if item == "-":
return False
return True
def swap_player_turn(self, player):
return 'X' if player =='O' else 'O'
def show_board(self):
for row in self.board:
for item in row:
print(item, end=" ")
print()
def start(self):
self.create_board()
player = 'X' if self.get_random_first_player() == 1 else 'O'
while True:
print(f"Player {player} turn")
self.show_board()
# user input
row, col = list(
map(int, input("Enter row and column numbers to fix spot: ").split()))
print()
#fixing spot
self.fix_spot(row - 1, col - 1, player)
#has current player won
if self.is_player_win(player):
print(f"{player} Wins!")
break
#is game a draw
if self.is_board_filled():
print("Draw!")
break
#swapping turn
player = self.swap_player_turn(player)
#final board
print()
self.show_board()
tic_tac_toe = TicTacToe()
tic_tac_toe.start()
The Tic_Tac-Toe Game worked up until I typed "3 1". I tested multiple games and it would always close after that input.
I have tried editing the scope of the following, as I believe that is what is causing it to malfunction
if win:
return win
return False
Unfortunately that has not fixed the problem. Any ideas or suggestions?
This code is so badly written that I wouldn't take it as an example for anything.
But if you really want to know why it ends on 3 1 as input, you should look here:
win = True
for i in range(n):
if self.board[r0w][n - 1 - r0w] != player:
win = False
break
if win:
return win
return False
Here r0w is not reset, it has the last value from the for loop, which is 2, and it's not changing in the loop, so there's only one check made, which is 3 1, translated to 2 0, which is the current player, so that's an instant win.
I assume this was supposed to be a loop to check the other diagonal, but it's clearly flawed.
I'm using discord.py 2.0 for the first time and I can't find a solution to change this code for a TicTacToe singleplayer game to multiplayer. I want to be able to write /tictactoe {member} and that you only can place your mark when it's your turn. At the moment any member can place a mark at anytime. The code is from Rapptz I only changed the command to a slash command. Thanks in advance! :D
EDIT: I found a solution and it is in the comments!
from typing import List
from discord.ext import commands
import discord
from discord import app_commands
class TicTacToeButton(discord.ui.Button['TicTacToe']):
def __init__(self, x: int, y: int):
super().__init__(style=discord.ButtonStyle.secondary, label='\u200b', row=y)
self.x = x
self.y = y
# This function is called whenever this particular button is pressed
# This is part of the "meat" of the game logic
async def callback(self, interaction: discord.Interaction):
assert self.view is not None
view: TicTacToe = self.view
state = view.board[self.y][self.x]
if state in (view.X, view.O):
return
if view.current_player == view.X:
self.style = discord.ButtonStyle.danger
self.label = 'X'
self.disabled = True
view.board[self.y][self.x] = view.X
view.current_player = view.O
content = "It is now O's turn"
else:
self.style = discord.ButtonStyle.success
self.label = 'O'
self.disabled = True
view.board[self.y][self.x] = view.O
view.current_player = view.X
content = "It is now X's turn"
winner = view.check_board_winner()
if winner is not None:
if winner == view.X:
content = 'X won!'
elif winner == view.O:
content = 'O won!'
else:
content = "It's a tie!"
for child in view.children:
child.disabled = True
view.stop()
await interaction.response.edit_message(content=content, view=view)
# This is our actual board View
class TicTacToe(discord.ui.View):
# This tells the IDE or linter that all our children will be TicTacToeButtons
# This is not required
children: List[TicTacToeButton]
X = -1
O = 1
Tie = 2
def __init__(self):
super().__init__()
self.current_player = self.X
self.board = [
[0, 0, 0],
[0, 0, 0],
[0, 0, 0],
]
# Our board is made up of 3 by 3 TicTacToeButtons
# The TicTacToeButton maintains the callbacks and helps steer
# the actual game.
for x in range(3):
for y in range(3):
self.add_item(TicTacToeButton(x, y))
# This method checks for the board winner -- it is used by the TicTacToeButton
def check_board_winner(self):
for across in self.board:
value = sum(across)
if value == 3:
return self.O
elif value == -3:
return self.X
# Check vertical
for line in range(3):
value = self.board[0][line] + self.board[1][line] + self.board[2][line]
if value == 3:
return self.O
elif value == -3:
return self.X
# Check diagonals
diag = self.board[0][2] + self.board[1][1] + self.board[2][0]
if diag == 3:
return self.O
elif diag == -3:
return self.X
diag = self.board[0][0] + self.board[1][1] + self.board[2][2]
if diag == 3:
return self.O
elif diag == -3:
return self.X
# If we're here, we need to check if a tie was made
if all(i != 0 for row in self.board for i in row):
return self.Tie
return None
class tictactoe(commands.Cog):
def __init__(self, client):
self.client = client
#app_commands.command(
name="tictactoe",
description="play tictactoe"
)
async def tictactoe(self,interaction: discord.Interaction):
await interaction.response.send_message('Tic Tac Toe: X goes first', view=TicTacToe())
async def setup(client: commands.Bot):
await client.add_cog(tictactoe(client))
Ok i did it with less than 10 lines of code if anyone wants a tictactoe command here it is:
from typing import List
from discord.ext import commands
import discord
from discord import app_commands
class TicTacToeButton(discord.ui.Button['TicTacToe']):
def __init__(self, x: int, y: int):
super().__init__(style=discord.ButtonStyle.secondary, label='\u200b', row=y)
self.x = x
self.y = y
# This function is called whenever this particular button is pressed
# This is part of the "meat" of the game logic
async def callback(self, interaction: discord.Interaction):
global player1
global player2
assert self.view is not None
view: TicTacToe = self.view
state = view.board[self.y][self.x]
if state in (view.X, view.O):
return
if view.current_player == view.X:
if interaction.user != player1:
await interaction.response.send_message("Its not your Turn!", ephemeral=True)
else:
self.style = discord.ButtonStyle.danger
self.label = 'X'
self.disabled = True
view.board[self.y][self.x] = view.X
view.current_player = view.O
content = "It is now O's turn"
else:
if interaction.user != player2:
await interaction.response.send_message("Its not your Turn!", ephemeral=True)
else:
self.style = discord.ButtonStyle.success
self.label = 'O'
self.disabled = True
view.board[self.y][self.x] = view.O
view.current_player = view.X
content = "It is now X's turn"
winner = view.check_board_winner()
if winner is not None:
if winner == view.X:
content = 'X won!'
elif winner == view.O:
content = 'O won!'
else:
content = "It's a tie!"
for child in view.children:
child.disabled = True
view.stop()
await interaction.response.edit_message(content=content, view=view)
# This is our actual board View
class TicTacToe(discord.ui.View):
# This tells the IDE or linter that all our children will be TicTacToeButtons
# This is not required
children: List[TicTacToeButton]
X = -1
O = 1
Tie = 2
def __init__(self):
super().__init__()
self.current_player = self.X
self.board = [
[0, 0, 0],
[0, 0, 0],
[0, 0, 0],
]
# Our board is made up of 3 by 3 TicTacToeButtons
# The TicTacToeButton maintains the callbacks and helps steer
# the actual game.
for x in range(3):
for y in range(3):
self.add_item(TicTacToeButton(x, y))
# This method checks for the board winner -- it is used by the TicTacToeButton
def check_board_winner(self):
for across in self.board:
value = sum(across)
if value == 3:
return self.O
elif value == -3:
return self.X
# Check vertical
for line in range(3):
value = self.board[0][line] + self.board[1][line] + self.board[2][line]
if value == 3:
return self.O
elif value == -3:
return self.X
# Check diagonals
diag = self.board[0][2] + self.board[1][1] + self.board[2][0]
if diag == 3:
return self.O
elif diag == -3:
return self.X
diag = self.board[0][0] + self.board[1][1] + self.board[2][2]
if diag == 3:
return self.O
elif diag == -3:
return self.X
# If we're here, we need to check if a tie was made
if all(i != 0 for row in self.board for i in row):
return self.Tie
return None
class tictactoe(commands.Cog):
def __init__(self, client):
self.client = client
#app_commands.command(
name="tictactoe",
description="play tictactoe"
)
async def tictactoe(self,interaction: discord.Interaction, enemy: discord.Member):
await interaction.response.send_message('Tic Tac Toe: X goes first', view=TicTacToe())
global player1
global player2
player1 = interaction.user
player2 = enemy
async def setup(client: commands.Bot):
await client.add_cog(tictactoe(client))```
I'm new to python and writing my first project. I'm trying to implement a check that if a space is already occupied, not to move there. I can't seem to figure out why my move_player method overwrites the index value of the board even though I am explicitly checking it (If it is O's turn and X has already been placed in the index O is trying to move to, it just overwrites it). I have tried hard coding the check for 'X' and 'O' instead of player.player as well but can't seem to figure it out. Does it have to do something with how Python works or am I implementing it wrong?
class Player:
def __init__(self, player):
self.player = player
class Board:
def __init__(self):
self.board = [[' ' for i in range(3)] for j in range(3)]
def display_board(self):
print('---------')
for row in self.board:
print('| ', end='')
for col in row:
print(f'{col} ', end='')
print('|')
print('---------')
def move_player(self, player):
try:
p1 = Player('X')
p2 = Player('O')
coordinates = [int(i) for i in input("Enter coordinates for move: ").split()]
xCoordinate = coordinates[0]
yCoordinate = coordinates[1]
if ((self.board[xCoordinate][yCoordinate] == p1.player) or
(self.board[xCoordinate][yCoordinate] == p2.player)):
print("That space is occupied, please choose another one.")
self.move_player(player)
else:
self.board[xCoordinate - 1][yCoordinate - 1] = player.player
except (ValueError, IndexError):
print("Please only enter numbers between 1 and 3.")
self.move_player(player)
def has_won(self, player):
if self.check_diagonal(player):
return True
elif self.check_across(player):
return True
elif self.check_down(player):
return True
return False
if __name__ == '__main__':
board = Board()
player1 = Player('X')
player2 = Player('O')
player = player1
while True:
board.display_board()
board.move_player(player)
if board.has_won(player):
board.display_board()
print(f'{player.player} wins!!!')
break
if player == player1:
player = player2
else:
player = player1
The code is very convoluted but from what I can see:
if ((self.board[xCoordinate][yCoordinate] == p1.player) or
(self.board[xCoordinate][yCoordinate] == p2.player)):
...
self.board[xCoordinate - 1][yCoordinate - 1] = player.player
You are checking [x,y] but assigning to [x-1,y-1].
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 7 years ago.
Improve this question
So I made a single player noughts and crosses in Python a little while ago in school.
score=[[' ',' ',' '],[' ',' ',' '],[' ',' ',' ']]
global attempts
attempts = 0
from random import randint
from time import sleep
def grid(): #draws playing grid
hideturtle()
speed(0)
pensize(0)
penup()
setpos(-200, -67)
pendown()
fd(400)
penup()
setpos(-200, 66)
pendown()
fd(400)
penup()
seth(90)
setpos(-67, -200)
pendown()
fd(400)
penup()
setpos(66, -200)
pendown()
fd(400)
def drawShape(s, x, y): #draws shape in grid box x and y = coord, s = shape type
hideturtle()
speed(100)
pensize(6)
penup()
if s == 'X': #draws 'X'
pencolor("orange")
setpos(-266+(133*x), -266+(133*y))
pendown()
seth(135)
fd(50)
rt(180)
fd(100)
rt(180)
fd(50)
rt(90)
fd(50)
rt(180)
fd(100)
elif s == 'O': #draws 'O'
pencolor("green")
setpos(-266+(133*x), -266+(133*y)-40)
seth(0)
pendown()
circle(40)
def ai(): #EXPERIMENTAL AI
x=0
y=0
d='O'
e='O'
f='O'
for i in range(3): #checks positions
if i == 0:
d=' '
elif i == 1:
d='O'
e=' '
elif i == 2:
d='O'
e='O'
f=' '
for c in range(3):
if score[c][0] == d and score[c][1] == e and score[c][2] == f:
x = c+1
y = i+1
print('v',c)
elif score[c][0] == d and score[c][1] == e and score[c][2] == f:
x = i=1
y = c+1
print('h',c)
if score[0][0] == d and score[1][1] == e and score[2][2] == f:
print('lr',i)
x = i+1
y = i+1
elif score[0][2] == d and score[1][1] == e and score[2][0] == f:
print('rl',i)
x = i+1
y = 4-i
d='X'
e='X'
f='X'
if x == 0 and y == 0: #checks oposition positions
for i in range(3):
if i == 0:
d=' '
elif i == 1:
d='X'
e=' '
elif i == 2:
d='X'
e='X'
f=' '
for c in range(3):
if score[c][0] == d and score[c][1] == e and score[c][2] == f:
x = c+1
y = i+1
print('op v')
elif score[c][0] == d and score[c][1] == e and score[c][2] == f:
x = i=1
y = c+1
print('op v')
if score[0][0] == d and score[1][1] == e and score[2][2] == f:
x = i+1
y = i+1
print('op bt')
elif score[0][2] == d and score[1][1] == e and score[2][0] == f:
x = i+1
y = 4-i
print('op tb')
if x == 0 and y == 0: #if no playable positions uses random
x = randint(1,3)
y = randint(1,3)
return x, y
def valid(u,x,y): #checks player move is valid
global attempts
if x > 3 or y > 3:
print ('Coordinate must be between 1 & 3')
elif x == '' or y == '':
print("Enter something!")
elif score[y-1][x-1] == ' ':
score[y-1][x-1] = u
drawShape(u, x, y)
attempts +=1
return True
elif score[y-1][x-1] == u:
print("You've already gone here! ")
return False
elif score[y-1][x-1] != u:
print("The other player is here! ")
return False
def userAgent(u): #makes AI or user prompts and sets array
global attempts
global a
global b
if u == 0:
a, b = ai()
score[b-1][a-1] = 'O'
print("The computer is taking its turn...")
print(a,b)
sleep(1)
drawShape('O', a, b)
attempts +=1
else:
x = input("Player "+u+": enter x coordinate (1-3) ")
y = input("Player "+u+": enter y coordinate (1-3) ")
try:
x = int(x)
y = int(y)
except ValueError:
print("That's not a valid number!")
userAgent(u)
while True:
if valid(u,x,y) == True:
break
x = input("Player "+u+": enter x coordinate (1-3) ")
y = input("Player "+u+": enter y coordinate (1-3) ")
try:
x = int(x)
y = int(y)
except ValueError:
print("That's not a valid number!")
def checkWin(n): #checks for a player win (3 in row) or stalemate
for i in range(3):
if score[i][0] == n and score[i][1] == n and score[i][2] == n:
print("Player "+n+" won!")
return True
elif score[0][i] == n and score[1][i] == n and score[2][i] == n:
print("Player "+n+" won!")
return True
if score[0][0] == n and score[1][1] == n and score[2][2] == n:
print("Player "+n+" won!")
return True
elif score[0][2] == n and score[1][1] == n and score[2][0] == n:
print("Player "+n+" won!")
return True
elif attempts == 9:
print("Stalemate!")
return True
else:
return False
def printGrid():
print(score[2])
print(score[1])
print(score[0])
from turtle import *
grid()
p = input("Are you playing by yourself? (SINGLE PLAYER EXPERIMENTAL) (y/n) ")
while True: #runs game until player win
if p == 'y':
userAgent('X')
printGrid()
if checkWin('X') == True:
break
userAgent(0)
printGrid()
if checkWin('O') == True:
break
elif p == 'n':
userAgent('X')
if checkWin('X') == True:
break
userAgent('O')
if checkWin('O') == True:
break
else:
print("You need to type y or n - try again!")
p = input("Are you playing by yourself? (SINGLE PLAYER EXPERIMENTAL) (y/n) ")
input('Press ENTER to exit')
Just ignore that AI function it's now permanently experimental (doesn't work) but that's not the problem.
I'm helping out at my school's open evening and I thought it'd be cool if 2 people could play against each other on different computers. So I'd host the server on my home PC with port forwarding, doing all the logic, and the clients would just take inputs, send them onto the server and draw moves by both players. I know HTTP POST/GET, but how would I get the server to tell the client the other player moved? I've looked into Twisted and it seems good, but I really don't understand classes (I've only been programming for a little while).
This would be on a school computer so I have no access to port forwarding for the client. Ideally I'd also have an IP whitelist so only the computer's I want can access the server....
Soooo can anyone help me out here? I just need to understand what code I'd need for the server and how the client would interact with it. Thanks :)
You can start from the twisted chatserver example
"""The most basic chat protocol possible.
run me with twistd -y chatserver.py, and then connect with multiple
telnet clients to port 1025
"""
from twisted.protocols import basic
class MyChat(basic.LineReceiver):
def connectionMade(self):
print "Got new client!"
self.factory.clients.append(self)
def connectionLost(self, reason):
print "Lost a client!"
self.factory.clients.remove(self)
def lineReceived(self, line):
print "received", repr(line)
for c in self.factory.clients:
c.message(line)
def message(self, message):
self.transport.write(message + '\n')
from twisted.internet import protocol
from twisted.application import service, internet
factory = protocol.ServerFactory()
factory.protocol = MyChat
factory.clients = []
application = service.Application("chatserver")
internet.TCPServer(1025, factory).setServiceParent(application)
The clients can use Python's builtin telnetlib to connect
Later on you can upgrade to using twisted for the client connections if you like.
The easiest way to have both clients interact through a server is to have both clients poll the server for updates. (you can do server side events, but that is way too complicated for what you are looking for).
However, if they are within the same network I recommend opening a socket server and client on each device directly communicating.
The way I would do it is to this:
Sockets servers are opened on both machines
Whoever starts the game opens a socket client and sends a the move directly to server, then reopens a socket server
The next move the computer opens a client and sends a move back to server.
This takes out all the unnecessary code for running a server.
See the python manual for sockets. There are great examples at the bottom for both server/client side.
https://docs.python.org/2/library/socket.html
You might want to take a look at ZeroMQ. http://zeromq.org/
Specifically, you'd want PyZMQ. http://zeromq.github.io/pyzmq/api/zmq.html
It's simple to set up, and you can connect the two computers directly. You'd be able to send messages back and forth between the two.
Definitely read the docs, but you're probably going to want a Request/Reply pattern.
I'm writing a tic-tac-toe game for an assignment. It needs to use object-oriented programming and it has to be relatively smart - it needs to block the player's success. I'm having a lot of trouble with this.
My trouble comes from my rowabouttowin method: I did a very convoluted list comprehension and I don't think that I did it correctly.
What I want is a method that checks if the player is about to win the game horizontally (O _ O, O O _, or _ O O if mark = O) and, if the player is, returns the position where the computer should play.
Any help or advice on how best to approach this?
from random import randint
class TTT:
board = [[' ' for row in range(3)] for col in range(3)]
currentgame = []
def print(self):
"""Displays the current board."""
print("\n-----\n".join("|".join(row) for row in self.board))
def mark(self,pos,mark):
"""Method that places designated mark at designated position on the board."""
x,y = pos
self.board[x][y] = mark
def win(self,mark):
"""Method that checks if someone has won the game."""
if mark == self.board[0][0] == self.board[1][1] == self.board[2][2]:
return True
if mark == self.board[2][0] == self.board[1][1] == self.board[0][2]:
return True
elif mark == self.board[0][0] == self.board[1][0] == self.board[2][0]:
return True
elif mark == self.board[1][0] == self.board[1][1] == self.board[1][2]:
return True
elif mark == self.board[0][1] == self.board[1][1] == self.board[2][1]:
return True
elif mark == self.board[0][2] == self.board[1][2] == self.board[2][2]:
return True
elif mark == self.board[0][0] == self.board[0][1] == self.board[0][2]:
return True
elif mark == self.board[2][0] == self.board[2][1] == self.board[2][2]:
return True
else:
return False
def choose(self,mark):
"""The computer chooses a place to play. If the player is not about to win,
plays randomly. Otherwise, does a series of checks to see if the player is about
to win horizontally, vertically, or diagonally. I only have horizontal done."""
spotx = randint(0,2)
spoty = randint(0,2)
if self.rowabouttowin(mark):
self.mark((self.rowabouttowin(mark)),mark)
elif self.legalspace(spotx,spoty):
self.mark((spotx,spoty),mark)
else:
self.choose(mark)
def legalspace(self,spotx,spoty):
"""Returns True if the provided spot is empty."""
if self.board[spotx][spoty] == ' ':
return True
else:
return False
def rowabouttowin(self,mark):
"""If the player is about to win via a horizontal 3-in-a-row,
returns location where the computer should play"""
for row in range(3):
if any(' ' == self.board[row][1] for i in range(3)) and any(self.board[row][i] == self.board[row][j] for i in range(3) for j in range(3)):
if self.board[row][i] == ' ' : yield(self.board[row][i % 3], self.board[row][i])
This currently gives this error message:
Traceback (most recent call last):
File "<pyshell#49>", line 1, in <module>
x.choose('x')
File "/Users/richiehoffman/Documents/Python Programs/Tic Tac Toe.py", line 40, in choose
self.mark((self.rowabouttowin(mark)),mark)
File "/Users/richiehoffman/Documents/Python Programs/Tic Tac Toe.py", line 11, in mark
x,y = pos
File "/Users/richiehoffman/Documents/Python Programs/Tic Tac Toe.py", line 61, in rowabouttowin
if self.board[row][i] == ' ' : yield(self.board[row][i % 3], self.board[row][i])
NameError: global name 'i' is not defined
A few tips:
You're using class variables, not instance variables, so look up the difference. I changed your class to use instance variables, as the variables that you set should belong in an instance.
Consider making things more readable.
Use __str__ to make the printable version of your class. That way, you can do print(class_instance) and it'll come out all nice.
Here's what I changed:
from random import randint
class TTT(object):
def __init__(self):
self.board = [[' ' for row in range(3)] for col in range(3)]
self.currentgame = []
def __str__(self):
"""Displays the current board."""
return "\n-----\n".join("|".join(row) for row in self.board)
def mark(self, pos, mark):
"""Method that places designated mark at designated position on the board."""
x, y = pos
self.board[x][y] = mark
def win(self, mark):
"""Method that checks if someone has won the game."""
for row in self.board:
if row[0] == row[1] == row[2]:
return True
for i in range(3):
if self.board[0][i] == self.board[1][i] == self.board[2][i]:
return True
if board[0][0] == board[1][1] == board[2][2]:
return True
elif board[0][2] == board[1][1] == board[2][0]:
return True
else:
return False
def choose(self, mark):
"""The computer chooses a place to play. If the player is not about to win,
plays randomly. Otherwise, does a series of checks to see if the player is about
to win horizontally, vertically, or diagonally. I only have horizontal done."""
spotx = randint(0, 2)
spoty = randint(0, 2)
if self.rowabouttowin(mark):
self.mark((self.rowabouttowin(mark)), mark)
elif self.legalspace(spotx, spoty):
self.mark((spotx, spoty), mark)
else:
self.choose(mark)
def legalspace(self, spotx, spoty):
"""Returns True if the provided spot is empty."""
return self.board[spotx][spoty] == ' '
def rowabouttowin(self, mark):
"""If the player is about to win via a horizontal 3-in-a-row,
returns location where the computer should play"""
for row in range(3):
check_one = any(' ' == self.board[row][1] for i in range(3))
check_two = any(self.board[row][i] == self.board[row][j] for i in range(3) for j in range(3))
# I have no idea what this code does
if self.board[row][i] == ' ' :
yield self.board[row][i % 3], self.board[row][i]