Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c82fdd28cf | ||
|
|
169d30f81f | ||
|
|
7799ce100c | ||
|
|
0935d7da52 | ||
|
|
b7a7be8a60 | ||
|
|
c63416489c | ||
|
|
4a237c8268 | ||
|
|
bb8cc12fb7 | ||
|
|
b6d95f9268 | ||
|
|
cbfa94131b | ||
|
|
ab8959c3f4 | ||
|
|
a1b7f180a2 | ||
|
|
c984624895 | ||
|
|
6f68bc1b04 | ||
|
|
e7b377bdb9 | ||
|
|
54dadb1f25 | ||
|
|
f2ede2767d | ||
|
|
59af3a2485 | ||
|
|
5f40507a7d | ||
|
|
920ee0d54c | ||
|
|
f992d25d29 | ||
|
|
6eb2811814 | ||
|
|
f552cc77a8 | ||
|
|
07cefd2776 | ||
|
|
59082be0cf | ||
|
|
31703cffb9 |
No files matched your search
@@ -8,9 +8,9 @@ and maybe even make the game mad. 🐇🥚
|
|||||||
|
|
||||||
## Download
|
## Download
|
||||||
|
|
||||||
App is hosted at [Hyperling.com](https://hyperling.com/home/#tictactoe) where
|
App is hosted at [git.hyperling.com](https://git.hyperling.com/me/android-tictactoe) where
|
||||||
it is also available for
|
it is also available for
|
||||||
[Direct Download](https://hyperling.com/files/apks/TicTacToe.apk).
|
[Direct Download](https://git.hyperling.com/me/android-tictactoe/releases).
|
||||||
|
|
||||||
## TODO
|
## TODO
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,28 @@
|
|||||||
|
# Changelog
|
||||||
|
|
||||||
|
Update history of this app.
|
||||||
|
|
||||||
|
## 1.1.2
|
||||||
|
|
||||||
|
**More Fixes**
|
||||||
|
|
||||||
|
- Correctly apply background color 333333 to icons.
|
||||||
|
- Ensure activity sits above the navigation buttons on newer version of Android (if they exist).
|
||||||
|
|
||||||
|
## 1.1.0
|
||||||
|
|
||||||
|
**Fix App Icon**
|
||||||
|
|
||||||
|
- Fix app icon for some versions of Android.
|
||||||
|
- Update to the latest versions of internal plugins so that app can be compiled successfully.
|
||||||
|
- Now targets Android SDK 37.
|
||||||
|
|
||||||
|
## 1.1.0
|
||||||
|
|
||||||
|
**Update Android Target; Release Old Commits**
|
||||||
|
|
||||||
|
- Update to SDK 36.
|
||||||
|
- AI fixes and UI improvements.
|
||||||
|
- Correct download URL.
|
||||||
|
|
||||||
|
Note that this release uses a new key due to the old one not existing in the keystore.
|
||||||
@@ -1,18 +1,19 @@
|
|||||||
plugins {
|
plugins {
|
||||||
alias(libs.plugins.androidApplication)
|
alias(libs.plugins.androidApplication)
|
||||||
alias(libs.plugins.jetbrainsKotlinAndroid)
|
//alias(libs.plugins.jetbrainsKotlinAndroid)
|
||||||
|
alias(libs.plugins.kotlinCompose)
|
||||||
}
|
}
|
||||||
|
|
||||||
android {
|
android {
|
||||||
namespace = "com.hyperling.tictactoe"
|
namespace = "com.hyperling.tictactoe"
|
||||||
compileSdk = 34
|
compileSdk = 37
|
||||||
|
|
||||||
defaultConfig {
|
defaultConfig {
|
||||||
applicationId = "com.hyperling.tictactoe"
|
applicationId = "com.hyperling.tictactoe"
|
||||||
minSdk = 21
|
minSdk = 23
|
||||||
targetSdk = 34
|
targetSdk = 37
|
||||||
versionCode = 1
|
versionCode = 6
|
||||||
versionName = "1.0"
|
versionName = "1.1.2"
|
||||||
|
|
||||||
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
|
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
|
||||||
vectorDrawables {
|
vectorDrawables {
|
||||||
@@ -22,16 +23,17 @@ android {
|
|||||||
|
|
||||||
buildTypes {
|
buildTypes {
|
||||||
release {
|
release {
|
||||||
isMinifyEnabled = false
|
isMinifyEnabled = true
|
||||||
proguardFiles(getDefaultProguardFile("proguard-android-optimize.txt"), "proguard-rules.pro")
|
isShrinkResources = true
|
||||||
|
proguardFiles(
|
||||||
|
getDefaultProguardFile("proguard-android-optimize.txt"),
|
||||||
|
"proguard-rules.pro"
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
compileOptions {
|
compileOptions {
|
||||||
sourceCompatibility = JavaVersion.VERSION_1_8
|
sourceCompatibility = JavaVersion.VERSION_17
|
||||||
targetCompatibility = JavaVersion.VERSION_1_8
|
targetCompatibility = JavaVersion.VERSION_17
|
||||||
}
|
|
||||||
kotlinOptions {
|
|
||||||
jvmTarget = "1.8"
|
|
||||||
}
|
}
|
||||||
buildFeatures {
|
buildFeatures {
|
||||||
compose = true
|
compose = true
|
||||||
@@ -47,7 +49,6 @@ android {
|
|||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
|
|
||||||
implementation(libs.androidx.core.ktx)
|
implementation(libs.androidx.core.ktx)
|
||||||
implementation(libs.androidx.lifecycle.runtime.ktx)
|
implementation(libs.androidx.lifecycle.runtime.ktx)
|
||||||
implementation(libs.androidx.activity.compose)
|
implementation(libs.androidx.activity.compose)
|
||||||
@@ -63,4 +64,10 @@ dependencies {
|
|||||||
androidTestImplementation(libs.androidx.ui.test.junit4)
|
androidTestImplementation(libs.androidx.ui.test.junit4)
|
||||||
debugImplementation(libs.androidx.ui.tooling)
|
debugImplementation(libs.androidx.ui.tooling)
|
||||||
debugImplementation(libs.androidx.ui.test.manifest)
|
debugImplementation(libs.androidx.ui.test.manifest)
|
||||||
|
|
||||||
|
// 2026-11-01 - Fix for "unresolved reference" on these in MainActivity:
|
||||||
|
//import androidx.compose.material.icons.Icons
|
||||||
|
//import androidx.compose.material.icons.rounded.Close
|
||||||
|
implementation("androidx.compose.material:material-icons-core")
|
||||||
|
implementation("androidx.compose.material:material-icons-extended")
|
||||||
}
|
}
|
||||||
@@ -10,8 +10,7 @@
|
|||||||
android:label="@string/app_name"
|
android:label="@string/app_name"
|
||||||
android:roundIcon="@mipmap/ic_icon_ttt"
|
android:roundIcon="@mipmap/ic_icon_ttt"
|
||||||
android:supportsRtl="true"
|
android:supportsRtl="true"
|
||||||
android:theme="@style/Theme.TicTacToe"
|
android:theme="@style/Theme.TicTacToe">
|
||||||
tools:targetApi="31">
|
|
||||||
<activity
|
<activity
|
||||||
android:name=".MainActivity"
|
android:name=".MainActivity"
|
||||||
android:exported="true"
|
android:exported="true"
|
||||||
|
|||||||
|
After Width: | Height: | Size: 5.5 KiB |
@@ -7,6 +7,7 @@ import android.util.Log
|
|||||||
import android.widget.Toast
|
import android.widget.Toast
|
||||||
import androidx.activity.ComponentActivity
|
import androidx.activity.ComponentActivity
|
||||||
import androidx.activity.compose.setContent
|
import androidx.activity.compose.setContent
|
||||||
|
import androidx.activity.enableEdgeToEdge
|
||||||
import androidx.compose.foundation.clickable
|
import androidx.compose.foundation.clickable
|
||||||
import androidx.compose.foundation.layout.*
|
import androidx.compose.foundation.layout.*
|
||||||
import androidx.compose.material.icons.Icons
|
import androidx.compose.material.icons.Icons
|
||||||
@@ -28,14 +29,20 @@ import androidx.compose.ui.text.style.TextAlign
|
|||||||
import androidx.compose.ui.tooling.preview.Devices
|
import androidx.compose.ui.tooling.preview.Devices
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import androidx.compose.ui.unit.sp
|
import androidx.compose.ui.unit.sp
|
||||||
|
import androidx.core.view.ViewCompat
|
||||||
|
import androidx.core.view.WindowCompat
|
||||||
|
import androidx.core.view.WindowInsetsCompat
|
||||||
|
|
||||||
class MainActivity : ComponentActivity() {
|
class MainActivity : ComponentActivity() {
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
|
enableEdgeToEdge()
|
||||||
setContent {
|
setContent {
|
||||||
TicTacToeTheme {
|
TicTacToeTheme {
|
||||||
Surface {
|
Box(Modifier.fillMaxSize().systemBarsPadding()) {
|
||||||
Game()
|
Surface {
|
||||||
|
Game()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -194,8 +201,8 @@ fun Game() {
|
|||||||
Column(
|
Column(
|
||||||
horizontalAlignment = Alignment.CenterHorizontally
|
horizontalAlignment = Alignment.CenterHorizontally
|
||||||
, verticalArrangement = Arrangement.Center
|
, verticalArrangement = Arrangement.Center
|
||||||
, modifier = Modifier
|
//, modifier = Modifier
|
||||||
.fillMaxSize()
|
// .fillMaxSize()
|
||||||
) {
|
) {
|
||||||
|
|
||||||
Spacer(modifier = Modifier.weight(0.1f))
|
Spacer(modifier = Modifier.weight(0.1f))
|
||||||
@@ -346,95 +353,112 @@ fun Game() {
|
|||||||
fontSize = 16.sp
|
fontSize = 16.sp
|
||||||
)
|
)
|
||||||
Spacer(modifier = Modifier.size(5.dp))
|
Spacer(modifier = Modifier.size(5.dp))
|
||||||
Row (
|
|
||||||
|
Row(
|
||||||
verticalAlignment = Alignment.CenterVertically,
|
verticalAlignment = Alignment.CenterVertically,
|
||||||
modifier = Modifier.clickable {
|
horizontalArrangement = Arrangement.SpaceEvenly
|
||||||
opponentHuman = setRadiosFalse()
|
) {
|
||||||
|
Column (
|
||||||
|
horizontalAlignment = Alignment.Start,
|
||||||
|
verticalArrangement = Arrangement.Top
|
||||||
|
) {
|
||||||
|
Row (
|
||||||
|
verticalAlignment = Alignment.CenterVertically,
|
||||||
|
modifier = Modifier.clickable {
|
||||||
|
opponentHuman = setRadiosFalse()
|
||||||
|
}
|
||||||
|
){
|
||||||
|
RadioButton(
|
||||||
|
selected = opponentHuman,
|
||||||
|
onClick = { opponentHuman = setRadiosFalse() },
|
||||||
|
)
|
||||||
|
Text(
|
||||||
|
text = stringResource(id = R.string.opponent_human),
|
||||||
|
fontSize = 16.sp
|
||||||
|
)
|
||||||
|
}
|
||||||
|
Row (
|
||||||
|
verticalAlignment = Alignment.CenterVertically,
|
||||||
|
modifier = Modifier.clickable {
|
||||||
|
opponentHard = setRadiosFalse()
|
||||||
|
}
|
||||||
|
){
|
||||||
|
RadioButton(
|
||||||
|
selected = opponentHard,
|
||||||
|
onClick = { opponentHard = setRadiosFalse() },
|
||||||
|
)
|
||||||
|
Text(
|
||||||
|
text = stringResource(id = R.string.opponent_hard),
|
||||||
|
fontSize = 16.sp
|
||||||
|
)
|
||||||
|
}
|
||||||
|
Row (
|
||||||
|
verticalAlignment = Alignment.CenterVertically,
|
||||||
|
modifier = Modifier.clickable {
|
||||||
|
opponentAnnoying = setRadiosFalse()
|
||||||
|
}
|
||||||
|
){
|
||||||
|
RadioButton(
|
||||||
|
selected = opponentAnnoying,
|
||||||
|
onClick = { opponentAnnoying = setRadiosFalse() },
|
||||||
|
)
|
||||||
|
Text(
|
||||||
|
text = stringResource(id = R.string.opponent_annoying),
|
||||||
|
fontSize = 16.sp
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
){
|
|
||||||
RadioButton(
|
Column (
|
||||||
selected = opponentHuman,
|
horizontalAlignment = Alignment.Start,
|
||||||
onClick = { opponentHuman = setRadiosFalse() },
|
verticalArrangement = Arrangement.Bottom
|
||||||
)
|
) {
|
||||||
Text(
|
Row (
|
||||||
text = stringResource(id = R.string.opponent_human),
|
verticalAlignment = Alignment.CenterVertically,
|
||||||
fontSize = 16.sp
|
modifier = Modifier.clickable {
|
||||||
)
|
opponentRandom = setRadiosFalse()
|
||||||
}
|
}
|
||||||
Row (
|
){
|
||||||
verticalAlignment = Alignment.CenterVertically,
|
RadioButton(
|
||||||
modifier = Modifier.clickable {
|
selected = opponentRandom,
|
||||||
opponentRandom = setRadiosFalse()
|
onClick = { opponentRandom = setRadiosFalse() },
|
||||||
|
)
|
||||||
|
Text(
|
||||||
|
text = stringResource(id = R.string.opponent_random),
|
||||||
|
fontSize = 16.sp
|
||||||
|
)
|
||||||
|
}
|
||||||
|
Row (
|
||||||
|
verticalAlignment = Alignment.CenterVertically,
|
||||||
|
modifier = Modifier.clickable {
|
||||||
|
opponentEasy = setRadiosFalse()
|
||||||
|
}
|
||||||
|
){
|
||||||
|
RadioButton(
|
||||||
|
selected = opponentEasy,
|
||||||
|
onClick = { opponentEasy = setRadiosFalse() },
|
||||||
|
)
|
||||||
|
Text(
|
||||||
|
text = stringResource(id = R.string.opponent_easy),
|
||||||
|
fontSize = 16.sp
|
||||||
|
)
|
||||||
|
}
|
||||||
|
Row (
|
||||||
|
verticalAlignment = Alignment.CenterVertically,
|
||||||
|
modifier = Modifier.clickable {
|
||||||
|
opponentShy = setRadiosFalse()
|
||||||
|
}
|
||||||
|
){
|
||||||
|
RadioButton(
|
||||||
|
selected = opponentShy,
|
||||||
|
onClick = { opponentShy = setRadiosFalse() },
|
||||||
|
)
|
||||||
|
Text(
|
||||||
|
text = stringResource(id = R.string.opponent_shy),
|
||||||
|
fontSize = 16.sp
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
){
|
|
||||||
RadioButton(
|
|
||||||
selected = opponentRandom,
|
|
||||||
onClick = { opponentRandom = setRadiosFalse() },
|
|
||||||
)
|
|
||||||
Text(
|
|
||||||
text = stringResource(id = R.string.opponent_random),
|
|
||||||
fontSize = 16.sp
|
|
||||||
)
|
|
||||||
}
|
|
||||||
Row (
|
|
||||||
verticalAlignment = Alignment.CenterVertically,
|
|
||||||
modifier = Modifier.clickable {
|
|
||||||
opponentHard = setRadiosFalse()
|
|
||||||
}
|
|
||||||
){
|
|
||||||
RadioButton(
|
|
||||||
selected = opponentHard,
|
|
||||||
onClick = { opponentHard = setRadiosFalse() },
|
|
||||||
)
|
|
||||||
Text(
|
|
||||||
text = stringResource(id = R.string.opponent_hard),
|
|
||||||
fontSize = 16.sp
|
|
||||||
)
|
|
||||||
}
|
|
||||||
Row (
|
|
||||||
verticalAlignment = Alignment.CenterVertically,
|
|
||||||
modifier = Modifier.clickable {
|
|
||||||
opponentEasy = setRadiosFalse()
|
|
||||||
}
|
|
||||||
){
|
|
||||||
RadioButton(
|
|
||||||
selected = opponentEasy,
|
|
||||||
onClick = { opponentEasy = setRadiosFalse() },
|
|
||||||
)
|
|
||||||
Text(
|
|
||||||
text = stringResource(id = R.string.opponent_easy),
|
|
||||||
fontSize = 16.sp
|
|
||||||
)
|
|
||||||
}
|
|
||||||
Row (
|
|
||||||
verticalAlignment = Alignment.CenterVertically,
|
|
||||||
modifier = Modifier.clickable {
|
|
||||||
opponentAnnoying = setRadiosFalse()
|
|
||||||
}
|
|
||||||
){
|
|
||||||
RadioButton(
|
|
||||||
selected = opponentAnnoying,
|
|
||||||
onClick = { opponentAnnoying = setRadiosFalse() },
|
|
||||||
)
|
|
||||||
Text(
|
|
||||||
text = stringResource(id = R.string.opponent_annoying),
|
|
||||||
fontSize = 16.sp
|
|
||||||
)
|
|
||||||
}
|
|
||||||
Row (
|
|
||||||
verticalAlignment = Alignment.CenterVertically,
|
|
||||||
modifier = Modifier.clickable {
|
|
||||||
opponentShy = setRadiosFalse()
|
|
||||||
}
|
|
||||||
){
|
|
||||||
RadioButton(
|
|
||||||
selected = opponentShy,
|
|
||||||
onClick = { opponentShy = setRadiosFalse() },
|
|
||||||
)
|
|
||||||
Text(
|
|
||||||
text = stringResource(id = R.string.opponent_shy),
|
|
||||||
fontSize = 16.sp
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Spacer(modifier = Modifier.weight(.05f))
|
Spacer(modifier = Modifier.weight(.05f))
|
||||||
@@ -632,10 +656,10 @@ fun playWeightedMove(grid: MutableList<String>, behavior: Int, piece: String) :
|
|||||||
// Easy, does not prevent human from winning and may try to win.
|
// Easy, does not prevent human from winning and may try to win.
|
||||||
0 -> {
|
0 -> {
|
||||||
causeWin = 100
|
causeWin = 100
|
||||||
preventLoss = -1
|
preventLoss = -25
|
||||||
middle = 1
|
middle = 0
|
||||||
corner = 1
|
corner = 0
|
||||||
side = 1
|
side = 0
|
||||||
}
|
}
|
||||||
// Hard, will try to win for itself and prevent the human from winning.
|
// Hard, will try to win for itself and prevent the human from winning.
|
||||||
1 -> {
|
1 -> {
|
||||||
@@ -647,7 +671,7 @@ fun playWeightedMove(grid: MutableList<String>, behavior: Int, piece: String) :
|
|||||||
}
|
}
|
||||||
// Annoying / stubborn, will not let you win but also will not try to win.
|
// Annoying / stubborn, will not let you win but also will not try to win.
|
||||||
2 -> {
|
2 -> {
|
||||||
causeWin = 99
|
causeWin = -25
|
||||||
preventLoss = 100
|
preventLoss = 100
|
||||||
middle = 4
|
middle = 4
|
||||||
corner = 3
|
corner = 3
|
||||||
@@ -655,11 +679,11 @@ fun playWeightedMove(grid: MutableList<String>, behavior: Int, piece: String) :
|
|||||||
}
|
}
|
||||||
// Shy, refuses to complete the game unless it's the only move left.
|
// Shy, refuses to complete the game unless it's the only move left.
|
||||||
3 -> {
|
3 -> {
|
||||||
causeWin = -1
|
causeWin = -25
|
||||||
preventLoss = -1
|
preventLoss = -25
|
||||||
middle = 1
|
middle = 4
|
||||||
corner = 1
|
corner = 3
|
||||||
side = 1
|
side = 2
|
||||||
}
|
}
|
||||||
// Random! No need for the other function anymore. ;)
|
// Random! No need for the other function anymore. ;)
|
||||||
else -> {
|
else -> {
|
||||||
@@ -680,132 +704,131 @@ fun playWeightedMove(grid: MutableList<String>, behavior: Int, piece: String) :
|
|||||||
|
|
||||||
// Top Row, Win Conditions
|
// Top Row, Win Conditions
|
||||||
if (grid[0] == piece && grid[1] == piece && grid[2].isBlank())
|
if (grid[0] == piece && grid[1] == piece && grid[2].isBlank())
|
||||||
weights[2] = causeWin
|
weights[2] += causeWin
|
||||||
if (grid[0] == piece && grid[1].isBlank() && grid[2] == piece)
|
if (grid[0] == piece && grid[1].isBlank() && grid[2] == piece)
|
||||||
weights[1] = causeWin
|
weights[1] += causeWin
|
||||||
if (grid[0].isBlank() && grid[1] == piece && grid[2] == piece)
|
if (grid[0].isBlank() && grid[1] == piece && grid[2] == piece)
|
||||||
weights[0] = causeWin
|
weights[0] += causeWin
|
||||||
|
|
||||||
// Top Row, Lose Conditions
|
// Top Row, Lose Conditions
|
||||||
if (grid[0] == human && grid[1] == human && grid[2].isBlank())
|
if (grid[0] == human && grid[1] == human && grid[2].isBlank())
|
||||||
weights[2] = preventLoss
|
weights[2] += preventLoss
|
||||||
if (grid[0] == human && grid[1].isBlank() && grid[2] == human)
|
if (grid[0] == human && grid[1].isBlank() && grid[2] == human)
|
||||||
weights[1] = preventLoss
|
weights[1] += preventLoss
|
||||||
if (grid[0].isBlank() && grid[1] == human && grid[2] == human)
|
if (grid[0].isBlank() && grid[1] == human && grid[2] == human)
|
||||||
weights[0] = preventLoss
|
weights[0] += preventLoss
|
||||||
|
|
||||||
// Middle Row, Win Conditions
|
// Middle Row, Win Conditions
|
||||||
if (grid[3] == piece && grid[4] == piece && grid[5].isBlank())
|
if (grid[3] == piece && grid[4] == piece && grid[5].isBlank())
|
||||||
weights[5] = causeWin
|
weights[5] += causeWin
|
||||||
if (grid[3] == piece && grid[4].isBlank() && grid[5] == piece)
|
if (grid[3] == piece && grid[4].isBlank() && grid[5] == piece)
|
||||||
weights[4] = causeWin
|
weights[4] += causeWin
|
||||||
if (grid[3].isBlank() && grid[4] == piece && grid[5] == piece)
|
if (grid[3].isBlank() && grid[4] == piece && grid[5] == piece)
|
||||||
weights[3] = causeWin
|
weights[3] += causeWin
|
||||||
|
|
||||||
// Middle Row, Lose Conditions
|
// Middle Row, Lose Conditions
|
||||||
if (grid[3] == human && grid[4] == human && grid[5].isBlank())
|
if (grid[3] == human && grid[4] == human && grid[5].isBlank())
|
||||||
weights[5] = preventLoss
|
weights[5] += preventLoss
|
||||||
if (grid[3] == human && grid[4].isBlank() && grid[5] == human)
|
if (grid[3] == human && grid[4].isBlank() && grid[5] == human)
|
||||||
weights[4] = preventLoss
|
weights[4] += preventLoss
|
||||||
if (grid[3].isBlank() && grid[4] == human && grid[5] == human)
|
if (grid[3].isBlank() && grid[4] == human && grid[5] == human)
|
||||||
weights[3] = preventLoss
|
weights[3] += preventLoss
|
||||||
|
|
||||||
// Bottom Row, Win Conditions
|
// Bottom Row, Win Conditions
|
||||||
if (grid[6] == piece && grid[7] == piece && grid[8].isBlank())
|
if (grid[6] == piece && grid[7] == piece && grid[8].isBlank())
|
||||||
weights[8] = causeWin
|
weights[8] += causeWin
|
||||||
if (grid[6] == piece && grid[7].isBlank() && grid[8] == piece)
|
if (grid[6] == piece && grid[7].isBlank() && grid[8] == piece)
|
||||||
weights[7] = causeWin
|
weights[7] += causeWin
|
||||||
if (grid[6].isBlank() && grid[7] == piece && grid[8] == piece)
|
if (grid[6].isBlank() && grid[7] == piece && grid[8] == piece)
|
||||||
weights[6] = causeWin
|
weights[6] += causeWin
|
||||||
|
|
||||||
// Bottom Row, Lose Conditions
|
// Bottom Row, Lose Conditions
|
||||||
if (grid[6] == human && grid[7] == human && grid[8].isBlank())
|
if (grid[6] == human && grid[7] == human && grid[8].isBlank())
|
||||||
weights[8] = preventLoss
|
weights[8] += preventLoss
|
||||||
if (grid[6] == human && grid[7].isBlank() && grid[8] == human)
|
if (grid[6] == human && grid[7].isBlank() && grid[8] == human)
|
||||||
weights[7] = preventLoss
|
weights[7] += preventLoss
|
||||||
if (grid[6].isBlank() && grid[7] == human && grid[8] == human)
|
if (grid[6].isBlank() && grid[7] == human && grid[8] == human)
|
||||||
weights[6] = preventLoss
|
weights[6] += preventLoss
|
||||||
|
|
||||||
// Left Column, Win Conditions
|
// Left Column, Win Conditions
|
||||||
if (grid[0] == piece && grid[3] == piece && grid[6].isBlank())
|
if (grid[0] == piece && grid[3] == piece && grid[6].isBlank())
|
||||||
weights[6] = causeWin
|
weights[6] += causeWin
|
||||||
if (grid[0] == piece && grid[3].isBlank() && grid[6] == piece)
|
if (grid[0] == piece && grid[3].isBlank() && grid[6] == piece)
|
||||||
weights[3] = causeWin
|
weights[3] += causeWin
|
||||||
if (grid[0].isBlank() && grid[3] == piece && grid[6] == piece)
|
if (grid[0].isBlank() && grid[3] == piece && grid[6] == piece)
|
||||||
weights[0] = causeWin
|
weights[0] += causeWin
|
||||||
|
|
||||||
// Left Column, Lose Conditions
|
// Left Column, Lose Conditions
|
||||||
if (grid[0] == human && grid[3] == human && grid[6].isBlank())
|
if (grid[0] == human && grid[3] == human && grid[6].isBlank())
|
||||||
weights[6] = preventLoss
|
weights[6] += preventLoss
|
||||||
if (grid[0] == human && grid[3].isBlank() && grid[6] == human)
|
if (grid[0] == human && grid[3].isBlank() && grid[6] == human)
|
||||||
weights[3] = preventLoss
|
weights[3] += preventLoss
|
||||||
if (grid[0].isBlank() && grid[3] == human && grid[6] == human)
|
if (grid[0].isBlank() && grid[3] == human && grid[6] == human)
|
||||||
weights[0] = preventLoss
|
weights[0] += preventLoss
|
||||||
|
|
||||||
// Middle Column, Win Conditions
|
// Middle Column, Win Conditions
|
||||||
if (grid[1] == piece && grid[4] == piece && grid[7].isBlank())
|
if (grid[1] == piece && grid[4] == piece && grid[7].isBlank())
|
||||||
weights[7] = causeWin
|
weights[7] += causeWin
|
||||||
if (grid[1] == piece && grid[4].isBlank() && grid[7] == piece)
|
if (grid[1] == piece && grid[4].isBlank() && grid[7] == piece)
|
||||||
weights[4] = causeWin
|
weights[4] += causeWin
|
||||||
if (grid[1].isBlank() && grid[4] == piece && grid[7] == piece)
|
if (grid[1].isBlank() && grid[4] == piece && grid[7] == piece)
|
||||||
weights[1] = causeWin
|
weights[1] += causeWin
|
||||||
|
|
||||||
// Middle Column, Lose Conditions
|
// Middle Column, Lose Conditions
|
||||||
if (grid[1] == human && grid[4] == human && grid[7].isBlank())
|
if (grid[1] == human && grid[4] == human && grid[7].isBlank())
|
||||||
weights[7] = preventLoss
|
weights[7] += preventLoss
|
||||||
if (grid[1] == human && grid[4].isBlank() && grid[7] == human)
|
if (grid[1] == human && grid[4].isBlank() && grid[7] == human)
|
||||||
weights[4] = preventLoss
|
weights[4] += preventLoss
|
||||||
if (grid[1].isBlank() && grid[4] == human && grid[7] == human)
|
if (grid[1].isBlank() && grid[4] == human && grid[7] == human)
|
||||||
weights[1] = preventLoss
|
weights[1] += preventLoss
|
||||||
|
|
||||||
// Right Column, Win Conditions
|
// Right Column, Win Conditions
|
||||||
if (grid[2] == piece && grid[5] == piece && grid[8].isBlank())
|
if (grid[2] == piece && grid[5] == piece && grid[8].isBlank())
|
||||||
weights[8] = causeWin
|
weights[8] += causeWin
|
||||||
if (grid[2] == piece && grid[5].isBlank() && grid[8] == piece)
|
if (grid[2] == piece && grid[5].isBlank() && grid[8] == piece)
|
||||||
weights[5] = causeWin
|
weights[5] += causeWin
|
||||||
if (grid[2].isBlank() && grid[5] == piece && grid[8] == piece)
|
if (grid[2].isBlank() && grid[5] == piece && grid[8] == piece)
|
||||||
weights[2] = causeWin
|
weights[2] += causeWin
|
||||||
|
|
||||||
// Right Column, Lose Conditions
|
// Right Column, Lose Conditions
|
||||||
if (grid[2] == human && grid[5] == human && grid[8].isBlank())
|
if (grid[2] == human && grid[5] == human && grid[8].isBlank())
|
||||||
weights[8] = preventLoss
|
weights[8] += preventLoss
|
||||||
if (grid[2] == human && grid[5].isBlank() && grid[8] == human)
|
if (grid[2] == human && grid[5].isBlank() && grid[8] == human)
|
||||||
weights[5] = preventLoss
|
weights[5] += preventLoss
|
||||||
if (grid[2].isBlank() && grid[5] == human && grid[8] == human)
|
if (grid[2].isBlank() && grid[5] == human && grid[8] == human)
|
||||||
weights[2] = preventLoss
|
weights[2] += preventLoss
|
||||||
|
|
||||||
// Top Left Diagonal, Win Conditions
|
// Top Left Diagonal, Win Conditions
|
||||||
if (grid[0] == piece && grid[4] == piece && grid[8].isBlank())
|
if (grid[0] == piece && grid[4] == piece && grid[8].isBlank())
|
||||||
weights[8] = causeWin
|
weights[8] += causeWin
|
||||||
if (grid[0] == piece && grid[4].isBlank() && grid[8] == piece)
|
if (grid[0] == piece && grid[4].isBlank() && grid[8] == piece)
|
||||||
weights[4] = causeWin
|
weights[4] += causeWin
|
||||||
if (grid[0].isBlank() && grid[4] == piece && grid[8] == piece)
|
if (grid[0].isBlank() && grid[4] == piece && grid[8] == piece)
|
||||||
weights[0] = causeWin
|
weights[0] += causeWin
|
||||||
|
|
||||||
// Top Left Diagonal, Lose Conditions
|
// Top Left Diagonal, Lose Conditions
|
||||||
if (grid[0] == human && grid[4] == human && grid[8].isBlank())
|
if (grid[0] == human && grid[4] == human && grid[8].isBlank())
|
||||||
weights[8] = preventLoss
|
weights[8] += preventLoss
|
||||||
if (grid[0] == human && grid[4].isBlank() && grid[8] == human)
|
if (grid[0] == human && grid[4].isBlank() && grid[8] == human)
|
||||||
weights[4] = preventLoss
|
weights[4] += preventLoss
|
||||||
if (grid[0].isBlank() && grid[4] == human && grid[8] == human)
|
if (grid[0].isBlank() && grid[4] == human && grid[8] == human)
|
||||||
weights[0] = preventLoss
|
weights[0] += preventLoss
|
||||||
|
|
||||||
// Top Right Diagonal, Win Conditions
|
// Top Right Diagonal, Win Conditions
|
||||||
if (grid[2] == piece && grid[4] == piece && grid[6].isBlank())
|
if (grid[2] == piece && grid[4] == piece && grid[6].isBlank())
|
||||||
weights[6] = causeWin
|
weights[6] += causeWin
|
||||||
if (grid[2] == piece && grid[4].isBlank() && grid[6] == piece)
|
if (grid[2] == piece && grid[4].isBlank() && grid[6] == piece)
|
||||||
weights[4] = causeWin
|
weights[4] += causeWin
|
||||||
if (grid[2].isBlank() && grid[4] == piece && grid[6] == piece)
|
if (grid[2].isBlank() && grid[4] == piece && grid[6] == piece)
|
||||||
weights[2] = causeWin
|
weights[2] += causeWin
|
||||||
|
|
||||||
// Top Right Diagonal, Lose Conditions
|
// Top Right Diagonal, Lose Conditions
|
||||||
if (grid[2] == human && grid[4] == human && grid[6].isBlank())
|
if (grid[2] == human && grid[4] == human && grid[6].isBlank())
|
||||||
weights[6] = preventLoss
|
weights[6] += preventLoss
|
||||||
if (grid[2] == human && grid[4].isBlank() && grid[6] == human)
|
if (grid[2] == human && grid[4].isBlank() && grid[6] == human)
|
||||||
weights[4] = preventLoss
|
weights[4] += preventLoss
|
||||||
if (grid[2].isBlank() && grid[4] == human && grid[6] == human)
|
if (grid[2].isBlank() && grid[4] == human && grid[6] == human)
|
||||||
weights[2] = preventLoss
|
weights[2] += preventLoss
|
||||||
|
|
||||||
// */
|
// */
|
||||||
|
|
||||||
// Set all the played pieces to a very low number.
|
// Set all the played pieces to a very low number.
|
||||||
|
|||||||
@@ -0,0 +1,20 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:width="108dp"
|
||||||
|
android:height="108dp"
|
||||||
|
android:viewportWidth="273"
|
||||||
|
android:viewportHeight="168.75">
|
||||||
|
<group android:scaleX="0.46"
|
||||||
|
android:scaleY="0.28434065"
|
||||||
|
android:translateX="73.71"
|
||||||
|
android:translateY="60.38376">
|
||||||
|
<group android:translateY="133.59375">
|
||||||
|
<path android:pathData="M57.375,-102.375L57.375,-0L32.703125,-0L32.703125,-102.375L57.375,-102.375ZM88.171875,-102.375L88.171875,-83.328125L2.609375,-83.328125L2.609375,-102.375L88.171875,-102.375Z"
|
||||||
|
android:fillColor="#333333"/>
|
||||||
|
<path android:pathData="M148.375,-102.375L148.375,0L123.703125,0L123.703125,-102.375L148.375,-102.375ZM179.17188,-102.375L179.17188,-83.328125L93.609375,-83.328125L93.609375,-102.375L179.17188,-102.375Z"
|
||||||
|
android:fillColor="#333333"/>
|
||||||
|
<path android:pathData="M239.375,-102.375L239.375,0L214.70312,0L214.70312,-102.375L239.375,-102.375ZM270.17188,-102.375L270.17188,-83.328125L184.60938,-83.328125L184.60938,-102.375L270.17188,-102.375Z"
|
||||||
|
android:fillColor="#333333"/>
|
||||||
|
</group>
|
||||||
|
</group>
|
||||||
|
</vector>
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
<background android:drawable="@drawable/ic_launcher_background" />
|
<background android:drawable="@color/ic_launcher_background"/>
|
||||||
<foreground android:drawable="@drawable/ic_launcher_foreground" />
|
<foreground android:drawable="@mipmap/ic_launcher_foreground"/>
|
||||||
<monochrome android:drawable="@drawable/ic_launcher_foreground" />
|
<monochrome android:drawable="@drawable/ic_launcher_monochrome"/>
|
||||||
</adaptive-icon>
|
</adaptive-icon>
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
<background android:drawable="@drawable/ic_launcher_background" />
|
<background android:drawable="@color/ic_launcher_background"/>
|
||||||
<foreground android:drawable="@drawable/ic_launcher_foreground" />
|
<foreground android:drawable="@mipmap/ic_launcher_foreground"/>
|
||||||
<monochrome android:drawable="@drawable/ic_launcher_foreground" />
|
<monochrome android:drawable="@drawable/ic_launcher_monochrome"/>
|
||||||
</adaptive-icon>
|
</adaptive-icon>
|
||||||
|
After Width: | Height: | Size: 2.6 KiB |
|
Before Width: | Height: | Size: 1.4 KiB |
|
After Width: | Height: | Size: 1.2 KiB |
|
After Width: | Height: | Size: 2.6 KiB |
|
Before Width: | Height: | Size: 2.8 KiB |
|
After Width: | Height: | Size: 1.8 KiB |
|
Before Width: | Height: | Size: 982 B |
|
After Width: | Height: | Size: 872 B |
|
After Width: | Height: | Size: 1.8 KiB |
|
Before Width: | Height: | Size: 1.7 KiB |
|
After Width: | Height: | Size: 3.7 KiB |
|
Before Width: | Height: | Size: 1.9 KiB |
|
After Width: | Height: | Size: 1.6 KiB |
|
After Width: | Height: | Size: 3.7 KiB |
|
Before Width: | Height: | Size: 3.8 KiB |
|
After Width: | Height: | Size: 6.0 KiB |
|
Before Width: | Height: | Size: 2.8 KiB |
|
After Width: | Height: | Size: 2.3 KiB |
|
After Width: | Height: | Size: 6.0 KiB |
|
Before Width: | Height: | Size: 5.8 KiB |
|
After Width: | Height: | Size: 8.5 KiB |
|
Before Width: | Height: | Size: 3.8 KiB |
|
After Width: | Height: | Size: 3.7 KiB |
|
After Width: | Height: | Size: 8.5 KiB |
|
Before Width: | Height: | Size: 7.6 KiB |
@@ -0,0 +1,4 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<resources>
|
||||||
|
<color name="ic_launcher_background">#333333</color>
|
||||||
|
</resources>
|
||||||
@@ -2,15 +2,15 @@
|
|||||||
<string name="app_name">Tic-Tac-Toe</string>
|
<string name="app_name">Tic-Tac-Toe</string>
|
||||||
|
|
||||||
<string name="opponent_header">Choose your opponent:</string>
|
<string name="opponent_header">Choose your opponent:</string>
|
||||||
<string name="opponent_human">Human - Someone next to you.</string>
|
<string name="opponent_human">Human</string>
|
||||||
<string name="opponent_random">AI : Random - Fills any open spot.</string>
|
<string name="opponent_random">AI : Random</string>
|
||||||
<string name="opponent_hard">AI : Hard - Your typical try-hard.</string>
|
<string name="opponent_hard">AI : Hard</string>
|
||||||
<string name="opponent_easy">AI : Easy - Opportunist, may try to win.</string>
|
<string name="opponent_easy">AI : Easy</string>
|
||||||
<string name="opponent_annoying">AI : Stubborn - Won\'t let you win.</string>
|
<string name="opponent_annoying">AI : Stubborn</string>
|
||||||
<string name="opponent_shy">AI : Shy - Too scared to win.</string>
|
<string name="opponent_shy">AI : Shy</string>
|
||||||
|
|
||||||
<string name="link1_text">Website</string>
|
<string name="link1_text">Website</string>
|
||||||
<string name="link1_uri">https://hyperling.com</string>
|
<string name="link1_uri">https://hyperling.com</string>
|
||||||
<string name="link2_text">GitHub</string>
|
<string name="link2_text">Source Code</string>
|
||||||
<string name="link2_uri">https://github.com/Hyperling/TicTacToeAndroid</string>
|
<string name="link2_uri">https://git.hyperling.com/me/android-tictactoe</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
Before Width: | Height: | Size: 2.5 KiB After Width: | Height: | Size: 2.1 KiB |
@@ -1,5 +1,6 @@
|
|||||||
// Top-level build file where you can add configuration options common to all sub-projects/modules.
|
// Top-level build file where you can add configuration options common to all sub-projects/modules.
|
||||||
plugins {
|
plugins {
|
||||||
alias(libs.plugins.androidApplication) apply false
|
alias(libs.plugins.androidApplication) apply false
|
||||||
alias(libs.plugins.jetbrainsKotlinAndroid) apply false
|
//alias(libs.plugins.jetbrainsKotlinAndroid) apply false
|
||||||
|
alias(libs.plugins.kotlinCompose) apply false
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
AuthorName: 'Chad Michael "Hyperling" Greenwood'
|
||||||
|
AuthorWebSite: 'https://hyperling.com/about/'
|
||||||
|
Donate: 'https://hyperling.com/donate/'
|
||||||
|
Liberapay: 'HyperVegan'
|
||||||
|
Bitcoin: 'bc1qsfe8dkvry3d34kztz449gkq67wq8fu2nkgfkh0'
|
||||||
|
Litecoin: 'ltc1qavmpu5d6ljntxsd6jj548m4yys83zwscl0dzkx'
|
||||||
|
IssueTracker: 'https://hyperling.com/contact/'
|
||||||
|
Categories:
|
||||||
|
- fdroid
|
||||||
|
- hyperling
|
||||||
|
- games
|
||||||
|
Name: Tic-Tac-Toe
|
||||||
|
AuthorEmail: 'me+tictactoe@hyperling.com'
|
||||||
|
Summary: 'Play against a friend or a range of AIs. Written to practice Kotlin/Compose.'
|
||||||
|
SourceCode: 'https://git.hyperling.com/me/android-tictactoe/'
|
||||||
|
WebSite: 'https://hyperling.com/apps/#tictactoe'
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
#This file is generated by updateDaemonJvm
|
||||||
|
toolchainUrl.FREE_BSD.AARCH64=https\://api.foojay.io/disco/v3.0/ids/cf726b4a1c84b50457225f9bba6d7650/redirect
|
||||||
|
toolchainUrl.FREE_BSD.X86_64=https\://api.foojay.io/disco/v3.0/ids/fa1e318c287360478e3c83a9a3ef1007/redirect
|
||||||
|
toolchainUrl.LINUX.AARCH64=https\://api.foojay.io/disco/v3.0/ids/cf726b4a1c84b50457225f9bba6d7650/redirect
|
||||||
|
toolchainUrl.LINUX.X86_64=https\://api.foojay.io/disco/v3.0/ids/fa1e318c287360478e3c83a9a3ef1007/redirect
|
||||||
|
toolchainUrl.MAC_OS.AARCH64=https\://api.foojay.io/disco/v3.0/ids/c2dd35c9d0aaf0ba6ad0791320f99dfc/redirect
|
||||||
|
toolchainUrl.MAC_OS.X86_64=https\://api.foojay.io/disco/v3.0/ids/e5810bd7fd1f8a586644409d395a7e55/redirect
|
||||||
|
toolchainUrl.UNIX.AARCH64=https\://api.foojay.io/disco/v3.0/ids/cf726b4a1c84b50457225f9bba6d7650/redirect
|
||||||
|
toolchainUrl.UNIX.X86_64=https\://api.foojay.io/disco/v3.0/ids/fa1e318c287360478e3c83a9a3ef1007/redirect
|
||||||
|
toolchainUrl.WINDOWS.AARCH64=https\://api.foojay.io/disco/v3.0/ids/7b3c4877c0749019e6805bb61e421497/redirect
|
||||||
|
toolchainUrl.WINDOWS.X86_64=https\://api.foojay.io/disco/v3.0/ids/d76df094a9cbbabd3b08251f9e61444a/redirect
|
||||||
|
toolchainVersion=25
|
||||||
@@ -1,13 +1,13 @@
|
|||||||
[versions]
|
[versions]
|
||||||
agp = "8.3.1"
|
agp = "9.5.0"
|
||||||
kotlin = "1.9.0"
|
kotlin = "2.4.21"
|
||||||
coreKtx = "1.10.1"
|
coreKtx = "1.19.1"
|
||||||
junit = "4.13.2"
|
junit = "4.13.2"
|
||||||
junitVersion = "1.1.5"
|
junitVersion = "1.3.0"
|
||||||
espressoCore = "3.5.1"
|
espressoCore = "3.7.0"
|
||||||
lifecycleRuntimeKtx = "2.6.1"
|
lifecycleRuntimeKtx = "2.11.0"
|
||||||
activityCompose = "1.7.0"
|
activityCompose = "1.13.0"
|
||||||
composeBom = "2023.08.00"
|
composeBom = "2026.09.00"
|
||||||
|
|
||||||
[libraries]
|
[libraries]
|
||||||
androidx-core-ktx = { group = "androidx.core", name = "core-ktx", version.ref = "coreKtx" }
|
androidx-core-ktx = { group = "androidx.core", name = "core-ktx", version.ref = "coreKtx" }
|
||||||
@@ -27,5 +27,5 @@ androidx-material3 = { group = "androidx.compose.material3", name = "material3"
|
|||||||
|
|
||||||
[plugins]
|
[plugins]
|
||||||
androidApplication = { id = "com.android.application", version.ref = "agp" }
|
androidApplication = { id = "com.android.application", version.ref = "agp" }
|
||||||
jetbrainsKotlinAndroid = { id = "org.jetbrains.kotlin.android", version.ref = "kotlin" }
|
#jetbrainsKotlinAndroid = { id = "org.jetbrains.kotlin.android", version.ref = "kotlin" }
|
||||||
|
kotlinCompose = { id = "org.jetbrains.kotlin.plugin.compose", version.ref = "kotlin" }
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
#Sat Mar 30 12:28:25 MST 2024
|
#Sun Nov 01 08:44:00 MST 2026
|
||||||
distributionBase=GRADLE_USER_HOME
|
distributionBase=GRADLE_USER_HOME
|
||||||
distributionPath=wrapper/dists
|
distributionPath=wrapper/dists
|
||||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.4-bin.zip
|
distributionUrl=https\://services.gradle.org/distributions/gradle-9.8.2-bin.zip
|
||||||
zipStoreBase=GRADLE_USER_HOME
|
zipStoreBase=GRADLE_USER_HOME
|
||||||
zipStorePath=wrapper/dists
|
zipStorePath=wrapper/dists
|
||||||