디스코드 틱택토 만들기! (한국어 버젼)

안녕하세요! 전에는 디스코드 봇과 서버를 생성을 했었죠?
이번에는 실제로 코딩을 해서 게임을 할수있는 봇을 만들어볼꺼에요!

목차
프로그렘 IDE 셋업
코당시작!
활용 방법!

셋업 방법
아래글을 읽고 따라하세요!

위에 글에서는 파이썬을 실제적으로 쓰기 위해서 뭐를 준비해야 하는지 알려줘요.ㅣ

이제 준비가 끝났으면 코딩을 시작합시다!
일단 파일을 생성할때, 우리가 전에 파이썬 봇을 다운 받았던 같은 위치에 시작하도록 하세요!
같은 위치에서 파일을 생성했으면 이제 시작합시다!

첫 3번째줄은 IMPORT이라고 합니다!

import discord
from discord.ext import commands
import random

이미 존재하는 모듈을 가지고 오기 위해 써요!

이제 다음 라인을 준비합시다.

client = commands.Bot(command_prefix="!")

player1 = ""
player2 = ""
turn = ""
gameOver = True

board = []

먼저 "!"를 통해 명령줄을 정의합니다.
즉, 작성한 명령(봇)을 사용하려면 먼저 "!"를 입력해야 합니다.
그런 다음 "@"와 플레이어의 사용자 이름을 사용하여 플레이어를 바로 정의합니다.
게임을 시작하는 간단한 명령은 다음과 같습니다.

!ticacto@yourusername@otherplayer

게임이 막 시작되었기 때문에 보드는 비어있고 빈 배열의 약자인 "[ ]"로 이어지고요.
게임이 종료되었는지 여부를 결정하는 게임 상태는 참으로 설정됩니다.

이제 다음 줄로 가봅시다.

winningConditions = [
    [0, 1, 2],
    [3, 4, 5],
    [6, 7, 8],
    [0, 3, 6],
    [1, 4, 7],
    [2, 5, 8],
    [0, 4, 8],
    [2, 4, 6]
]

자 우리는 틱톡토 게임을 이기기 위해 가능한 모든 조합을 만들었습니다.
하지만, 게임이 시작하기전 몇가지를 정해야합니다.
보드 배치 + 이기는 조건 + 누구와 경기 3가지를 알아야지만 게임을 할수있죠
블록을 배치하기 전에 몇 가지 규칙을 정합시다
X에게 연속해서 배치하거나, 뭐 하나만 배치해서 이긴다던지, 그런거는 말이 안되니까 빼야하죠.

@client.command()
async def tictactoe(ctx, p1: discord.Member, p2: discord.Member):
    global count
    global player1
    global player2
    global turn
    global gameOver

    if gameOver:
        global board
        board = [":white_large_square:", ":white_large_square:", ":white_large_square:",
                 ":white_large_square:", ":white_large_square:", ":white_large_square:",
                 ":white_large_square:", ":white_large_square:", ":white_large_square:"]
        turn = ""
        gameOver = False
        count = 0

        player1 = p1
        player2 = p2

자, 이제 명령어를 정합시다.

  1. 명령 이름(틱톡토)
  2. 다음 2명의 선수(디스코드).멤버) 및 각 멤버의 이름(p1 및 p2)

그리고 우리가 "글로벌 변수"라고 설정합니다.
즉, 코드가 그들에게 돌아가 그들에게 무슨 일이 일어나고 있는지 또는 무엇이 바뀌었는지 볼 수 있습니다.

디스코드는 사실 그림 그리는 것을 허락하지 않기 때문에 이모티콘으로 대신할 거예요.
이모티콘으로 보드를 만드다니!!! 너무 신기해요~~~
암튼,
따라서 white_large_square는 흰색 블록 이모티콘일 뿐이며 3x3 방식으로 설정하면 보드를 만들수있죠~.

그런 다음 글로벌을 다음과 같이 설정합니다.

turn = “”
gameOver = False
count = 0
player1 = p1
player2 = p2

게임 종료 시, 이동 횟수(카운트), 플레이어의 이름을 표시합니다.

여기 좀 더 복잡한 코드가 있습니다.

line = ""
        for x in range(len(board)):
            if x == 2 or x == 5 or x == 8:
                line += " " + board[x]
                await ctx.send(line)
                line = ""
            else:
                line += " " + board[x]

        num = random.randint(1, 2)
        if num == 1:
            turn = player1
            await ctx.send("It is <@" + str(player1.id) + ">'s turn.")
        elif num == 2:
            turn = player2
            await ctx.send("It is <@" + str(player2.id) + ">'s turn.")
    else:
        await ctx.send("A game is already in progress! Finish it before starting a new one.")

그럼 이제 실제 명령으로 넘어갑시다!

`@client.command()
async def place(ctx, pos: int):
global turn
global player1
global player2
global board
global count
global gameOver

if not gameOver:
    mark = ""
    if turn == ctx.author:
        if turn == player1:
            mark = ":regional_indicator_x:"
        elif turn == player2:
            mark = ":o2:"
        if 0 < pos < 10 and board[pos - 1] == ":white_large_square:" :
            board[pos - 1] = mark
            count += 1

            line = ""
            for x in range(len(board)):
                if x == 2 or x == 5 or x == 8:
                    line += " " + board[x]
                    await ctx.send(line)
                    line = ""
                else:
                    line += " " + board[x]

            checkWinner(winningConditions, mark)
            print(count)
            if gameOver == True:
                await ctx.send(mark + " wins!")
            elif count >= 9:
                gameOver = True
                await ctx.send("It's a tie!")

            # switch turns
            if turn == player1:
                turn = player2
            elif turn == player2:
                turn = player1
        else:
            await ctx.send("Be sure to choose an integer between 1 and 9 (inclusive) and an unmarked tile.")
    else:
        await ctx.send("It is not your turn.")
else:
    await ctx.send("Please start a new game using the !tictactoe command.")`

워워, 이거 길어요. 좀 더 세분화해보죠.

첫 번째 블록을 살펴보겠습니다.

@client.command()
async def place(ctx, pos: int):
  ... #means skipping the global 
    if not gameOver:
        mark = ""
        if turn == ctx.author:
            if turn == player1:
                mark = ":regional_indicator_x:"
            elif turn == player2:
                mark = ":o2:"
            if 0 < pos < 10 and board[pos - 1] == ":white_large_square:" :
                board[pos - 1] = mark
                count += 1

                line = ""
                for x in range(len(board)):
                    if x == 2 or x == 5 or x == 8:
                        line += " " + board[x]
                        await ctx.send(line)
                        line = ""
                    else:
                        line += " " + board[x]

이제 명령어를 살펴보겠습니다.
"!place X"가 될 것입니다. 여기서 x는 보드를 구성하는 0에서 8 사이의 정수 값을 나타냅니다.
그래서 우리는 먼저 게임이 아직 끝나지 않았다고 가정해야 합니다. 여기서 "게임 오버가 아니라면"이 발생합니다.

그러면 입력을 받을 빈 문자열인 마크가 나옵니다. 따라서 이 코드는 사용자가 각 플레이어를 위해 배치한 내용을 추적할 수 있습니다.

그래서 만약 우리의 플레이어와 같은 순서라면, 우리는 white_large_square를 큰 o2 이모지로 바꿀 수 있는 0~10개의 입력을 받게 될 거에요!
그런 다음 카운트(총 이동 수)가 1만큼 증가합니다.

그리고 나서 우리는 사용자의 입력과 함께 우리의 새 보드를 프린트해서 보낼거고요.

이제 다음 블록으로 가기 전에 플레이어가 이겼는지 아닌지를 확인하는 기능을 실제로 살펴봐야 합니다.

def checkWinner(winningConditions, mark):
    global gameOver
    for condition in winningConditions:
        if board[condition[0]] == mark and board[condition[1]] == mark and board[condition[2]] == mark:
            gameOver = True

여기 우리의 승리 조건이 있습니다. 우리가 모든 승리 조건을 어떻게 정의했는지 기억하죠?
그래서 우리는 마크를 보고 만약 사용자의 입력이 어떤 조건과 일치한다면,
게임 오버 문장은 사용자가 이겼기 때문에 참입니다!

그럼 다음 다음 블록으로 이동합니다.

checkWinner(winningConditions, mark)
                print(count)
                if gameOver == True:
                    await ctx.send(mark + " wins!")
                elif count >= 9:
                    gameOver = True
                    await ctx.send("It's a tie!")

                # switch turns
                if turn == player1:
                    turn = player2
                elif turn == player2:
                    turn = player1
            else:
                await ctx.send("Be sure to choose an integer between 1 and 9 (inclusive) and an unmarked tile.")
        else:
            await ctx.send("It is not your turn.")
    else:
        await ctx.send("Please start a new game using the !tictactoe command.")

그래서 이긴 사람이 이겼는지 안 이겼는지 확인한 후, 이긴 사람의 이름 + 누가 이겼는지, 동점이면 동점을 부여하고! (동점인지 아닌지를 판단하기 위해 총 이동 수를 살펴봅니다. 최대 수는 9개입니다.)

만약 이 모든 일이 일어나지 않는다면, 우리가 하는 모든 것은 선수들의 차례를 바꾸는 것이다.

오류에 대해서는:
사용자가 당사의 범위 밖에 있는 번호를 입력한 경우 다음을 전송해야하고요.

1~9(포함)의 정수와 표시되지 않은 타일을 선택해야 합니다.

만약 그것이 잘못된 방향이라면, 우리는 다음과 같이 프린트를 하죠.

당신 차례가 아닙니다.

종료된 경우 다음과 같이 말합니다.

!ticactoe 명령을 사용하여 새 게임을 시작하십시오.

@tictactoe.error
async def tictactoe_error(ctx, error):
    print(error)
    if isinstance(error, commands.MissingRequiredArgument):
        await ctx.send("Please mention 2 players for this command.")
    elif isinstance(error, commands.BadArgument):
        await ctx.send("Please make sure to mention/ping players (ie. <@688534433879556134>).")

@place.error
async def place_error(ctx, error):
    if isinstance(error, commands.MissingRequiredArgument):
        await ctx.send("Please enter a position you would like to mark.")
    elif isinstance(error, commands.BadArgument):
        await ctx.send("Please make sure to enter an integer.")

에러가 나면…

이 지휘를 위해 2명의 선수를 언급해 주세요.
또는
선수에 대한 언급/핑(ping)을 반드시 해주시기 바랍니다. <@688534433879556134>).

배치 오류일 경우 다음을 반환합니다.

표시할 위치를 입력하십시오.
또는
정수를 입력하세요.

그리고 그것이 끝나면:
우리는 마지막 토킨을 씁니다

client.run("ABCDEFGHIJKLMNOP1234567890")

""에 들어가는 것은 앞에서 말한 당신의 토큰이어야 해요!!.
위에서 설명한 명령으로 봇을 "실행"합니다.

그러면 봇이 활성화되고 게임을 시작할 수 있습니다!

import discord
from discord.ext import commands
import random

client = commands.Bot(command_prefix="!")

player1 = ""
player2 = ""
turn = ""
gameOver = True

board = []

winningConditions = [
    [0, 1, 2],
    [3, 4, 5],
    [6, 7, 8],
    [0, 3, 6],
    [1, 4, 7],
    [2, 5, 8],
    [0, 4, 8],
    [2, 4, 6]
]

@client.command()
async def tictactoe(ctx, p1: discord.Member, p2: discord.Member):
    global count
    global player1
    global player2
    global turn
    global gameOver

    if gameOver:
        global board
        board = [":white_large_square:", ":white_large_square:", ":white_large_square:",
                 ":white_large_square:", ":white_large_square:", ":white_large_square:",
                 ":white_large_square:", ":white_large_square:", ":white_large_square:"]
        turn = ""
        gameOver = False
        count = 0

        player1 = p1
        player2 = p2

        # 보드 만들기
        line = ""
        for x in range(len(board)):
            if x == 2 or x == 5 or x == 8:
                line += " " + board[x]
                await ctx.send(line)
                line = ""
            else:
                line += " " + board[x]

        # 누가 먼저 하는지 결정
        num = random.randint(1, 2)
        if num == 1:
            turn = player1
            await ctx.send("It is <@" + str(player1.id) + ">'s turn.")
        elif num == 2:
            turn = player2
            await ctx.send("It is <@" + str(player2.id) + ">'s turn.")
    else:
        await ctx.send("A game is already in progress! Finish it before starting a new one.")

@client.command()
async def place(ctx, pos: int):
    global turn
    global player1
    global player2
    global board
    global count
    global gameOver

    if not gameOver:
        mark = ""
        if turn == ctx.author:
            if turn == player1:
                mark = ":regional_indicator_x:"
            elif turn == player2:
                mark = ":o2:"
            if 0 < pos < 10 and board[pos - 1] == ":white_large_square:" :
                board[pos - 1] = mark
                count += 1

                # 보드 업데이트
                line = ""
                for x in range(len(board)):
                    if x == 2 or x == 5 or x == 8:
                        line += " " + board[x]
                        await ctx.send(line)
                        line = ""
                    else:
                        line += " " + board[x]

                checkWinner(winningConditions, mark)
                print(count)
                if gameOver == True:
                    await ctx.send(mark + " wins!")
                elif count >= 9:
                    gameOver = True
                    await ctx.send("It's a tie!")

                # switch turns
                if turn == player1:
                    turn = player2
                elif turn == player2:
                    turn = player1
            else:
                await ctx.send("Be sure to choose an integer between 1 and 9 (inclusive) and an unmarked tile.")
        else:
            await ctx.send("It is not your turn.")
    else:
        await ctx.send("Please start a new game using the !tictactoe command.")


def checkWinner(winningConditions, mark):
    global gameOver
    for condition in winningConditions:
        if board[condition[0]] == mark and board[condition[1]] == mark and board[condition[2]] == mark:
            gameOver = True

@tictactoe.error
async def tictactoe_error(ctx, error):
    print(error)
    if isinstance(error, commands.MissingRequiredArgument):
        await ctx.send("Please mention 2 players for this command.")
    elif isinstance(error, commands.BadArgument):
        await ctx.send("Please make sure to mention/ping players (ie. <@688534433879556134>).")

@place.error
async def place_error(ctx, error):
    if isinstance(error, commands.MissingRequiredArgument):
        await ctx.send("Please enter a position you would like to mark.")
    elif isinstance(error, commands.BadArgument):
        await ctx.send("Please make sure to enter an integer.")

client.run("")

이제 끝~~~!

2 Likes