Tic tac toe
This is a problem set. Some of these are easy, others are far more difficult. The purpose of these problems sets are:
- to build your skill applying computational thinking to a problem
- to assess your knowledge and skills of different programming practices
What is this problem set trying to do[edit]
This problem set is testing your computational thinking, your skill and understanding of lists, and your skill and understanding of loops
The Problem[edit]
Your program must do three things:
- it must allow a human to play against a computer a game of tic tac toe
- your program must have win and lose conditions
- it must draw a tic tac to board, updated with x's and O's as the computer and human play.
- It must follow the rules of tic tac toe
Hacker edition[edit]
In the hacker version:
- Your program should be good at playing tic tac toe
Python Version[edit]
import random
# initialization stuff here:
board = [1,2,3,4,5,6,7,8,9]
computerSpaces = []
humanSpaces =[1]
game = 0
def drawPieces(position):
if position in humanSpaces:
return "X"
elif position in computerSpaces:
return "O"
else:
return position
# this function draws the board
def drawBoard():
print("")
print("")
print(" ",drawPieces(1)," | (2) | (3) ")
print(" | | ")
print("----------------------")
print(" (4) | (5) | (6) ")
print(" | | ")
print("----------------------")
print(" (7) | (8) | (9) ")
print(" | | ")
return
# this function manages player moves
def playerMove(move):
return
# this function manages computer moves
def computerMove(computerMove):
return
while True:
print(drawBoard())
move=input("Please choose a move (99 to quit): ")
if move == "99":
break
elif str(move) in computerSpaces or str(move) in humanSpaces:
print("this is a invalid move")
else:
humanSpaces.append(move)
print(humanSpaces)
# playerMove(move)
Javascript Version[edit]
How you will be assessed[edit]
Your solution will be graded using the following axis:
Scope
- To what extent does your code implement the features required by our specification?
- To what extent is there evidence of effort?
Correctness
- To what extent did your code meet specifications?
- To what extent did your code meet unit tests?
- To what extent is your code free of bugs?
Design
- To what extent is your code written well (i.e. clearly, efficiently, elegantly, and/or logically)?
- To what extent is your code eliminating repetition?
- To what extent is your code using functions appropriately?
Style
- To what extent is your code readable?
- To what extent is your code commented?
- To what extent are your variables well named?
- To what extent do you adhere to style guide?
References[edit]
A possible solution[edit]
Click the expand link to see one possible solution in Python, but NOT before you have tried and failed!
import PySimpleGUI as sg
import random
from PySimpleGUI.PySimpleGUI import WINDOW_CLOSED
sg.theme('Python')
turn = 1
turn2 = 0
board = [0,1,2,3,4,5,6,7,8]
win_p = [
[0,1,2],
[3,4,5],
[6,7,8],
[0,3,6],
[1,4,7],
[2,5,8],
[0,4,8],
[2,4,6]
]
def draw_board():
print(board[0],board[1],board[2])
print(board[3],board[4],board[5])
print(board[6],board[7],board[8])
computer_first_move = random.choice(board)
board[computer_first_move-1] = "X"
layout = [
[sg.Text('The turn is:',font=("Helevtica", 25), key='D'), sg.Text(turn, key = 'D1',font=("Helevtica", 25))],
[sg.Button(board[0],font=("Helevtica", 50),key = '0'),sg.Button(board[1],font=("Helevtica", 50),key = '1'),sg.Button(board[2],font=("Helevtica", 50),key = '2')],
[sg.Button(board[3],font=("Helevtica", 50),key = '3'),sg.Button(board[4],font=("Helevtica", 50),key = '4'),sg.Button(board[5],font=("Helevtica", 50),key = '5')],
[sg.Button(board[6],font=("Helevtica", 50),key = '6'),sg.Button(board[7],font=("Helevtica", 50),key = '7'),sg.Button(board[8],font=("Helevtica", 50),key = '8')],
]
window = sg.Window('TicTacToe', layout)
while True:
event, values = window.read()
if event == WINDOW_CLOSED:
break
print(event)
for i in range(0,9):
if str(event) == str(board[i]):
window[str(i)].update('O')
board[i] = "O"
draw_board()
computer_turn = True
count2 = 0
win = 0
loss = 0
#================================================================
if(event):
for x in win_p:
count = 0
count1 = 0
poss = []
for i in x:
if(board[i]) == "O":
count = count +1
if count == 3:
win += 1
break
if win == 1:
draw_board()
sg.popup('YOU WON!')
# #================================================================
for x in win_p:
count = 0
count1 = 0
poss = []
for i in x:
if(board[i]) == "O":
count = count +1
if count == 0:
for i in x:
if(board[i]) == "X":
count1 = count1 + 1
if (count1 == 2) and (computer_turn == True):
for i in x:
if(board[i]) != "X":
window[str(i)].update('X')
board[i] = "X"
loss = loss + 1
break
computer_turn == False
if loss == 1:
draw_board()
sg.popup("YOU LOST")
break
#=============================================================================
for x in win_p:
count = 0
count1 = 0
poss = []
for i in x:
if(board[i]) == "O":
count = count +1
if count == 2 and computer_turn == True:
for i in x:
if(board[i]) != "O" and (board[i]) != "X":
board[i] = "X"
window[str(i)].update('X')
computer_turn = False
# #=============================================================================
for x in win_p:
count = 0
count1 = 0
poss = []
for i in x:
if(board[i]) == "O":
count = count +1
if count == 0:
for i in x:
if(board[i]) == "X":
count1 =+ 1
if (count1 == 1) and (computer_turn == True):
print(x)
for i in x:
print(i,board[i])
if(board[i]) != "X":
poss.append(i)
print(poss)
q = random.choice(poss)
board[q] = "X"
window[str(q)].update('X')
computer_turn = False
for i in range(0,9):
if board[i] != i:
count2 = count2 + 1
print("count2:",count2)
if count2 == 8:
for i in range(0,9):
if board[i] == i:
board[i] = "X"
window[str(i)].update('X')
draw_board()
sg.popup("Tie")
break
if count2 == 9:
draw_board()
sg.popup("Tie")
break
print("="*25)
draw_board()
turn = turn+1
window['D1'].update(turn)
print("loop")
# ====================== another example below ==================================
import os, random, time
#setting
table = ["\033[1;30m1\033[0m","\033[1;30m2\033[0m","\033[1;30m3\033[0m","\033[1;30m4\033[0m","\033[1;30m5\033[0m","\033[1;30m6\033[0m","\033[1;30m7\033[0m","\033[1;30m8\033[0m","\033[1;30m9\033[0m"]
# table1 = ["\033[1;30m1\033[0m","\033[1;30m2\033[0m","\033[1;30m3\033[0m","\033[1;30m4\033[0m","\033[1;30m5\033[0m","\033[1;30m6\033[0m","\033[1;30m7\033[0m","\033[1;30m8\033[0m","\033[1;30m9\033[0m"]
ending = False
def drawing():
os.system('clear')
print(f"{table[0]} {table[1]} {table[2]}")
print(f"\n{table[3]} {table[4]} {table[5]}")
print(f"\n{table[6]} {table[7]} {table[8]}")
#event loop
while True:
drawing()
a=0
b=0
#win or lose or draw
# if any(table1) in table:
# print("You draw!")
# ending = True
if table[0] == table[4] == table[8]:
if table[0] == 'O':
print("You Win!")
ending = True
else:
print("You Lose!")
ending = True
elif table[2] == table[4] == table[6]:
if table[2] == 'O':
print("You Win!")
ending = True
else:
print("You Lose!")
ending = True
for i in range(3):
if table[a] == table[a+1] == table[a+2]:
if table[a] == 'O':
print("You Win!")
ending = True
else:
print("You Lose!")
ending = True
elif table[b] == table[b+3] == table[b+6]:
if table[b] == 'O':
print("You Win!")
ending = True
else:
print("You Lose!")
ending = True
a += 3
b += 1
if ending == True:
break
#user's turn
user_move = int(input("\nplace number: "))
if table[user_move-1] != 'O' and table[user_move-1] != 'X':
table[user_move-1] = 'O'
else:
input("that's not proper place...")
continue
drawing()
#computer's turn
while True:
a=0
b=0
## simple UI logic
# if table[4] == 'X' or 'O':
# if table[4] == table[0] or table[4] == table[8]:
# if table[0] == 'O' or 'X':
# table[8] = 'X'
# break
# elif table[8] == 'O' or 'X':
# table[0] = 'X'
# break
# elif table[4] == table[2] or table[4] == table[6]:
# if table[2] == 'O' or 'X':
# table[6] == 'X'
# break
# elif table[6] == 'O' or 'X':
# table[2] == 'X'
# break
# else:
# pass
# for i in range(3):
# if table[a] == table[a+1] or table[a+1] == table[a+2] and table[a+1] == 'X' or 'O':
# if table[a] == 'O' or 'X':
# table[a] = 'X'
# logic_loop = False
# if table[a+2] == 'O' or 'X':
# table[a+2] = 'X'
# break
# elif table[b] == table[b+3] or table[b+3] == table[b+6] and table[b+3] == 'X' or 'O':
# if table[b] == 'O' or 'X':
# table[b] = 'X'
# break
# if table[b+6] == 'O' or 'X':
# table[b+6] = 'X'
# break
# else:
# pass
# a += 3
# b += 1
com_move = random.randrange(1,10)
if table[com_move-1] != 'O' and table[com_move-1] != 'X':
table[com_move-1] = 'X'
break
else:
continue
time.sleep(0.7)
# ============================ second example below ====================
import random
# initialization stuff here:
board = [1,2,3,4,5,6,7,8,9]
computerSpaces = []
humanSpaces =[]
game = 0
# this function draws pieces on the board.
def drawPieces(position):
if position in humanSpaces:
return "X"
elif position in computerSpaces:
return "O"
else:
return position
# this function manages player moves
def playerMove(move):
humanSpaces.append(move)
humanSpaces.sort()
board.remove(int(move))
return
# this function manages computer moves
def computerMove():
# we choose a possible move from any moves left in the list board
move=random.choice(board)
# we append the move we just made into a list
computerSpaces.append(str(move))
# we sort the list because our win conditions are in a certain order. 1,2,3 is a win, but 3,2,1 isn't.
# sorting is a bit of a hack (there might be a better way to test for membership in a list iregardless of order)
computerSpaces.sort()
# finally, we remove the place from our list keeping track of the places.
board.remove(move)
return
# this function draws the board
def drawBoard():
print("")
print("")
print(" ",drawPieces('1')," | ",drawPieces('2')," | ",drawPieces('3'), " ")
print(" | | ")
print("----------------------")
print(" ",drawPieces('4')," | ",drawPieces('5')," | ",drawPieces('6'), " ")
print(" | | ")
print("----------------------")
print(" ",drawPieces('7')," | ",drawPieces('8')," | ",drawPieces('9'), " ")
print(" | | ")
return
# this functions looks for win win conditions
def winConditions():
winConditions = [['1','2','3'],['4','5','6'],['7','8','9'],['1','5','9'],['3','5','7'],['1','4','7'],['2','5','8'],['3','6','9']]
if any(humanSpaces) in winConditions:
print("human won")
raise SystemExit
elif any(computerSpaces) in winConditions:
print("commputer won")
raise SystemExit
return
# main game loop
while True:
print(board)
print(drawBoard())
move=input("Please choose a move (99 to quit): ")
if move == "99":
break
elif str(move) in computerSpaces or str(move) in humanSpaces:
print("this is a invalid move")
else:
playerMove(move)
computerMove()
winConditions()
print(humanSpaces)
print(computerSpaces)
# playerMove(move)
#
# ==========================. example three below ==================
#
import itertools
import random
import os
def check_win(board):
for j in [0,3,6]:
if board[j] == board[j+1] and board[j] == board[j+2] and board[j] != "-":
return board[j]
for j in [0,1,2]:
if board[j] == board[j+3] and board[j] == board[j+6] and board[j] != "-":
return board[j]
if board[0] == board[4] and board[0] == board[8] and board[0] != "-":
return board[0]
if board[2] == board[4] and board[2] == board[6] and board[2] != "-":
return board[2]
return "draw"
def calculate(stones):
table = ["-", "-", "-", "-", "-", "-", "-", "-", "-"]
pl_1 = [stones[0],stones[2],stones[4],stones[6],stones[8]]
for j in range(9):
k = stones[j]
if k in pl_1:
table[k-1] = "1"
else:
table[k-1] = "2"
result = check_win(table)
if result == "1":
return "player 1"
elif result == "2":
return "player 2"
else:
pass
return "draw"
def find_ans(log,turn):
INF = 10**10
rates = []
left = [1,2,3,4,5,6,7,8,9]
for i in log:
left.remove(i)
left_clone = []
for i in left:
left_clone.append(i)
for k in left_clone:
t_logs = []
left.remove(k)
for i in itertools.permutations(left,len(left)):
b = list(i)
t_logs.append(log +[k]+ b)
left = [1,2,3,4,5,6,7,8,9]
for i in log:
left.remove(i)
count = 0
wincount = 0
losecount = 0
for i in t_logs:
count += 1
result = calculate(i)
if turn == 0:
if result == "player 1":
losecount += 1
if result == "player 2":
wincount += 1
elif turn == 1:
if result == "player 2":
losecount += 1
if result == "player 1":
wincount += 1
winrate = wincount/count
loserate = losecount/count
rates.append([k,winrate, loserate])
g_lose = INF
for i in rates:
if i[2] < g_lose:
decision = i[0]
g_win = i[1]
g_lose = i[2]
elif i[2] == g_lose and i[1] > g_win:
decision = i[0]
g_win = i[1]
g_lose = i[2]
elif i[2] == g_lose and i[1] == g_win:
if random.choice([True, False]):
decision = i[0]
g_win = i[1]
g_lose = i[2]
if i[1] >= 0.95:
decision = i[0]
g_win = i[1]
g_lose = i[2]
break
return decision
# tic-tac-toe
table = ["-","-","-","-","-","-","-","-","-"]
log = []
first = random.choice(['your',"opponent's"])
if first == 'your':
now = True
else:
now = False
def turn(choice,sign):
table[choice-1] = sign
log.append(choice)
update_color('grid1',table[0])
update_color('grid2',table[1])
update_color('grid3',table[2])
update_color('grid4',table[3])
update_color('grid5',table[4])
update_color('grid6',table[5])
update_color('grid7',table[6])
update_color('grid8',table[7])
update_color('grid9',table[8])
end = check_win(table)
if end == "draw":
pass
elif end == "x":
sg.popup("Blue win!")
return 'break'
elif end == "o":
sg.popup("Red win!")
return 'break'
if '-' not in table:
return 'break'
import PySimpleGUI as sg
colors = [None, 'red','blue']
def update_color(grid,mark):
if mark == '-':
window[grid].update(background_color='white')
elif mark == 'o':
window[grid].update(background_color='red')
elif mark == 'x':
window[grid].update(background_color='blue')
sg.theme('DarkAmber')
layout = [
[sg.Text(f"{first} turn", key='Turn')],
[sg.Text(key='grid1',size=(5,3),background_color='white',text_color='black'),sg.Text(key='grid2',size=(5,3),background_color='white',text_color='black'),sg.Text(key='grid3',size=(5,3),background_color='white',text_color='black')],
[sg.Text(key='grid4',size=(5,3),background_color='white',text_color='black'),sg.Text(key='grid5',size=(5,3),background_color='white',text_color='black'),sg.Text(key='grid6',size=(5,3),background_color='white',text_color='black')],
[sg.Text(key='grid7',size=(5,3),background_color='white',text_color='black'),sg.Text(key='grid8',size=(5,3),background_color='white',text_color='black'),sg.Text(key='grid9',size=(5,3),background_color='white',text_color='black')],
[sg.Button('1',size=(1.5,1.5)),sg.Button('2',size=(1.5,1.5)),sg.Button('3',size=(1.5,1.5))],
[sg.Button('4',size=(1.5,1.5)),sg.Button('5',size=(1.5,1.5)),sg.Button('6',size=(1.5,1.5))],
[sg.Button('7',size=(1.5,1.5)),sg.Button('8',size=(1.5,1.5)),sg.Button('9',size=(1.5,1.5))],
[sg.Button('pass turn',)]
]
window = sg.Window('IMPOSIBLE TIC_TAC_TOE',layout)
while True:
p1_choice = '$$'
event, value = window.read()
if event == sg.WINDOW_CLOSED:
break
if True:
if event == '1':
if table[0] == '-':
p1_choice = 1
if event == '2':
if table[1] == '-':
p1_choice = 2
if event == '3':
if table[2] == '-':
p1_choice = 3
if event == '4':
if table[3] == '-':
p1_choice = 4
if event == '5':
if table[4] == '-':
p1_choice = 5
if event == '6':
if table[5] == '-':
p1_choice = 6
if event == '7':
if table[6] == '-':
p1_choice = 7
if event == '8':
if table[7] == '-':
p1_choice = 8
if event == '9':
if table[8] == '-':
p1_choice = 9
if not now:
p1_choice = -1
if p1_choice == '$$':
continue
if first == 'your':
if now:
if turn(p1_choice,'x') == 'break':
break
else:
p2_choice = find_ans(log,0)
if turn(p2_choice,'o') == 'break':
break
if first == "opponent's":
if now:
if turn(p1_choice,'o') == 'break':
break
else:
p2_choice = find_ans(log,1)
if turn(p2_choice,'x') == 'break':
break
if now:
window['Turn'].update("opponent's turn")
else:
window['Turn'].update("your turn")
now = not now
end = check_win(table)
if end == "draw":
sg.popup("draw")
window.close()
Click the expand link to see one possible solution in Javascript, but NOT before you have tried and failed!