From 21a786e5493814f9dba0200fec6178f58eb4c633 Mon Sep 17 00:00:00 2001 From: sumin Date: Thu, 30 May 2024 20:40:41 +0900 Subject: [PATCH 1/6] docs: Update README.md --- README.md | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 08a8c8a..b913de9 100644 --- a/README.md +++ b/README.md @@ -1 +1,12 @@ -# android-omok-precourse \ No newline at end of file +# android-omok-precourse +## 게임기능 +### 화면 그리기 +- [ ] 배경색을 가진 격자 그리기 +- [ ] 격자 교차점을 터치했을 때 돌을 그리기 + - [ ] 이미 돌이 있는 곳에는 돌을 놓을 수 없음 + - [ ] 흑, 백 번갈아 가며 그리기 +### 게임 진행 +- [ ] 최대 연결 수 계산하기 +- [ ] 처음으로 5목 이상 배치시 게임 종료 +- [ ] 끝나면 다시하기 여부 물어보기 +- [ ] 재시작 시 맵 초기화 하기 \ No newline at end of file From cf924cdab20417448e6338c8d2a8647b0443b1e4 Mon Sep 17 00:00:00 2001 From: sumin Date: Fri, 31 May 2024 17:59:54 +0900 Subject: [PATCH 2/6] =?UTF-8?q?feat:=20Add=20=EB=8F=8C=20=EC=B0=A9?= =?UTF-8?q?=EC=88=98=20=EA=B8=B0=EB=8A=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit OmokSystem: - 오목 게임을 관리하는 클래스 - nowStone: 현재 착수할 돌 색깔 프로퍼티 registerClickListener: - 게임 보드의 각 imageView마다 클릭시 한턴을 수행하는 함수 등록 performTurn: - 한턴을 수행하는 함수 putStone: - 돌을 착수하는 함수 - performTurn함수 내부에서 호출 - 터치한 위치의 이미지뷰에 돌을 그림 - 이미 착수된 위치라면 착수하지 않음 getBoardImageView: - TableLayout에 존재하는 imageView에 간단하게 접근하게 도와주는 함수 - row, col정보를 전달하면 해당위치의 이미지 뷰 반환 isPositionEmpty: - 착수하려는 위치가 비어있는지 확인하는 함수 - 비어있으면 true를 반환, 비어있지 않으면 Toas메시지를 표시하고 false 반환 Cache: - Drawable을 얻어오는 동작을 줄여주는 클래스 - 착수할 때마다 돌을 불러오는 동작을 방지하기 위해 생성 - OmokSystem 객체가 생성될 때 내부에서 생성 --- README.md | 4 + .../main/java/nextstep/omok/MainActivity.kt | 8 +- app/src/main/java/nextstep/omok/OmokSystem.kt | 91 +++++++++++++++++++ 3 files changed, 97 insertions(+), 6 deletions(-) create mode 100644 app/src/main/java/nextstep/omok/OmokSystem.kt diff --git a/README.md b/README.md index b913de9..a639545 100644 --- a/README.md +++ b/README.md @@ -5,6 +5,10 @@ - [ ] 격자 교차점을 터치했을 때 돌을 그리기 - [ ] 이미 돌이 있는 곳에는 돌을 놓을 수 없음 - [ ] 흑, 백 번갈아 가며 그리기 +- [x] 배경색을 가진 격자 그리기 +- [x] 격자 교차점을 터치했을 때 돌을 그리기 + - [x] 이미 돌이 있는 곳에는 돌을 놓을 수 없음 + - [x] 흑, 백 번갈아 가며 그리기 ### 게임 진행 - [ ] 최대 연결 수 계산하기 - [ ] 처음으로 5목 이상 배치시 게임 종료 diff --git a/app/src/main/java/nextstep/omok/MainActivity.kt b/app/src/main/java/nextstep/omok/MainActivity.kt index e6cc7b8..d77af01 100644 --- a/app/src/main/java/nextstep/omok/MainActivity.kt +++ b/app/src/main/java/nextstep/omok/MainActivity.kt @@ -13,11 +13,7 @@ class MainActivity : AppCompatActivity() { setContentView(R.layout.activity_main) val board = findViewById(R.id.board) - board - .children - .filterIsInstance() - .flatMap { it.children } - .filterIsInstance() - .forEach { view -> view.setOnClickListener { view.setImageResource(R.drawable.black_stone) } } + val omokSystem = OmokSystem(this, board) + omokSystem.registerClickListener() } } diff --git a/app/src/main/java/nextstep/omok/OmokSystem.kt b/app/src/main/java/nextstep/omok/OmokSystem.kt new file mode 100644 index 0000000..786ae8f --- /dev/null +++ b/app/src/main/java/nextstep/omok/OmokSystem.kt @@ -0,0 +1,91 @@ +package nextstep.omok + +import android.content.Context +import android.graphics.drawable.Drawable +import android.widget.ImageView +import android.widget.TableLayout +import android.widget.TableRow +import android.widget.Toast +import androidx.core.content.res.ResourcesCompat +import androidx.core.view.children + +class OmokSystem ( + val context: Context, + val board: TableLayout) { + private val BLACK = "흑" + private val WHITE = "백" + private val scoreCombo = 5 + + private var nowStone = BLACK + private val cache = Cache() + fun registerClickListener() { + board.children.forEachIndexed { row, tableRow -> + tableRow as TableRow + tableRow.children.forEachIndexed { col, imgView -> + imgView as ImageView + imgView.setOnClickListener { + performTurn(row, col) + } + } + } + } + + // 이미지뷰를 터치했을 때 수행할 한턴의 동작 + private fun performTurn(row: Int, col: Int) { + putStone(row, col) + } + + // 돌을 착수하는 함수 + // performTurn 내부에서 호출 + private fun putStone(row: Int, col: Int) { + val currView = getBoardImageView(row, col) + if (isPositionEmpty(currView)) { + if (nowStone == WHITE) { + currView.setImageDrawable(cache.stoneCache[cache.STONE_WHITE]) + nowStone = BLACK + } else { + currView.setImageDrawable(cache.stoneCache[cache.STONE_BLACK]) + nowStone = WHITE + } + } + } + + // 보드의 row, col 위치에 존재하는 imageView 반환 + private fun getBoardImageView(row: Int, col: Int): ImageView { + return (board.getChildAt(row) as TableRow).getChildAt(col) as ImageView + } + + // 돌을 놓으려는 위치가 비어있는지 확인하는 함수 + // putStone 내부에서 호출 + private fun isPositionEmpty(imgView: ImageView): Boolean { + if (imgView.drawable == null) + return true + else + Toast.makeText(context, "이미 돌이 착수된 자리입니다!", Toast.LENGTH_SHORT).show() + return false + } + + // 돌을 착수 할 때마다 Drawable을 얻어오는 동작을 줄이기 위해 캐시로 갖고있는 클래스 + // OmokSystem 객체가 생성될 때 내부에서 생성 + private inner class Cache() { + // 돌 관련 상수 + val STONE_BLACK = R.drawable.black_stone + val STONE_WHITE = R.drawable.white_stone + + // 캐시 + val stoneCache: HashMap + + init { + stoneCache = createStoneCache() + } + + private fun createStoneCache(): HashMap { + val res = HashMap() + + res[STONE_WHITE] = ResourcesCompat.getDrawable(context.resources, STONE_WHITE, null) + res[STONE_BLACK] = ResourcesCompat.getDrawable(context.resources, STONE_BLACK, null) + + return res + } + } +} \ No newline at end of file From 591e1fe7d806ac7219d74e50a28bfd6e3767bee5 Mon Sep 17 00:00:00 2001 From: sumin Date: Fri, 31 May 2024 20:39:26 +0900 Subject: [PATCH 3/6] =?UTF-8?q?feat:=20=EC=B5=9C=EB=8C=80=20=EC=97=B0?= =?UTF-8?q?=EA=B2=B0=20=EC=88=98=20=EA=B3=84=EC=82=B0=EA=B8=B0=EB=8A=A5=20?= =?UTF-8?q?=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit calculateCombo: - 4가지 방향에 대해 가장 큰 연속 연결(Combo)수를 반환 checkVerticalCombo, checkHorizontalCombo, checkUpperRightCombo, checkUpperLeftCombo: - 각 방향 Combo 계산 - 대상에서 인접한 돌을 위/아래로 4개씩 검사하여 같은 drawable인지 확인 - 같으면 combo++ - 다르면 break --- README.md | 6 +- app/src/main/java/nextstep/omok/OmokSystem.kt | 112 +++++++++++++++++- 2 files changed, 112 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index a639545..715b4ac 100644 --- a/README.md +++ b/README.md @@ -1,16 +1,12 @@ # android-omok-precourse ## 게임기능 ### 화면 그리기 -- [ ] 배경색을 가진 격자 그리기 -- [ ] 격자 교차점을 터치했을 때 돌을 그리기 - - [ ] 이미 돌이 있는 곳에는 돌을 놓을 수 없음 - - [ ] 흑, 백 번갈아 가며 그리기 - [x] 배경색을 가진 격자 그리기 - [x] 격자 교차점을 터치했을 때 돌을 그리기 - [x] 이미 돌이 있는 곳에는 돌을 놓을 수 없음 - [x] 흑, 백 번갈아 가며 그리기 ### 게임 진행 -- [ ] 최대 연결 수 계산하기 +- [x] 최대 연결 수 계산하기 - [ ] 처음으로 5목 이상 배치시 게임 종료 - [ ] 끝나면 다시하기 여부 물어보기 - [ ] 재시작 시 맵 초기화 하기 \ No newline at end of file diff --git a/app/src/main/java/nextstep/omok/OmokSystem.kt b/app/src/main/java/nextstep/omok/OmokSystem.kt index 786ae8f..12ee4ac 100644 --- a/app/src/main/java/nextstep/omok/OmokSystem.kt +++ b/app/src/main/java/nextstep/omok/OmokSystem.kt @@ -2,12 +2,14 @@ package nextstep.omok import android.content.Context import android.graphics.drawable.Drawable +import android.util.Log import android.widget.ImageView import android.widget.TableLayout import android.widget.TableRow import android.widget.Toast import androidx.core.content.res.ResourcesCompat import androidx.core.view.children +import androidx.core.view.size class OmokSystem ( val context: Context, @@ -15,9 +17,17 @@ class OmokSystem ( private val BLACK = "흑" private val WHITE = "백" private val scoreCombo = 5 + private val rowSize: Int + private val colSize: Int private var nowStone = BLACK private val cache = Cache() + init { + rowSize = board.childCount + colSize = (board.getChildAt(0) as TableRow).childCount + } + + // 각 이미지뷰에 onClickListener를 부착하는 함수 fun registerClickListener() { board.children.forEachIndexed { row, tableRow -> tableRow as TableRow @@ -33,6 +43,7 @@ class OmokSystem ( // 이미지뷰를 터치했을 때 수행할 한턴의 동작 private fun performTurn(row: Int, col: Int) { putStone(row, col) + calculateCombo(row, col) } // 돌을 착수하는 함수 @@ -60,9 +71,108 @@ class OmokSystem ( private fun isPositionEmpty(imgView: ImageView): Boolean { if (imgView.drawable == null) return true - else + else { Toast.makeText(context, "이미 돌이 착수된 자리입니다!", Toast.LENGTH_SHORT).show() return false + } + } + + // 콤보를 계산하는 함수 + // 4가지 방향에 대해 가장 큰 콤보를 반환 + private fun calculateCombo(row: Int, col: Int): Int { + return maxOf( + checkVerticalCombo(row, col), + checkHorizontalCombo(row, col), + checkUpperRightCombo(row, col), + checkUpperLeftCombo(row, col) + ) + } + + // 4가지 방향 각각에 대해 콤보를 계산하는 함수 + // 각각의 함수는 calculateCombo함수 내부에서 호출되어 사용 + // 점수를 내는 기준인 scoreCombo개수까지만 인접한 돌을 셈 + // 수직 방향 + private fun checkVerticalCombo(row: Int, col: Int) : Int { + var combo = 1 + val targetStone = getBoardImageView(row, col) + + for (d in 1..= rowSize || + targetStone.drawable != getBoardImageView(row + d, col).drawable) + break + combo++ + } + + return combo + } + + // 수평 방향 + private fun checkHorizontalCombo(row: Int, col: Int) : Int { + var combo = 1 + val targetStone = getBoardImageView(row, col) + + for (d in 1..= colSize || + targetStone.drawable != getBoardImageView(row, col + d).drawable) + break + combo++ + } + + return combo + } + + // 오른쪽 위를 향하는 대각선 방향 + private fun checkUpperRightCombo(row: Int, col: Int) : Int { + var combo = 1 + val targetStone = getBoardImageView(row, col) + + for (d in 1..= rowSize || + targetStone.drawable != getBoardImageView(row + d, col - d).drawable) + break + combo++ + } + for (d in 1..= colSize || row - d < 0 || + targetStone.drawable != getBoardImageView(row - d, col + d).drawable) + break + combo++ + } + + return combo + } + + // 왼쪽 위를 향하는 대각선 방향 + private fun checkUpperLeftCombo(row: Int, col: Int) : Int { + var combo = 1 + val targetStone = getBoardImageView(row, col) + + for (d in 1..= colSize || row + d >= rowSize || + targetStone.drawable != getBoardImageView(row + d, col + d).drawable) + break + combo++ + } + for (d in 1.. Date: Sat, 1 Jun 2024 15:51:35 +0900 Subject: [PATCH 4/6] =?UTF-8?q?feat:=20=EC=B2=98=EC=9D=8C=EC=9C=BC?= =?UTF-8?q?=EB=A1=9C=205=EB=AA=A9=20=EC=9D=B4=EC=83=81=20=EB=B0=B0?= =?UTF-8?q?=EC=B9=98=EC=8B=9C=20=EA=B2=8C=EC=9E=84=20=EC=A2=85=EB=A3=8C=20?= =?UTF-8?q?=EA=B8=B0=EB=8A=A5=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit isGameEnd: - performTurn 내부에서 호출 - 기준 콤보(scoreCombo)를 넘으면 true 반환 alertEnd: - 게임 종료조건을 충족하였을 때 호출 - 승리한 색을 알림 - 재시작 여부를 확인 resetBoard: - 재시작 선택시 alertEnd내부에서 호출 - 보드에 놓여진 돌의 이미지를 모두 지움 - 처음 착수하는 돌의 색깔인 BLACK으로 설정 --- README.md | 6 +-- app/src/main/java/nextstep/omok/OmokSystem.kt | 44 ++++++++++++++++++- 2 files changed, 46 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 715b4ac..5e5d409 100644 --- a/README.md +++ b/README.md @@ -7,6 +7,6 @@ - [x] 흑, 백 번갈아 가며 그리기 ### 게임 진행 - [x] 최대 연결 수 계산하기 -- [ ] 처음으로 5목 이상 배치시 게임 종료 -- [ ] 끝나면 다시하기 여부 물어보기 -- [ ] 재시작 시 맵 초기화 하기 \ No newline at end of file +- [x] 처음으로 5목 이상 배치시 게임 종료 + - [x] 끝나면 다시하기 여부 물어보기 + - [x] 재시작 시 맵 초기화 하기 \ No newline at end of file diff --git a/app/src/main/java/nextstep/omok/OmokSystem.kt b/app/src/main/java/nextstep/omok/OmokSystem.kt index 12ee4ac..761fff9 100644 --- a/app/src/main/java/nextstep/omok/OmokSystem.kt +++ b/app/src/main/java/nextstep/omok/OmokSystem.kt @@ -7,6 +7,7 @@ import android.widget.ImageView import android.widget.TableLayout import android.widget.TableRow import android.widget.Toast +import androidx.appcompat.app.AlertDialog import androidx.core.content.res.ResourcesCompat import androidx.core.view.children import androidx.core.view.size @@ -43,7 +44,9 @@ class OmokSystem ( // 이미지뷰를 터치했을 때 수행할 한턴의 동작 private fun performTurn(row: Int, col: Int) { putStone(row, col) - calculateCombo(row, col) + val combo = calculateCombo(row, col) + if (isGameEnd(combo)) + alertEnd(row, col) } // 돌을 착수하는 함수 @@ -175,6 +178,45 @@ class OmokSystem ( return combo } + // 현재 combo가 게임이 끝나는 기준을 넘었는지 확인 + private fun isGameEnd(combo: Int): Boolean { + return combo >= scoreCombo + } + + // 게임 종료 알림 함수 + private fun alertEnd(row: Int, col: Int): Unit { + val targetStone = getBoardImageView(row, col) + AlertDialog.Builder(context).apply { + setCancelable(false) + setTitle("게임이 종료되었습니다! 😎") + if (targetStone.drawable == cache.stoneCache[cache.STONE_BLACK]) + setMessage("🎉${BLACK}⚫️이 승리했습니다!🎉\n재시작 하시겠습니까?") + else + setMessage("🎉${WHITE}⚪️️이 승리했습니다!🎉\n재시작 하시겠습니까?") + + setPositiveButton("네") { dialog, _ -> + resetBoard() + dialog.dismiss() + } + + setNegativeButton("아니요") { dialog, _ -> + dialog.dismiss() + } + }.create().show() + } + + /* 보드 초기화 함수 */ + private fun resetBoard(): Unit { + board.children.forEach { tableRow -> + tableRow as TableRow + tableRow.children.forEach { imgView -> + imgView as ImageView + imgView.setImageDrawable(null) + } + } + nowStone = BLACK + } + // 돌을 착수 할 때마다 Drawable을 얻어오는 동작을 줄이기 위해 캐시로 갖고있는 클래스 // OmokSystem 객체가 생성될 때 내부에서 생성 private inner class Cache() { From b62d7db7957c25d465cd63fadd8740d82e3df048 Mon Sep 17 00:00:00 2001 From: sumin Date: Mon, 3 Jun 2024 04:24:04 +0900 Subject: [PATCH 5/6] =?UTF-8?q?test:=20=ED=85=8C=EC=8A=A4=ED=8A=B8=20?= =?UTF-8?q?=EC=BD=94=EB=93=9C=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit OmokSystem.kt: - 테스트코드를 위해 일부 함수, 프로퍼티를 public으로 변경 --- .../nextstep/omok/OmokSystemAndroidTest.kt | 148 ++++++++++++++++++ app/src/main/java/nextstep/omok/OmokSystem.kt | 20 +-- 2 files changed, 158 insertions(+), 10 deletions(-) create mode 100644 app/src/androidTest/java/nextstep/omok/OmokSystemAndroidTest.kt diff --git a/app/src/androidTest/java/nextstep/omok/OmokSystemAndroidTest.kt b/app/src/androidTest/java/nextstep/omok/OmokSystemAndroidTest.kt new file mode 100644 index 0000000..2fa48aa --- /dev/null +++ b/app/src/androidTest/java/nextstep/omok/OmokSystemAndroidTest.kt @@ -0,0 +1,148 @@ +package nextstep.omok + +import org.assertj.core.api.Assertions.* +import android.content.Context +import android.graphics.drawable.Drawable +import android.media.Image +import android.provider.ContactsContract.CommonDataKinds.Im +import android.widget.ImageView +import android.widget.TableLayout +import android.widget.TableRow +import androidx.core.content.res.ResourcesCompat +import androidx.test.core.app.ActivityScenario +import androidx.test.ext.junit.rules.ActivityScenarioRule +import org.junit.Rule +import org.junit.jupiter.api.AfterEach +import org.junit.jupiter.api.BeforeEach +import org.junit.jupiter.api.DisplayName +import org.junit.jupiter.api.Test + +class OmokSystemAndroidTest { + + + @Test + @DisplayName("board에서 지정한 row, col의 이미지뷰를 가져오는 함수 검사") + fun getBoardImageViewTest() { + val activityScenario = ActivityScenario.launch(MainActivity::class.java) + activityScenario.onActivity { + val board = it.findViewById(R.id.board) + val omokSystem = OmokSystem(it, board) + val imageView: ImageView = (board.getChildAt(1) as TableRow).getChildAt(1) as ImageView + assertThat(omokSystem.getBoardImageView(1,1)).isEqualTo(imageView) + } + } + + @Test + @DisplayName("착수 기능 검사") + fun putStoneTest() { + val activityScenario = ActivityScenario.launch(MainActivity::class.java) + activityScenario.onActivity { + val board = it.findViewById(R.id.board) + val omokSystem = OmokSystem(it, board) + + // 지정한 위치에 착수 + setStoneBlack(omokSystem) + omokSystem.putStone(1, 1) + val oldStone = (board.getChildAt(1) as TableRow).getChildAt(1) as ImageView + assertThat(omokSystem.getBoardImageView(1,1)).isEqualTo(oldStone) + + // 이미 착수한 곳에 착수 시도: 기존의 돌이 유지되어야 함 + omokSystem.putStone(1, 1) + assertThat(omokSystem.getBoardImageView(1, 1)).isEqualTo(oldStone) + } + } + + @Test + @DisplayName("combo계산 기능 검사") + fun calculateCombo() { + val activityScenario = ActivityScenario.launch(MainActivity::class.java) + + activityScenario.onActivity { + val board = it.findViewById(R.id.board) + val omokSystem = OmokSystem(it, board) + + setStoneBlack(omokSystem) + omokSystem.putStone(1, 1) + setStoneBlack(omokSystem) + omokSystem.putStone(1, 2) + setStoneBlack(omokSystem) + omokSystem.putStone(1, 3) + setStoneBlack(omokSystem) + omokSystem.putStone(1, 4) + setStoneBlack(omokSystem) + omokSystem.putStone(1, 5) + assertThat(omokSystem.calculateCombo(1,1)).isEqualTo(5) + assertThat(omokSystem.calculateCombo(1,2)).isEqualTo(5) + assertThat(omokSystem.calculateCombo(1,3)).isEqualTo(5) + assertThat(omokSystem.calculateCombo(1,4)).isEqualTo(5) + assertThat(omokSystem.calculateCombo(1,5)).isEqualTo(5) + + setStoneWhite(omokSystem) + omokSystem.putStone(2, 2) + setStoneWhite(omokSystem) + omokSystem.putStone(3, 3) + setStoneWhite(omokSystem) + omokSystem.putStone(4, 4) + setStoneWhite(omokSystem) + omokSystem.putStone(5, 5) + setStoneWhite(omokSystem) + omokSystem.putStone(6, 6) + assertThat(omokSystem.calculateCombo(2,2)).isEqualTo(5) + assertThat(omokSystem.calculateCombo(3,3)).isEqualTo(5) + assertThat(omokSystem.calculateCombo(4,4)).isEqualTo(5) + assertThat(omokSystem.calculateCombo(5,5)).isEqualTo(5) + assertThat(omokSystem.calculateCombo(6,6)).isEqualTo(5) + + } + } + + @Test + @DisplayName("기준 점수를 넘었을 때 종료 플래그 반환") + fun isGameEndTest() { + val activityScenario = ActivityScenario.launch(MainActivity::class.java) + + activityScenario.onActivity { + val board = it.findViewById(R.id.board) + val omokSystem = OmokSystem(it, board) + + assertThat(omokSystem.isGameEnd(omokSystem.scoreCombo - 1)).isEqualTo(false) + assertThat(omokSystem.isGameEnd(omokSystem.scoreCombo)).isEqualTo(true) + assertThat(omokSystem.isGameEnd(omokSystem.scoreCombo + 1)).isEqualTo(true) + } + } + + @Test + @DisplayName("보드 초기화 기능 검사") + fun resetBoardTest() { + val activityScenario = ActivityScenario.launch(MainActivity::class.java) + + activityScenario.onActivity { + val board = it.findViewById(R.id.board) + val omokSystem = OmokSystem(it, board) + + // 판에 돌을 모두 착수 + for (i in 0..14) { + for (j in 0..14) { + omokSystem.putStone(i,j) + assertThat(omokSystem.getBoardImageView(i,j).drawable).isNotNull + } + } + omokSystem.resetBoard() + // 리셋되었는지 확인 + for (i in 0..14) { + for (j in 0..14) { + assertThat(omokSystem.getBoardImageView(i,j).drawable).isNull() + } + } + assertThat(omokSystem.nowStone).isEqualTo(omokSystem.BLACK) + } + } + + private fun setStoneBlack(omokSystem: OmokSystem) { + omokSystem.nowStone = omokSystem.BLACK + } + + private fun setStoneWhite(omokSystem: OmokSystem) { + omokSystem.nowStone = omokSystem.WHITE + } +} \ No newline at end of file diff --git a/app/src/main/java/nextstep/omok/OmokSystem.kt b/app/src/main/java/nextstep/omok/OmokSystem.kt index 761fff9..5add50b 100644 --- a/app/src/main/java/nextstep/omok/OmokSystem.kt +++ b/app/src/main/java/nextstep/omok/OmokSystem.kt @@ -15,13 +15,13 @@ import androidx.core.view.size class OmokSystem ( val context: Context, val board: TableLayout) { - private val BLACK = "흑" - private val WHITE = "백" - private val scoreCombo = 5 + val BLACK = "흑" + val WHITE = "백" + val scoreCombo = 5 private val rowSize: Int private val colSize: Int - private var nowStone = BLACK + var nowStone = BLACK private val cache = Cache() init { rowSize = board.childCount @@ -51,7 +51,7 @@ class OmokSystem ( // 돌을 착수하는 함수 // performTurn 내부에서 호출 - private fun putStone(row: Int, col: Int) { + fun putStone(row: Int, col: Int) { val currView = getBoardImageView(row, col) if (isPositionEmpty(currView)) { if (nowStone == WHITE) { @@ -65,13 +65,13 @@ class OmokSystem ( } // 보드의 row, col 위치에 존재하는 imageView 반환 - private fun getBoardImageView(row: Int, col: Int): ImageView { + fun getBoardImageView(row: Int, col: Int): ImageView { return (board.getChildAt(row) as TableRow).getChildAt(col) as ImageView } // 돌을 놓으려는 위치가 비어있는지 확인하는 함수 // putStone 내부에서 호출 - private fun isPositionEmpty(imgView: ImageView): Boolean { + fun isPositionEmpty(imgView: ImageView): Boolean { if (imgView.drawable == null) return true else { @@ -82,7 +82,7 @@ class OmokSystem ( // 콤보를 계산하는 함수 // 4가지 방향에 대해 가장 큰 콤보를 반환 - private fun calculateCombo(row: Int, col: Int): Int { + fun calculateCombo(row: Int, col: Int): Int { return maxOf( checkVerticalCombo(row, col), checkHorizontalCombo(row, col), @@ -179,7 +179,7 @@ class OmokSystem ( } // 현재 combo가 게임이 끝나는 기준을 넘었는지 확인 - private fun isGameEnd(combo: Int): Boolean { + fun isGameEnd(combo: Int): Boolean { return combo >= scoreCombo } @@ -206,7 +206,7 @@ class OmokSystem ( } /* 보드 초기화 함수 */ - private fun resetBoard(): Unit { + fun resetBoard(): Unit { board.children.forEach { tableRow -> tableRow as TableRow tableRow.children.forEach { imgView -> From 8499404967dc6018835841d96a3744142937858c Mon Sep 17 00:00:00 2001 From: sumin Date: Mon, 3 Jun 2024 11:57:44 +0900 Subject: [PATCH 6/6] =?UTF-8?q?test:=20=ED=85=8C=EC=8A=A4=ED=8A=B8=20?= =?UTF-8?q?=EC=BD=94=EB=93=9C=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ActivityScenario launch후 close() --- .../nextstep/omok/OmokSystemAndroidTest.kt | 28 ++++++------------- 1 file changed, 9 insertions(+), 19 deletions(-) diff --git a/app/src/androidTest/java/nextstep/omok/OmokSystemAndroidTest.kt b/app/src/androidTest/java/nextstep/omok/OmokSystemAndroidTest.kt index 2fa48aa..d7635c4 100644 --- a/app/src/androidTest/java/nextstep/omok/OmokSystemAndroidTest.kt +++ b/app/src/androidTest/java/nextstep/omok/OmokSystemAndroidTest.kt @@ -1,27 +1,16 @@ package nextstep.omok import org.assertj.core.api.Assertions.* -import android.content.Context -import android.graphics.drawable.Drawable -import android.media.Image -import android.provider.ContactsContract.CommonDataKinds.Im import android.widget.ImageView import android.widget.TableLayout import android.widget.TableRow -import androidx.core.content.res.ResourcesCompat import androidx.test.core.app.ActivityScenario -import androidx.test.ext.junit.rules.ActivityScenarioRule -import org.junit.Rule -import org.junit.jupiter.api.AfterEach -import org.junit.jupiter.api.BeforeEach -import org.junit.jupiter.api.DisplayName -import org.junit.jupiter.api.Test +import org.junit.Test class OmokSystemAndroidTest { @Test - @DisplayName("board에서 지정한 row, col의 이미지뷰를 가져오는 함수 검사") fun getBoardImageViewTest() { val activityScenario = ActivityScenario.launch(MainActivity::class.java) activityScenario.onActivity { @@ -30,10 +19,10 @@ class OmokSystemAndroidTest { val imageView: ImageView = (board.getChildAt(1) as TableRow).getChildAt(1) as ImageView assertThat(omokSystem.getBoardImageView(1,1)).isEqualTo(imageView) } + activityScenario.close() } @Test - @DisplayName("착수 기능 검사") fun putStoneTest() { val activityScenario = ActivityScenario.launch(MainActivity::class.java) activityScenario.onActivity { @@ -50,10 +39,10 @@ class OmokSystemAndroidTest { omokSystem.putStone(1, 1) assertThat(omokSystem.getBoardImageView(1, 1)).isEqualTo(oldStone) } + activityScenario.close() } @Test - @DisplayName("combo계산 기능 검사") fun calculateCombo() { val activityScenario = ActivityScenario.launch(MainActivity::class.java) @@ -92,12 +81,11 @@ class OmokSystemAndroidTest { assertThat(omokSystem.calculateCombo(4,4)).isEqualTo(5) assertThat(omokSystem.calculateCombo(5,5)).isEqualTo(5) assertThat(omokSystem.calculateCombo(6,6)).isEqualTo(5) - } + activityScenario.close() } @Test - @DisplayName("기준 점수를 넘었을 때 종료 플래그 반환") fun isGameEndTest() { val activityScenario = ActivityScenario.launch(MainActivity::class.java) @@ -109,10 +97,11 @@ class OmokSystemAndroidTest { assertThat(omokSystem.isGameEnd(omokSystem.scoreCombo)).isEqualTo(true) assertThat(omokSystem.isGameEnd(omokSystem.scoreCombo + 1)).isEqualTo(true) } + activityScenario.close() + } @Test - @DisplayName("보드 초기화 기능 검사") fun resetBoardTest() { val activityScenario = ActivityScenario.launch(MainActivity::class.java) @@ -136,13 +125,14 @@ class OmokSystemAndroidTest { } assertThat(omokSystem.nowStone).isEqualTo(omokSystem.BLACK) } + activityScenario.close() } - private fun setStoneBlack(omokSystem: OmokSystem) { + fun setStoneBlack(omokSystem: OmokSystem) { omokSystem.nowStone = omokSystem.BLACK } - private fun setStoneWhite(omokSystem: OmokSystem) { + fun setStoneWhite(omokSystem: OmokSystem) { omokSystem.nowStone = omokSystem.WHITE } } \ No newline at end of file