Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Step2]: πŸš€ 2단계 - 지뒰 μ°ΎκΈ°(지뒰 개수) #414

Open
wants to merge 22 commits into
base: dlwnsgus777
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
33b75e5
refactor: 리턴 νƒ€μž… λͺ…μ‹œ
Dec 8, 2023
4384cfe
refactor: μ‚¬μš©ν•˜μ§€ μ•ŠλŠ” ν•¨μˆ˜ 제거
Dec 8, 2023
937bfd1
feat: νŒŒλΌλ―Έν„° 이름 λ³€κ²½
dlwnsgus777 Dec 8, 2023
87e088f
feat: νŒŒλΌλ―Έν„° 이름 λ³€κ²½
dlwnsgus777 Dec 8, 2023
d7f3900
feat: 리뷰 반영
dlwnsgus777 Dec 8, 2023
f7c94a6
feat: ν•„λ“œμ˜ rowλ₯Ό μ˜λ―Έν•˜λŠ” Row 객체 생성
dlwnsgus777 Dec 8, 2023
3f540f9
feat: intλ₯Ό 감싼 Row 클래슀 생성
Dec 11, 2023
8bfbda7
feat: μ§€λ’°λ‚˜ 일반 발판의 값을 μ˜λ―Έν•˜λŠ” Mark 클래슀 μΆ”κ°€
Dec 11, 2023
e70df0b
feat: position νŒ¨ν‚€μ§€ μΆ”κ°€
Dec 11, 2023
f7eebaf
feat: positions 일급 μ»¬λ ‰μ…˜ μΆ”κ°€
Dec 11, 2023
57ec133
feat: 지뒰 갯수 좜λ ₯ κΈ°λŠ₯ 개발
Dec 11, 2023
12754be
feat: ν…ŒμŠ€νŠΈ μΌ€μ΄μŠ€ μΆ”κ°€
Dec 11, 2023
875d734
feat: 지뒰 갯수 μ„€μ • 클래슀 뢄리
Dec 11, 2023
140ec03
feat: μ—λŸ¬ λ©”μ‹œμ§€ μΆ”κ°€
Dec 11, 2023
31e02a4
feat: ν•¨μˆ˜λ₯Ό 더 κ°„λ‹¨ν•˜κ²Œ λ³€κ²½
Dec 14, 2023
fdbda58
feat: μ—λŸ¬ λ©”μ‹œμ§€ λ³€κ²½
Dec 14, 2023
cfdce4b
feat: editor μ„€μ • λ³€κ²½
Dec 14, 2023
0a4a2ae
feat: μ—λŸ¬ 검증 μΆ”κ°€
dlwnsgus777 Dec 15, 2023
632971f
feat: 컨트둀러 둜직 쀄이기
dlwnsgus777 Dec 15, 2023
227cf4c
feat: ktlint
dlwnsgus777 Dec 15, 2023
90a2b65
feat: FieldFactory 생성
dlwnsgus777 Dec 15, 2023
7e62807
feat: 값이 없을 λ•Œ 처리 μΆ”κ°€
Dec 14, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 3 additions & 6 deletions src/main/kotlin/mineswipper/MineGame.kt
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package mineswipper

import mineswipper.domain.map.Field
import mineswipper.domain.map.Size
import mineswipper.domain.map.position.Size
import mineswipper.domain.map.util.FieldFactory
import mineswipper.domain.map.util.PositionFactory
import mineswipper.domain.map.util.RandomMinePositionGenerator
import mineswipper.ui.InputManager
Expand All @@ -17,10 +17,7 @@ class MineGame(
val width = inputManager.inputWidth()
val size = Size(width, height)
val mine = inputManager.inputMine()
val field = Field(
size,
positionFactory.generateMinePositions(size, mine)
)
val field = FieldFactory(size).createField(positionFactory.generateMinePositions(size, mine))

outputManager.printStartGame()
outputManager.printField(field)
Expand Down
38 changes: 17 additions & 21 deletions src/main/kotlin/mineswipper/domain/map/Field.kt
Original file line number Diff line number Diff line change
@@ -1,32 +1,28 @@
package mineswipper.domain.map

import mineswipper.domain.map.position.Position
import mineswipper.domain.map.position.Row
import mineswipper.domain.map.position.Size

class Field(
private val size: Size,
positions: List<Position>
val field: Map<Row, Pedals>
) {
val field: Map<Int, Pedals>
fun findPedal(position: Position): Pedal {
val pedals = field[position.toRow()]
require(pedals != null) { VALID_MESSAGE }

init {
val initField: MutableMap<Int, Pedals> = mutableMapOf()
repeat(size.height) { x ->
initField[x] = pedalSetting(x, positions)
}
field = initField.toMap()
return pedals.get(position.x)
}

private fun pedalSetting(x: Int, positions: List<Position>): Pedals {
val pedalList = (0 until size.width).map { y ->
val position = Position(x, y)
createPedal(positions, position)
}
return Pedals(pedalList)
fun getSize(): Size {
val pedals = field[Row(FIRST_ROW_FOR_SIZE)]
require(pedals != null) { VALID_MESSAGE }

return Size(field.size, pedals.value.size)
}

private fun createPedal(
positions: List<Position>,
position: Position
) = when (positions.contains(position)) {
true -> Mine()
false -> NormalPedal()
companion object {
private const val VALID_MESSAGE: String = "ν•΄λ‹Ή μœ„μΉ˜μ— 값이 μ‘΄μž¬ν•˜μ§€ μ•ŠμŠ΅λ‹ˆλ‹€."
private const val FIRST_ROW_FOR_SIZE: Int = 0
}
}
6 changes: 6 additions & 0 deletions src/main/kotlin/mineswipper/domain/map/Mark.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package mineswipper.domain.map

@JvmInline
value class Mark(
val value: String
)
4 changes: 3 additions & 1 deletion src/main/kotlin/mineswipper/domain/map/Mine.kt
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
package mineswipper.domain.map

class Mine : Pedal
class Mine(
override var mark: Mark? = Mark("*")

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

var 둜 μ •μ˜ν•œ μ΄μœ κ°€ μž‡μ„κΉŒμš”?
μ™ΈλΆ€μ—μ„œ μ‰½κ²Œ 변경이 κ°€λŠ₯ν•œ κ΅¬μ‘°λ„€μš”!

) : Pedal
4 changes: 3 additions & 1 deletion src/main/kotlin/mineswipper/domain/map/NormalPedal.kt
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
package mineswipper.domain.map

class NormalPedal : Pedal
class NormalPedal(
override var mark: Mark? = null
) : Pedal
3 changes: 2 additions & 1 deletion src/main/kotlin/mineswipper/domain/map/Pedal.kt
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
package mineswipper.domain.map

sealed interface Pedal {
}
var mark: Mark?

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nullable λ³€μˆ˜λ‘œ μ •μ˜ ν•œ μ΄μœ κ°€ μžˆμ„κΉŒμš”?
또 λΆˆλ³€κ°μ²΄λ‘œ λ§Œλ“€μ–΄λ³΄λŠ”κ±΄ μ–΄λ–¨κΉŒμš”?

}
13 changes: 12 additions & 1 deletion src/main/kotlin/mineswipper/domain/map/Pedals.kt
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,15 @@ package mineswipper.domain.map
@JvmInline
value class Pedals(
val value: List<Pedal>
)
) {
fun get(index: Int): Pedal {
val result = value.getOrNull(index)
require(result != null) { ERROR_MESSAGE }
return result
}

companion object {
private const val ERROR_MESSAGE: String = "ν•΄λ‹Ή μΈλ±μŠ€μ— 값이 μ‘΄μž¬ν•˜μ§€ μ•ŠμŠ΅λ‹ˆλ‹€."
}
}

6 changes: 0 additions & 6 deletions src/main/kotlin/mineswipper/domain/map/Position.kt

This file was deleted.

22 changes: 22 additions & 0 deletions src/main/kotlin/mineswipper/domain/map/position/Position.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package mineswipper.domain.map.position

data class Position(
val x: Int,
val y: Int
) {
fun getAroundPositions(size: Size): Positions {
return (x - 1..x + 1).flatMap { xVal ->
(y - 1..y + 1).map { yVal -> Position(xVal, yVal) }
Comment on lines +8 to +9

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

x - 1, x - 1, y+1,y-1 등이 무엇을 μ˜λ―Έν• κΉŒμš”?
λ”°λ‘œ 객체λ₯Ό 관리해보면 μ–΄λ–¨κΉŒμš”?

}.filter { it.isValid(size.width, size.height) && it != this }.toPositions()
}

fun toRow(): Row {
return Row(y)
}

private fun isValid(width: Int, height: Int): Boolean {
return x in 0 until width && y in 0 until height
}
}

fun List<Position>.toPositions(): Positions = Positions(this)
9 changes: 9 additions & 0 deletions src/main/kotlin/mineswipper/domain/map/position/Positions.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package mineswipper.domain.map.position

data class Positions(
val positions: List<Position>
) {
fun contains(position: Position): Boolean {
return positions.contains(position)
}
}
4 changes: 4 additions & 0 deletions src/main/kotlin/mineswipper/domain/map/position/Row.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
package mineswipper.domain.map.position

@JvmInline
value class Row(val value: Int)
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package mineswipper.domain.map
package mineswipper.domain.map.position

data class Size(
val width: Int,
Expand Down
45 changes: 45 additions & 0 deletions src/main/kotlin/mineswipper/domain/map/util/FieldFactory.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
package mineswipper.domain.map.util

import mineswipper.domain.map.Field
import mineswipper.domain.map.Mine
import mineswipper.domain.map.NormalPedal
import mineswipper.domain.map.Pedal
import mineswipper.domain.map.Pedals
import mineswipper.domain.map.position.Position
import mineswipper.domain.map.position.Positions
import mineswipper.domain.map.position.Row
import mineswipper.domain.map.position.Size

class FieldFactory(
private val size: Size
) {
fun createField(
// size: Size,
minePositions: Positions
): Field {
val initField: MutableMap<Row, Pedals> = mutableMapOf()
repeat(size.height) { x ->
initField[Row(x)] = pedalSetting(x, minePositions)
}

val fakeField = Field(initField.toMap())

MarkGenerator.markGeneration(fakeField)

return fakeField
}
private fun createPedal(
minePositions: Positions,
position: Position
): Pedal {
return if (minePositions.contains(position)) Mine() else NormalPedal()
}

private fun pedalSetting(x: Int, minePositions: Positions): Pedals {
val pedalList = (0 until size.width).map { y ->
val position = Position(x, y)
createPedal(minePositions, position)
}
return Pedals(pedalList)
}
}
28 changes: 28 additions & 0 deletions src/main/kotlin/mineswipper/domain/map/util/MarkGenerator.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package mineswipper.domain.map.util

import mineswipper.domain.map.Field
import mineswipper.domain.map.Mark
import mineswipper.domain.map.Mine
import mineswipper.domain.map.position.Position

object MarkGenerator {
fun markGeneration(field: Field, position: Position = Position(0, 0)): Mark {
val pedal = field.findPedal(position)
if (pedal.mark != null) return pedal.mark!!

val aroundPositions = position.getAroundPositions(field.getSize())
val count = aroundPositions.positions.count {
val findPedal = field.findPedal(it)
findPedal is Mine
}

val mark = Mark(count.toString())
pedal.mark = mark

aroundPositions.positions.forEach {
markGeneration(field, it)
}

return mark
}
}
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
package mineswipper.domain.map.util

import mineswipper.domain.map.Position
import mineswipper.domain.map.Size
import mineswipper.domain.map.position.Positions
import mineswipper.domain.map.position.Size

interface MinePositionStrategy {
fun createMinePosition(size: Size, mineAmount: Int): List<Position>
}
fun createMinePosition(size: Size, mineAmount: Int): Positions
}
15 changes: 3 additions & 12 deletions src/main/kotlin/mineswipper/domain/map/util/PositionFactory.kt
Original file line number Diff line number Diff line change
@@ -1,21 +1,12 @@
package mineswipper.domain.map.util

import mineswipper.domain.map.Position
import mineswipper.domain.map.Size
import mineswipper.domain.map.position.Positions
import mineswipper.domain.map.position.Size

class PositionFactory(
private val minePositionStrategy: MinePositionStrategy
) {

fun generateMinePositions(height: Int, width: Int, mineAmount: Int): List<Position> {
return (0 until mineAmount).map {
val x = (0 until height).random()
val y = (0 until width).random()
Position(x, y)
}
}

fun generateMinePositions(size: Size, mineAmount: Int): List<Position> {
fun generateMinePositions(size: Size, mineAmount: Int): Positions {
require(size.width >= mineAmount && size.height >= mineAmount) { MINE_AMOUNT_VALID_MESSAGE }

return minePositionStrategy.createMinePosition(size, mineAmount)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
package mineswipper.domain.map.util

import mineswipper.domain.map.Position
import mineswipper.domain.map.Size
import mineswipper.domain.map.position.Position
import mineswipper.domain.map.position.Positions
import mineswipper.domain.map.position.Size

class RandomMinePositionGenerator : MinePositionStrategy {
override fun createMinePosition(size: Size, mineAmount: Int): List<Position> {
override fun createMinePosition(size: Size, mineAmount: Int): Positions {
val positions = mutableSetOf<Position>()

while (positions.size < mineAmount) {
Expand All @@ -13,6 +14,6 @@ class RandomMinePositionGenerator : MinePositionStrategy {
positions.add(Position(x, y))
}

return positions.toList()
return Positions(positions.toList())
}
}
3 changes: 1 addition & 2 deletions src/main/kotlin/mineswipper/ui/OutputManager.kt
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ class OutputManager {
private fun printWidth(pedals: Pedals) {
val pedal = pedals.value.joinToString(" ") {
when (it) {
is NormalPedal -> NORMAL_PEDAL
is NormalPedal -> it.mark?.value ?: "0"
is Mine -> MINE_PEDAL
}
}
Expand All @@ -29,7 +29,6 @@ class OutputManager {
}

companion object {
private const val NORMAL_PEDAL: String = "c"
private const val MINE_PEDAL: String = "*"
private const val START_GAME: String = "지뒰찾기 κ²Œμž„ μ‹œμž‘"
}
Expand Down
34 changes: 34 additions & 0 deletions src/test/kotlin/mineswipper/domain/map/FieldTest.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package mineswipper.domain.map

import io.kotest.matchers.types.shouldBeInstanceOf
import mineswipper.domain.map.position.Position
import mineswipper.domain.map.position.Positions
import mineswipper.domain.map.position.Size
import mineswipper.domain.map.util.FieldFactory
import mineswipper.domain.map.util.MinePositionStrategy
import org.junit.jupiter.api.Test

class FieldTest {

@Test
fun `ν•„λ“œμ—λŠ” 지뒰 발판이 μžˆλ‹€`() {
val size = Size(2, 2)
val mine = 2
val field = FieldFactory(size).createField(
MineMarkTestStrategy().createMinePosition(size, mine)
)

field.findPedal(Position(1, 0)).shouldBeInstanceOf<Mine>()
}
}

class MineMarkTestStrategy : MinePositionStrategy {
override fun createMinePosition(size: Size, mineAmount: Int): Positions {
return Positions(
listOf(
Position(1, 0),
Position(0, 1)
)
)
}
}
Loading