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
|
||||
|
||||
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
|
||||
|
||||
|
||||
@@ -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 {
|
||||
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 = 6
|
||||
versionName = "1.1.2"
|
||||
|
||||
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")
|
||||
}
|
||||
@@ -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"
|
||||
|
||||
|
After Width: | Height: | Size: 5.5 KiB |
@@ -7,6 +7,7 @@ import android.util.Log
|
||||
import android.widget.Toast
|
||||
import androidx.activity.ComponentActivity
|
||||
import androidx.activity.compose.setContent
|
||||
import androidx.activity.enableEdgeToEdge
|
||||
import androidx.compose.foundation.clickable
|
||||
import androidx.compose.foundation.layout.*
|
||||
import androidx.compose.material.icons.Icons
|
||||
@@ -28,18 +29,24 @@ import androidx.compose.ui.text.style.TextAlign
|
||||
import androidx.compose.ui.tooling.preview.Devices
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.unit.sp
|
||||
import androidx.core.view.ViewCompat
|
||||
import androidx.core.view.WindowCompat
|
||||
import androidx.core.view.WindowInsetsCompat
|
||||
|
||||
class MainActivity : ComponentActivity() {
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
enableEdgeToEdge()
|
||||
setContent {
|
||||
TicTacToeTheme {
|
||||
Box(Modifier.fillMaxSize().systemBarsPadding()) {
|
||||
Surface {
|
||||
Game()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
@@ -194,8 +201,8 @@ fun Game() {
|
||||
Column(
|
||||
horizontalAlignment = Alignment.CenterHorizontally
|
||||
, verticalArrangement = Arrangement.Center
|
||||
, modifier = Modifier
|
||||
.fillMaxSize()
|
||||
//, modifier = Modifier
|
||||
// .fillMaxSize()
|
||||
) {
|
||||
|
||||
Spacer(modifier = Modifier.weight(0.1f))
|
||||
@@ -346,6 +353,15 @@ fun Game() {
|
||||
fontSize = 16.sp
|
||||
)
|
||||
Spacer(modifier = Modifier.size(5.dp))
|
||||
|
||||
Row(
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
horizontalArrangement = Arrangement.SpaceEvenly
|
||||
) {
|
||||
Column (
|
||||
horizontalAlignment = Alignment.Start,
|
||||
verticalArrangement = Arrangement.Top
|
||||
) {
|
||||
Row (
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
modifier = Modifier.clickable {
|
||||
@@ -361,21 +377,6 @@ fun Game() {
|
||||
fontSize = 16.sp
|
||||
)
|
||||
}
|
||||
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 {
|
||||
@@ -391,21 +392,6 @@ fun Game() {
|
||||
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 {
|
||||
@@ -421,6 +407,42 @@ fun Game() {
|
||||
fontSize = 16.sp
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
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 {
|
||||
@@ -437,6 +459,8 @@ fun Game() {
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
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.
|
||||
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 +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.
|
||||
2 -> {
|
||||
causeWin = 99
|
||||
causeWin = -25
|
||||
preventLoss = 100
|
||||
middle = 4
|
||||
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.
|
||||
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 +704,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>
|
||||
|
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="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>
|
||||
|
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.
|
||||
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
|
||||
}
|
||||
@@ -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]
|
||||
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" }
|
||||
@@ -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
|
||||