In this article, we are going to make a sudoku solver Android app in Kotlin and xml. The main focus of the app will be on the sudoku-solving algorithm so the the design part has been hardcoded. A sample video is given below to get an idea about what we are going to do in this article.
Step by Step Implementation
Step 1: Create a New Project in Android Studio
To create a new project in Android Studio please refer to How to Create/Start a New Project in Android Studio. Note that select Kotlin as the programming language.
- Now we will create the layout of the sudoku solver using Table Layout, you just need to create one row and copy paste that 9 times and give the ids as shown.
- Although you can reduce this redundancy using recyclerview but to keep it simple I have Hardcoded the table.
Add viewBinding in builde.gradle(app:Module) inside android{} and sync the files.
viewBinding{ enabled = true
} |
Step 2: Working with the activity_main.xml file
Navigate to the app > res > layout > activity_main.xml and add the below code to that file. Below is the code for the activity_main.xml file. Comments are added inside the code to understand the code in more detail.
<? xml version = "1.0" encoding = "utf-8" ?>
< LinearLayout android:layout_width = "match_parent"
android:layout_height = "match_parent"
android:orientation = "vertical"
android:padding = "15dp"
tools:context = ".MainActivity" >
< TableLayout
android:layout_width = "match_parent"
android:layout_height = "wrap_content"
android:padding = "5dp" >
< TableRow >
< EditText
android:id = "@+id/a_00"
android:layout_width = "0dp"
android:layout_height = "45dp"
android:layout_weight = "1"
android:gravity = "center"
android:inputType = "number" />
< EditText
android:id = "@+id/a_01"
android:layout_width = "0dp"
android:layout_height = "45dp"
android:layout_weight = "1"
android:gravity = "center"
android:inputType = "number" />
< EditText
android:id = "@+id/a_02"
android:layout_width = "0dp"
android:layout_height = "45dp"
android:layout_weight = "1"
android:gravity = "center"
android:inputType = "number"
android:layout_marginRight = "22dp" />
< EditText
android:id = "@+id/a_03"
android:layout_width = "0dp"
android:layout_height = "45dp"
android:layout_weight = "1"
android:gravity = "center"
android:inputType = "number" />
< EditText
android:id = "@+id/a_04"
android:layout_width = "0dp"
android:layout_height = "45dp"
android:layout_weight = "1"
android:gravity = "center"
android:inputType = "number" />
< EditText
android:id = "@+id/a_05"
android:layout_width = "0dp"
android:layout_height = "45dp"
android:layout_weight = "1"
android:gravity = "center"
android:inputType = "number"
android:layout_marginRight = "22dp" />
< EditText
android:id = "@+id/a_06"
android:layout_width = "0dp"
android:layout_height = "45dp"
android:layout_weight = "1"
android:gravity = "center"
android:inputType = "number" />
< EditText
android:id = "@+id/a_07"
android:layout_width = "0dp"
android:layout_height = "45dp"
android:layout_weight = "1"
android:gravity = "center"
android:inputType = "number" />
< EditText
android:id = "@+id/a_08"
android:layout_width = "0dp"
android:layout_height = "45dp"
android:layout_weight = "1"
android:gravity = "center"
android:inputType = "number" />
</ TableRow >
< TableRow >
< EditText
android:id = "@+id/a_10"
android:layout_width = "0dp"
android:layout_height = "45dp"
android:layout_weight = "1"
android:gravity = "center"
android:inputType = "number" />
< EditText
android:id = "@+id/a_11"
android:layout_width = "0dp"
android:layout_height = "45dp"
android:layout_weight = "1"
android:gravity = "center"
android:inputType = "number" />
< EditText
android:id = "@+id/a_12"
android:layout_width = "0dp"
android:layout_height = "45dp"
android:layout_weight = "1"
android:gravity = "center"
android:inputType = "number"
android:layout_marginRight = "22dp" />
< EditText
android:id = "@+id/a_13"
android:layout_width = "0dp"
android:layout_height = "45dp"
android:layout_weight = "1"
android:gravity = "center"
android:inputType = "number" />
< EditText
android:id = "@+id/a_14"
android:layout_width = "0dp"
android:layout_height = "45dp"
android:layout_weight = "1"
android:gravity = "center"
android:inputType = "number" />
< EditText
android:id = "@+id/a_15"
android:layout_width = "0dp"
android:layout_height = "45dp"
android:layout_weight = "1"
android:inputType = "number"
android:gravity = "center"
android:layout_marginRight = "22dp" />
< EditText
android:id = "@+id/a_16"
android:layout_width = "0dp"
android:layout_height = "45dp"
android:layout_weight = "1"
android:gravity = "center"
android:inputType = "number" />
< EditText
android:id = "@+id/a_17"
android:layout_width = "0dp"
android:layout_height = "45dp"
android:layout_weight = "1"
android:gravity = "center"
android:inputType = "number" />
< EditText
android:id = "@+id/a_18"
android:layout_width = "0dp"
android:layout_height = "45dp"
android:layout_weight = "1"
android:gravity = "center"
android:inputType = "number" />
</ TableRow >
< TableRow >
< EditText
android:id = "@+id/a_20"
android:layout_width = "0dp"
android:layout_height = "45dp"
android:layout_weight = "1"
android:gravity = "center"
android:inputType = "number" />
< EditText
android:id = "@+id/a_21"
android:layout_width = "0dp"
android:layout_height = "45dp"
android:layout_weight = "1"
android:gravity = "center"
android:inputType = "number" />
< EditText
android:id = "@+id/a_22"
android:layout_width = "0dp"
android:layout_height = "45dp"
android:layout_weight = "1"
android:gravity = "center"
android:inputType = "number"
android:layout_marginRight = "22dp" />
< EditText
android:id = "@+id/a_23"
android:layout_width = "0dp"
android:layout_height = "45dp"
android:layout_weight = "1"
android:gravity = "center"
android:inputType = "number" />
< EditText
android:id = "@+id/a_24"
android:layout_width = "0dp"
android:layout_height = "45dp"
android:layout_weight = "1"
android:gravity = "center"
android:inputType = "number" />
< EditText
android:id = "@+id/a_25"
android:layout_width = "0dp"
android:layout_height = "45dp"
android:layout_weight = "1"
android:gravity = "center"
android:inputType = "number"
android:layout_marginRight = "22dp" />
< EditText
android:id = "@+id/a_26"
android:layout_width = "0dp"
android:layout_height = "45dp"
android:layout_weight = "1"
android:gravity = "center"
android:inputType = "number" />
< EditText
android:id = "@+id/a_27"
android:layout_width = "0dp"
android:layout_height = "45dp"
android:layout_weight = "1"
android:gravity = "center"
android:inputType = "number" />
< EditText
android:id = "@+id/a_28"
android:layout_width = "0dp"
android:layout_height = "45dp"
android:layout_weight = "1"
android:gravity = "center"
android:inputType = "number" />
</ TableRow >
< TableRow
android:layout_marginTop = "16dp" >
< EditText
android:id = "@+id/a_30"
android:layout_width = "0dp"
android:layout_height = "45dp"
android:layout_weight = "1"
android:gravity = "center"
android:inputType = "number" />
< EditText
android:id = "@+id/a_31"
android:layout_width = "0dp"
android:layout_height = "45dp"
android:layout_weight = "1"
android:gravity = "center"
android:inputType = "number" />
< EditText
android:id = "@+id/a_32"
android:layout_width = "0dp"
android:layout_height = "45dp"
android:layout_weight = "1"
android:gravity = "center"
android:inputType = "number"
android:layout_marginRight = "22dp" />
< EditText
android:id = "@+id/a_33"
android:layout_width = "0dp"
android:layout_height = "45dp"
android:layout_weight = "1"
android:gravity = "center"
android:inputType = "number" />
< EditText
android:id = "@+id/a_34"
android:layout_width = "0dp"
android:layout_height = "45dp"
android:layout_weight = "1"
android:gravity = "center"
android:inputType = "number" />
< EditText
android:id = "@+id/a_35"
android:layout_width = "0dp"
android:layout_height = "45dp"
android:layout_weight = "1"
android:gravity = "center"
android:inputType = "number"
android:layout_marginRight = "22dp" />
< EditText
android:id = "@+id/a_36"
android:layout_width = "0dp"
android:layout_height = "45dp"
android:layout_weight = "1"
android:gravity = "center"
android:inputType = "number" />
< EditText
android:id = "@+id/a_37"
android:layout_width = "0dp"
android:layout_height = "45dp"
android:layout_weight = "1"
android:gravity = "center"
android:inputType = "number" />
< EditText
android:id = "@+id/a_38"
android:layout_width = "0dp"
android:layout_height = "45dp"
android:layout_weight = "1"
android:gravity = "center"
android:inputType = "number" />
</ TableRow >
< TableRow >
< EditText
android:id = "@+id/a_40"
android:layout_width = "0dp"
android:layout_height = "45dp"
android:layout_weight = "1"
android:gravity = "center"
android:inputType = "number" />
< EditText
android:id = "@+id/a_41"
android:layout_width = "0dp"
android:layout_height = "45dp"
android:layout_weight = "1"
android:gravity = "center"
android:inputType = "number" />
< EditText
android:id = "@+id/a_42"
android:layout_width = "0dp"
android:layout_height = "45dp"
android:layout_weight = "1"
android:gravity = "center"
android:inputType = "number"
android:layout_marginRight = "22dp" />
< EditText
android:id = "@+id/a_43"
android:layout_width = "0dp"
android:layout_height = "45dp"
android:layout_weight = "1"
android:gravity = "center"
android:inputType = "number" />
< EditText
android:id = "@+id/a_44"
android:layout_width = "0dp"
android:layout_height = "45dp"
android:layout_weight = "1"
android:gravity = "center"
android:inputType = "number" />
< EditText
android:id = "@+id/a_45"
android:layout_width = "0dp"
android:layout_height = "45dp"
android:layout_weight = "1"
android:gravity = "center"
android:inputType = "number"
android:layout_marginRight = "22dp" />
< EditText
android:id = "@+id/a_46"
android:layout_width = "0dp"
android:layout_height = "45dp"
android:layout_weight = "1"
android:gravity = "center"
android:inputType = "number" />
< EditText
android:id = "@+id/a_47"
android:layout_width = "0dp"
android:layout_height = "45dp"
android:layout_weight = "1"
android:gravity = "center"
android:inputType = "number" />
< EditText
android:id = "@+id/a_48"
android:layout_width = "0dp"
android:layout_height = "45dp"
android:layout_weight = "1"
android:gravity = "center"
android:inputType = "number" />
</ TableRow >
< TableRow >
< EditText
android:id = "@+id/a_50"
android:layout_width = "0dp"
android:layout_height = "45dp"
android:layout_weight = "1"
android:gravity = "center"
android:inputType = "number" />
< EditText
android:id = "@+id/a_51"
android:layout_width = "0dp"
android:layout_height = "45dp"
android:layout_weight = "1"
android:gravity = "center"
android:inputType = "number" />
< EditText
android:id = "@+id/a_52"
android:layout_width = "0dp"
android:layout_height = "45dp"
android:layout_weight = "1"
android:gravity = "center"
android:inputType = "number"
android:layout_marginRight = "22dp" />
< EditText
android:id = "@+id/a_53"
android:layout_width = "0dp"
android:layout_height = "45dp"
android:layout_weight = "1"
android:gravity = "center"
android:inputType = "number" />
< EditText
android:id = "@+id/a_54"
android:layout_width = "0dp"
android:layout_height = "45dp"
android:layout_weight = "1"
android:gravity = "center"
android:inputType = "number" />
< EditText
android:id = "@+id/a_55"
android:layout_width = "0dp"
android:layout_height = "45dp"
android:layout_weight = "1"
android:gravity = "center"
android:inputType = "number"
android:layout_marginRight = "22dp" />
< EditText
android:id = "@+id/a_56"
android:layout_width = "0dp"
android:layout_height = "45dp"
android:layout_weight = "1"
android:gravity = "center"
android:inputType = "number" />
< EditText
android:id = "@+id/a_57"
android:layout_width = "0dp"
android:layout_height = "45dp"
android:layout_weight = "1"
android:gravity = "center"
android:inputType = "number" />
< EditText
android:id = "@+id/a_58"
android:layout_width = "0dp"
android:layout_height = "45dp"
android:layout_weight = "1"
android:gravity = "center"
android:inputType = "number" />
</ TableRow >
< TableRow android:layout_marginTop = "16dp" >
< EditText
android:id = "@+id/a_60"
android:layout_width = "0dp"
android:layout_height = "45dp"
android:layout_weight = "1"
android:gravity = "center"
android:inputType = "number" />
< EditText
android:id = "@+id/a_61"
android:layout_width = "0dp"
android:layout_height = "45dp"
android:layout_weight = "1"
android:gravity = "center"
android:inputType = "number" />
< EditText
android:id = "@+id/a_62"
android:layout_width = "0dp"
android:layout_height = "45dp"
android:layout_weight = "1"
android:gravity = "center"
android:inputType = "number"
android:layout_marginRight = "22dp" />
< EditText
android:id = "@+id/a_63"
android:layout_width = "0dp"
android:layout_height = "45dp"
android:layout_weight = "1"
android:gravity = "center"
android:inputType = "number" />
< EditText
android:id = "@+id/a_64"
android:layout_width = "0dp"
android:layout_height = "45dp"
android:layout_weight = "1"
android:gravity = "center"
android:inputType = "number" />
< EditText
android:id = "@+id/a_65"
android:layout_width = "0dp"
android:layout_height = "45dp"
android:layout_weight = "1"
android:gravity = "center"
android:inputType = "number"
android:layout_marginRight = "22dp" />
< EditText
android:id = "@+id/a_66"
android:layout_width = "0dp"
android:layout_height = "45dp"
android:layout_weight = "1"
android:gravity = "center"
android:inputType = "number" />
< EditText
android:id = "@+id/a_67"
android:layout_width = "0dp"
android:layout_height = "45dp"
android:layout_weight = "1"
android:gravity = "center"
android:inputType = "number" />
< EditText
android:id = "@+id/a_68"
android:layout_width = "0dp"
android:layout_height = "45dp"
android:layout_weight = "1"
android:gravity = "center"
android:inputType = "number" />
</ TableRow >
< TableRow >
< EditText
android:id = "@+id/a_70"
android:layout_width = "0dp"
android:layout_height = "45dp"
android:layout_weight = "1"
android:gravity = "center"
android:inputType = "number" />
< EditText
android:id = "@+id/a_71"
android:layout_width = "0dp"
android:layout_height = "45dp"
android:layout_weight = "1"
android:gravity = "center"
android:inputType = "number" />
< EditText
android:id = "@+id/a_72"
android:layout_width = "0dp"
android:layout_height = "45dp"
android:layout_weight = "1"
android:gravity = "center"
android:inputType = "number"
android:layout_marginRight = "22dp" />
< EditText
android:id = "@+id/a_73"
android:layout_width = "0dp"
android:layout_height = "45dp"
android:layout_weight = "1"
android:gravity = "center"
android:inputType = "number" />
< EditText
android:id = "@+id/a_74"
android:layout_width = "0dp"
android:layout_height = "45dp"
android:layout_weight = "1"
android:gravity = "center"
android:inputType = "number" />
< EditText
android:id = "@+id/a_75"
android:layout_width = "0dp"
android:layout_height = "45dp"
android:layout_weight = "1"
android:gravity = "center"
android:inputType = "number"
android:layout_marginRight = "22dp" />
< EditText
android:id = "@+id/a_76"
android:layout_width = "0dp"
android:layout_height = "45dp"
android:layout_weight = "1"
android:gravity = "center"
android:inputType = "number" />
< EditText
android:id = "@+id/a_77"
android:layout_width = "0dp"
android:layout_height = "45dp"
android:layout_weight = "1"
android:gravity = "center"
android:inputType = "number" />
< EditText
android:id = "@+id/a_78"
android:layout_width = "0dp"
android:layout_height = "45dp"
android:layout_weight = "1"
android:gravity = "center"
android:inputType = "number" />
</ TableRow >
< TableRow >
< EditText
android:id = "@+id/a_80"
android:layout_width = "0dp"
android:layout_height = "45dp"
android:layout_weight = "1"
android:gravity = "center"
android:inputType = "number" />
< EditText
android:id = "@+id/a_81"
android:layout_width = "0dp"
android:layout_height = "45dp"
android:layout_weight = "1"
android:gravity = "center"
android:inputType = "number" />
< EditText
android:id = "@+id/a_82"
android:layout_width = "0dp"
android:layout_height = "45dp"
android:layout_weight = "1"
android:gravity = "center"
android:inputType = "number"
android:layout_marginRight = "22dp" />
< EditText
android:id = "@+id/a_83"
android:layout_width = "0dp"
android:layout_height = "45dp"
android:layout_weight = "1"
android:gravity = "center"
android:inputType = "number" />
< EditText
android:id = "@+id/a_84"
android:layout_width = "0dp"
android:layout_height = "45dp"
android:layout_weight = "1"
android:gravity = "center"
android:inputType = "number" />
< EditText
android:id = "@+id/a_85"
android:layout_width = "0dp"
android:layout_height = "45dp"
android:layout_weight = "1"
android:gravity = "center"
android:inputType = "number"
android:layout_marginRight = "22dp" />
< EditText
android:id = "@+id/a_86"
android:layout_width = "0dp"
android:layout_height = "45dp"
android:layout_weight = "1"
android:gravity = "center"
android:inputType = "number" />
< EditText
android:id = "@+id/a_87"
android:layout_width = "0dp"
android:layout_height = "45dp"
android:layout_weight = "1"
android:gravity = "center"
android:inputType = "number" />
< EditText
android:id = "@+id/a_88"
android:layout_width = "0dp"
android:layout_height = "45dp"
android:layout_weight = "1"
android:gravity = "center"
android:inputType = "number" />
</ TableRow >
</ TableLayout >
< LinearLayout
android:layout_width = "match_parent"
android:layout_height = "wrap_content"
android:orientation = "horizontal"
android:layout_marginTop = "32dp" >
< Button
android:id = "@+id/solve"
android:layout_width = "0dp"
android:layout_weight = "1"
android:layout_height = "wrap_content"
android:background = "#283593"
android:padding = "5dp"
android:layout_margin = "8dp"
android:text = "SOLVE"
android:textStyle = "bold"
android:textSize = "20sp" />
< Button
android:id = "@+id/clear"
android:layout_width = "0dp"
android:layout_weight = "1"
android:layout_height = "wrap_content"
android:background = "#283593"
android:padding = "5dp"
android:layout_margin = "8dp"
android:text = "CLEAR"
android:textStyle = "bold"
android:textSize = "20sp" />
</ LinearLayout >
</ LinearLayout >
|
Step 3: Working with the MainActivity.kt file
Go to the MainActivity.kt file and refer to the following code. Below is the code for the MainActivity.kt file. Comments are added inside the code to understand the code in more detail.
Inside MainActivity class declare the binding variable so that it can be used globally
private lateinit var binding: ActivityMainBinding
|
Inside the onCreate method, we will use a 2d array of string to store the input and a 1d array that contains all the ids of editTexts.
super .onCreate(savedInstanceState)
binding = ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.root)
val matrix = arrayOf(
arrayOf( "" , "" , "" , "" , "" , "" , "" , "" , "" ),
arrayOf( "" , "" , "" , "" , "" , "" , "" , "" , "" ),
arrayOf( "" , "" , "" , "" , "" , "" , "" , "" , "" ),
arrayOf( "" , "" , "" , "" , "" , "" , "" , "" , "" ),
arrayOf( "" , "" , "" , "" , "" , "" , "" , "" , "" ),
arrayOf( "" , "" , "" , "" , "" , "" , "" , "" , "" ),
arrayOf( "" , "" , "" , "" , "" , "" , "" , "" , "" ),
arrayOf( "" , "" , "" , "" , "" , "" , "" , "" , "" ),
arrayOf( "" , "" , "" , "" , "" , "" , "" , "" , "" ),
)
var arr = ArrayList<EditText>()
binding.apply {
arr.addAll(
arrayOf(
a00, a01, a02, a03, a04, a05, a06, a07, a08,
a10, a11, a12, a13, a14, a15, a16, a17, a18,
a20, a21, a22, a23, a24, a25, a26, a27, a28,
a30, a31, a32, a33, a34, a35, a36, a37, a38,
a40, a41, a42, a43, a44, a45, a46, a47, a48,
a50, a51, a52, a53, a54, a55, a56, a57, a58,
a60, a61, a62, a63, a64, a65, a66, a67, a68,
a70, a71, a72, a73, a74, a75, a76, a77, a78,
a80, a81, a82, a83, a84, a85, a86, a87, a88,
)
)
}
|
Now when the user types in the input integers and click solve then we have to first check for the validity of sudoku, so continuing the above code in onCreate
binding.solve.setOnClickListener { var k = 0
for (i in 0 .. 8 ) {
for (j in 0 .. 8 ) {
if (arr[k].text.isNotEmpty()) {
matrix[i][j] = arr[k].text.toString()
}
k++
}
}
if (!isValidConfig(matrix)) {
Clear(matrix, arr)
Toast.makeText( this @MainActivity , "Invalid Sudoku" , Toast.LENGTH_SHORT)
.show()
} else {
solve(matrix, 0 , 0 )
k = 0
for (i in 0 .. 8 ) {
for (j in 0 .. 8 ) {
arr[k].setText(matrix[i][j])
k++
}
}
}
}
binding.clear.setOnClickListener {
Clear(matrix, arr)
}
|
Now write the below code outside onCreate for validity check
fun isValidConfig(arr: Array<Array<String>>): Boolean { val n=arr.size
for (i in 0 ..n - 1 ) {
for (j in 0 ..n - 1 ) {
if (arr[i][j]!= "" && !valid(arr, i, j)) return false
}
}
return true
}
private fun valid(arr: Array<Array<String>>, row: Int, col: Int): Boolean {
return (arr[row][col] !in "1" .. "9" ) && notInRow(arr, row) && notInCol(arr, col) &&
notInBox(arr, row - row % 3 , col - col % 3 )
} fun notInRow(matrix: Array<Array<String>>, row: Int): Boolean { val st = HashSet<String>()
for (i in 0 .. 8 ) {
if (st.contains(matrix[row][i])) return false
if (matrix[row][i] != "" ) st.add(matrix[row][i])
}
return true
} fun notInCol(arr: Array<Array<String>>, col: Int): Boolean { val st = HashSet<String>()
for (i in 0 .. 8 ) {
if (st.contains(arr[i][col])) return false
if (arr[i][col] != "" ) st.add(arr[i][col])
}
return true
} fun notInBox( arr: Array<Array<String>>,
startRow: Int,
startCol: Int
): Boolean {
val st = HashSet<String>()
for (row in 0 .. 2 ) {
for (col in 0 .. 2 ) {
val curr = arr[row + startRow][col + startCol]
if (st.contains(curr)) return false
if (curr != "" ) st.add(curr)
}
}
return true
}
// on clicking the clear button to clear sudoku private fun Clear(matrix: Array<Array<String>>, arr: ArrayList<EditText>) {
var k = 0
for (i in 0 .. 8 ) {
for (j in 0 .. 8 ) {
matrix[i][j] = ""
arr[k].setText( "" )
k++
}
}
}
|
If the sudoku is invalid toast will be printed else if it is valid below code will be executed
private fun solve(matrix: Array<Array<String>>, i: Int, j: Int): Boolean {
if (i == 9 ) return true
if (j == 9 ) return solve(matrix, i + 1 , 0 )
if (matrix[i][j] != "" ) return solve(matrix, i, j + 1 )
for (it in 1 .. 9 ) {
if (isvalid(matrix, i, j, it)) {
matrix[i][j] = "$it"
if (solve(matrix, i, j + 1 )) return true
matrix[i][j] = ""
}
}
return false
}
private fun isvalid(matrix: Array<Array<String>>, i: Int, j: Int, value: Int): Boolean {
val row = i - (i % 3 )
val col = j - (j % 3 )
for (x in 0 .. 8 ) if (matrix[x][j] == "$value" ) return false
for (y in 0 .. 8 ) if (matrix[i][y] == "$value" ) return false
for (x in 0 .. 2 ) for (y in 0 .. 2 ) if (matrix[row + x][col + y] == "$value"
) return false
return true
}
|
Complete MainActivity Code:
package com.example.sudokusolver20
import android.os.Bundle
import android.widget.EditText
import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity
import com.example.sudokusolver20.databinding.ActivityMainBinding
class MainActivity : AppCompatActivity() {
private lateinit var binding: ActivityMainBinding
override fun onCreate(savedInstanceState: Bundle?) {
super .onCreate(savedInstanceState)
binding = ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.root)
val matrix = arrayOf(
arrayOf( "" , "" , "" , "" , "" , "" , "" , "" , "" ),
arrayOf( "" , "" , "" , "" , "" , "" , "" , "" , "" ),
arrayOf( "" , "" , "" , "" , "" , "" , "" , "" , "" ),
arrayOf( "" , "" , "" , "" , "" , "" , "" , "" , "" ),
arrayOf( "" , "" , "" , "" , "" , "" , "" , "" , "" ),
arrayOf( "" , "" , "" , "" , "" , "" , "" , "" , "" ),
arrayOf( "" , "" , "" , "" , "" , "" , "" , "" , "" ),
arrayOf( "" , "" , "" , "" , "" , "" , "" , "" , "" ),
arrayOf( "" , "" , "" , "" , "" , "" , "" , "" , "" ),
)
var arr = ArrayList<EditText>()
binding.apply {
arr.addAll(
arrayOf(
a00, a01, a02, a03, a04, a05, a06, a07, a08,
a10, a11, a12, a13, a14, a15, a16, a17, a18,
a20, a21, a22, a23, a24, a25, a26, a27, a28,
a30, a31, a32, a33, a34, a35, a36, a37, a38,
a40, a41, a42, a43, a44, a45, a46, a47, a48,
a50, a51, a52, a53, a54, a55, a56, a57, a58,
a60, a61, a62, a63, a64, a65, a66, a67, a68,
a70, a71, a72, a73, a74, a75, a76, a77, a78,
a80, a81, a82, a83, a84, a85, a86, a87, a88,
)
)
}
binding.solve.setOnClickListener {
var k = 0
for (i in 0 .. 8 ) {
for (j in 0 .. 8 ) {
if (arr[k].text.isNotEmpty()) {
matrix[i][j] = arr[k].text.toString()
}
k++
}
}
if (!isValidConfig(matrix)) {
Clear(matrix, arr)
Toast.makeText( this @MainActivity , "Invalid Sudoku" , Toast.LENGTH_SHORT)
.show()
} else {
solve(matrix, 0 , 0 )
k = 0
for (i in 0 .. 8 ) {
for (j in 0 .. 8 ) {
arr[k].setText(matrix[i][j])
k++
}
}
}
}
binding.clear.setOnClickListener {
Clear(matrix, arr)
}
}
private fun Clear(matrix: Array<Array<String>>, arr: ArrayList<EditText>) {
var k = 0
for (i in 0 .. 8 ) {
for (j in 0 .. 8 ) {
matrix[i][j] = ""
arr[k].setText( "" )
k++
}
}
}
private fun solve(matrix: Array<Array<String>>, i: Int, j: Int): Boolean {
if (i == 9 ) return true
if (j == 9 ) return solve(matrix, i + 1 , 0 )
if (matrix[i][j] != "" ) return solve(matrix, i, j + 1 )
for (it in 1 .. 9 ) {
if (isvalid(matrix, i, j, it)) {
matrix[i][j] = "$it"
if (solve(matrix, i, j + 1 )) return true
matrix[i][j] = ""
}
}
return false
}
private fun isvalid(matrix: Array<Array<String>>, i: Int, j: Int, value: Int): Boolean {
val row = i - (i % 3 )
val col = j - (j % 3 )
for (x in 0 .. 8 ) if (matrix[x][j] == "$value" ) return false
for (y in 0 .. 8 ) if (matrix[i][y] == "$value" ) return false
for (x in 0 .. 2 ) for (y in 0 .. 2 ) if (matrix[row + x][col + y] == "$value"
) return false
return true
}
fun notInRow(matrix: Array<Array<String>>, row: Int): Boolean {
val st = HashSet<String>()
for (i in 0 .. 8 ) {
if (st.contains(matrix[row][i])) return false
if (matrix[row][i] != "" ) st.add(matrix[row][i])
}
return true
}
fun notInCol(arr: Array<Array<String>>, col: Int): Boolean {
val st = HashSet<String>()
for (i in 0 .. 8 ) {
if (st.contains(arr[i][col])) return false
if (arr[i][col] != "" ) st.add(arr[i][col])
}
return true
}
fun notInBox(
arr: Array<Array<String>>,
startRow: Int,
startCol: Int
): Boolean {
val st = HashSet<String>()
for (row in 0 .. 2 ) {
for (col in 0 .. 2 ) {
val curr = arr[row + startRow][col + startCol]
if (st.contains(curr)) return false
if (curr != "" ) st.add(curr)
}
}
return true
}
fun isValidConfig(arr: Array<Array<String>>): Boolean {
val n=arr.size
for (i in 0 ..n - 1 ) {
for (j in 0 ..n - 1 ) {
if (arr[i][j]!= "" && !valid(arr, i, j)) return false
}
}
return true
}
private fun valid(arr: Array<Array<String>>, row: Int, col: Int): Boolean {
return (arr[row][col] !in "1" .. "9" ) && notInRow(arr, row) && notInCol(arr, col) &&
notInBox(arr, row - row % 3 , col - col % 3 )
}
} |
Output: