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

[강원대 android_이세영] 미션 제출합니다 #38

Open
wants to merge 7 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
16 changes: 15 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1 +1,15 @@
# android-omok-precourse
# android-omok-precourse

1. 현재 플레이어에 따라 흑돌, 흰돌 구분하여 놓기
2. 오목 룰에 따라 5개 이상이 되었는지 확인하기
3. 이미 돌이 놓인 곳인지 확인
4. 오목판에 둘 곳이 있는지 확인
5. 초기화 버튼 만들기

후기/소감
처음엔 계획을 세우고 시작했었는데 중간중간 수정할 점이나 추가해야할 점들을 할 때
commit하는 것을 깜박해서 기능 단위 commit을 못했다
아직 습관이 안된 것 같다
저번 과제에서는 commit/push와 test코드 작성이 이해안되고 어려웠는데
아직 JUnit, assertJ 을 이용한 test코드 작성을 모르겠다 기능 단위 테스트 라고 공부하고 따라해보는데 아마 gradle에서의 버전이나 의존성
문제로 실행이 안되는 것 같다...
25 changes: 14 additions & 11 deletions app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -49,15 +49,18 @@ dependencies {
implementation("com.google.android.material:material:1.10.0")
implementation("androidx.activity:activity-ktx:1.8.2")
implementation("androidx.constraintlayout:constraintlayout:2.1.4")
testImplementation("org.junit.jupiter:junit-jupiter:5.10.2")
testImplementation("org.assertj:assertj-core:3.25.3")
testImplementation("io.kotest:kotest-runner-junit5:5.8.0")
androidTestImplementation("androidx.test.ext:junit:1.1.5")
androidTestImplementation("androidx.test.espresso:espresso-core:3.5.1")
androidTestImplementation("androidx.test:runner:1.4.0")
androidTestImplementation("org.junit.jupiter:junit-jupiter:5.10.2")
androidTestImplementation("org.assertj:assertj-core:3.25.3")
androidTestImplementation("io.kotest:kotest-runner-junit5:5.8.0")
androidTestImplementation("de.mannodermaus.junit5:android-test-core:1.3.0")
androidTestRuntimeOnly("de.mannodermaus.junit5:android-test-runner:1.3.0")

// testImplementation("junit:junit:4.12")
// testImplementation("org.junit.jupiter:junit-

// testImplementation ("org.junit.jupiter:junit-jupiter-api:5.8.2")
// testImplementation ("org.assertj:assertj-core:3.23.1")

// testImplementation ("junit:junit:4.13.2")
testImplementation ("org.junit.jupiter:junit-jupiter-api:5.8.2")
testImplementation ("org.assertj:assertj-core:3.23.1")
testImplementation ("org.junit.jupiter:junit-jupiter-engine:5.8.2")
// androidTestImplementation ("androidx.test.ext:junit:1.1.3")
// androidTestImplementation ("androidx.test.espresso:espresso-core:3.4.0")

}
180 changes: 177 additions & 3 deletions app/src/main/java/nextstep/omok/MainActivity.kt
Original file line number Diff line number Diff line change
@@ -1,23 +1,197 @@
package nextstep.omok

import android.graphics.Color
import android.os.Bundle
import android.util.Log
import android.widget.Button
import android.widget.ImageView
import android.widget.TableLayout
import android.widget.TableRow
import android.widget.TextView
import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity
import androidx.core.view.children

class MainActivity : AppCompatActivity() {

var isblackturn: Boolean = true
lateinit var nowTurnDisplay: TextView
lateinit var reset: Button
var stoneArray = Array(15) { IntArray(15) { 0 } }
var fullBoard = 225
var stoneCount = 0

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)

reset = findViewById(R.id.reset)
nowTurnDisplay = findViewById(R.id.nowTurnDisplay)
val board = findViewById<TableLayout>(R.id.board)
board
.children

var rowIndex = 0
board.children
.filterIsInstance<TableRow>()
.forEach { tableRow ->
var colIndex = 0
tableRow.children.filterIsInstance<ImageView>().forEach { view ->
view.setOnClickListener { onStonePlace(view) }
view.tag = "$rowIndex,$colIndex"
colIndex++
}
rowIndex++
}

reset.setOnClickListener { resetGame(board) }

}

fun isEmptyPlace(row: Int, col: Int): Boolean {
return row in 0..14 && col in 0..14 && stoneArray[row][col] == 0
}

fun onStonePlace(view: ImageView) {
val tag = view.tag as? String
tag?.let {
val (rowIndex, colIndex) = it.split(",").map { it.toInt() }
if (isEmptyPlace(rowIndex, colIndex)) {
placeStone(view, rowIndex, colIndex)
checkFullBoard()
switchTurn()
} else {
Toast.makeText(this, "빈 곳에 놓아주세요", Toast.LENGTH_SHORT).show()
}
}
}

fun placeStone(view: ImageView, rowIndex: Int, colIndex: Int) {
if (isblackturn) {
view.setImageResource(R.drawable.black_stone)
stoneArray[rowIndex][colIndex] = 1
} else {
view.setImageResource(R.drawable.white_stone)
stoneArray[rowIndex][colIndex] = 2
}
// Log.d("testt", "$rowIndex,$colIndex") //디버깅 용
checkWin(rowIndex, colIndex)
// fullBoard-- //
// stoneCount++
// Log.d("fullBoard", "${fullBoard.toString()} ${stoneCount.toString()}") 디버깅 용
}

fun switchTurn() {
isblackturn = !isblackturn
displayNowTurn(isblackturn)
}

fun checkFullBoard() {
if (fullBoard == 0) showEndGameDialog("무승부")
}

//차례를 표시하는 TextView
fun displayNowTurn(isblackturn: Boolean) {
if (isblackturn) {
nowTurnDisplay.text = "현재 차례\nBLACK"
nowTurnDisplay.setBackgroundColor(Color.BLACK)
nowTurnDisplay.setTextColor(Color.WHITE)
} else {
nowTurnDisplay.text = "현재 차례\nWHITE"
nowTurnDisplay.setBackgroundColor(Color.WHITE)
nowTurnDisplay.setTextColor(Color.BLACK)
}
}

//게임리셋 버튼
fun resetGame(board: TableLayout) {
board.children
.filterIsInstance<TableRow>()
.flatMap { it.children }
.filterIsInstance<ImageView>()
.forEach { view -> view.setOnClickListener { view.setImageResource(R.drawable.black_stone) } }
.forEach { view -> view.setImageResource(0) } //각 이미지뷰 리소스를 0으로 설정

stoneArray = Array(15) { IntArray(15) { 0 } } //좌표 데이터도 초기화
isblackturn = true //흑돌 선공 결정
displayNowTurn(isblackturn) //현재 차례 흑돌 설정
fullBoard = 225
stoneCount = 0
}

//승리판별
fun checkWin(row: Int, col: Int) {
val directions = listOf(
listOf(1 to 0, -1 to 0), // 수평 방향
listOf(0 to 1, 0 to -1), // 수직 방향
listOf(1 to 1, -1 to -1), // 대각선 방향 (오른쪽 아래로)
listOf(1 to -1, -1 to 1) // 대각선 방향 (오른쪽 위로)
)
val stone = stoneArray[row][col] // 흑,백 판별 흑이면 1 백이면 2
for (direction in directions) {
val (dx1, dy1) = direction[0]
val (dx2, dy2) = direction[1]
var count = 1

// 첫 번째 방향으로 돌 카운트
count = countStone(row,dx1,col,dy1,stone,count)
// 두 번째 방향으로 돌 카운트
count = countStone(row,dx2,col,dy2,stone,count)

Log.d("testt", "Count: $count")

if (count >= 5) {
whenWin(stone)
}
}
}

fun checkSameStone(newRow : Int, newCol : Int, stone : Int):Boolean{
return (newRow in 0..14 && newCol in 0..14 && stoneArray[newRow][newCol] == stone)
}

fun countStone (row: Int, dx : Int, col : Int, dy : Int, stone : Int, count : Int) : Int{

var result = count

for (i in 1 until 5) {
val newRow1 = row + i * dx
val newCol1 = col + i * dy

if (checkSameStone(newRow1, newCol1, stone)) {
result++
} else {
break
}
}
return result
}


//게임 종료시 재실행 여부 확인
fun showEndGameDialog(winner: String) {
val builder = androidx.appcompat.app.AlertDialog.Builder(this)
builder.setTitle("게임 종료")
if(winner.equals("무승부")){
builder.setMessage("무승부\n다시 하시겠습니까?")
}
else builder.setMessage("$winner 승리!\n다시 하시겠습니까?")

builder.setPositiveButton("다시하기") { dialog, _ ->
resetGame(findViewById(R.id.board))
dialog.dismiss()
}

builder.setNegativeButton("종료하기") { dialog, _ ->
finish()
}

builder.setCancelable(false)
builder.show()
}

//승리 Toast메세지 출력
fun whenWin(stone : Int){
val winner = if (stone == 1) "흑돌" else "백돌"
showEndGameDialog(winner)
}

}

38 changes: 36 additions & 2 deletions app/src/main/res/layout/activity_main.xml
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content">
android:layout_height="wrap_content"
android:orientation="vertical">

<TableLayout
android:id="@+id/board"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_height="wrap_content"
android:stretchColumns="*">

<TableRow android:layout_weight="1">
Expand Down Expand Up @@ -592,7 +593,9 @@
android:layout_weight="1"
android:background="@drawable/board_center" />

<!-- (7,7)-->
<ImageView
android:id="@+id/center"
android:layout_width="0dp"
android:layout_weight="1"
android:background="@drawable/board_center" />
Expand Down Expand Up @@ -1180,4 +1183,35 @@
</TableRow>

</TableLayout>

<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">

<Button
android:id="@+id/reset"
android:layout_width="150dp"
android:layout_height="50dp"
android:layout_marginTop="30dp"
android:layout_marginLeft="20dp"
android:text="초기화">
</Button>

<TextView
android:id="@+id/nowTurnDisplay"
android:layout_width="150dp"
android:layout_height="100dp"
android:layout_marginTop="30dp"
android:layout_marginLeft="40dp"
android:layout_marginBottom="20dp"
android:text="현재 차례\nBLACK"
android:textSize="30dp"
android:gravity="center"
android:background="@color/black"
android:textColor="@color/white">
</TextView>

</LinearLayout>

</LinearLayout>
73 changes: 73 additions & 0 deletions app/src/test/java/nextstep/omok/Test.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
package nextstep.omok

import org.assertj.core.api.Assertions.assertThat
import org.junit.jupiter.api.BeforeEach
import org.junit.jupiter.api.Test
class Test {

private lateinit var mainActivity: MainActivity

@BeforeEach
fun setUp() {
mainActivity = MainActivity()
}

@Test
fun `isEmptyPlace with empty place`() {
val result = mainActivity.isEmptyPlace(0, 0)
assertThat(result).isTrue()
}

@Test
fun `isEmptyPlace with occupied place`() {
mainActivity.stoneArray[0][0] = 1
val result = mainActivity.isEmptyPlace(0, 0)
assertThat(result).isFalse()
}

// @Test
// fun `placeStone with black stone`() {
// mainActivity.placeStone(ImageView(), 0, 0)
// val result = mainActivity.stoneArray[0][0]
// assertThat(result).isEqualTo(1)
// }
//
// @Test
// fun `placeStone with white stone`() {
// mainActivity.isblackturn = false
// mainActivity.placeStone(ImageView(), 0, 0)
// val result = mainActivity.stoneArray[0][0]
// assertThat(result).isEqualTo(2)
// }

@Test
fun `switchTurn from black to white`() {
mainActivity.switchTurn()
assertThat(mainActivity.isblackturn).isFalse()
}

@Test
fun `switchTurn from white to black`() {
mainActivity.isblackturn = false
mainActivity.switchTurn()
assertThat(mainActivity.isblackturn).isTrue()
}

@Test
fun `checkFullBoard with full board`() {
repeat(15) { row ->
repeat(15) { col ->
mainActivity.stoneArray[row][col] = 1
}
}
mainActivity.checkFullBoard()
assertThat(mainActivity.fullBoard).isEqualTo(0)
}

@Test
fun `checkFullBoard with non-full board`() {
mainActivity.checkFullBoard()
assertThat(mainActivity.fullBoard).isEqualTo(225)
}

}
1 change: 1 addition & 0 deletions build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,4 @@ plugins {
allprojects {
apply(plugin = "org.jlleitschuh.gradle.ktlint")
}