Part 1: Tic-Tac-Toe with changeable board size (Part 1)
I just revisited all my previous questions and saw that I hadn't updated my Tic-Tac-Toe code. So, I improvised my code as per @Austin Hastings suggestions
Here's the updated code:
import os
from random import randint
from textwrap import dedent
cls = lambda: os.system('CLS') # Works only in command console.
# Random names
names = [
'Jacob', 'Michael',
'Joshua', 'Ethan', 'Matthew', 'Daniel',
'Christopher', 'Andrew', 'Anthony', 'William',
'Joseph', 'Alexander', 'David', 'Ryan',
'Noah', 'James', 'Nicholas', 'Tyler',
'Logan', 'John', 'Christian', 'Jonathan',
'Nathan', 'Benjamin', 'Samuel', 'Dylan',
'Brandon', 'Gabriel', 'Elijah', 'Aiden',
'Angel', 'Jose', 'Zachary', 'Caleb',
'Jack', 'Jackson', 'Kevin', 'Gavin',
'Mason', 'Isaiah', 'Austin', 'Evan',
'Luke', 'Aidan', 'Justin', 'Jordan',
'Robert', 'Isaac', 'Landon', 'Jayden',
'Thomas', 'Cameron', 'Connor', 'Hunter',
'Jason', 'Diego', 'Aaron', 'Bryan',
'Owen', 'Lucas', 'Charles', 'Juan',
'Luis', 'Adrian', 'Adam', 'Julian',
'Alex', 'Sean', 'Nathaniel', 'Carlos',
'Jeremiah', 'Brian', 'Hayden', 'Jesus',
'Carter', 'Sebastian', 'Eric', 'Xavier',
'Brayden', 'Kyle', 'Ian', 'Wyatt',
'Chase', 'Cole', 'Dominic', 'Tristan',
'Carson', 'Jaden', 'Miguel', 'Steven',
'Caden', 'Kaden', 'Antonio', 'Timothy',
'Henry', 'Alejandro', 'Blake', 'Liam',
'Richard', 'Devin', 'Riley', 'Jesse',
'Seth', 'Victor', 'Brady', 'Cody',
'Jake', 'Vincent', 'Bryce', 'Patrick',
'Colin', 'Marcus', 'Cooper', 'Preston',
'Kaleb', 'Parker', 'Josiah', 'Oscar',
'Ayden', 'Jorge', 'Ashton', 'Alan',
'Jeremy', 'Joel', 'Trevor', 'Eduardo',
'Ivan', 'Kenneth', 'Mark', 'Alexis',
'Omar', 'Cristian', 'Colton', 'Paul',
'Levi', 'Damian', 'Jared', 'Garrett',
'Eli', 'Nicolas', 'Braden', 'Tanner',
'Edward', 'Conner', 'Nolan', 'Giovanni',
'Brody', 'Micah', 'Maxwell', 'Malachi',
'Fernando', 'Ricardo', 'George', 'Peyton',
'Grant', 'Gage', 'Francisco', 'Edwin',
'Derek', 'Max', 'Andres', 'Javier',
'Travis', 'Manuel', 'Stephen', 'Emmanuel',
'Peter', 'Cesar', 'Shawn', 'Jonah',
'Edgar', 'Dakota', 'Oliver', 'Erick',
'Hector', 'Bryson', 'Johnathan', 'Mario',
'Shane', 'Jeffrey', 'Collin', 'Spencer',
'Abraham', 'Leonardo', 'Brendan', 'Elias',
'Jace', 'Bradley', 'Erik', 'Wesley',
'Jaylen', 'Trenton', 'Josue', 'Raymond',
'Sergio', 'Damien', 'Devon', 'Donovan',
'Dalton', 'Martin', 'Landen', 'Miles',
'Israel', 'Andy', 'Drew', 'Marco',
'Andre', 'Gregory', 'Roman', 'Ty',
'Jaxon', 'Avery', 'Cayden', 'Jaiden',
'Roberto', 'Dominick', 'Rafael', 'Grayson',
'Pedro', 'Calvin', 'Camden', 'Taylor',
'Dillon', 'Braxton', 'Keegan', 'Clayton',
'Ruben', 'Jalen', 'Troy', 'Kayden',
'Santiago', 'Harrison', 'Dawson', 'Corey',
'Maddox', 'Leo', 'Johnny', 'Kai',
'Drake', 'Julio', 'Lukas', 'Kaiden',
'Zane', 'Aden', 'Frank', 'Simon',
'Sawyer', 'Marcos', 'Hudson', 'Trey'
]
# Dummy Variable
start = 0
# Essential Variables:
player = 'Player' # Player name
board_type = 2 # Board Type (1 or 2)
board = [['', '', ''], ['', '', ''], ['', '', '']] # The TicTacToe board
win_board = [['', '', ''], ['', '', ''], ['', '', '']] # Traces the win (if any) of 'board'
X = 'X'
O = 'O'
size = 3
def empty_cells():
empty = []
for i in range(size):
for j in range(size):
if board[i][j] != X and board[i][j] != O:
empty.append((i, j))
return empty
def countWins(p):
"""
Counts the wins possible in the current move for player 'p'
"""
count = 0
empty = empty_cells()
for i, j in empty:
copy = board[i][j]
board[i][j] = p
count += win(p)
board[i][j] = copy
return count
def get_insane_AI_move(ai, pl, x=0, name=''):
"""
ai: ai character
pl: player character
x: dummy variable
name: ai name
The best AI
Follows all the tips and checks for moves leading to multiple wins constantly
"""
empty = empty_cells()
length = len(empty)
if length == 1:
i, j = empty[0]
if x:
print(name + ' Moved To Grid', i * size + j + 1)
return
for i, j in empty:
copy = board[i][j]
board[i][j] = ai
if win(ai):
if x:
print(name + ' Moved To Grid', i * size + j + 1)
return
board[i][j] = copy
for i, j in empty:
copy = board[i][j]
board[i][j] = pl
if win(pl) or length == 1:
board[i][j] = ai
if x:
print(name + ' Moved To Grid', i * size + j + 1)
return
board[i][j] = copy
wins2 = []
l = 0
for i, j in empty:
copy = board[i][j]
board[i][j] = ai
if countWins(ai) > 1:
l += 1
r = [i, j]
wins2.append(r)
board[i][j] = copy
if l:
m = wins2[randint(0, 1000) % l]
board[m[0]][m[1]] = ai
if x:
print(name + ' Moved To Grid', m[0] * size + m[1] + 1)
return
l = 0
pos_centers = [[i, j] for i in range(size) for j in range(size)
if (i in [0, size - 1]) == (j in [0, size - 1]) == False]
centers = []
for i in range(len(pos_centers)):
x = pos_centers[i][0]
y = pos_centers[i][1]
if board[x][y] != ai and board[x][y] != pl:
centers.append(pos_centers[i])
l += 1
if l:
r = centers[randint(1, 1000) % l]
board[r[0]][r[1]] = ai
if x:
print(name + ' Moved To Grid', r[0] * size + r[1] + 1)
return
l1 = l2 = 0
pos_edges = [[0, 0], [0, size - 1], [size - 1, 0], [size - 1, size - 1]]
edges = []
for i in range(len(pos_edges)):
x = pos_edges[i][0]
y = pos_edges[i][1]
if board[x][y] != ai and board[x][y] != pl:
edges.append(pos_edges[i])
l1 += 1
if l1:
r = edges[randint(1, 1000) % l1]
board[r[0]][r[1]] = ai
if x:
print(name + ' Moved To Grid', r[0] * size + r[1] + 1)
return
pos_middles = [[i, j] for i in range(size) for j in range(size)
if (i in [0, size - 1]) != (j in [0, size - 1])]
middles = []
for i in range(len(pos_middles)):
x = pos_middles[i][0]
y = pos_middles[i][1]
if board[x][y] != ai and board[x][y] != pl:
middles.append(pos_middles[i])
l2 += 1
r = middles[randint(1, 1000) % l2]
board[r[0]][r[1]] = ai
if x:
print(name + ' Moved To Grid', r[0] * size + r[1] + 1)
return
def get_hard_AI_move(ai, pl, x=0, name=''):
"""
A medium AI
Can only look ahead 1 move
"""
empty = empty_cells()
length = len(empty)
if length == 1:
i, j = empty[0]
if x:
print(name + ' Moved To Grid', i * size + j + 1)
return
for i, j in empty:
copy = board[i][j]
board[i][j] = ai
if win(ai) == 1:
if x:
print(name + ' Moved To Grid', i * size + j + 1)
return
board[i][j] = copy
for i, j in empty:
copy = board[i][j]
board[i][j] = pl
if win(pl) == 1:
board[i][j] = ai
if x:
print(name + ' Moved To Grid', i * size + j + 1)
return
board[i][j] = copy
l = 0
possible = [[i, j] for i in range(size) for j in range(size)]
available = []
for i in range(len(possible)):
x = possible[i][0]
y = possible[i][1]
if board[x][y] != ai and board[x][y] != pl:
available.append(possible[i])
l += 1
r = available[randint(1, 1000) % l]
board[r[0]][r[1]] = ai
if x:
print(name + ' Moved To Grid', r[0] * size + r[1] + 1)
return
def get_easy_AI_move(ai, pl, x=0, name=''):
"""
An easy AI
Moves randomly
"""
l = 0
available = []
for x, y in empty_cells():
if board[x][y] != ai and board[x][y] != pl:
available.append((x, y))
l += 1
r = available[randint(1, 1000) % l]
board[r[0]][r[1]] = ai
if x:
print(name + ' Moved To Grid', r[0] * size + r[1] + 1)
return
def get_user_move(p1, p2):
""" Gets user input and processes it """
g = int(input(f'Please Enter Grid Number (1 ~ {size * size}): ')) - 1
x = g // size
y = g % size
if x >= size or y >= size or board[x][y] == p1 or board[x][y] == p2:
print('Please Enter A Valid Move')
get_user_move(p1, p2)
return
print(player + ' Moved To Grid', g + 1)
board[x][y] = p1
print()
def get_win(p):
""" Traces the win into 'win_board' """
for i in range(size):
# Rows
if all(board[i][j] == p for j in range(size)):
for j in range(size):
win_board[i][j] = p
return
# Columns
if all(board[j][i] == p for j in range(size)):
for j in range(size):
win_board[j][i] = p
return
# Diagonals
if all(board[i][i] == p for i in range(size)):
for i in range(size):
win_board[i][i] = p
return
if all(board[i][-(i + 1)] == p for i in range(size)):
for i in range(size):
win_board[i][-(i + 1)] = p
return
## Returns in every case as multiple wins might be traced out
def printBoard1():
""" Prints board type 1 """
for i in range(size - 1):
print(' ' + '| ' * (size - 1))
print(end=' ')
for j in range(size - 1):
print(board[i][j], end=' | ')
print(board[i][-1])
print(' ' + '| ' * (size - 1))
print('------' + '--------' * (size - 1))
' | '
print(' ' + '| ' * (size - 1))
print(end=' ')
for j in range(size - 1):
print(board[-1][j], end=' | ')
print(board[-1][-1])
print(' ' + '| ' * (size - 1))
print()
def printBoard2():
""" Prints board type 2 """
for i in range(size - 1):
for j in range(size - 1):
print(board[i][j], end=' | ')
print(board[i][-1])
print('---' * size + '-' * (size - 3))
for j in range(size - 1):
print(board[-1][j], end=' | ')
print(board[-1][-1])
print()
def printWin(p):
""" Prints 'win_board' at board type 2"""
get_win(p)
for i in range(size - 1):
for j in range(size - 1):
print(win_board[i][j], end=' | ')
print(win_board[i][-1])
print('---' * size + '-' * (size - 2))
for j in range(size - 1):
print(win_board[-1][j], end=' | ')
print(win_board[-1][-1])
print()
def getRandomName():
""" Gets random names from 'names' """
name = names[randint(1, 1000) % 250]
return name
def helper():
""" Help section containing Rules, Tips and Credits """
print()
print('B for Back\n')
print('1. Rules')
print('2. Tips')
print('3. Credits')
option = input('\nPlease Enter Your Option: ').lower()
print()
if option == 'b': return
if option == '1': rules()
if option == '2': tips()
if option == '3': about()
input('Enter To Continue . . . ')
print()
helper()
def about():
print('This Game Of Tic-Tac-Toe Is Created By Srivaths')
print('If You Are Unfamiliar With This Game, Please Read The Rules And Tips')
print('Enjoy!!\n')
def changeName():
""" Changes player name: 'player' """
global player
player = input('Please Enter Your Name: ')
def changeBoard():
""" Changes board type: 'board_type' """
global board_type
print()
print('B for Back\n')
print('1.')
printBoard1()
print('2.\n')
printBoard2()
print()
option = input('\nPlease Enter Your Option: ')
if option == 'b' or option == 'B':
return
if option == '1': board_type = 1
if option == '2': board_type = 2
def changeCharacters():
""" Changes characters: 'X', 'O' """
global X, O
print()
X = input('Please Enter Character For Player 1 (currently ' + X + '): ')
O = input('Please Enter Character For Player 2 (currently ' + O + '): ')
def changeSize():
""" Changes board size: 'size' """
global size
size = int(input('Please Enter Size: '))
initialize()
def settings():
""" Settings """
print()
print('B for Back\n')
print('1. Change Name')
print('2. Change Size')
print('3. Change Board')
print('4. Change Characters')
option = input('\nPlease Enter Your Option: ').lower()
if option == 'b':
return
if option == '1': changeName()
if option == '2': changeSize()
if option == '3': changeBoard()
if option == '4': changeCharacters()
print()
settings()
def main_menu():
""" The main menu """
global start
# cls()
print()
if start == 0:
intro()
start = 1
main_menu()
return
print('Hello ' + player)
print('\nQ for Quit\n')
print('1. Help')
print('2. Settings')
print('3. Play')
option = input('\nPlease Enter Your Option: ')
if option == '1':
helper()
if option == '2':
settings()
if option == '3':
initialize()
play('X', 'O')
if option == 'q' or option == 'Q':
print('Thanks For Playing!\n')
return
print()
main_menu()
def rules():
""" Basic rules """
print(
dedent('''
1. In Tic-Tac-Toe, there are 2 players and their characters are X and O respectively
2. Any row or column or diagonal filled the same character is a win
3. A board where there are no moves left is a tie
4. You are not allowed to place characters over another
5. The playes must play in alternate turns, starting with X
''')
)
def tips():
""" Basic tips """
print(
dedent(
'''
1. Always try and capture the center
2. Next try to capture the edges
3. Occupy the edges only if necessary
4. Be aware of immediate moves
5. Try the easy bot to get the hang of the game
'''
)
)
def intro():
""" Introduction """
global board_type
initialize()
print('Hello Player', end=', ')
changeName()
print('\nHello ' + player + ', Welcome To The Game Of Tic-Tac-Toe!!')
know = input('Are You Familiar With The Game? (y / n): ').lower()
if know == 'n':
print('\nFirst A Little Introduction To The Rules: \n')
rules()
print('\nNext A Few Tips: \n')
tips()
print('\nAnd That\'s ALL!!!\n')
input('Enter To Continue . . . ')
print('\n')
print('\nPlease Pick Your Board Preference: \n')
print('1.')
printBoard1()
print('2.\n')
printBoard2()
print()
option = input('Please Enter Your Option: ')
if option == '1': board_type = 1
if option == '2': board_type = 2
print(
dedent('''
Change Characters Via [Main Menu -> Settings -> Change Characters]
Here You Must Try Your Luck Against Three Levels!!
1. Easy
2. Hard
3. Insane
Can YOU Beat Them ALL????
Let's See....
''')
)
input('Enter To Continue . . . ')
def play(p1, p2):
"""
The play area
p1: Player 1
p2: Player 2
"""
print()
initialize()
computer = getRandomName()
print('1. Easy')
print('2. Hard')
print('3. Insane')
print()
level = int(input('Please Enter Level: '))
print()
while computer == player:
computer = getRandomName()
print('\t\t' + player + ' VS ' + computer + '\n\n')
c = randint(0, 1)
pl = p1
ai = p2
if c == 0:
ai = p1
pl = p2
print('\n' + computer + ' Goes First!\n\n')
else:
print('\n' + player + ' Goes First!\n\n')
if board_type == 1:
printBoard1()
else:
printBoard2()
d = 0
while True:
t = d % 2
if t == c:
if level == 1: get_easy_AI_move(ai, pl, 1, computer)
if level == 2: get_hard_AI_move(ai, pl, 1, computer)
if level == 3: get_insane_AI_move(ai, pl, 1, computer)
if board_type == 1:
printBoard1()
else:
printBoard2()
if win(ai):
print(computer + ' Wins!\n')
print('Below Is How ' + computer + ' Won\n\n')
printWin(ai)
break
else:
get_user_move(pl, ai)
if board_type == 1:
printBoard1()
else:
printBoard2()
if win(pl):
print(player + ' Wins!')
print('Below Is How ' + player + ' Won\n')
printWin(pl)
break
if len(empty_cells()) == 0:
print('Tie!')
break
d += 1
play_again(p1, p2)
def initialize():
""" Resets the board """
global board, win_board
board = [[' ' for _ in range(size)] for __ in range(size)]
win_board = [[' ' for _ in range(size)] for __ in range(size)]
def play_again(p1, p2):
""" Gets input from the player asking if they want to play again """
option = input('Would You Like To Play Again? (y(yes) / n(no) / m(Main Menu): ').lower()
if option == 'y':
play(p1, p2)
elif option == 'n':
return
elif option == 'm':
return
else:
print('\nPlease Enter a Valid Option')
play_again(p1, p2)
def win(p):
""" Checks for win """
if any(all(board[i][j] == p for j in range(size)) for i in range(size)):
return True
if any(all(board[j][i] == p for j in range(size)) for i in range(size)):
return True
if all(board[i][i] == p for i in range(size)):
return True
if all(board[i][-(i + 1)] == p for i in range(size)):
return True
return False
main_menu()
Hope @Austin Hastings will answer this question too!