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