객체지향 좀 더 이해하기 - 블랙잭 게임 구현 (5)

Java·2016.11.28 00:00

2-5. Rule 구현하기

Rule은 승자를 판단하는 역할을 갖고 있습니다.
그래서 게임에 참여한 Player들의 카드를 비교해 승자를 구하는 코드를 구현해보겠습니다.

    public Player getWinner(List<Player> players){
        Player highestPlayer = null;
        int highestPoint = 0;

        for(Player player : players) {
            int playerPointSum = getPointSum(player.openCards());
            if(playerPointSum > highestPoint){
                highestPlayer = player;
                highestPoint = playerPointSum;
            }
        }

        return highestPlayer;
    }

    private int getPointSum (List<Card> cards) {
        int sum = 0;

        for(Card card : cards) {
            sum += card.getPoint();
        }

        return sum;
    }

여기서는 getWinner가 point의 합계를 구하는 역할까지 하는 것을 방지하기 위해 getPointSum 메소드를 통해 역할을 분리하였습니다.
현재 코드에선 부족한 것이 하나 있습니다.
승리한 Player를 전달해주지만, 콘솔에 어느 Player가 승리하였는지 표시할 수 있는 방법이 없습니다.
그래서 이를 위해 Player / Gamer / Dealer에 getName이라는 메소드를 추가하도록 하겠습니다.

public interface Player {
    .....

    String getName();
}

public class Gamer implements Player {
    private List<Card> cards;
    private boolean turn;
    private String name;

    public Gamer(String name) {
        this.cards = new ArrayList<>();
        this.name = name;
    }

    ....

    @Override
    public String getName() {
        return this.name;
    }
}

public class Dealer implements Player {
    private List<Card> cards;
    private boolean turn;

    private static final int CAN_RECEIVE_POINT = 16;
    private static final String NAME = "딜러";

    ..... 

    @Override
    public String getName() {
        return NAME;
    }
}

이 부분의 특이한 점은 Gamer의 getName과 Dealer의 getName이 서로 방식으로 리턴한다는 것입니다.
Gamer의 경우 생성자로 전달 받은 name값을 전달하지만,
Dealer의 경우 상수로 지정된 "딜러" 를 전달합니다.
이는 Dealer의 경우엔 한 게임에 딜러 1명 외에는 존재할 수 없지만, Gamer의 경우엔 여러 Gamer가 참여할 수 있기 때문에 name이 변경 가능해야하기 때문입니다.
Scanner로 Gamer의 name을 입력 받을 수 있지만 여기선 생성자에 바로 입력해서 play 메소드를 완성시키겠습니다.


Game.java

    public void play(){
        System.out.println("========= Blackjack =========");
        Scanner sc = new Scanner(System.in);
        Rule rule = new Rule();
        CardDeck cardDeck = new CardDeck();

        List<Player> players = Arrays.asList(new Gamer("사용자1"), new Dealer());
        List<Player> initAfterPlayers = initPhase(cardDeck, players);
        List<Player> playingAfterPlayers = playingPhase(sc, cardDeck, initAfterPlayers);

        Player winner = rule.getWinner(playingAfterPlayers);
        System.out.println("승자는 " + winner.getName());
    }

    .....

    private List<Player> receiveCardAllPlayers(Scanner sc, CardDeck cardDeck, List<Player> players) {
        for(Player player : players) {
            System.out.println(player.getName()+"님 차례입니다.");

            if(isReceiveCard(sc)) {
                Card card = cardDeck.draw();
                player.receiveCard(card);
                player.turnOn();
            }else{
                player.turnOff();
            }
        }

        return players;
    }     

추가로 현재 차례가 누군지 확인하기 위해 receiveCardAllPlayers에도 getName을 활용한 안내메세지를 추가하였습니다.
이렇게 완성후 게임을 진행해보면!!


(게임 결과!) 


원하는 대로 콘솔에서 게임을 진행이 되는 것을 확인할 수 있습니다.
드디어 게임이 완성되었습니다.
현재 버전이 100% 라고 할수는 없습니다.
아직도 많은 리팩토링이 필요하고, 부족함이 많은 예제라 생각합니다.
다만 현재 버전은 여기서 마무리 하겠습니다^^;
만약 예제를 좀 더 사용하고자 하신다면 꼭꼭! Java8의 람다와 스트림으로 코드를 변경해보시는 것을 추천드립니다.

후기

코딩하는 시간보다 생각하는 시간이 더 많았습니다.
하루 4시간은 꼭 코딩해야지 라는 규칙을 가지고 있었는데, 이렇게 짜면 되나? 아 이건 좀 별로네? 등의 생각과 함께 모니터를 보는 시간이 더 많아지고 진도는 나가지 않아서 다른 포스팅보다 훨씬 더 어려웠던 시간이였던 것 같습니다.
제일 걱정했던 것은 제가 작성했던 모든 코드가 틀린 것은 아닐까 하는것 이였습니다.
그런 걱정이 드니 오히려 더 해봐야겠다는 생각이 들었습니다.
전부 잘못되었다면 혹은 일부 잘못된게 있는데 고치지 못하면 그게 더 나쁜 습관으로 남을 것 같았습니다.
아무쪼록 부족한 내용이지만 여기까지 읽어주셔서 정말 감사드립니다.
다음에 더 좋은 내용으로 또 뵙겠습니다.

참고 자료


블로그가 도움이 되셨다면 아래 공감과 광고 클릭을 부탁드립니다!

공감과 광고클릭은 앞으로 계속 글을 쓰는데 큰 힘이 됩니다!




IntelliJ & 안드로이드 스튜디오의 기본기를 배우고 싶다면 아래 영상을 참고해보세요 !

Posted by 창천향로 창천향로

태그


티스토리 툴바