Tic Tac Toe ๐ŸŽฎ with Python tkinter - 2๋ถ€

43014 ๋‹จ์–ด beginnerstutorialtkinterpython
์ด ์ž์Šต์„œ๋Š” ์‹œ๋ฆฌ์ฆˆ์˜ ์ผ๋ถ€์ž…๋‹ˆ๋‹ค. ์•„์ง ํ™•์ธํ•˜์ง€ ์•Š์€ ๊ฒฝ์šฐ ๋ฅผ ํ™•์ธํ•˜์‹ญ์‹œ์˜ค.
์ด ํŠœํ† ๋ฆฌ์–ผ์—์„œ๋Š” 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/

์ข‹์€ ์›นํŽ˜์ด์ง€ ์ฆ๊ฒจ์ฐพ๊ธฐ