21 Commits
Author SHA1 Message Date
me c63416489c icon, fix Android Studio's screw up of the background color, color picker is bugged and fixing it in the XML afterwards did not do any sort of reapply. 2026-11-01 10:11:20 -07:00
me 4a237c8268 Merge pull request '1.1.1' (#2) from dev into main
Reviewed-on: #2
2026-11-01 09:58:58 -07:00
me bb8cc12fb7 icon, import via Android Studio so that it works on all versions of Android. 2026-11-01 09:55:54 -07:00
me b6d95f9268 Update versions and migrate to Kotlin Compose so that app compiles successfully, otherwise was in a stuck failed state due to deprecations. 2026-11-01 09:55:32 -07:00
me cbfa94131b Update Gradle. 2026-10-22 17:31:52 -07:00
me ab8959c3f4 fdroid, add specifier to email and put the field in the app-specific section. 2026-09-29 07:16:39 -07:00
me a1b7f180a2 Add more fdroid details while refactoring the file. 2026-07-04 15:00:56 -07:00
me c984624895 Update issue tracker to be proper HTTP link, use contact page. Change website page to go directly to the app. 2026-07-04 10:45:40 -07:00
me 6f68bc1b04 Add manifest file for fdroid server. 2026-07-03 17:34:51 -07:00
me e7b377bdb9 Merge pull request 'v1.1.0 - Update Android Target; Release Old Commits' (#1) from dev into main
Reviewed-on: #1
2025-08-17 09:35:20 -07:00
me 54dadb1f25 Run AGP Upgrade Assistant. 2025-08-17 09:18:07 -07:00
me f2ede2767d Remove extra whitespace. 2025-07-23 07:47:29 -07:00
me 59af3a2485 Fix location of app and its downloads. 2025-07-23 05:26:05 -07:00
me 5f40507a7d Upgrade gradle version. 2025-07-23 05:25:54 -07:00
me 920ee0d54c Upgrade minor versions since this release will include unreleased game changes. 2025-07-23 05:25:46 -07:00
me f992d25d29 AGP Upgrade Assistant. 2025-01-02 15:34:05 -07:00
me 6eb2811814 Update the GitHub button due to my migration off of there. ;) 2025-01-02 15:21:17 -07:00
me f552cc77a8 Increment the version before making any changes. 2025-01-02 15:20:27 -07:00
me 07cefd2776 Studio upgraded the gradle version. 2024-07-01 15:03:14 -07:00
me 59082be0cf Make the AI a little more consistent by using += instead of =. 2024-04-04 12:13:39 -07:00
me 31703cffb9 Fix UI being too tall for some devices. 2024-04-04 12:06:00 -07:00
41 changed files with 268 additions and 193 deletions

No files matched your search

+2 -2
View File
@@ -8,9 +8,9 @@ and maybe even make the game mad. 🐇🥚
## 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
[Direct Download](https://hyperling.com/files/apks/TicTacToe.apk).
[Direct Download](https://git.hyperling.com/me/android-tictactoe/releases).
## TODO
+21 -14
View File
@@ -1,18 +1,19 @@
plugins {
alias(libs.plugins.androidApplication)
alias(libs.plugins.jetbrainsKotlinAndroid)
//alias(libs.plugins.jetbrainsKotlinAndroid)
alias(libs.plugins.kotlinCompose)
}
android {
namespace = "com.hyperling.tictactoe"
compileSdk = 34
compileSdk = 37
defaultConfig {
applicationId = "com.hyperling.tictactoe"
minSdk = 21
targetSdk = 34
versionCode = 1
versionName = "1.0"
minSdk = 23
targetSdk = 37
versionCode = 5
versionName = "1.1.1"
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
vectorDrawables {
@@ -22,16 +23,17 @@ android {
buildTypes {
release {
isMinifyEnabled = false
proguardFiles(getDefaultProguardFile("proguard-android-optimize.txt"), "proguard-rules.pro")
isMinifyEnabled = true
isShrinkResources = true
proguardFiles(
getDefaultProguardFile("proguard-android-optimize.txt"),
"proguard-rules.pro"
)
}
}
compileOptions {
sourceCompatibility = JavaVersion.VERSION_1_8
targetCompatibility = JavaVersion.VERSION_1_8
}
kotlinOptions {
jvmTarget = "1.8"
sourceCompatibility = JavaVersion.VERSION_17
targetCompatibility = JavaVersion.VERSION_17
}
buildFeatures {
compose = true
@@ -47,7 +49,6 @@ android {
}
dependencies {
implementation(libs.androidx.core.ktx)
implementation(libs.androidx.lifecycle.runtime.ktx)
implementation(libs.androidx.activity.compose)
@@ -63,4 +64,10 @@ dependencies {
androidTestImplementation(libs.androidx.ui.test.junit4)
debugImplementation(libs.androidx.ui.tooling)
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")
}
+2 -3
View File
@@ -10,8 +10,7 @@
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_icon_ttt"
android:supportsRtl="true"
android:theme="@style/Theme.TicTacToe"
tools:targetApi="31">
android:theme="@style/Theme.TicTacToe">
<activity
android:name=".MainActivity"
android:exported="true"
@@ -27,4 +26,4 @@
</activity>
</application>
</manifest>
</manifest>
Binary file not shown.

After

Width:  |  Height:  |  Size: 5.5 KiB

@@ -194,8 +194,8 @@ fun Game() {
Column(
horizontalAlignment = Alignment.CenterHorizontally
, verticalArrangement = Arrangement.Center
, modifier = Modifier
.fillMaxSize()
//, modifier = Modifier
// .fillMaxSize()
) {
Spacer(modifier = Modifier.weight(0.1f))
@@ -346,95 +346,112 @@ fun Game() {
fontSize = 16.sp
)
Spacer(modifier = Modifier.size(5.dp))
Row (
Row(
verticalAlignment = Alignment.CenterVertically,
modifier = Modifier.clickable {
opponentHuman = setRadiosFalse()
horizontalArrangement = Arrangement.SpaceEvenly
) {
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(
selected = opponentHuman,
onClick = { opponentHuman = setRadiosFalse() },
)
Text(
text = stringResource(id = R.string.opponent_human),
fontSize = 16.sp
)
}
Row (
verticalAlignment = Alignment.CenterVertically,
modifier = Modifier.clickable {
opponentRandom = setRadiosFalse()
Column (
horizontalAlignment = Alignment.Start,
verticalArrangement = Arrangement.Bottom
) {
Row (
verticalAlignment = Alignment.CenterVertically,
modifier = Modifier.clickable {
opponentRandom = setRadiosFalse()
}
){
RadioButton(
selected = opponentRandom,
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))
@@ -632,10 +649,10 @@ fun playWeightedMove(grid: MutableList<String>, behavior: Int, piece: String) :
// Easy, does not prevent human from winning and may try to win.
0 -> {
causeWin = 100
preventLoss = -1
middle = 1
corner = 1
side = 1
preventLoss = -25
middle = 0
corner = 0
side = 0
}
// Hard, will try to win for itself and prevent the human from winning.
1 -> {
@@ -647,7 +664,7 @@ fun playWeightedMove(grid: MutableList<String>, behavior: Int, piece: String) :
}
// Annoying / stubborn, will not let you win but also will not try to win.
2 -> {
causeWin = 99
causeWin = -25
preventLoss = 100
middle = 4
corner = 3
@@ -655,11 +672,11 @@ fun playWeightedMove(grid: MutableList<String>, behavior: Int, piece: String) :
}
// Shy, refuses to complete the game unless it's the only move left.
3 -> {
causeWin = -1
preventLoss = -1
middle = 1
corner = 1
side = 1
causeWin = -25
preventLoss = -25
middle = 4
corner = 3
side = 2
}
// Random! No need for the other function anymore. ;)
else -> {
@@ -680,132 +697,131 @@ fun playWeightedMove(grid: MutableList<String>, behavior: Int, piece: String) :
// Top Row, Win Conditions
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)
weights[1] = causeWin
weights[1] += causeWin
if (grid[0].isBlank() && grid[1] == piece && grid[2] == piece)
weights[0] = causeWin
weights[0] += causeWin
// Top Row, Lose Conditions
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)
weights[1] = preventLoss
weights[1] += preventLoss
if (grid[0].isBlank() && grid[1] == human && grid[2] == human)
weights[0] = preventLoss
weights[0] += preventLoss
// Middle Row, Win Conditions
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)
weights[4] = causeWin
weights[4] += causeWin
if (grid[3].isBlank() && grid[4] == piece && grid[5] == piece)
weights[3] = causeWin
weights[3] += causeWin
// Middle Row, Lose Conditions
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)
weights[4] = preventLoss
weights[4] += preventLoss
if (grid[3].isBlank() && grid[4] == human && grid[5] == human)
weights[3] = preventLoss
weights[3] += preventLoss
// Bottom Row, Win Conditions
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)
weights[7] = causeWin
weights[7] += causeWin
if (grid[6].isBlank() && grid[7] == piece && grid[8] == piece)
weights[6] = causeWin
weights[6] += causeWin
// Bottom Row, Lose Conditions
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)
weights[7] = preventLoss
weights[7] += preventLoss
if (grid[6].isBlank() && grid[7] == human && grid[8] == human)
weights[6] = preventLoss
weights[6] += preventLoss
// Left Column, Win Conditions
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)
weights[3] = causeWin
weights[3] += causeWin
if (grid[0].isBlank() && grid[3] == piece && grid[6] == piece)
weights[0] = causeWin
weights[0] += causeWin
// Left Column, Lose Conditions
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)
weights[3] = preventLoss
weights[3] += preventLoss
if (grid[0].isBlank() && grid[3] == human && grid[6] == human)
weights[0] = preventLoss
weights[0] += preventLoss
// Middle Column, Win Conditions
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)
weights[4] = causeWin
weights[4] += causeWin
if (grid[1].isBlank() && grid[4] == piece && grid[7] == piece)
weights[1] = causeWin
weights[1] += causeWin
// Middle Column, Lose Conditions
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)
weights[4] = preventLoss
weights[4] += preventLoss
if (grid[1].isBlank() && grid[4] == human && grid[7] == human)
weights[1] = preventLoss
weights[1] += preventLoss
// Right Column, Win Conditions
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)
weights[5] = causeWin
weights[5] += causeWin
if (grid[2].isBlank() && grid[5] == piece && grid[8] == piece)
weights[2] = causeWin
weights[2] += causeWin
// Right Column, Lose Conditions
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)
weights[5] = preventLoss
weights[5] += preventLoss
if (grid[2].isBlank() && grid[5] == human && grid[8] == human)
weights[2] = preventLoss
weights[2] += preventLoss
// Top Left Diagonal, Win Conditions
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)
weights[4] = causeWin
weights[4] += causeWin
if (grid[0].isBlank() && grid[4] == piece && grid[8] == piece)
weights[0] = causeWin
weights[0] += causeWin
// Top Left Diagonal, Lose Conditions
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)
weights[4] = preventLoss
weights[4] += preventLoss
if (grid[0].isBlank() && grid[4] == human && grid[8] == human)
weights[0] = preventLoss
weights[0] += preventLoss
// Top Right Diagonal, Win Conditions
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)
weights[4] = causeWin
weights[4] += causeWin
if (grid[2].isBlank() && grid[4] == piece && grid[6] == piece)
weights[2] = causeWin
weights[2] += causeWin
// Top Right Diagonal, Lose Conditions
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)
weights[4] = preventLoss
weights[4] += preventLoss
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.
@@ -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"?>
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
<background android:drawable="@drawable/ic_launcher_background" />
<foreground android:drawable="@drawable/ic_launcher_foreground" />
<monochrome android:drawable="@drawable/ic_launcher_foreground" />
<background android:drawable="@color/ic_launcher_background"/>
<foreground android:drawable="@mipmap/ic_launcher_foreground"/>
<monochrome android:drawable="@drawable/ic_launcher_monochrome"/>
</adaptive-icon>
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
<background android:drawable="@drawable/ic_launcher_background" />
<foreground android:drawable="@drawable/ic_launcher_foreground" />
<monochrome android:drawable="@drawable/ic_launcher_foreground" />
<background android:drawable="@color/ic_launcher_background"/>
<foreground android:drawable="@mipmap/ic_launcher_foreground"/>
<monochrome android:drawable="@drawable/ic_launcher_monochrome"/>
</adaptive-icon>
Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 982 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 872 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.5 KiB

Binary file not shown.

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>
+8 -8
View File
@@ -2,15 +2,15 @@
<string name="app_name">Tic-Tac-Toe</string>
<string name="opponent_header">Choose your opponent:</string>
<string name="opponent_human">Human - Someone next to you.</string>
<string name="opponent_random">AI : Random - Fills any open spot.</string>
<string name="opponent_hard">AI : Hard - Your typical try-hard.</string>
<string name="opponent_easy">AI : Easy - Opportunist, may try to win.</string>
<string name="opponent_annoying">AI : Stubborn - Won\'t let you win.</string>
<string name="opponent_shy">AI : Shy - Too scared to win.</string>
<string name="opponent_human">Human</string>
<string name="opponent_random">AI : Random</string>
<string name="opponent_hard">AI : Hard</string>
<string name="opponent_easy">AI : Easy</string>
<string name="opponent_annoying">AI : Stubborn</string>
<string name="opponent_shy">AI : Shy</string>
<string name="link1_text">Website</string>
<string name="link1_uri">https://hyperling.com</string>
<string name="link2_text">GitHub</string>
<string name="link2_uri">https://github.com/Hyperling/TicTacToeAndroid</string>
<string name="link2_text">Source Code</string>
<string name="link2_uri">https://git.hyperling.com/me/android-tictactoe</string>
</resources>
BIN
View File
Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.5 KiB

After

Width:  |  Height:  |  Size: 2.1 KiB

+2 -1
View File
@@ -1,5 +1,6 @@
// Top-level build file where you can add configuration options common to all sub-projects/modules.
plugins {
alias(libs.plugins.androidApplication) apply false
alias(libs.plugins.jetbrainsKotlinAndroid) apply false
//alias(libs.plugins.jetbrainsKotlinAndroid) apply false
alias(libs.plugins.kotlinCompose) apply false
}
+16
View File
@@ -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'
+12
View File
@@ -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
+10 -10
View File
@@ -1,13 +1,13 @@
[versions]
agp = "8.3.1"
kotlin = "1.9.0"
coreKtx = "1.10.1"
agp = "9.5.0"
kotlin = "2.4.21"
coreKtx = "1.19.1"
junit = "4.13.2"
junitVersion = "1.1.5"
espressoCore = "3.5.1"
lifecycleRuntimeKtx = "2.6.1"
activityCompose = "1.7.0"
composeBom = "2023.08.00"
junitVersion = "1.3.0"
espressoCore = "3.7.0"
lifecycleRuntimeKtx = "2.11.0"
activityCompose = "1.13.0"
composeBom = "2026.09.00"
[libraries]
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]
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" }
+2 -2
View File
@@ -1,6 +1,6 @@
#Sat Mar 30 12:28:25 MST 2024
#Sun Nov 01 08:44:00 MST 2026
distributionBase=GRADLE_USER_HOME
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
zipStorePath=wrapper/dists