티스토리 뷰

반응형

 

 

 

해커랭크 Day 23 챌린지를 시작해보자. 😊

 

오늘은 TicTacToe 게임을 만들어 보았다.

 

TicTacToe 게임을 모르는 독자들을 위해

잠시 게임을 설명한다.

 

🤔 TicTacToe 게임이란?

오목과 아주 유사한 형태인 추상전략 보드 게임으로

'삼목'이라고 불리기도 한다.

 

판 크기틑 3x3 정사각형이고

2인 전용 게임이다.

 

🤔 TicTacToe 게임 하는 방법

1. 종이 위에 가로줄 2줄 세로줄 2줄을 그린다.

2. 9칸 위에 1P는 O, 2P는 X를 번갈아가며 그린다.

3. 먼저 O나 X를 3개가 직선으로 이어지게 만드는 사람이 승리한다.

 

 

나무위키에는 위와 같이 설명되어 있다.

다음의 링크를 클릭하면

나무위키 사이트로 이동하며

실제 게임을 시뮬레이션 하는 영상이 있으니

위의 설명으로 이해가 안된다면 참고하자.

 

 

그럼 오늘의 소스 코드를 확인해보자. ❗❗

 

 


// Picture of Game with Index:
// 0 | 1 | 2
// ------------
// 3 | 4 | 5
// ------------
// 6 | 7 | 8
// ------------

// WHAT THE USER THINKS:
// 1 | 2 | 3
// ------------
// 4 | 5 | 6
// ------------
// 7 | 8 | 9
// ------------

// UI Picture of Game:
// INIT:
// | - | - | -
// ------------
// | - | - | -
// ------------
// | - | - | -
// ------------

// GAMEPLAY:
//| O | - | O
//------------
//| - | X | -
//------------
//| - | - | X


public class TicTacToe {
    protected char[] board;
    protected char userMarker;
    protected char aiMarker;
    protected char winner;
    protected char currentMarker;

    public TicTacToe(char playToken, char aiMarker) {
        this.userMarker = playToken;
        this.aiMarker = aiMarker;
        this.winner = '0';
        this.board = setBoard();
        this.currentMarker = userMarker;
    }

    public char[] setBoard() {
        char[] board = new char[9];
        for (int i = 0; i < board.length; i++) {
            board[i] = '-';
        }
        return board;
    }

    public boolean playTurn(int spot) {
        boolean isValid = withinRange(spot) && !isSpotTaken(spot);
        if (isValid) {
            board[spot - 1] = currentMarker;
            currentMarker = (currentMarker == userMarker) ? aiMarker : userMarker;
        }
        return isValid;
    }

    // Check if our spot is in range
    public boolean withinRange(int number) {
        return number > 0 && number < board.length + 1; // here's 1~9
    }

    // Check if the spot is taken
    public boolean isSpotTaken(int number) {
        return board[number - 1] != '-';
    }

    public void printBoard() {
        // Attempting to create...
        //| - | - | -
        //------------
        //| - | - | -
        //------------
        //| - | - | -

        System.out.println();
        for (int i = 0; i < board.length; i++) {
            if (i % 3 == 0 && i != 0) {
                System.out.println();
                System.out.println("------------");
            }
            System.out.print(" | " + board[i]);
        }
        System.out.println();
    }

    public static void printIndexBoard() {
        System.out.println();
        for (int i = 0; i < 9; i++) {
            if (i % 3 == 0 && i != 0) {
                System.out.println();
                System.out.println("------------");
            }
            System.out.print(" | " + (i+1));
        }
        System.out.println();
    }

    public boolean isThereAWinner() {
        boolean diagonalsAndMiddles = (rightDi() || leftDi() || middleRow() || secondCol()) && board[4] != '-';
        boolean topAndFirst = (topRow() || firstCol()) && board[0] != '-';
        boolean bottomAndThird = (bottomRow() || thirdCol()) && board[8] != '-';
        if (diagonalsAndMiddles) {
            this.winner = board[4];
        } else if (topAndFirst) {
            this.winner = board[8];
        } else if (bottomAndThird) {
            this.winner = board[8];
        }
        return diagonalsAndMiddles || topAndFirst || bottomAndThird;
    }

    public boolean topRow() {
        return board[0] == board[1] && board[1] == board[2];
    }

    public boolean middleRow() {
        return board[3] == board[4] && board[4] == board[5];
    }

    public boolean bottomRow() {
        return board[6] == board[7] && board[7] == board[8];
    }

    public boolean firstCol() {
        return board[0] == board[3] && board[3] == board[6];
    }

    public boolean secondCol() {
        return board[1] == board[4] && board[4] == board[7];
    }

    public boolean thirdCol() {
        return board[2] == board[5] && board[5] == board[8];
    }

    public boolean rightDi() {
        return board[0] == board[4] && board[4] == board[8];
    }

    public boolean leftDi() {
        return board[2] == board[4] && board[4] == board[6];
    }

    public boolean isTheBoardFilled() {
        for (int i = 0; i < board.length; i++) {
            if (board[i] == '-') {
                return false;
            }
        }
        return true;
    }

    public String gameOver() {
        boolean didSomeoneWine = isThereAWinner();
        if (didSomeoneWine) {
            return "We have a winner! The winner is " + this.winner + "'s";
        } else if (isTheBoardFilled()) {
            return "Draw: Game Over!";
        } else {
            return "notOver";
        }
    }
}

TicTacToe.java

 

 

 


import java.util.Scanner;

public class TicTacToeApplication {
    public static void main(String[] args) {
        // Getting input
        Scanner sc = new Scanner(System.in);
        // Allows for continuous games
        boolean doYouWantToPlay = true;
        while(doYouWantToPlay) {
            // Setting up out tokens and AI
            System.out.println("Welcome to Tic Tac Toe! You are about to go against "
                    + "the master of Tic Tac Toe. Are you ready? I hope so!\n BUT FIRST, you"
                    + "must pick what character you want to be and which character I will be");
            System.out.println();
            System.out.println("Enter a single character that will represent you on the board");
            char playerToken = sc.next().charAt(0);
            System.out.println("Enter a single character that will represent that will represent your opponent on the board");
            char opponentToken = sc.next().charAt(0);
            TicTacToe game = new TicTacToe(playerToken, opponentToken);
            AI ai = new AI();

            // Set up the game
            System.out.println();
            System.out.println("Now we can start the game. To play, enter a number and your token shall be put "
            +"in its place. \nThe numbers go from 1-9, left to right. Well shall see who will win this round.");
            TicTacToe.printIndexBoard();
            System.out.println();

            // Let's play!
            while(game.gameOver().equals("notOver")) {
                if(game.currentMarker == game.userMarker) {
                    // USER TURN
                    System.out.println("It's your turn! Enter a spot for your token");
                    int spot = sc.nextInt();
                    while(!game.playTurn(spot)) {
                        System.out.println("Try again. " + spot + " is invalid. This spot is already taken"
                        + " or it is out of range");
                    }
                    System.out.println("You picked " + spot + "!");
                } else {
                    // AI Turn
                    System.out.println("It's my turn!");
                    // Pick spot
                    int aiSpot = ai.pickSpot(game);
                    game.playTurn(aiSpot);
                    System.out.println("I picked " + aiSpot + "!");
                }
                // Print out new board
                System.out.println();
                game.printBoard();
            }
            System.out.println(game.gameOver());
            System.out.println();
            // Set up a new Game.. or not depending on the response
            System.out.println("Do you want to play again? Enter Y if you do."
                    + "Enter anything else if you are tired of me.");
            char response = sc.next().charAt(0);
            doYouWantToPlay = (response== 'Y');
            System.out.println();
            System.out.println();
        }
    }
}

TicTacToeApplication.java

 

 


import java.util.ArrayList;
import java.util.Random;

public class AI {
    public int pickSpot(TicTacToe game) {
        ArrayList<Integer> choices = new ArrayList<>();
        for(int i = 0; i < 9; i++) {
            // If the slot is not taken, add it as a choice
            if(game.board[i] == '-') {
                choices.add(i + 1);
            }
        }
        Random rand = new Random();
        int choice = choices.get(Math.abs(rand.nextInt() % choices.size()));
        return choice;
    }
}

AI.java

 

 

 

 

오늘은 소스코드의 양이 상당하다.

강의를 들으며 직접 따라해보기를 추천한다.

 

혹시나 소스코드를 보고 바로 이해가 되지 않는 사람을 위해

필자가 이해했던 정리본(?)을 공유한다

(각 메서드가 어떤 것을 하는지 적어둠.)

 

각 메서드별 설명

 

필자도 솔직히 처음에 한번에

이해하는 데는 어려움이 있었다.

 

게임의 원리를 하나씩 차근차근 이해하고

소스 코드를 받아적는 데 한 번 강의를 듣고,

반복해서 또 한 번 강의를 듣고,

모르는 부분은 직접 손으로 그려가며 수업을 반복해서 들으며 이해했다.

 

필자의 설명과 강의를 듣고도

이해하지 못하는 부분이 있따면

댓글을 남겨주면 답글 달도록 하겠다!!

 


 

 

그럼 우리는 다음 포스팅에서

소스 코드 리뷰로 다시 만나자. 😊

반응형