반응형
🎾 Kotlin으로 복식 경기 Round-Robin 매칭 구성하기

이 글은 Kotlin과 Jetpack Compose를 사용하는 Android 앱에서 복식 경기 매칭을 어떻게 구성할 수 있는지 기록한 개발자 경험 공유입니다. 예제 코드는 초보자도 이해할 수 있도록 주석과 함께 설명합니다.
🧩 사용 시나리오
앱 사용자는 4명 이상의 참여자를 등록한 후, 복식 경기 방식으로 매칭을 자동 생성합니다.
- 경기 방식은 Round-Robin 방식 (모든 가능한 조합을 구성)
- 같은 팀 또는 상대가 중복되지 않도록 구성
- 선수 수가 홀수인 경우 마지막 한 명을 제외
- 참가자 수가 4명일 경우에도 다양한 팀 구성을 고려
🧠 핵심 데이터 구조
// 경기 참가자
data class Contestant(
val pk: String, // 고유 ID
val tokenId: String,
val enterTime: Long,
val exitTime: Long
)
// 경기 매칭
data class Match(
val pk: String, // "Round_0", "Round_1" 등
val startTime: Long,
val endTime: Long,
val teamA: List, // 2인 1조
val teamB: List,
val isDoubles: Boolean = true
)
⚙️ 매칭 로직 구현
복식 경기를 위한 모든 가능한 조합을 만들고, 이전 경기에 바로 참여한 선수는 다음 경기에서 쉬도록 구성합니다.
// 복식 팀 조합을 생성하는 함수
fun generateDoublesTeamPairs(players: List): List<List<Contestant>> {
val validPlayers = if (players.size % 2 != 0) players.dropLast(1) else players
val teamPairs = mutableListOf<List<Contestant>>()
// 모든 2명 조합 생성
for (i in validPlayers.indices) {
for (j in i + 1 until validPlayers.size) {
teamPairs.add(listOf(validPlayers[i], validPlayers[j]))
}
}
return teamPairs
}
이후 이 조합으로 가능한 모든 2팀 매칭을 구성합니다.
// 복식 경기를 위한 가능한 Match 조합 생성
fun generateDoublesMatches(players: List<Contestant>): List<Match> {
val validPlayers = if (players.size % 2 != 0) players.dropLast(1) else players
val teamPairs = generateDoublesTeamPairs(validPlayers)
val matchList = mutableListOf<Match>()
var idx = 0
val usedMatches = mutableSetOf<Set<String>>()
for (i in teamPairs.indices) {
for (j in i + 1 until teamPairs.size) {
val teamA = teamPairs[i]
val teamB = teamPairs[j]
// 팀원이 겹치지 않는지 확인
if (teamA.intersect(teamB.toSet()).isEmpty()) {
val allPlayers = (teamA + teamB).map { it.pk }.toSet()
// 동일한 구성의 경기인지 중복 확인
if (allPlayers !in usedMatches) {
usedMatches.add(allPlayers)
// 실제 Match 객체 생성
val match = Match(
pk = "Round_${idx++}",
startTime = System.currentTimeMillis(),
endTime = System.currentTimeMillis() + 10 * 60 * 1000,
teamA = teamA,
teamB = teamB,
isDoubles = true
)
matchList.add(match)
}
}
}
}
return matchList
}
✨ 위 함수는 4명이 참여했을 때도 3가지 가능한 조합 중 1경기로 끝나는 일이 없도록 팀 구성 중복 여부를 고려해 최소 2경기 이상이 생성될 수 있도록 보완하였습니다.
🔍 로그 출력 예시 (디버깅용)
Log.e("MatchGen", "Valid players (${validPlayers.size}): ${validPlayers.map { it.pk }}")
Log.e("MatchGen", "Generated ${teamPairs.size} teams")
for (match in matchList) {
Log.e("MatchGen", "Match: ${match.teamA.map { it.pk }} vs ${match.teamB.map { it.pk }}")
}
✅ 결과 예시 (4명일 때)
Match: A, B vs C, D
Match: A, C vs B, D
📌 마무리
이 방식은 경기 운영 자동화나 라운드로빈 방식의 배치 자동화에 유용하며, 참여자 수의 변화에 따라 유연하게 대응할 수 있는 점이 큰 장점입니다.
필요에 따라 매칭 조건(예: 직전 경기 제외, 최소 휴식 시간 보장 등)을 더 정교하게 설계해 나갈 수 있습니다.
문의나 개선 아이디어가 있다면 댓글로 남겨주세요! 😊
어디까지나... chatGPT 의 의견은 아직 100% 신뢰도를 보장 하지 않습니다.
반응형
'모바일 앱(안드로이드)' 카테고리의 다른 글
| AI 가 안드로이드 개발자에게 미치는 영향 ... (ft Google IO 2025) (3) | 2025.08.03 |
|---|---|
| Wear OS 워치에서 심박수 측정 → 30초마다 폰으로 전송하기 (2) | 2025.08.02 |
| Nearby Connections API에서 기기 이름이 다르게 나오는 이유 (2) | 2025.07.25 |
| Google Nearby Connections API 완전 정복 가이드 (feat Claude.ai) (6) | 2025.07.23 |
| Android에서 Kakao 로컬 API로 주소/좌표 변환하기 : 앱에 적용해 보기. (3) | 2025.07.21 |