# Tic Tac Toe
def drawBoard(board):
# This function prints out the board that it was passed.
# "board" is a list of 10 strings representing the board (ignore index 0)
print(' ' + board[7] + ' | ' + board[8] + ' | ' + board[9]) print(' ' + board[4] + ' | ' + board[5] + ' | ' + board[6]) print(' ' + board[1] + ' | ' + board[2] + ' | ' + board[3])
def inputPlayerLetter():
# Lets the player type which letter they want to be.
# Returns a list with the player's letter as the first item, and the computer's letter as the second.
letter = ''
while not (letter == 'X' or letter == 'O'): # letter가 X 또는 O이 아니라면 계속 반복
print('Do you want to be X or O?') letter = input().upper() # 플레이어의 글자가 된다.
# the first element in the tuple is the player's letter, the second is the computer's letter.
# 정해진 글자들을 리스트로 반환한다 [플레이어,컴퓨터]
if letter == 'X':
else:
def whoGoesFirst():
# Randomly choose the player who goes first.
if random.randint(0, 1) == 0: # 랜덤 수를 이용해 누가 먼저할 지를 뽑는다.
else:
def playAgain():
# This function returns True if the player wants to play again, otherwise it returns False.
print('Do you want to play again? (yes or no)') return input().lower().startswith('y') # startswith('@')메소드 : 문자열이 @로 시작하는 검사한다.
def makeMove(board, letter, move):
board[move] = letter
# 리스트와 딕셔너리의 데이터 타입은 함수 파라미터로 값을 넣어 변경해주어도 값이 없어지지 않는다.
# 일반 primitve data type가 다르다.
# 리스트 레퍼런스(Reference), 딕셔너리 레퍼런스(Dictionary Reference)
# 레퍼런스 는 가르키는 값이다. 그러므로 리스트를 복사시, 리스트 자체가 아닌 레퍼런스를 집어넣기 때문에
# 동일한 리스트를 가르키는 값을 가진다.
def isWinner(bo, le):
# Given a board and a player's letter, this function returns True if that player has won.
# We use bo instead of board and le instead of letter so we don't have to type as much.
return ((bo[7] == le and bo[8] == le and bo[9] == le) or # across the top (bo[4] == le and bo[5] == le and bo[6] == le) or # across the middle
(bo[1] == le and bo[2] == le and bo[3] == le) or # across the bottom
(bo[7] == le and bo[4] == le and bo[1] == le) or # down the left side
(bo[8] == le and bo[5] == le and bo[2] == le) or # down the middle
(bo[9] == le and bo[6] == le and bo[3] == le) or # down the right side
(bo[7] == le and bo[5] == le and bo[3] == le) or # diagonal
(bo[9] == le and bo[5] == le and bo[1] == le)) # diagonal
def getBoardCopy(board):
# Make a duplicate of the board list and return it the duplicate.
dupeBoard = []
for i in board:
dupeBoard.append(i)
def isSpaceFree(board, move):
# Return true if the passed move is free on the passed board.
def getPlayerMove(board):
# Let the player type in his move.
move = ' '
# 건너뛰기(Short-Circuit) : or 연산자 왼쪽에 있는 조건이 True가 되면 전체 표현식은 True가 되므로, 오른쪽의 값은 호출하지 않고 넘어간다.
# - 그러므로 밑의 isSpaceFree함수의 파라미터 int() 형변환에서 에러가 발생하지 않는다.
# - 하지만 순서가 조건의 순서가 바뀐다면 문제가 생길 수 있다.
while move not in '1 2 3 4 5 6 7 8 9'.split() or not isSpaceFree(board, int(move)): print('What is your next move? (1-9)') move = input()
def chooseRandomMoveFromList(board, movesList):
# Returns a valid move from the passed list on the passed board.
# Returns None if there is no valid move.
possibleMoves = []
for i in movesList:
if isSpaceFree(board, i):
possibleMoves.append(i) # 움직일 수 있는 위치를 판멸해 리스트에 저장한다.
if len(possibleMoves) != 0: # 움직일 수 있는 위치의 리스트의 길이가 0이 아니라면
return random.choice(possibleMoves) # 랜덤으로 리스트 중 하나를 뽑아낸다. else: # 길이가 0이라면, 뽑아낼 수 있는 위치가 없다는 뜻이다.
return None # None 값은 변수에 할당할 수 있는 특수한 값으로 None Value 값이 없다는 뜻이다.
def getComputerMove(board, computerLetter): # 컴퓨터의 인공지능 부분
# Given a board and the computer's letter, determine where to move and return that move.
if computerLetter == 'X':
playerLetter = 'O'
else:
playerLetter = 'X'
# Here is our algorithm for our Tic Tac Toe AI:
# First, check if we can win in the next move
# 다음 수로 컴퓨터가 이기는 지 검사한다.
for i in range(1, 10):
copy = getBoardCopy(board)
if isSpaceFree(copy, i):
makeMove(copy, computerLetter, i)
if isWinner(copy, computerLetter):
# Check if the player could win on his next move, and block them.
# 다음 수로 플레이어가 이기는 지 검사한다.
for i in range(1, 10):
copy = getBoardCopy(board)
if isSpaceFree(copy, i):
makeMove(copy, playerLetter, i)
if isWinner(copy, playerLetter):
# Try to take one of the corners, if they are free.
move = chooseRandomMoveFromList(board, [1, 3, 7, 9])
if move != None:
# Try to take the center, if it is free.
if isSpaceFree(board, 5):
# Move on one of the sides.
return chooseRandomMoveFromList(board, [2, 4, 6, 8])
def isBoardFull(board):
# Return True if every space on the board has been taken. Otherwise return False.
for i in range(1, 10):
if isSpaceFree(board, i):
print('Welcome to Tic Tac Toe!')
while True:
# Reset the board
theBoard = [' '] * 10 # 곱하기(*)연산자로 쉽게 문자열을 만들 수 있다. = ['','','','','','','','','','']
playerLetter, computerLetter = inputPlayerLetter()
turn = whoGoesFirst()
print('The ' + turn + ' will go first.') gameIsPlaying = True
while gameIsPlaying:
if turn == 'player':
# Player's turn.
drawBoard(theBoard)
move = getPlayerMove(theBoard)
makeMove(theBoard, playerLetter, move)
if isWinner(theBoard, playerLetter):
drawBoard(theBoard)
print('Hooray! You have won the game!') gameIsPlaying = False
else:
if isBoardFull(theBoard):
drawBoard(theBoard)
print('The game is a tie!') break
else:
turn = 'computer'
else:
# Computer's turn.
move = getComputerMove(theBoard, computerLetter)
makeMove(theBoard, computerLetter, move)
if isWinner(theBoard, computerLetter):
drawBoard(theBoard)
print('The computer has beaten you! You lose.') gameIsPlaying = False
else:
if isBoardFull(theBoard):
drawBoard(theBoard)
print('The game is a tie!') break
else:
turn = 'player'
if not playAgain():
break