문제
해결 방안 고민
랭킹전 기능 추가
1. 플레이어가 입장 신청 시
1. 매칭이 가능한 방이 없다? => 새로운 방 생성 후 입장
2. 해당 방에는 처음 입장한 플레이어 레벨 기준으로 -10부터 +10까지 입장 가능 (-10 <= x <= 10)
2. 입장 가능한 방이 있다면
1. 입장시킨 다음 방의 정원이 모두 찰 때까지 대기
2. 입장 가능한 방이 여러 개인 경우 먼저 생성된 방에 입장시킴
3. 방의 정원이 모두 차면 게임을 시작
플레이어 수 p
플레이어 닉네임 n
플레이어 레빌 l
방 한 개의 정원 m
해당 조건을 거쳐 최종적으로 만들어진 방의 상태와 입장 플레이어들을 출력
== 입력 ==
첫 번째 줄 => p, m 이 주어짐
두 번째 줄부터 p개의 줄에는 플레이어의 레벨과 닉네임 n이 공백을 두고 주어짐
닉네임은 중복되지 않으며 공백을 포함하지 않는 알파벳 소문자로 구성되어 있음.
닉네임의 길이는 16을 넘지 않음
== 출력 ==
모든 생성된 방에 대해 게임의 시작 유무와 방에 들어있는 플레이어들의 레벨과 아이디(닉네임) 출력
시작 유무와 플레이어의 정보들은 줄 바꿈으로 구분되며 레벨과 닉네임은 한 줄에서 공백으로 구분됨
방은 생성된 순서대로 출력됨
방에 있는 플레이어들의 정보는 닉네임이 사전순으로 앞서는 플레이어부터 출력 (사전순 - 정렬)
방이 시작되었으면 "Started!"를 대기 중이면 "Waiting!"을 출력
25 d
30 e
26 h
24 i
28 j
Markdown
복사
•
처음에는 Map을 활용하여 푸는 것이라고 생각했다.
•
하지만 입출력 형태와 조건을 고려했을 때 Map을 활용하는 것이 아님을 직감했다.
•
결국 Deque를 생각했지만 정작 어떻게 Deque를 활용하여 문제를 해결하는 방법이 떠오르지 않았다.
•
문제는 이해했으나 코드로 구현하는 게 쉽게 떠오르지 않았다.
•
결국 다른 사람이 구현한 코드를 참고했는데 생각보다 괜찮은 코드가 있어서 입출력 관련 코드내용만 수정하고 결과를 출력했더니 원하는 결과가 나왔다.
•
Deque를 활용하는 것은 예상했지만 중첩 클래스와 생성자, 인터페이스 개념까지 활용할 것이라고는 전혀 생각하지 못했다. 거기에 ArrayList와 객체를 제네릭 타입으로 같이 활용하여 변수로 활용하는 내용은 앞으로도 활용할 부분이 많다고 느꼈다.
해결 방법
•
문제 조건에 맞는 로직을 구현할 수 있도록 방, 플레이어의 중첩 클래스를 생성한다.
•
이름을 사전 순으로 정렬하기 위해 Comparable, compareTo 를 활용하였다.
코드
package algo250218;
import java.io.*;
import java.util.*;
public class Baek20006 {
public static int p, m;
// 방 클래스 (중첩 클래스)
public static class Room {
int level; // 방장 레벨
int count; // 방 인원수
ArrayList<Player> players = new ArrayList<>();
Room(int level, Player player) {
this.level = level;
this.players.add(player);
this.count = 1;
}
}
// 플레이어 클래스
public static class Player implements Comparable<Player> {
int level; // 플레이어 레벨
String name; // 플레이어 이름
Player(int level, String name) {
this.level = level;
this.name = name;
}
// 이름 사전 순으로 정렬
@Override
public int compareTo(Player p) {
return (this.name).compareTo(p.name);
}
}
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
StringTokenizer st = new StringTokenizer(br.readLine(), " ");
// 입력 받기
p = Integer.parseInt(st.nextToken()); // 플레이어 수
m = Integer.parseInt(st.nextToken()); // 방 정원
Deque<Room> dq = new ArrayDeque<>(); // 방 목록
// 플레이어 입력
for (int i = 0; i < p; i++) {
st = new StringTokenizer(br.readLine(), " ");
int level = Integer.parseInt(st.nextToken());
String name = st.nextToken();
boolean check = false; // 모든 방 찾았는지 여부
// 모든 방 앞에서부터 탐색
for (Room room : dq) {
// 레벨 조건이 맞고 방이 다 차지 않은 경우 입장
if (Math.abs(level - room.level) <= 10 & room.count < m) {
room.players.add(new Player(level, name));
room.count += 1; // 방 인원 증가
check = true; // 방을 찾음
break;
}
}
// 방을 찾지 못한 경우 새로운 방 생성
if (!check) {
dq.addLast(new Room(level, new Player(level, name))); // 플레이어 생성, 방 생성, 목록에 저장
}
}
// 모든 방 앞에서부터 출력
for (Room room : dq) {
// 정원이 다 찬 경우
if (room.count == m) {
bw.write("Started!");
} else { // 다 차지 못한 경우
bw.write("Waiting!");
}
bw.newLine();
// 참가자 이름 사전순으로 정렬
Collections.sort(room.players);
// for loop 안에서 size() 메서드를 계속 호출하면 List 사이즈를 계속 측정 후 돌려주는
// 연산이 발생하므로 다음과 같이 설정
int size = room.players.size();
// 순서대로 출력
for (int i = 0; i < size; i++) {
bw.write(room.players.get(i).level + " " + room.players.get(i).name);
bw.newLine();
}
}
bw.flush();
bw.close();
br.close();
}
}
Java
복사
학습 키워드
•
생성자, ArrayList, Comparable, compareTo, 중첩 클래스