forked from woowacourse/kotlin-omok
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[둘리] 1, 2단계 오목 제출합니다. (woowacourse#26)
* docs: 오목 기능 목록 작성 * feat: 1부터 15 위치를 가진 오목알 클래스 구현 * feat: 중복 오목알 처리를 위한 오목알 일급 컬렉션 구현 * docs: .gitkeep 파일 제거 * feat: 오목알을 놓은 플레이어가 게임에서 이겼는지 확인하는 기능 구현 * feat: 사용자가 오목알을 놓았을 때 상태를 반환하는 기능 구현 * feat: 오목판에 돌을 올려놓는 기능 구현 * feat: 플레이어의 오목알을 놓는 턴을 바꾸는 기능 구현 * refactor: 돌을 놓으면 새로운 상태를 가진 플레이어 반환하는 기능 구현 * feat: 플레이어가 놓은 마지막 돌을 리턴하는 기능 구현 * refactor: 오목알을 놓을 수 있는지 확인하는 함수를 Players 클래스로 이동 * feat: 오목 게임 진행하는 기능 구현 * feat: 오목 게임 입력, 출력 화면 구현 * feat: 오목 컨트롤러 구현 * refactor: 도메인 패키지 분리 * fix: 중간에 오목알을 뒀을 때 승리 판정하지 않는 오류 수정 * feat: 렌주룰 기능 추가 (미완성) * feat: 렌주룰 적용 (완성) --------- Co-authored-by: tmdgh1592 <[email protected]>
- Loading branch information
Showing
36 changed files
with
1,046 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
import controller.OmokController | ||
|
||
fun main() { | ||
OmokController().start() | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
package controller | ||
|
||
import domain.game.Omok | ||
import domain.rule.RenjuRule | ||
import view.InputView | ||
import view.OutputView | ||
|
||
class OmokController { | ||
fun start() { | ||
Omok(OutputView(), InputView(), RenjuRule()).run() | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
package domain.board | ||
|
||
import domain.player.Player | ||
import domain.player.Players | ||
import domain.rule.OmokRule | ||
import domain.stone.Stone | ||
import domain.stone.StoneColor | ||
|
||
class Board(private val players: Players) { | ||
constructor(blackPlayer: Player, whitePlayer: Player, rule: OmokRule) : this(Players(blackPlayer, whitePlayer, rule)) | ||
|
||
fun putStone(stoneColor: StoneColor, stone: Stone): Board? { | ||
if (players.canPlace(stone)) { | ||
return Board(players.putStone(stoneColor, stone)) | ||
} | ||
return null | ||
} | ||
|
||
fun getPlayers(): Players = players.copy() | ||
|
||
fun isRunning(): Boolean = players.isRunning | ||
|
||
fun isLose(): Boolean = players.isBlackLose | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
package domain.game | ||
|
||
import domain.board.Board | ||
import domain.player.BlackPlayer | ||
import domain.player.WhitePlayer | ||
import domain.rule.OmokRule | ||
import domain.stone.Stone | ||
import domain.stone.StoneColor | ||
import listener.OmokStartEndEventListener | ||
import listener.OmokTurnEventListener | ||
|
||
class Omok( | ||
private val startEndEventListener: OmokStartEndEventListener, | ||
private val turnEventListener: OmokTurnEventListener, | ||
private val rule: OmokRule | ||
) { | ||
fun run() { | ||
startEndEventListener.onStartGame() | ||
var curStoneColor: StoneColor = StoneColor.BLACK | ||
var curBoard = Board(BlackPlayer(), WhitePlayer(), rule) | ||
do { | ||
curBoard = takeTurn(curBoard, curStoneColor) | ||
startEndEventListener.onEndTurn(curBoard.getPlayers()) | ||
curStoneColor = curStoneColor.next() | ||
} while (curBoard.isRunning()) | ||
if (curBoard.isLose()) startEndEventListener.onEndGame(curStoneColor) | ||
else startEndEventListener.onEndGame(curStoneColor.next()) | ||
} | ||
|
||
private fun takeTurn(board: Board, stoneColor: StoneColor): Board { | ||
val newStone = Stone.of(turnEventListener.onTakeTurn(stoneColor)) | ||
val newBoard = board.putStone(stoneColor, newStone) | ||
if (newBoard == null) { | ||
turnEventListener.onNotPlaceable() | ||
return takeTurn(board, stoneColor) | ||
} | ||
return newBoard | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
package domain.player | ||
|
||
import domain.rule.OmokRule | ||
import domain.state.LoseState | ||
import domain.state.PlayerState | ||
import domain.state.PlayingState | ||
import domain.stone.Stone | ||
import domain.stone.Stones | ||
|
||
class BlackPlayer(state: PlayerState = PlayingState()) : Player(state) { | ||
val isLose | ||
get() = state is LoseState | ||
|
||
override fun putStone(stone: Stone, otherStones: Stones, rule: OmokRule): Player { | ||
val blackStones = state.getAllStones() | ||
if (rule.check(blackStones, otherStones, stone)) { | ||
return BlackPlayer(LoseState(state.getAllStones())) | ||
} | ||
return BlackPlayer(state.add(stone, rule)) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
package domain.player | ||
|
||
import domain.position.Position | ||
import domain.rule.OmokRule | ||
import domain.state.LoseState | ||
import domain.state.PlayerState | ||
import domain.state.WinState | ||
import domain.stone.Stone | ||
import domain.stone.Stones | ||
|
||
abstract class Player(protected val state: PlayerState) : Cloneable { | ||
fun canPlace(): Boolean = state !is WinState && state !is LoseState | ||
|
||
fun isPlaced(stone: Stone): Boolean = state.hasStone(stone) | ||
|
||
fun getPositions(): List<Position> = state.getPlaced() | ||
|
||
fun getLastStone(): Stone = state.getLastStone() | ||
|
||
fun getAllStones(): Stones = state.getAllStones() | ||
|
||
abstract fun putStone(stone: Stone, otherStones: Stones, rule: OmokRule): Player | ||
|
||
public override fun clone(): Player = super.clone() as Player | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
package domain.player | ||
|
||
import domain.rule.OmokRule | ||
import domain.rule.RenjuRule | ||
import domain.stone.Stone | ||
import domain.stone.StoneColor | ||
|
||
data class Players private constructor(private val players: List<Player>, private val rule: OmokRule) { | ||
val isRunning: Boolean | ||
get() = players.all { it.canPlace() } | ||
val isBlackLose: Boolean | ||
get() = (getBlackPlayer() as BlackPlayer).isLose | ||
|
||
constructor(blackPlayer: Player, whitePlayer: Player, rule: OmokRule) : this( | ||
listOf( | ||
blackPlayer.clone(), | ||
whitePlayer.clone() | ||
), | ||
rule | ||
) | ||
|
||
fun putStone(stoneColor: StoneColor, stone: Stone): Players { | ||
val whiteStones = getWhitePlayer().getAllStones() | ||
val blackStones = getBlackPlayer().getAllStones() | ||
|
||
return when (stoneColor) { | ||
StoneColor.BLACK -> { | ||
Players( | ||
blackPlayer = getBlackPlayer().putStone(stone, whiteStones, RenjuRule()), | ||
whitePlayer = getWhitePlayer(), | ||
rule, | ||
) | ||
} | ||
|
||
StoneColor.WHITE -> { | ||
Players( | ||
blackPlayer = getBlackPlayer(), | ||
whitePlayer = getWhitePlayer().putStone(stone, blackStones, rule), | ||
rule, | ||
) | ||
} | ||
} | ||
} | ||
|
||
fun getBlackPlayer(): Player = players.first { it is BlackPlayer } | ||
|
||
fun getWhitePlayer(): Player = players.first { it is WhitePlayer } | ||
|
||
fun canPlace(stone: Stone): Boolean = players.none { it.isPlaced(stone) } | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
package domain.player | ||
|
||
import domain.rule.OmokRule | ||
import domain.state.PlayerState | ||
import domain.state.PlayingState | ||
import domain.stone.Stone | ||
import domain.stone.Stones | ||
|
||
class WhitePlayer(state: PlayerState = PlayingState()) : Player(state) { | ||
override fun putStone(stone: Stone, otherStones: Stones, rule: OmokRule): Player = | ||
WhitePlayer(state.add(stone, rule)) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
package domain.position | ||
|
||
data class Position(val row: Int, val col: Int) { | ||
init { | ||
require(row in POSITION_RANGE) { ROW_OUT_OF_RANGE_ERROR_MESSAGE } | ||
require(col in POSITION_RANGE) { COLUMN_OUT_OF_RANGE_ERROR_MESSAGE } | ||
} | ||
|
||
companion object { | ||
private const val MIN_BOUND = 1 | ||
private const val MAX_BOUND = 15 | ||
val POSITION_RANGE = (MIN_BOUND..MAX_BOUND) | ||
private const val ROW_OUT_OF_RANGE_ERROR_MESSAGE = "행의 범위는 ${MIN_BOUND}부터 ${MAX_BOUND}입니다" | ||
private const val COLUMN_OUT_OF_RANGE_ERROR_MESSAGE = "열의 범위는 ${MIN_BOUND}부터 ${MAX_BOUND}입니다" | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
package domain.rule | ||
|
||
import domain.stone.Stone | ||
import domain.stone.Stones | ||
|
||
interface OmokRule { | ||
fun check(blackStones: Stones, whiteStones: Stones, startStone: Stone): Boolean | ||
} |
Oops, something went wrong.