Tic Tac Toe ๐ฎ with Python tkinter - 2๋ถ
์ด ํํ ๋ฆฌ์ผ์์๋ Tic-Tac-Toe ๊ฒ์์ ๊ธฐ๋ฅ์ ์ถ๊ฐํฉ๋๋ค: ํ๋ ์ด์ด ๋ ์ปดํจํฐ ๐
Tic-Tac-Toe์ ๋ ผ๋ฆฌ ๐ฎ
๊ณ์ํด์ ์ปดํจํฐ๊ฐ ์ด ๊ฒ์์์ ์์ง์์ ๊ฒฐ์ ํ๋ ํจ์๋ฅผ ๋ง๋ค์ด ๋ด ์๋ค.
def auto_play():
์ฝ๋๋ฅผ ์์ฑํ๊ธฐ ์ ์ ๋ก์ง ๐ค์ ์ดํด๋ณด๊ฒ ์ต๋๋ค.
1. ์ปดํจํฐ๋ ํ๋ ์ด์ด๊ฐ ๋ค์ ์์์ ๊ฒ์์ ์ด๊ธธ ์ ์๋ ๊ฒฝ์ฐ
์ปดํจํฐ๊ฐ ๋ค์ ์ด๋์์ ๊ฒ์์ ์ด๊ธธ ์ ์์ ๋ ์ด๋์ ์๋ฃํด์ผ ํฉ๋๋ค. ๋ค์ ์ด๋์์ ํ๋ ์ด์ด๊ฐ ๊ฒ์์์ ์ด๊ธธ ์ ์๋ค๋ฉด ์ต์ ์ ์ ํ์ ๊ทธ๊ฒ์ ๋ฐฉ์งํ๋ ๊ฒ์ ๋๋ค. Python์์ ๋ค์๊ณผ ๊ฐ์ด ๊ตฌํํ ์ ์์ต๋๋ค.
# If winning of computer is possible on the next move, go ahead and win the game
for winning_possibility in winning_possibilities:
winning_possibility.check('O') # Check how many conditions for winning of computer are satisfied
if winning_possibility.p1_satisfied and winning_possibility.p2_satisfied: # If condition 1 and 2 are satisfied, satisfy condition 3
for point in XO_points:
if point.x == winning_possibility.x3 and point.y == winning_possibility.y3 and point not in X_points + O_points: # Find the point that needs to be occupied to satisfy condtion 3 and make sure that it is not already occupied
point.set() # Occupy point
return # End the function
elif winning_possibility.p2_satisfied and winning_possibility.p3_satisfied: # If condition 2 and 3 are satisfied, satisfy condition 1
for point in XO_points:
if point.x == winning_possibility.x1 and point.y == winning_possibility.y1 and point not in X_points + O_points: # Find the point that needs to be occupied to satisfy condition 1 and make sure that it is not already occupied
point.set() # Occupy point
return # End the function
elif winning_possibility.p3_satisfied and winning_possibility.p1_satisfied: # If condition 1 and 3 are satisfied, satisfy condition 2
for point in XO_points:
if point.x == winning_possibility.x2 and point.y == winning_possibility.y2 and point not in X_points + O_points: # Find the point that needs to be occupied to satisfy condition 2 and make sure that it is not already occupied
point.set() # Occupy point
return # End the function
# If the player might win on the next move, prevent it
for winning_possibility in winning_possibilities:
winning_possibility.check('X') # Check how many conditions for winning of player are satisfied
if winning_possibility.p1_satisfied and winning_possibility.p2_satisfied: # If condition 1 and 2 are satisfied, prevent condition 3 from being satisfied
for point in XO_points:
if point.x == winning_possibility.x3 and point.y == winning_possibility.y3 and point not in X_points + O_points: # Find the point and make sure that it is not already occupied
point.set() # Occupy point
return # End function
elif winning_possibility.p2_satisfied and winning_possibility.p3_satisfied: # If condition 2 and 3 are satisfied, prevent condition 1 from being satisfied
for point in XO_points:
if point.x == winning_possibility.x1 and point.y == winning_possibility.y1 and point not in X_points + O_points: # Find the point and make sure that it is not already occupied
point.set() # Occupy point
return # End function
elif winning_possibility.p3_satisfied and winning_possibility.p1_satisfied: # If condition 1 and 3 are satisfied, prevent condition 2 from being satisfied
for point in XO_points:
if point.x == winning_possibility.x2 and point.y == winning_possibility.y2 and point not in X_points + O_points: # Find the point and make sure that it is not already occupied
point.set() # Occupy point
return # End function
"WinningPossibility" ํด๋์ค์ "check" ๊ธฐ๋ฅ์ ๋ํ ์ผ๋ถ ๋ณ๊ฒฝ ์ฌํญ
๊ฒ์์์ ์ด๊ธฐ๊ธฐ ์ํด ํ์ฌ ์ผ๋ง๋ ๋ง์ ์กฐ๊ฑด์ด ์ถฉ์กฑ๋์๋์ง ํ์ธํ๋ ค๋ฉด ํจ์ ์ธ๋ถ์์ ๋ณ์
p1_satisfied
, p2_satisfied
๋ฐ p3_satisfied
์ ์ก์ธ์คํ ์ ์๋๋ก ํด์ผ ํฉ๋๋ค. ๋ฐ๋ผ์ ์ด๋ฆ์ ๊ฐ๊ฐ self.p1_satisfied
, self.p2_satisfied
๋ฐ self.p3_satisfied
๋ก ๋ฐ๊พธ๊ฒ ์ต๋๋ค. ํจ์์ ์ ์ฝ๋๋ ๋ค์๊ณผ ๊ฐ์ต๋๋ค.def check(self, for_chr):
self.p1_satisfied = False
self.p2_satisfied = False
self.p3_satisfied = False
if for_chr == 'X':
for point in X_points:
if point.x == self.x1 and point.y == self.y1:
self.p1_satisfied = True
elif point.x == self.x2 and point.y == self.y2:
self.p2_satisfied = True
elif point.x == self.x3 and point.y == self.y3:
self.p3_satisfied = True
elif for_chr == 'O':
for point in O_points:
if point.x == self.x1 and point.y == self.y1:
self.p1_satisfied = True
elif point.x == self.x2 and point.y == self.y2:
self.p2_satisfied = True
elif point.x == self.x3 and point.y == self.y3:
self.p3_satisfied = True
return all([self.p1_satisfied, self.p2_satisfied, self.p3_satisfied])
2. ์ผํฐ๊ฐ ํ์ฌ ์ ์ ๋์ง ์์ ๊ฒฝ์ฐ
ํ์ฌ ์ ์ ๋์ง ์์ ์ผํฐ๋ฅผ ์ ์ ํ๋ ๊ฒ์ด ์ข์ต๋๋ค. Python์์ ๋ค์๊ณผ ๊ฐ์ด ๊ตฌํํ ์ ์์ต๋๋ค.
center_occupied = False
for point in X_points + O_points: # Check if center is already occupied
if point.x == 2 and point.y == 2:
center_occupied = True
break
if not center_occupied: # If center is not occupied
for point in XO_points:
if point.x == 2 and point.y == 2:
point.set() # Occupy center
return # End the function
3. ์ผํฐ๊ฐ ์ด๋ฏธ ์ ์ ๋์ด ํ์ฌ ๋น์ฒจ ๊ฐ๋ฅ์ฑ์ด ์๋ ๊ฒฝ์ฐ
์ด ๊ฒฝ์ฐ ๊ผญ์ง์ ์ด๋ ์ค๊ฐ ์ง์ ์ ์ ์ ํด์ผ ํฉ๋๋ค. ํ๋ ์ด์ด๊ฐ 2๊ฐ ๋ฏธ๋ง์ ์ฝ๋๋ฅผ ์ ์ ํ ๊ฒฝ์ฐ "O"๋ ๋๋จธ์ง ์ฝ๋๋ฅผ ์ ์ ํด์ผ ํฉ๋๋ค. 2๊ฐ ์ด์์ ์ฝ๋๊ฐ ํ๋ ์ด์ด์ ์ํด ์ ์ ๋ ๊ฒฝ์ฐ ๋์ ์ค๊ฐ ์ง์ ์ ์ ์ ํ๋ ๊ฒ์ด ๋ ์์ ํฉ๋๋ค. ์ด๊ฒ์ Python์์ ๋ค์๊ณผ ๊ฐ์ด ๊ตฌํํ ์ ์์ต๋๋ค.
corner_points = [(1, 1), (1, 3), (3, 1), (3, 3)]
middle_points = [(1, 2), (2, 1), (2, 3), (3, 2)]
num_of_corner_points_occupied_by_X = 0
for point in X_points: # Iterate over all points occupied by the player
if (point.x, point.y) in corner_points:
num_of_corner_points_occupied_by_X += 1
if num_of_corner_points_occupied_by_X >= 2: # If two or more corner points are occupied by the player
for point in XO_points:
if (point.x, point.y) in middle_points and point not in X_points + O_points: # Find a middle point and make sure that it is not already occupied
point.set() # Occupy the point
return # End the function
elif num_of_corner_points_occupied_by_X < 2: # If less than two corner points are occupied by the player
for point in XO_points:
if (point.x, point.y) in corner_points and point not in X_points + O_points: # Find a corner point and make sure that it is not already occupied
point.set() # Occupy the point
return # End the function
๋ชจ๋ ์ฝ๋๋ฅผ ๊ฒฐํฉํ์ฌ auto_play ํจ์๋ฅผ ์์ฑํด ๋ณด๊ฒ ์ต๋๋ค.
def auto_play():
# If winning is possible in the next move
for winning_possibility in winning_possibilities:
winning_possibility.check('O')
if winning_possibility.p1_satisfied and winning_possibility.p2_satisfied:
for point in XO_points:
if point.x == winning_possibility.x3 and point.y == winning_possibility.y3 and point not in X_points + O_points:
point.set()
return
elif winning_possibility.p2_satisfied and winning_possibility.p3_satisfied:
for point in XO_points:
if point.x == winning_possibility.x1 and point.y == winning_possibility.y1 and point not in X_points + O_points:
point.set()
return
elif winning_possibility.p3_satisfied and winning_possibility.p1_satisfied:
for point in XO_points:
if point.x == winning_possibility.x2 and point.y == winning_possibility.y2 and point not in X_points + O_points:
point.set()
return
# If the opponent can win in the next move
for winning_possibility in winning_possibilities:
winning_possibility.check('X')
if winning_possibility.p1_satisfied and winning_possibility.p2_satisfied:
for point in XO_points:
if point.x == winning_possibility.x3 and point.y == winning_possibility.y3 and point not in X_points + O_points:
point.set()
return
elif winning_possibility.p2_satisfied and winning_possibility.p3_satisfied:
for point in XO_points:
if point.x == winning_possibility.x1 and point.y == winning_possibility.y1 and point not in X_points + O_points:
point.set()
return
elif winning_possibility.p3_satisfied and winning_possibility.p1_satisfied:
for point in XO_points:
if point.x == winning_possibility.x2 and point.y == winning_possibility.y2 and point not in X_points + O_points:
point.set()
return
# If the center is free...
center_occupied = False
for point in X_points + O_points:
if point.x == 2 and point.y == 2:
center_occupied = True
break
if not center_occupied:
for point in XO_points:
if point.x == 2 and point.y == 2:
point.set()
return
# Occupy corner or middle based on what opponent occupies
corner_points = [(1, 1), (1, 3), (3, 1), (3, 3)]
middle_points = [(1, 2), (2, 1), (2, 3), (3, 2)]
num_of_corner_points_occupied_by_X = 0
for point in X_points:
if (point.x, point.y) in corner_points:
num_of_corner_points_occupied_by_X += 1
if num_of_corner_points_occupied_by_X >= 2:
for point in XO_points:
if (point.x, point.y) in middle_points and point not in X_points + O_points:
point.set()
return
elif num_of_corner_points_occupied_by_X < 2:
for point in XO_points:
if (point.x, point.y) in corner_points and point not in X_points + O_points:
point.set()
return
์ปดํจํฐ์ ํ๋ ์ด ๋๋ ์ฌ๋๊ณผ ํ๋ ์ด๋ฅผ ์ ํํ๋ ๋ฒํผ ๋ง๋ค๊ธฐ
์๋๋ฐฉ์ ์ธ๊ฐ ๋๋ ์ปดํจํฐ๋ก ์ ํํ ์ ์๋ ๋ฒํผ์ ๋ง๋ค๊ณ ํ ๊ธ ๋ฒํผ ํ ์คํธ ๋ฐ ๋ช ๋ น์ ๋ณ๊ฒฝํ๋ ์ฝ๋ฐฑ์ ๋ง๋ค์ด ๋ด ์๋ค.
play_with = "Computer"
def play_with_human():
global play_with
play_with = "Human" # switch opponent to human
play_with_button['text'] = "Play with computer" # switch text
play_with_button['command'] = play_with_computer # switch command so that the user can play with the computer again, if required
play_again() # restart game
def play_with_computer():
global play_with
play_with = "Computer" # switch opponent to computer
play_with_button['text'] = "Play with human" # switch text
play_with_button['command'] = play_with_human # switch command so that the user can play with a human again, if required
play_again() # restart game
play_with_button = tk.Button(root, text='Play with human', font=('Ariel', 15), command=play_with_human)
play_with_button.pack()
์ฐ๋ฆฌ๋ O์ ์ฐจ๋ก๊ฐ ๋ ๋๋ง๋ค
auto_play
ํจ์๋ฅผ ํธ์ถํด์ผ ํ๊ณ play_with
์ ๊ฐ์ "Computer"
์
๋๋ค. ์ด๋ฅผ ์ํด ํด๋์ค set
์ ํจ์XOPoint
์ ๋ค์ ์ฝ๋๋ฅผ ์ถ๊ฐํฉ๋๋ค.if play_with == "Computer" and status_label['text'] == "O's turn":
auto_play()
๊ฒฐ๊ณผ
์ด ๊ธฐ์ฌ๊ฐ ์ ์ฉํ๋ค๊ณ ์๊ฐ๋๋ฉด ์ข์์ โญ๋ฅผ ๋๋ฅด๊ณ ์ ๋ฅผ ํ๋ก์ฐํ์ฌ ๋ชจ๋ ์ต์ ์ฝํ ์ธ ๋ฅผ ๋ฐ์๋ณด์ธ์.
GitHub ๋ฆฌํฌ์งํ ๋ฆฌ์ ์ ์ฒด ์ฝ๋: https://github.com/Jothin-kumar/tic-tac-toe/
Reference
์ด ๋ฌธ์ ์ ๊ดํ์ฌ(Tic Tac Toe ๐ฎ with Python tkinter - 2๋ถ), ์ฐ๋ฆฌ๋ ์ด๊ณณ์์ ๋ ๋ง์ ์๋ฃ๋ฅผ ๋ฐ๊ฒฌํ๊ณ ๋งํฌ๋ฅผ ํด๋ฆญํ์ฌ ๋ณด์๋ค https://dev.to/jothinkumar/tic-tac-toe-with-python-tkinter-part-2-9mpํ ์คํธ๋ฅผ ์์ ๋กญ๊ฒ ๊ณต์ ํ๊ฑฐ๋ ๋ณต์ฌํ ์ ์์ต๋๋ค.ํ์ง๋ง ์ด ๋ฌธ์์ URL์ ์ฐธ์กฐ URL๋ก ๋จ๊ฒจ ๋์ญ์์ค.
์ฐ์ํ ๊ฐ๋ฐ์ ์ฝํ ์ธ ๋ฐ๊ฒฌ์ ์ ๋ (Collection and Share based on the CC Protocol.)
์ข์ ์นํ์ด์ง ์ฆ๊ฒจ์ฐพ๊ธฐ
๊ฐ๋ฐ์ ์ฐ์ ์ฌ์ดํธ ์์ง
๊ฐ๋ฐ์๊ฐ ์์์ผ ํ ํ์ ์ฌ์ดํธ 100์ ์ถ์ฒ ์ฐ๋ฆฌ๋ ๋น์ ์ ์ํด 100๊ฐ์ ์์ฃผ ์ฌ์ฉํ๋ ๊ฐ๋ฐ์ ํ์ต ์ฌ์ดํธ๋ฅผ ์ ๋ฆฌํ์ต๋๋ค