카테고리 없음

[TIL] 유니티 스파르타 7기 6일차 - 틱택토

맏난거 2025. 1. 27. 20:41

/*
0 0 0
0 0 0
0 0 0
 
 */
namespace SpartaCSharp
{
    internal class Program
    {
        static void Main(string[] args)
        {
            TickTackTok tic = new TickTackTok();

            while (true) 
            {
                if (tic.MyTurn)
                {
                    while (true)
                    {
                        tic.ShowBoard(); // 현재 보드판 상황
                        int idx = tic.GetInputValue(); // 입력값
                        if (tic.SetBoard(idx) > 0) // 보드판 수정
                            break;
                    }
                }
                else
                {
                    tic.RunComputer(); // 컴퓨터 차례
                }

                if (tic.Winner != 0) break;
            }

            if (tic.Winner == (int)ObjectType.PLAYER) Console.WriteLine("승리!");
            else if (tic.Winner == (int)ObjectType.COMPUTER) Console.WriteLine("패배!");
            else Console.WriteLine("비겼다!");
        }
    }
}

public struct TickTackTok
{
    public TickTackTok()
    {
        this.size = 3;
        
        MyTurn = (new Random().Next(0,2) == 0) ? true : false;

        board = new int[size * size];
        randomArray = CreateRandomArray();

    }

    int[] CreateRandomArray(int count = 1000)
    {
        int length = size * size;
        int[] arr = new int[length];

        for (int i = 0; i < arr.Length; i++)
            arr[i] = i;

        Random rand = new Random();
        for(int i = 0; i < count; i++)
        {
            int idx1 = rand.Next(0, length - 1);
            int idx2 = rand.Next(0, length - 1);

            if (idx1 == idx2) continue;

            int swap = arr[idx1];
            arr[idx1] = arr[idx2];
            arr[idx2] = swap;
        }

        return arr;
    }

    ObjectType GetBoard(int idx)
    {
        return (board[idx] == 0) ? ObjectType.DEFAULT : (board[idx] == 1) ? ObjectType.PLAYER : ObjectType.COMPUTER;
    }

    public int GetInputValue()
    {
        int value = 0;
        while (true)
        {
            Console.Write($"숫자를 입력해주세요(1~{size * size}) : "); // 3x3
            if (int.TryParse(Console.ReadLine(), out value))
            {
                value -= 1;

                if (value < 0 || value >= size * size) continue;

                return value;
            }

            continue;
        }
    }

    public void ShowBoard()
    {
        for(int i = 0; i < size * size; i++)
        {
            if (i != 0 && i % size == 0) Console.WriteLine("|");

            switch (GetBoard(i))
            {
                case ObjectType.DEFAULT:
                    Console.Write("|  ");
                    break;
                case ObjectType.PLAYER:
                    Console.Write("|● ");
                    break;
                case ObjectType.COMPUTER:
                    Console.Write("| X");
                    break;
            }
        }

        Console.WriteLine("|\n");
    }

    public int SetBoard(int idx)
    {

        if (GetBoard(idx) != ObjectType.DEFAULT)
        {
            Console.Clear();
            Console.WriteLine("다시 한번 확인 해주세요");
            return -1;
        }

        board[idx] = (int)(MyTurn ? ObjectType.PLAYER : ObjectType.COMPUTER);
        Winner = CheckWin();
        MyTurn = !MyTurn;
        return 1;
    }
    
    public void RunComputer()
    {
        int idx = 0;

        while (idx < size * size)
        {
            if (GetBoard(randomArray[idx]) != ObjectType.DEFAULT)
            {
                idx++;
                continue;
            }

            SetBoard(randomArray[idx]);
            break;
        }
    }

    public int CheckWin()
    {
        /*
        0 1 2
        3 4 5
        6 7 8

        00 01 02 03
        04 05 06 07
        08 09 10 11
        12 13 14 15
         */
        
        // 가로
        for(int idx = 0; idx < size; idx++)
        {
            if(GetBoard(size * idx) != ObjectType.DEFAULT)
            {
                if (GetBoard(size * idx) == GetBoard(size * idx + 1) && GetBoard(size * idx) == GetBoard(size * idx + 2))
                    return (int)(MyTurn ? ObjectType.PLAYER : ObjectType.COMPUTER);
            }
        }
        // 세로
        for (int idx = 0; idx < size; idx++)
        {
            if (GetBoard(idx) != ObjectType.DEFAULT)
            {
                if ( GetBoard(idx) == GetBoard(size + idx) && GetBoard(idx) == GetBoard(size*2 + idx) )
                    return (int)(MyTurn ? ObjectType.PLAYER : ObjectType.COMPUTER);
            }
        }

        int count = 0; // 대각선 체크
        // 대각선 01
        for (int idx = 0; idx < size - 1; idx++)
        {
            if (GetBoard((size + 1) * idx) != ObjectType.DEFAULT)
            {
                if (GetBoard((size + 1) * idx) == GetBoard((size + 1) * (idx + 1)))
                    count++;
            }
        }
        if (count == size - 1) return (int)(MyTurn ? ObjectType.PLAYER : ObjectType.COMPUTER);

        count = 0;
        // 대각선 02
        for (int idx = 0; idx < size - 1; idx++)
        {
            if (GetBoard((size-1) * (idx + 1)) != ObjectType.DEFAULT)
            {
                if (GetBoard((size - 1) * (idx + 1)) == GetBoard((size - 1) * (idx + 2)))
                    count++;
            }
        }
        if (count == size - 1) return (int)(MyTurn ? ObjectType.PLAYER : ObjectType.COMPUTER);

        count = 0;
        for (int i = 0; i < size * size; i++)
        {
            if(GetBoard(i) != ObjectType.DEFAULT)
                count++;
        }

        if (count >= size * size) return (int)ObjectType.DRAW;
        return (int)ObjectType.DEFAULT;
    }

    public int Winner { get; set; }
    public bool MyTurn { get; set; }
    int size;
    int[] board;
    int[] randomArray;
}

enum ObjectType
{
    DEFAULT,
    PLAYER,
    COMPUTER,
    DRAW,
}

오늘은 C# 문법 종합반 강의 2주차 과제로 틱택토 게임을 만들어봤습니다.

클래스는 그다음 장에 배워서 구조체로 만들었고,

최대한 깔끔하게 코딩하고 싶어서 시간을 투자했습니다.

시작전에 AI와 플레이어 선공격을 먼저 정할 수 있고,

AI는 인덱스가 들어있는 배열들을 섞어서 다음 인덱스를 호출 => 만약 뽑은 인덱스가 있으면 다음 인덱스를 호출하도록 설정

CheckWin() 메서드 같은 경우에는 가로, 세로, 대각선 2개  체크하고,

보드판에 남는 공간이 없으면 비겼다 출력.

문제있으면 댓글 적어주세요.