Skip to content
17 changes: 16 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1 +1,16 @@
# android-omok-precourse
# android-omok-precourse

-KakaoTechCampus Step1 2차 미니과제
-안드로이드 프레임워크를 사용하여 모바일 앱으로 오목을 구현한다.

#기능 목록
1. 오목판 초기화
- 오목판을 비워져있도록 구성한다.
2. 돌 놓기 기능
- 사용자는 오목판을 클릭하여 돌을 놓을 수 있다.
- 흑돌과 백돌이 번갈아가면서 돌을 놓도록 한다.
3. 승리 여부 확인 기능
- 가로나 세로, 대각선으로 다섯 개의 연속된 돌이 있는 확인한다.
- 렌주 룰과 같은 복잡한 룰을 고려하지 않고, 6목 이상의 장목도 승리 조건으로 인정한다.
4. 무승부 기능
- 판을 전부 돌로 채웠어도 승부가 결정나지 않으면 무승부로 처리한다.
123 changes: 123 additions & 0 deletions app/src/androidTest/java/nextstep/omok/MainActivityTest.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
package nextstep.omok

import androidx.test.core.app.ActivityScenario
import org.assertj.core.api.Assertions.assertThat
import org.junit.Test
import android.widget.ImageView
import android.widget.TableLayout
import android.widget.TableRow
import android.widget.TextView
import androidx.core.view.children
class MainActivityTest {
private lateinit var activity: MainActivity

@Test
fun testStonePlacement() {
ActivityScenario.launch(MainActivity::class.java).onActivity {
activity = it

val board = activity.findViewById<TableLayout>(R.id.board)
val firstCell = board
.children
.filterIsInstance<TableRow>()
.flatMap { it.children }
.filterIsInstance<ImageView>()
.first()

firstCell.performClick()

val row = 0
val col = 0
val expectedDrawable = R.drawable.black_stone

assertThat(firstCell.drawable).isNotNull
assertThat((firstCell.drawable.constantState)).isEqualTo(activity.getDrawable(expectedDrawable)!!.constantState)
assertThat(activity.boardState[row][col]).isEqualTo("black")
}
}

@Test
fun testFiveVictory() {
ActivityScenario.launch(MainActivity::class.java).onActivity {
activity = it

val board = activity.findViewById<TableLayout>(R.id.board)
val cells = board
.children
.filterIsInstance<TableRow>()
.flatMap { it.children }
.filterIsInstance<ImageView>()
.toList()

for (i in 0 until 5) {
val cell = cells[i]
cell.performClick()
if (i < 4) {
activity.changePlayer()
}
}

val showWinner = activity.findViewById<TextView>(R.id.showWinner)

assertThat(showWinner.text.toString()).isEqualTo("흑돌 승리!")
assertThat(activity.winnerPlayer).isEqualTo("black")
assertThat(activity.gameOver).isTrue
}
}
@Test
fun testFiveVictory2() {
ActivityScenario.launch(MainActivity::class.java).onActivity {
activity = it

val board = activity.findViewById<TableLayout>(R.id.board)
val cells = board
.children
.filterIsInstance<TableRow>()
.flatMap { it.children }
.filterIsInstance<ImageView>()
.toList()

for (i in 0 until 5) {
val cell = cells[i * (activity.boardSize + 1)]
cell.performClick()
if (i < 4) {
activity.changePlayer()
}
}

val showWinner = activity.findViewById<TextView>(R.id.showWinner)

assertThat(showWinner.text.toString()).isEqualTo("흑돌 승리!")
assertThat(activity.winnerPlayer).isEqualTo("black")
assertThat(activity.gameOver).isTrue
}
}
@Test
fun testFiveVictory3() {
ActivityScenario.launch(MainActivity::class.java).onActivity {
activity = it

val board = activity.findViewById<TableLayout>(R.id.board)
val cells = board
.children
.filterIsInstance<TableRow>()
.flatMap { it.children }
.filterIsInstance<ImageView>()
.toList()

for (i in 0 until 5) {
val cell = cells[(i + 1) * (activity.boardSize - 1)]
cell.performClick()
if (i < 4) {
activity.changePlayer()
}
}

val showWinner = activity.findViewById<TextView>(R.id.showWinner)

assertThat(showWinner.text.toString()).isEqualTo("흑돌 승리!")
assertThat(activity.winnerPlayer).isEqualTo("black")
assertThat(activity.gameOver).isTrue
}
}
}
98 changes: 97 additions & 1 deletion app/src/main/java/nextstep/omok/MainActivity.kt
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,21 @@ import android.os.Bundle
import android.widget.ImageView
import android.widget.TableLayout
import android.widget.TableRow
import android.widget.TextView
import androidx.appcompat.app.AppCompatActivity
import androidx.core.view.children

val derivative = arrayOf(
arrayOf(1, 0), arrayOf(0, 1), arrayOf(1, 1), arrayOf(1, -1)
)

class MainActivity : AppCompatActivity() {
val boardSize: Int = 15
var player: String = "black"
var winnerPlayer: String = ""
var gameOver: Boolean = false
var boardState = Array(boardSize) { Array(boardSize) { "" } }

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
Expand All @@ -18,6 +29,91 @@ class MainActivity : AppCompatActivity() {
.filterIsInstance<TableRow>()
.flatMap { it.children }
.filterIsInstance<ImageView>()
.forEach { view -> view.setOnClickListener { view.setImageResource(R.drawable.black_stone) } }
.forEachIndexed { index, view ->
view.setOnClickListener { onCellClicked(index, view) }
}

}

fun onCellClicked(index: Int, view: ImageView) {
if (gameOver) {
return
}

val row: Int = index / boardSize
val col: Int = index % boardSize
if (boardState[row][col] == "") {
placeStone(view)
boardState[row][col] = player
if (checkGameSet(row, col)) {
winnerPlayer = player
showWinner()
} else if (isBoardFull()) {
showDraw()
} else {
changePlayer()
}
}
}

fun placeStone(view: ImageView) {
if (player == "black") {
view.setImageResource(R.drawable.black_stone)
} else {
view.setImageResource(R.drawable.white_stone)
}
}

fun checkGameSet(row: Int, col: Int): Boolean {
for (direction in derivative) {
var count = 1

count += countStones(row, col, direction[0], direction[1])
count += countStones(row, col, -direction[0], -direction[1])

if (count >= 5) {
return true
}
}
return false
}

fun countStones(row: Int, col: Int, rowDir: Int, colDir: Int): Int {
var currentRow = row + rowDir
var currentCol = col + colDir
var count = 0

while (currentRow in 0 until boardSize && currentCol in 0 until boardSize && boardState[currentRow][currentCol] == player) {
count++
currentRow += rowDir
currentCol += colDir
}
return count
}

fun changePlayer() {
player = if (player == "black") "white" else "black"
}

fun showWinner() {
val showWinner = findViewById<TextView>(R.id.showWinner)
showWinner.text = if (winnerPlayer == "black") "흑돌 승리!" else "백돌 승리!"
gameOver = true
}
fun showDraw() {
val showWinner = findViewById<TextView>(R.id.showWinner)
showWinner.text = "무승부!"
gameOver = true
}

fun isBoardFull(): Boolean {
for (row in boardState) {
for (cell in row) {
if (cell == "") {
return false
}
}
}
return true
}
}
8 changes: 8 additions & 0 deletions app/src/main/res/layout/activity_main.xml
Original file line number Diff line number Diff line change
Expand Up @@ -1179,5 +1179,13 @@
android:background="@drawable/board_bottom_right" />
</TableRow>

<TextView
android:id="@+id/showWinner"
android:layout_width="100dp"
android:layout_height="70dp"
android:gravity="center"
android:textColor="@color/black"
android:textSize="30dp" />

</TableLayout>
</LinearLayout>