테니스 점수판
출력
> 경기의 세트 수(3 or 5), 두 선수의 이름을 각각 입력해주세요 ? 3 라이언 어피치
[0, 0]
라이언 [15, 0, 0, 0, 0, 0]
어피치 [0, 0, 0, 0, 0, 0]
[0, 0]
라이언 [30, 0, 0, 0, 0, 0]
어피치 [0, 0, 0, 0, 0, 0]
[0, 0]
라이언 [30, 0, 0, 0, 0, 0]
어피치 [15, 0, 0, 0, 0, 0]
[0, 0]
라이언 [30, 0, 0, 0, 0, 0]
어피치 [30, 0, 0, 0, 0, 0]
[0, 0]
라이언 [30, 0, 0, 0, 0, 0]
어피치 [40, 0, 0, 0, 0, 0]
[0, 0]
라이언 [40, 0, 0, 0, 0, 0]
어피치 [40, 0, 0, 0, 0, 0]
[0, 0]
라이언 [40, 0, 0, 0, 0, 0]
어피치 [45, 0, 0, 0, 0, 0]
[0, 0]
라이언 [40, 0, 0, 0, 0, 0]
어피치 [40, 0, 0, 0, 0, 0]
[0, 0]
라이언 [45, 0, 0, 0, 0, 0]
어피치 [40, 0, 0, 0, 0, 0]
[0, 0]
라이언 [40, 0, 0, 0, 0, 0]
어피치 [40, 0, 0, 0, 0, 0]
[0, 0]
라이언 [45, 0, 0, 0, 0, 0]
어피치 [40, 0, 0, 0, 0, 0]
[0, 0]
라이언 [40, 0, 0, 0, 0, 0]
어피치 [40, 0, 0, 0, 0, 0]
[0, 0]
라이언 [45, 0, 0, 0, 0, 0]
어피치 [40, 0, 0, 0, 0, 0]
[0, 0]
라이언 [40, 0, 0, 0, 0, 0]
어피치 [40, 0, 0, 0, 0, 0]
[0, 0]
라이언 [40, 0, 0, 0, 0, 0]
어피치 [45, 0, 0, 0, 0, 0]
[0, 0]
라이언 [40, 0, 0, 0, 0, 0]
어피치 [40, 0, 0, 0, 0, 0]
[0, 0]
라이언 [45, 0, 0, 0, 0, 0]
어피치 [40, 0, 0, 0, 0, 0]
[0, 0]
라이언 [40, 0, 0, 0, 0, 0]
어피치 [40, 0, 0, 0, 0, 0]
[0, 0]
라이언 [45, 0, 0, 0, 0, 0]
어피치 [40, 0, 0, 0, 0, 0]
[0, 0]
라이언 [40, 0, 0, 0, 0, 0]
어피치 [40, 0, 0, 0, 0, 0]
[0, 0]
라이언 [40, 0, 0, 0, 0, 0]
어피치 [45, 0, 0, 0, 0, 0]
[0, 0]
라이언 [40, 0, 0, 0, 0, 0]
어피치 [40, 0, 0, 0, 0, 0]
[0, 0]
라이언 [40, 0, 0, 0, 0, 0]
어피치 [45, 0, 0, 0, 0, 0]
[0, 0]
라이언 [40, 0, 0, 0, 0, 0]
어피치 [40, 0, 0, 0, 0, 0]
[0, 0]
라이언 [45, 0, 0, 0, 0, 0]
어피치 [40, 0, 0, 0, 0, 0]
[0, 0]
라이언 [40, 0, 0, 0, 0, 0]
어피치 [40, 0, 0, 0, 0, 0]
[0, 0]
라이언 [45, 0, 0, 0, 0, 0]
어피치 [40, 0, 0, 0, 0, 0]
[1, 0]
라이언 [50, 0, 0, 0, 0, 0]
어피치 [40, 0, 0, 0, 0, 0]
> 라이언가 어피치를 50 : 40 으로 이겼습니다.
> 엔터를 입력하면 다음게임을 시작합니다.
[1, 0]
라이언 [50, 0, 0, 0, 0, 0]
어피치 [40, 15, 0, 0, 0, 0]
[1, 0]
라이언 [50, 15, 0, 0, 0, 0]
어피치 [40, 15, 0, 0, 0, 0]
[1, 0]
라이언 [50, 30, 0, 0, 0, 0]
어피치 [40, 15, 0, 0, 0, 0]
[1, 0]
라이언 [50, 40, 0, 0, 0, 0]
어피치 [40, 15, 0, 0, 0, 0]
[1, 0]
라이언 [50, 40, 0, 0, 0, 0]
어피치 [40, 30, 0, 0, 0, 0]
[2, 0]
라이언 [50, 45, 0, 0, 0, 0]
어피치 [40, 30, 0, 0, 0, 0]
> 라이언가 어피치를 45 : 30 으로 이겼습니다.
> 엔터를 입력하면 다음게임을 시작합니다.
[2, 0]
라이언 [50, 45, 15, 0, 0, 0]
어피치 [40, 30, 0, 0, 0, 0]
[2, 0]
라이언 [50, 45, 15, 0, 0, 0]
어피치 [40, 30, 15, 0, 0, 0]
[2, 0]
라이언 [50, 45, 30, 0, 0, 0]
어피치 [40, 30, 15, 0, 0, 0]
[2, 0]
라이언 [50, 45, 40, 0, 0, 0]
어피치 [40, 30, 15, 0, 0, 0]
[3, 0]
라이언 [50, 45, 45, 0, 0, 0]
어피치 [40, 30, 15, 0, 0, 0]
> 라이언가 어피치를 45 : 15 으로 이겼습니다.
> 엔터를 입력하면 다음게임을 시작합니다.
[3, 0]
라이언 [50, 45, 45, 15, 0, 0]
어피치 [40, 30, 15, 0, 0, 0]
[3, 0]
라이언 [50, 45, 45, 30, 0, 0]
어피치 [40, 30, 15, 0, 0, 0]
[3, 0]
라이언 [50, 45, 45, 30, 0, 0]
어피치 [40, 30, 15, 15, 0, 0]
[3, 0]
라이언 [50, 45, 45, 30, 0, 0]
어피치 [40, 30, 15, 30, 0, 0]
[3, 0]
라이언 [50, 45, 45, 40, 0, 0]
어피치 [40, 30, 15, 30, 0, 0]
[4, 0]
라이언 [50, 45, 45, 45, 0, 0]
어피치 [40, 30, 15, 30, 0, 0]
> 라이언가 어피치를 45 : 30 으로 이겼습니다.
> 엔터를 입력하면 다음게임을 시작합니다.
[4, 0]
라이언 [50, 45, 45, 45, 15, 0]
어피치 [40, 30, 15, 30, 0, 0]
[4, 0]
라이언 [50, 45, 45, 45, 15, 0]
어피치 [40, 30, 15, 30, 15, 0]
[4, 0]
라이언 [50, 45, 45, 45, 30, 0]
어피치 [40, 30, 15, 30, 15, 0]
[4, 0]
라이언 [50, 45, 45, 45, 40, 0]
어피치 [40, 30, 15, 30, 15, 0]
[5, 0]
라이언 [50, 45, 45, 45, 45, 0]
어피치 [40, 30, 15, 30, 15, 0]
> 라이언가 어피치를 45 : 15 으로 이겼습니다.
> 엔터를 입력하면 다음게임을 시작합니다.
[5, 0]
라이언 [50, 45, 45, 45, 45, 0]
어피치 [40, 30, 15, 30, 15, 15]
[5, 0]
라이언 [50, 45, 45, 45, 45, 15]
어피치 [40, 30, 15, 30, 15, 15]
[5, 0]
라이언 [50, 45, 45, 45, 45, 15]
어피치 [40, 30, 15, 30, 15, 30]
[5, 0]
라이언 [50, 45, 45, 45, 45, 30]
어피치 [40, 30, 15, 30, 15, 30]
[5, 0]
라이언 [50, 45, 45, 45, 45, 30]
어피치 [40, 30, 15, 30, 15, 40]
[5, 1]
라이언 [50, 45, 45, 45, 45, 30]
어피치 [40, 30, 15, 30, 15, 45]
> 어피치가 라이언를 45 : 30 으로 이겼습니다.
> 엔터를 입력하면 다음게임을 시작합니다.
[5, 1]
라이언 [15, 0, 0, 0, 0, 0]
어피치 [0, 0, 0, 0, 0, 0]
[5, 1]
라이언 [30, 0, 0, 0, 0, 0]
어피치 [0, 0, 0, 0, 0, 0]
[5, 1]
라이언 [40, 0, 0, 0, 0, 0]
어피치 [0, 0, 0, 0, 0, 0]
[6, 1]
라이언 [45, 0, 0, 0, 0, 0]
어피치 [0, 0, 0, 0, 0, 0]
> 라이언가 어피치를 45 : 0 으로 이겼습니다.
------------------------------
< 1 세트 결과 >
라이언 [45, 0, 0, 0, 0, 0]
어피치 [0, 0, 0, 0, 0, 0]
> 1 세트 승리자 : 라이언
라이언가 총 이긴 게임 수 : 6
어피치가 총 이긴 게임 수 : 1
------------------------------
> 엔터를 입력하면 다음게임을 시작합니다.
[0, 0]
라이언 [0, 0, 0, 0, 0, 0]
어피치 [15, 0, 0, 0, 0, 0]
[0, 0]
라이언 [0, 0, 0, 0, 0, 0]
어피치 [30, 0, 0, 0, 0, 0]
[0, 0]
라이언 [15, 0, 0, 0, 0, 0]
어피치 [30, 0, 0, 0, 0, 0]
[0, 0]
라이언 [30, 0, 0, 0, 0, 0]
어피치 [30, 0, 0, 0, 0, 0]
[0, 0]
라이언 [40, 0, 0, 0, 0, 0]
어피치 [30, 0, 0, 0, 0, 0]
[0, 0]
라이언 [40, 0, 0, 0, 0, 0]
어피치 [40, 0, 0, 0, 0, 0]
[0, 0]
라이언 [40, 0, 0, 0, 0, 0]
어피치 [45, 0, 0, 0, 0, 0]
[0, 0]
라이언 [40, 0, 0, 0, 0, 0]
어피치 [40, 0, 0, 0, 0, 0]
[0, 0]
라이언 [40, 0, 0, 0, 0, 0]
어피치 [45, 0, 0, 0, 0, 0]
[0, 0]
라이언 [40, 0, 0, 0, 0, 0]
어피치 [40, 0, 0, 0, 0, 0]
[0, 0]
라이언 [45, 0, 0, 0, 0, 0]
어피치 [40, 0, 0, 0, 0, 0]
[0, 0]
라이언 [40, 0, 0, 0, 0, 0]
어피치 [40, 0, 0, 0, 0, 0]
[0, 0]
라이언 [45, 0, 0, 0, 0, 0]
어피치 [40, 0, 0, 0, 0, 0]
[0, 0]
라이언 [40, 0, 0, 0, 0, 0]
어피치 [40, 0, 0, 0, 0, 0]
[0, 0]
라이언 [45, 0, 0, 0, 0, 0]
어피치 [40, 0, 0, 0, 0, 0]
[1, 0]
라이언 [50, 0, 0, 0, 0, 0]
어피치 [40, 0, 0, 0, 0, 0]
> 라이언가 어피치를 50 : 40 으로 이겼습니다.
> 엔터를 입력하면 다음게임을 시작합니다.
[1, 0]
라이언 [50, 0, 0, 0, 0, 0]
어피치 [40, 15, 0, 0, 0, 0]
[1, 0]
라이언 [50, 0, 0, 0, 0, 0]
어피치 [40, 30, 0, 0, 0, 0]
[1, 0]
라이언 [50, 0, 0, 0, 0, 0]
어피치 [40, 40, 0, 0, 0, 0]
[1, 1]
라이언 [50, 0, 0, 0, 0, 0]
어피치 [40, 45, 0, 0, 0, 0]
> 어피치가 라이언를 45 : 0 으로 이겼습니다.
> 엔터를 입력하면 다음게임을 시작합니다.
[1, 1]
라이언 [50, 0, 15, 0, 0, 0]
어피치 [40, 45, 0, 0, 0, 0]
[1, 1]
라이언 [50, 0, 30, 0, 0, 0]
어피치 [40, 45, 0, 0, 0, 0]
[1, 1]
라이언 [50, 0, 30, 0, 0, 0]
어피치 [40, 45, 15, 0, 0, 0]
[1, 1]
라이언 [50, 0, 30, 0, 0, 0]
어피치 [40, 45, 30, 0, 0, 0]
[1, 1]
라이언 [50, 0, 30, 0, 0, 0]
어피치 [40, 45, 40, 0, 0, 0]
[1, 2]
라이언 [50, 0, 30, 0, 0, 0]
어피치 [40, 45, 45, 0, 0, 0]
> 어피치가 라이언를 45 : 30 으로 이겼습니다.
> 엔터를 입력하면 다음게임을 시작합니다.
[1, 2]
라이언 [50, 0, 30, 15, 0, 0]
어피치 [40, 45, 45, 0, 0, 0]
[1, 2]
라이언 [50, 0, 30, 30, 0, 0]
어피치 [40, 45, 45, 0, 0, 0]
[1, 2]
라이언 [50, 0, 30, 40, 0, 0]
어피치 [40, 45, 45, 0, 0, 0]
[2, 2]
라이언 [50, 0, 30, 45, 0, 0]
어피치 [40, 45, 45, 0, 0, 0]
> 라이언가 어피치를 45 : 0 으로 이겼습니다.
> 엔터를 입력하면 다음게임을 시작합니다.
[2, 2]
라이언 [50, 0, 30, 45, 0, 0]
어피치 [40, 45, 45, 0, 15, 0]
[2, 2]
라이언 [50, 0, 30, 45, 0, 0]
어피치 [40, 45, 45, 0, 30, 0]
[2, 2]
라이언 [50, 0, 30, 45, 15, 0]
어피치 [40, 45, 45, 0, 30, 0]
[2, 2]
라이언 [50, 0, 30, 45, 30, 0]
어피치 [40, 45, 45, 0, 30, 0]
[2, 2]
라이언 [50, 0, 30, 45, 40, 0]
어피치 [40, 45, 45, 0, 30, 0]
[3, 2]
라이언 [50, 0, 30, 45, 45, 0]
어피치 [40, 45, 45, 0, 30, 0]
> 라이언가 어피치를 45 : 30 으로 이겼습니다.
> 엔터를 입력하면 다음게임을 시작합니다.
[3, 2]
라이언 [50, 0, 30, 45, 45, 15]
어피치 [40, 45, 45, 0, 30, 0]
[3, 2]
라이언 [50, 0, 30, 45, 45, 15]
어피치 [40, 45, 45, 0, 30, 15]
[3, 2]
라이언 [50, 0, 30, 45, 45, 30]
어피치 [40, 45, 45, 0, 30, 15]
[3, 2]
라이언 [50, 0, 30, 45, 45, 40]
어피치 [40, 45, 45, 0, 30, 15]
[4, 2]
라이언 [50, 0, 30, 45, 45, 45]
어피치 [40, 45, 45, 0, 30, 15]
> 라이언가 어피치를 45 : 15 으로 이겼습니다.
> 엔터를 입력하면 다음게임을 시작합니다.
[4, 2]
라이언 [15, 0, 0, 0, 0, 0]
어피치 [0, 0, 0, 0, 0, 0]
[4, 2]
라이언 [15, 0, 0, 0, 0, 0]
어피치 [15, 0, 0, 0, 0, 0]
[4, 2]
라이언 [15, 0, 0, 0, 0, 0]
어피치 [30, 0, 0, 0, 0, 0]
[4, 2]
라이언 [30, 0, 0, 0, 0, 0]
어피치 [30, 0, 0, 0, 0, 0]
[4, 2]
라이언 [30, 0, 0, 0, 0, 0]
어피치 [40, 0, 0, 0, 0, 0]
[4, 3]
라이언 [30, 0, 0, 0, 0, 0]
어피치 [45, 0, 0, 0, 0, 0]
> 어피치가 라이언를 45 : 30 으로 이겼습니다.
> 엔터를 입력하면 다음게임을 시작합니다.
[4, 3]
라이언 [30, 15, 0, 0, 0, 0]
어피치 [45, 0, 0, 0, 0, 0]
[4, 3]
라이언 [30, 30, 0, 0, 0, 0]
어피치 [45, 0, 0, 0, 0, 0]
[4, 3]
라이언 [30, 30, 0, 0, 0, 0]
어피치 [45, 15, 0, 0, 0, 0]
[4, 3]
라이언 [30, 40, 0, 0, 0, 0]
어피치 [45, 15, 0, 0, 0, 0]
[5, 3]
라이언 [30, 45, 0, 0, 0, 0]
어피치 [45, 15, 0, 0, 0, 0]
> 라이언가 어피치를 45 : 15 으로 이겼습니다.
> 엔터를 입력하면 다음게임을 시작합니다.
[5, 3]
라이언 [30, 45, 0, 0, 0, 0]
어피치 [45, 15, 15, 0, 0, 0]
[5, 3]
라이언 [30, 45, 0, 0, 0, 0]
어피치 [45, 15, 30, 0, 0, 0]
[5, 3]
라이언 [30, 45, 15, 0, 0, 0]
어피치 [45, 15, 30, 0, 0, 0]
[5, 3]
라이언 [30, 45, 15, 0, 0, 0]
어피치 [45, 15, 40, 0, 0, 0]
[5, 4]
라이언 [30, 45, 15, 0, 0, 0]
어피치 [45, 15, 45, 0, 0, 0]
> 어피치가 라이언를 45 : 15 으로 이겼습니다.
> 엔터를 입력하면 다음게임을 시작합니다.
[5, 4]
라이언 [30, 45, 15, 15, 0, 0]
어피치 [45, 15, 45, 0, 0, 0]
[5, 4]
라이언 [30, 45, 15, 15, 0, 0]
어피치 [45, 15, 45, 15, 0, 0]
[5, 4]
라이언 [30, 45, 15, 30, 0, 0]
어피치 [45, 15, 45, 15, 0, 0]
[5, 4]
라이언 [30, 45, 15, 40, 0, 0]
어피치 [45, 15, 45, 15, 0, 0]
[5, 4]
라이언 [30, 45, 15, 40, 0, 0]
어피치 [45, 15, 45, 30, 0, 0]
[5, 4]
라이언 [30, 45, 15, 40, 0, 0]
어피치 [45, 15, 45, 40, 0, 0]
[5, 4]
라이언 [30, 45, 15, 45, 0, 0]
어피치 [45, 15, 45, 40, 0, 0]
[6, 4]
라이언 [30, 45, 15, 50, 0, 0]
어피치 [45, 15, 45, 40, 0, 0]
> 라이언가 어피치를 50 : 40 으로 이겼습니다.
------------------------------
< 2 세트 결과 >
라이언 [30, 45, 15, 50, 0, 0]
어피치 [45, 15, 45, 40, 0, 0]
> 2 세트 승리자 : 라이언
라이언가 총 이긴 게임 수 : 6
어피치가 총 이긴 게임 수 : 4
------------------------------
.
.
.
.
.
------------------------------
< 최종 게임 결과 >
> 1세트: 라이언
> 2세트: 라이언
라이언가 총 이긴 세트 수 : 2
어피치가 총 이긴 세트 수 : 0
҉ ٩(๑>ω<๑)۶҉ ( ✪ワ✪)ノʸᵉᵃʰᵎ
라이언 이(가) 3 세트의 테니스게임을 승리했습니다.
(◍’౪`◍)♡ (^▽^)/ ʸᵉᔆᵎ
------------------------------
Main
package tennis;
import static tennis.Condition.*;
import static tennis.Tennis.*;
import java.util.Random;
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Tennis.makeNewFile(); // 파일이 이미 있다면 내용을 비움
Scanner sc = new Scanner(System.in);
Random random = new Random();
scoreBoard.put(1, new int[6]);
scoreBoard.put(2, new int[6]);
System.out.print("> 경기의 세트 수(3 or 5), 두 선수의 이름을 각각 입력해주세요 ? ");
set = sc.nextInt();
// 세트 수는 3 이나 5 이어야 함
if (set != 3 && set != 5) {
System.out.println("> 세트 수는 3세트와 5세트만 있습니다.");
return;
}
// 선수이름 입력
players[0] = sc.next();
players[1] = sc.next();
// 게임시작
Game: while (true) {
int winPlayer;
// 게임한판
while (true) {
winPlayer = random.nextInt(2) + 1; // 1 or 2 이 이기는지지는지 여기서 결정
int losePlayer = winPlayer == 2 ? 1 : 2;
checkBoard(); // 게임배열의 인덱스가 배열크기를 초과했는지 확인
// 이긴 사람이 40 이고 진 사람이 45 이면 진 사람의 점수를 40 으로 변경
if (isForty(winPlayer) && Condition.isFortyfive(losePlayer)) {
scoreIdxs[losePlayer - 1]--;
scoreBoard.get(losePlayer)[curGame] = scores[scoreIdxs[losePlayer - 1] - 1];
} else {
pointWinner(winPlayer); // 이긴사람의 점수를 증가
}
// 이긴 사람이 45 이상이고 듀스가 아니라면 승수를 더하고 다음게임
if (overFortyfive(winPlayer) && !isDeuce(winPlayer)) {
Tennis.gameEnded(winPlayer, losePlayer);
break;
}
// 점수판 출력 및 세트가 2점차로 끝났는지 확인
dispScoreBoard();
} // 안쪽 while
// 한 세트가 끝났다면
if (setEnded(winPlayer)) {
saveScoreBoard();
printSetResult(winPlayer);
setCount++;
// 3선2승 혹은 5선3승을 하면
if (Tennis.winMoreThanHalf(winPlayer)) {
resetBoardAndScore(winPlayer);
Tennis.saveGameResult();
break Game; // 모든 게임을 종료
}
}
System.out.println("> 엔터를 입력하면 다음게임을 시작합니다.");
Tennis.keyBoardInput();
} // 바깥 while
}
}
Tennis
package tennis;
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map.Entry;
public class Tennis {
static HashMap<Integer, int[]> scoreBoard = new HashMap<>();
static int[] scores = { 0, 15, 30, 40, 45, 50 }; // 점수 배열을 방문할 인덱스 값
static int[] scoreIdxs = { 1, 1 }; // { 1번 플레이어의 점수 인덱스 값, 2번 플레이어의 점수 인덱스 값 }
static String[] players = new String[2]; // 선수 이름 배열
static int set;
static int curGame = 0; // 0 ~ 5 현재 게임의 인덱스
static int[] setWinner = new int[2]; // 세트 당 게임 승리 수
static ArrayList<Integer> totalSetScore = new ArrayList<Integer>();
static int winInARow;
static int setCount = 1;
// 점수판을 출력
static void dispScoreBoard() {
System.out.println(Arrays.toString(setWinner));
scoreBoard.forEach((k, v) -> System.out.println(players[k - 1] + " " + Arrays.toString(v)));
}
static void pointWinner(int winner) {
scoreBoard.get(winner)[curGame] = scores[scoreIdxs[winner - 1]];
scoreIdxs[winner - 1]++;
}
public static void resetBoardAndScore(int winPlayer) {
for (int i = 0; i < 5; i++) {
System.out.println("\t\t . \t\t ");
}
System.out.println("-".repeat(30));
clearBoard();
printGameResult();
System.out.println("-".repeat(30));
}
// 게임배열을 텍스트파일로 저장
public static void saveScoreBoard() {
String path = "src\\tennis\\Game_Result.txt";
try (BufferedWriter bw = new BufferedWriter(new FileWriter(path, true))) {
Iterator<Entry<Integer, int[]>> entry = scoreBoard.entrySet().iterator();
while (entry.hasNext()) {
Entry<Integer, int[]> ir = entry.next();
String line = players[ir.getKey() - 1] + " " + Arrays.toString(ir.getValue()) + "\n";
bw.write(line);
}
} catch (Exception e) {
e.printStackTrace();
}
}
// 게임배열을 모두 비움
public static void clearBoard() {
curGame = 0;
Arrays.fill(scoreBoard.get(1), 0);
Arrays.fill(scoreBoard.get(2), 0);
}
// curGame 배열의 인덱스가 배열크기를 초과하면 게임배열 초기화
static void checkBoard() {
if (curGame >= scoreBoard.get(1).length) {
saveScoreBoard();
clearBoard();
}
}
// 세트결과 저장
static void saveGameResult(int winPlayer) {
String path = "src\\tennis\\Game_Result.txt";
try (BufferedWriter bw = new BufferedWriter(new FileWriter(path, true))) {
bw.write("-".repeat(30) + "\n");
bw.write(String.format(" < %d 세트 결과 > \n", setCount));
bw.write("\n");
bw.write(String.format("> %d 세트 승리자 : %s\n", setCount, players[winPlayer - 1]));
bw.write("\n");
int Agame = setWinner[0];
int Bgame = setWinner[1];
bw.write(String.format("%s가 총 이긴 게임 수 : %d\n", players[0], Agame));
bw.write(String.format("%s가 총 이긴 게임 수 : %d\n", players[1], Bgame));
bw.write("\n");
bw.write("-".repeat(30) + "\n");
} catch (Exception e) {
e.printStackTrace();
}
}
static void printSetResult(int winPlayer) {
System.out.println("-".repeat(30));
System.out.printf(" < %d 세트 결과 > \n", setCount);
scoreBoard.forEach((k, v) -> System.out.println(players[k - 1] + " " + Arrays.toString(v)));
System.out.println();
System.out.printf("> %d 세트 승리자 : %s\n", setCount, players[winPlayer - 1]);
System.out.println();
int Agame = setWinner[0];
int Bgame = setWinner[1];
System.out.printf("%s가 총 이긴 게임 수 : %d\n", players[0], Agame);
System.out.printf("%s가 총 이긴 게임 수 : %d\n", players[1], Bgame);
System.out.println();
System.out.println("-".repeat(30));
saveGameResult(winPlayer);
totalSetScore.add(winPlayer);
clearBoard();
// 점수배열의 인덱스와 승수를 초기화
Arrays.fill(scoreIdxs, 1);
Arrays.fill(setWinner, 0);
}
private static void printGameResult() {
System.out.println(" < 최종 게임 결과 > ");
int Aset = 0;
int Bset = 0;
for (int i = 0; i < totalSetScore.size(); i++) {
System.out.printf("> %d세트: " + players[totalSetScore.get(i) - 1] + "\n", (i + 1));
if (totalSetScore.get(i) == 1) {
Aset++;
} else if (totalSetScore.get(i) == 2) {
Bset++;
}
}
System.out.printf("\n%s가 총 이긴 세트 수 : %d\n", players[0], Aset);
System.out.printf("%s 가 총 이긴 세트 수 : %d\n\n", players[1], Bset);
System.out.println("҉ ٩(๑>ω<๑)۶҉\t\t( ✪ワ✪)ノʸᵉᵃʰᵎ");
System.out.printf("%s 이(가) %d 세트의 테니스게임을 승리했습니다.\n", players[Aset > Bset ? 0 : 1], set);
System.out.println("(◍’౪`◍)♡\t\t(^▽^)/ ʸᵉᔆᵎ");
}
// 최종 게임결과 저장
public static void saveGameResult() {
String path = "src\\tennis\\Game_Result.txt";
try (BufferedWriter bw = new BufferedWriter(new FileWriter(path, true))) {
int Aset = 0;
int Bset = 0;
bw.write("\n\n < 최종 게임 결과 > ");
for (int i = 0; i < totalSetScore.size(); i++) {
bw.write(String.format("\n> %d세트: " + players[totalSetScore.get(i) - 1], (i + 1)));
if (totalSetScore.get(i) == 1) {
Aset++;
} else if (totalSetScore.get(i) == 2) {
Bset++;
}
}
bw.write(String.format("\n\n%s가 총 이긴 세트 수 : %d\n", players[0], Aset));
bw.write(String.format("%s가 총 이긴 세트 수 : %d\n\n", players[1], Bset));
bw.write("҉ ٩(๑>ω<๑)۶҉\t\t( ✪ワ✪)ノʸᵉᵃʰᵎ\n");
bw.write(String.format("%s 이(가) %d 세트의 테니스게임을 승리했습니다.\n", players[Aset > Bset ? 0 : 1], set));
bw.write("(◍’౪`◍)♡\t\t(^▽^)/ ʸᵉᔆᵎ");
} catch (Exception e) {
e.printStackTrace();
}
}
public static boolean winMoreThanHalf(int winPlayer) {
int half = set / 2 + 1;
int setScore = (int) totalSetScore.stream().filter(i -> i == winPlayer).count();
return setScore == half;
}
public static void gameEnded(int winPlayer, int losePlayer) {
setWinner[winPlayer - 1]++;
Arrays.fill(scoreIdxs, 1);
dispScoreBoard();
System.out.printf("> %s가 %s를 %d : %d 으로 이겼습니다.\n", players[winPlayer - 1], players[losePlayer - 1],
scoreBoard.get(winPlayer)[curGame], scoreBoard.get(losePlayer)[curGame]);
curGame++;
}
// 키보드 입력을 기다림
public static void keyBoardInput() {
try {
System.in.read();
System.in.skip(System.in.available());
} catch (IOException e) {
e.printStackTrace();
}
}
public static void makeNewFile() {
try {
new FileWriter("src\\tennis\\Game_Result.txt");
} catch (IOException e) {
e.printStackTrace();
}
}
}
Condition
package tennis;
import static tennis.Tennis.*;
public interface Condition {
// 플레이어의 현재점수가 40 이면 true 반환
static boolean isForty(int player) {
return scoreBoard.get(player)[curGame] == 40;
}
// 플레이어의 현재점수가 45 이면 true 반환
static boolean isFortyfive(int player) {
return scoreBoard.get(player)[curGame] == 45;
}
// 듀스이면 true 반환
static boolean isDeuce(int winPlayer) {
int losePlayer = winPlayer == 2 ? 1 : 2;
return scoreIdxs[winPlayer - 1] - scoreIdxs[losePlayer - 1] < 2;
}
// 한 명이 6점 이상이고 이긴 사람과 진 사람의 승수가 2점이상 차이가 나면 true 반환
static boolean setEnded(int winPlayer) {
int losePlayer = winPlayer == 2 ? 1 : 2;
return setWinner[winPlayer - 1] >= 6 && setWinner[winPlayer - 1] - setWinner[losePlayer - 1] >= 2;
}
// 플레이어의 현재점수가 45 를 넘으면 true 반환
static boolean overFortyfive(int player) {
return scoreBoard.get(player)[curGame] >= 45;
}
}
후기
객체지향의 특성을 잘 사용하지 못했다.
클래스를 잘 사용하여 나누고 (캡슐화), 접근지정자를 활발히 사용하고 (정보은닉), 상속과 다형성을 사용했어야 했다.
디자인패턴도 공부해야 할 것 같다.
객체지향의 5가지 원칙을 잘 지키자. (SOLID)
단일책임원칙 (SRP: Single responsibility principle): 객체는 오직 하나의 책임을 가져야 한다.
계산기 프로그램에서 계산클래스와 GUI 클래스가 있다면 객체는 오직 하나의 책임을 가져야 한다.
만약 중간에 귀찮다고 GUI 관련 코드를 계산클래스에 넣어버리면 계산클래스는 두 가지 책임을 지게되는 것이다.
GUI 수정사항이 발생하면 별 상관도 없어보이는 계산클래스를 고치게 된다.
이런 것을 스파게티 코드라고 한다.개방-폐쇄 원칙 (OCP: Open-Closed Principle): 객체는 확장에 대해서는 개방적이고 수정에 대해서는 폐쇄적이어야 한다는 원칙.
스타크래프트에서 유닛의 이동메서드에서 이동패턴을 나타내는 코드를 별도의 메서드로 분리하고 구현을 하위클래스에 맡긴다. (브루들링 클래스의 이동패턴 메서드만 재정의 한다.)
리스코프 치환 원칙 (LSP: Liskov Substitution Principle): 자식 클래스는 언제나 부모 클래스를 대체할 수 있다는 원칙.
컴퓨터용 마우스 클래스가 있다. 볼마우스던 광마우스던 GPS 를 이용하던 보통의 마우스와 다를 바가 없으면 사용자는 특별한 추가 버튼이 있는 마우스더라도 문제없이 잘 사용한다.
하지만 오른쪽/왼족 버튼 대신 옆쪽 버튼을 사용하는 펜마우스를 접하면 사용자는 이상을 호소할 것이고 이건 LSP 를 잘 지키지 못한 것이다.인터페이스 분리 원칙 (ISP: Interface Segregation Principle): 인터페이스의 SRP 이다.
게임을 만드는데 충돌처리와 이펙트처리를 하는 서버를 두고 클라이언트에게 보내야한다.
Client 라는 인터페이스를 정의하고 충돌전달() 과 이펙트전달(이펙트) 를 넣어놓았다.
그리고 충돌서버와 인터페이스서버에서 이 인터페이스를 구현하는 객체들을 모아두고 때에따라 적절히 신호를 보낸다.
하지만 이러면 충돌서버에겐 필요없는 이펙트전달 인터페이스가, 이펙트서버에겐 쓸모없는 충돌전달 인터페이스가 제공된다.
이걸 막기위해 Cient 인터페이스를 쪼개 이펙트전달가능 인터페이스, 충돌전달가능 인터페이스로 나눈 후 충돌은 충돌에만 이펙트는 이펙트에만 전달하면 된다.
또한 Client 인터페이스는 남겨두되 이펙트 전달가능과 충돌전달가능 이 둘을 상속하면 된다.의존성 역전 원칙 (DIP: Dependency Inversion Principle): 추상성이 높고 안정적인 고수준의 클래스는 구체적이고 불안정한 저수준의 클래스에 의존해서는 안된다는 원칙.
인터페이스를 통해 이 원칙을 준수할 수 있다. 디자인패턴의 전략패턴을 떠올린다.
나는 테니스클래스와 조건클래스로 나누었지만
- 파일생성 클래스
- 입력 클래스
- 출력 클래스
- 게임계산 클래스 (듀스구현)
- 세트계산 클래스 (6게임 2차이로 이기면 세트승리 구현)
- 점수저장 클래스 (싱글톤패턴)
이렇게 나누는 게 맞았다.
Main
File
Game
package pattern;
import java.util.Random;
public class Game {
static String[] scores = { "0", "15", "30", "40", "40A"};
static int[] scoreIdxs = { 0, 0 }; // { 1번 플레이어의 점수 인덱스 값, 2번 플레이어의 점수 인덱스 값 }
static void playGame() {
Random random = new Random();
while (true) {
int winPlayer = random.nextInt(2) + 1; // 1 or 2 이 이기는지지는지 여기서 결정
int losePlayer = winPlayer == 2 ? 1 : 2;
// checkBoard(); // 게임배열의 인덱스가 배열크기를 초과했는지 확인
if (scoreIdxs[winPlayer - 1] == 3 && scoreIdxs[losePlayer - 1] == 4) {
scoreIdxs[losePlayer - 1]--;
} else {
pointWinner(winPlayer); // 이긴사람의 점수를 증가
}
// 이긴 사람이 45 이상이고 듀스가 아니라면 승수를 더하고 다음게임
if (scoreIdxs[winPlayer - 1] == 4 && scoreIdxs[losePlayer - 1] <= 2) {
ScoreBoard.getInstance().gameScore[winPlayer - 1]++;
break;
}
// 점수판 출력 및 세트가 2점차로 끝났는지 확인
dispScoreBoard();
} // 안쪽 while
}
private static void dispScoreBoard() {
// TODO Auto-generated method stub
}
private static void pointWinner(int winPlayer) {
scoreIdxs[winPlayer - 1]++;
}
}
Set
Input
package pattern;
import java.util.Scanner;
public class Input {
static void setGame() {
ScoreBoard scoreBoard = ScoreBoard.getInstance();
System.out.print("> 경기의 세트 수(3 or 5), 두 선수의 이름을 각각 입력해주세요 ? ");
Scanner sc = new Scanner(System.in);
scoreBoard.set = sc.nextInt();
if (scoreBoard.set != 3 && scoreBoard.set != 5) {
System.out.println("> 세트 수는 3세트와 5세트만 있습니다.");
return;
}
scoreBoard.players[0] = sc.next();
scoreBoard.players[1] = sc.next();
}
}
Output
ScoreBoard
package pattern;
import java.util.ArrayList;
import java.util.HashMap;
public class ScoreBoard {
private static ScoreBoard scoreBoard;
HashMap<Integer, int[]> gameBoard = new HashMap<>();
ArrayList<String> setWinner = new ArrayList<>();
public int[] gameScore = new int[2]; // 세트 당 게임 승리 수
String[] players = new String[2];
int set;
private ScoreBoard() {}
public static ScoreBoard getInstance() {
if (scoreBoard == null)
scoreBoard = new ScoreBoard();
return scoreBoard;
}
}