From aedb86030aa3f2123a659dd93a9f35cbceec187f Mon Sep 17 00:00:00 2001 From: Chad Date: Sun, 31 Mar 2024 18:33:11 -0700 Subject: [PATCH] First Full Release (#1) * Commit default app. * Add future strings. * Start trying to make changes. Laptop is very upset at Android Studio, or vice versa. * Still nothing working. About to restart and not choose Empty Activity, do everything from scratch. Unsure if it's a laptop performance issue or if the default app really comes broken. * Builds successfully now, but still has 21 errors and 3 warnings. Very weird. Emulator will not run, will try a different laptop. * It works!! Still needs some UI enhancements like the buttons being fixed sizes and looking more like a grid but it's completely playable with a friend and may not even have any bugs. ;) * Made the board not shift around when letters are added. Still need to fix the clear board button from shifting all contents up. * UI is done, game is still playable. AIs not functional yet, Random is coded but radio buttons not working. * Reorganization. Turning on the AI logic freezes up the interactive preview and emulator is not working so can't do a real test yet. * Fixed all the warnings. Toasts might work now but preview freezes up when trying to test them. * Everything besides the weighted opponents seem done. Preview is really unhappy. Need to get a device connected. * Got the theme working properly with dark/night. Starting to generate debug APKs for testing on phones. * More work on the random AI after realizing what it was doing. Making the bottom buttons more generic, controlled via strings xml. Layout improvements. Fixing the AI's turn taking ability. Shortening Toast. * Large refactor and some bugfixes. Random AI is working in the preview. Toasts and radio buttons are not, but they do on a real phone. All warnings fixed. * Fix toast having the wrong opponent piece. * Fix radio button areas not all being clickable. Increase link font sizes. Change URIs to be exactly how the browser shows them * Make the toggle switch text clickable. * Game is finished!! Can't find any bugs either. * Change TODO to TBD so Android Studio does not complain. * Force portrait mode. Game is completed, all AI have been tested to work as expected. Cannot find any combinations to crash the app. * Add app art. * Ignore keystores. * Be more specific about keystores. * Don't include release files. * Add information to README. * Change X and O formatting. * Fix direct download URI. --- .gitignore | 5 + README.md | 17 +- app/.gitignore | 1 + app/build.gradle.kts | 66 ++ app/proguard-rules.pro | 21 + .../tictactoe/ExampleInstrumentedTest.kt | 24 + app/src/main/AndroidManifest.xml | 30 + app/src/main/ic_icon_ttt-playstore.png | Bin 0 -> 5610 bytes .../com/hyperling/tictactoe/MainActivity.kt | 838 ++++++++++++++++++ .../com/hyperling/tictactoe/ui/theme/Color.kt | 11 + .../com/hyperling/tictactoe/ui/theme/Theme.kt | 70 ++ .../com/hyperling/tictactoe/ui/theme/Type.kt | 34 + .../drawable-v24/ic_launcher_foreground.xml | 30 + .../res/drawable/ic_icon_ttt_background.xml | 74 ++ .../res/drawable/ic_launcher_background.xml | 170 ++++ .../res/mipmap-anydpi-v26/ic_icon_ttt.xml | 5 + .../mipmap-anydpi-v26/ic_icon_ttt_round.xml | 5 + .../res/mipmap-anydpi-v26/ic_launcher.xml | 6 + .../mipmap-anydpi-v26/ic_launcher_round.xml | 6 + app/src/main/res/mipmap-hdpi/ic_icon_ttt.webp | Bin 0 -> 866 bytes .../mipmap-hdpi/ic_icon_ttt_foreground.webp | Bin 0 -> 372 bytes .../res/mipmap-hdpi/ic_icon_ttt_round.webp | Bin 0 -> 2390 bytes app/src/main/res/mipmap-hdpi/ic_launcher.webp | Bin 0 -> 1404 bytes .../res/mipmap-hdpi/ic_launcher_round.webp | Bin 0 -> 2898 bytes app/src/main/res/mipmap-mdpi/ic_icon_ttt.webp | Bin 0 -> 794 bytes .../mipmap-mdpi/ic_icon_ttt_foreground.webp | Bin 0 -> 334 bytes .../res/mipmap-mdpi/ic_icon_ttt_round.webp | Bin 0 -> 1642 bytes app/src/main/res/mipmap-mdpi/ic_launcher.webp | Bin 0 -> 982 bytes .../res/mipmap-mdpi/ic_launcher_round.webp | Bin 0 -> 1772 bytes .../main/res/mipmap-xhdpi/ic_icon_ttt.webp | Bin 0 -> 1152 bytes .../mipmap-xhdpi/ic_icon_ttt_foreground.webp | Bin 0 -> 374 bytes .../res/mipmap-xhdpi/ic_icon_ttt_round.webp | Bin 0 -> 3204 bytes .../main/res/mipmap-xhdpi/ic_launcher.webp | Bin 0 -> 1900 bytes .../res/mipmap-xhdpi/ic_launcher_round.webp | Bin 0 -> 3918 bytes .../main/res/mipmap-xxhdpi/ic_icon_ttt.webp | Bin 0 -> 1330 bytes .../mipmap-xxhdpi/ic_icon_ttt_foreground.webp | Bin 0 -> 422 bytes .../res/mipmap-xxhdpi/ic_icon_ttt_round.webp | Bin 0 -> 4688 bytes .../main/res/mipmap-xxhdpi/ic_launcher.webp | Bin 0 -> 2884 bytes .../res/mipmap-xxhdpi/ic_launcher_round.webp | Bin 0 -> 5914 bytes .../main/res/mipmap-xxxhdpi/ic_icon_ttt.webp | Bin 0 -> 1644 bytes .../ic_icon_ttt_foreground.webp | Bin 0 -> 480 bytes .../res/mipmap-xxxhdpi/ic_icon_ttt_round.webp | Bin 0 -> 6272 bytes .../main/res/mipmap-xxxhdpi/ic_launcher.webp | Bin 0 -> 3844 bytes .../res/mipmap-xxxhdpi/ic_launcher_round.webp | Bin 0 -> 7778 bytes app/src/main/res/values/colors.xml | 10 + app/src/main/res/values/strings.xml | 16 + app/src/main/res/values/themes.xml | 5 + app/src/main/res/xml/backup_rules.xml | 13 + .../main/res/xml/data_extraction_rules.xml | 19 + .../hyperling/tictactoe/ExampleUnitTest.kt | 17 + art/drawing01.xcf | Bin 0 -> 48507 bytes art/drawing02.xcf | Bin 0 -> 49586 bytes art/drawing02_Circle.png | Bin 0 -> 10045 bytes art/drawing02_Circle.xcf | Bin 0 -> 63006 bytes art/drawing03_Circle.png | Bin 0 -> 10003 bytes art/drawing03_Circle.xcf | Bin 0 -> 61670 bytes art/drawing04_Circle.png | Bin 0 -> 10136 bytes art/drawing04_Circle.xcf | Bin 0 -> 59514 bytes art/drawing05.png | Bin 0 -> 2541 bytes art/drawing05.xcf | Bin 0 -> 45690 bytes art/drawing05_Circle.png | Bin 0 -> 10185 bytes art/drawing05_Circle.xcf | Bin 0 -> 58914 bytes build.gradle.kts | 5 + gradle.properties | 23 + gradle/libs.versions.toml | 31 + gradle/wrapper/gradle-wrapper.jar | Bin 0 -> 59203 bytes gradle/wrapper/gradle-wrapper.properties | 6 + gradlew | 185 ++++ gradlew.bat | 89 ++ settings.gradle.kts | 23 + 70 files changed, 1854 insertions(+), 1 deletion(-) create mode 100644 app/.gitignore create mode 100644 app/build.gradle.kts create mode 100644 app/proguard-rules.pro create mode 100644 app/src/androidTest/java/com/hyperling/tictactoe/ExampleInstrumentedTest.kt create mode 100644 app/src/main/AndroidManifest.xml create mode 100644 app/src/main/ic_icon_ttt-playstore.png create mode 100644 app/src/main/java/com/hyperling/tictactoe/MainActivity.kt create mode 100644 app/src/main/java/com/hyperling/tictactoe/ui/theme/Color.kt create mode 100644 app/src/main/java/com/hyperling/tictactoe/ui/theme/Theme.kt create mode 100644 app/src/main/java/com/hyperling/tictactoe/ui/theme/Type.kt create mode 100644 app/src/main/res/drawable-v24/ic_launcher_foreground.xml create mode 100644 app/src/main/res/drawable/ic_icon_ttt_background.xml create mode 100644 app/src/main/res/drawable/ic_launcher_background.xml create mode 100644 app/src/main/res/mipmap-anydpi-v26/ic_icon_ttt.xml create mode 100644 app/src/main/res/mipmap-anydpi-v26/ic_icon_ttt_round.xml create mode 100644 app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml create mode 100644 app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml create mode 100644 app/src/main/res/mipmap-hdpi/ic_icon_ttt.webp create mode 100644 app/src/main/res/mipmap-hdpi/ic_icon_ttt_foreground.webp create mode 100644 app/src/main/res/mipmap-hdpi/ic_icon_ttt_round.webp create mode 100644 app/src/main/res/mipmap-hdpi/ic_launcher.webp create mode 100644 app/src/main/res/mipmap-hdpi/ic_launcher_round.webp create mode 100644 app/src/main/res/mipmap-mdpi/ic_icon_ttt.webp create mode 100644 app/src/main/res/mipmap-mdpi/ic_icon_ttt_foreground.webp create mode 100644 app/src/main/res/mipmap-mdpi/ic_icon_ttt_round.webp create mode 100644 app/src/main/res/mipmap-mdpi/ic_launcher.webp create mode 100644 app/src/main/res/mipmap-mdpi/ic_launcher_round.webp create mode 100644 app/src/main/res/mipmap-xhdpi/ic_icon_ttt.webp create mode 100644 app/src/main/res/mipmap-xhdpi/ic_icon_ttt_foreground.webp create mode 100644 app/src/main/res/mipmap-xhdpi/ic_icon_ttt_round.webp create mode 100644 app/src/main/res/mipmap-xhdpi/ic_launcher.webp create mode 100644 app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp create mode 100644 app/src/main/res/mipmap-xxhdpi/ic_icon_ttt.webp create mode 100644 app/src/main/res/mipmap-xxhdpi/ic_icon_ttt_foreground.webp create mode 100644 app/src/main/res/mipmap-xxhdpi/ic_icon_ttt_round.webp create mode 100644 app/src/main/res/mipmap-xxhdpi/ic_launcher.webp create mode 100644 app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp create mode 100644 app/src/main/res/mipmap-xxxhdpi/ic_icon_ttt.webp create mode 100644 app/src/main/res/mipmap-xxxhdpi/ic_icon_ttt_foreground.webp create mode 100644 app/src/main/res/mipmap-xxxhdpi/ic_icon_ttt_round.webp create mode 100644 app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp create mode 100644 app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp create mode 100644 app/src/main/res/values/colors.xml create mode 100644 app/src/main/res/values/strings.xml create mode 100644 app/src/main/res/values/themes.xml create mode 100644 app/src/main/res/xml/backup_rules.xml create mode 100644 app/src/main/res/xml/data_extraction_rules.xml create mode 100644 app/src/test/java/com/hyperling/tictactoe/ExampleUnitTest.kt create mode 100644 art/drawing01.xcf create mode 100644 art/drawing02.xcf create mode 100644 art/drawing02_Circle.png create mode 100644 art/drawing02_Circle.xcf create mode 100644 art/drawing03_Circle.png create mode 100644 art/drawing03_Circle.xcf create mode 100644 art/drawing04_Circle.png create mode 100644 art/drawing04_Circle.xcf create mode 100644 art/drawing05.png create mode 100644 art/drawing05.xcf create mode 100644 art/drawing05_Circle.png create mode 100644 art/drawing05_Circle.xcf create mode 100644 build.gradle.kts create mode 100644 gradle.properties create mode 100644 gradle/libs.versions.toml create mode 100644 gradle/wrapper/gradle-wrapper.jar create mode 100644 gradle/wrapper/gradle-wrapper.properties create mode 100755 gradlew create mode 100644 gradlew.bat create mode 100644 settings.gradle.kts diff --git a/.gitignore b/.gitignore index 347e252..60ffe4f 100644 --- a/.gitignore +++ b/.gitignore @@ -31,3 +31,8 @@ google-services.json # Android Profiling *.hprof +/app/debug/output-metadata.json + +# Ha! +keystore/* +release \ No newline at end of file diff --git a/README.md b/README.md index 8646a6c..01fd259 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,17 @@ # TicTacToeAndroid -Simple tic-tac-toe game for practicing with Android/Kotlin. + +Simple tic-tac-toe game written for practicing Android/Kotlin/Compose. + +Allows player to choose whether they'd like to go first `X` or second `O`, +play with a friend or against a choice of algorithms, +and maybe even make the game mad. 🐇🥚 + +## Download + +App is hosted at [Hyperling.com](https://hyperling.com/home/#tictactoe) where +it is also available for +[Direct Download](https://hyperling.com/files/apks/TicTacToe.apk). + +## TODO + +May add it to F-Droid later if time permits, would like to learn how that works. diff --git a/app/.gitignore b/app/.gitignore new file mode 100644 index 0000000..42afabf --- /dev/null +++ b/app/.gitignore @@ -0,0 +1 @@ +/build \ No newline at end of file diff --git a/app/build.gradle.kts b/app/build.gradle.kts new file mode 100644 index 0000000..a281a7c --- /dev/null +++ b/app/build.gradle.kts @@ -0,0 +1,66 @@ +plugins { + alias(libs.plugins.androidApplication) + alias(libs.plugins.jetbrainsKotlinAndroid) +} + +android { + namespace = "com.hyperling.tictactoe" + compileSdk = 34 + + defaultConfig { + applicationId = "com.hyperling.tictactoe" + minSdk = 21 + targetSdk = 34 + versionCode = 1 + versionName = "1.0" + + testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" + vectorDrawables { + useSupportLibrary = true + } + } + + buildTypes { + release { + isMinifyEnabled = false + proguardFiles(getDefaultProguardFile("proguard-android-optimize.txt"), "proguard-rules.pro") + } + } + compileOptions { + sourceCompatibility = JavaVersion.VERSION_1_8 + targetCompatibility = JavaVersion.VERSION_1_8 + } + kotlinOptions { + jvmTarget = "1.8" + } + buildFeatures { + compose = true + } + composeOptions { + kotlinCompilerExtensionVersion = "1.5.1" + } + packaging { + resources { + excludes += "/META-INF/{AL2.0,LGPL2.1}" + } + } +} + +dependencies { + + implementation(libs.androidx.core.ktx) + implementation(libs.androidx.lifecycle.runtime.ktx) + implementation(libs.androidx.activity.compose) + implementation(platform(libs.androidx.compose.bom)) + implementation(libs.androidx.ui) + implementation(libs.androidx.ui.graphics) + implementation(libs.androidx.ui.tooling.preview) + implementation(libs.androidx.material3) + testImplementation(libs.junit) + androidTestImplementation(libs.androidx.junit) + androidTestImplementation(libs.androidx.espresso.core) + androidTestImplementation(platform(libs.androidx.compose.bom)) + androidTestImplementation(libs.androidx.ui.test.junit4) + debugImplementation(libs.androidx.ui.tooling) + debugImplementation(libs.androidx.ui.test.manifest) +} \ No newline at end of file diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro new file mode 100644 index 0000000..481bb43 --- /dev/null +++ b/app/proguard-rules.pro @@ -0,0 +1,21 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile \ No newline at end of file diff --git a/app/src/androidTest/java/com/hyperling/tictactoe/ExampleInstrumentedTest.kt b/app/src/androidTest/java/com/hyperling/tictactoe/ExampleInstrumentedTest.kt new file mode 100644 index 0000000..c7eab98 --- /dev/null +++ b/app/src/androidTest/java/com/hyperling/tictactoe/ExampleInstrumentedTest.kt @@ -0,0 +1,24 @@ +package com.hyperling.tictactoe + +import androidx.test.platform.app.InstrumentationRegistry +import androidx.test.ext.junit.runners.AndroidJUnit4 + +import org.junit.Test +import org.junit.runner.RunWith + +import org.junit.Assert.* + +/** + * Instrumented test, which will execute on an Android device. + * + * See [testing documentation](http://d.android.com/tools/testing). + */ +@RunWith(AndroidJUnit4::class) +class ExampleInstrumentedTest { + @Test + fun useAppContext() { + // Context of the app under test. + val appContext = InstrumentationRegistry.getInstrumentation().targetContext + assertEquals("com.hyperling.tictactoe", appContext.packageName) + } +} \ No newline at end of file diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml new file mode 100644 index 0000000..a3e89b7 --- /dev/null +++ b/app/src/main/AndroidManifest.xml @@ -0,0 +1,30 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/ic_icon_ttt-playstore.png b/app/src/main/ic_icon_ttt-playstore.png new file mode 100644 index 0000000000000000000000000000000000000000..65c8bd9f94f43311a94e9a87460c7d18a34f5949 GIT binary patch literal 5610 zcmeHLYfzJC7Cs35@JvohI0Ar0ODwo;L64QvAIt#Hw7`Tr^wP9 zi%*Ct0Y@`rUGH|B@xkrd^Pbjv#qX0~LhzYaTs)EtBXbPSW0T~Z~?d}dxf5ln+AA=yGpJzdA z0-W5JO;J`*=F&C9Z2?pwsfs9><#ti=2WEEr#a~p*(w$0x*LFmy=HXK}0BHD=T zvZaRmn1!0BoNO%Dah~B>Zd3aE3X@2tbewoFA)z5-$q(msglaPo}!bhgIdM$SM}Kf#@~N~ z)T9e?yjFIc>)9jw2m&kNi)0X!aIgm#_XZXwUx1_+Am0b}d12x_Fo$b_UFHTy-t%Nf z1QZWtXY@&!fd$S>8ECc+BdguaulcoskTZ@aTQI zw}^$;nR3%bxhhh$G}g?e3~vXn!mgn{G7YJv)qSFA>1*#yP6Te;7+%DPpTj|15Y)d9 za2W^b-T)s%t_KzZec<=610-PCd)$DX1p8bu;O!2#0-a6&4G@)l%tAq$ut3G=ACuIP zGdW~6{UA|m6)z%wgahX;*#07|5@?xv{u+FL(SDJ`?xRD8$+z~ZxGogZc1Y{)<=t7e#S!8OWc~-G(3$!pX{8z zeb2#?k^RukP}iQ@S=UInDf$eRe&p^ktNCbb^!mhPbG5z8QqOr?dW)=DS5WMp!JLAe zZWa&pUt*rbWbJ{Ro$C__#H|u9cRxJgruh+)&PrLuoNGr(6v{>_( zRl>%n3@|VVu|*ejz9Ez8QKvx;rFO_|Dw7Eq7fr)!J6c z38UcV%#LFXI?ZE84BQa>L+!dKhgnz~;1NYD{AgrvM?l2JLxWVsV%mKr!GhQ_tLh_H z@Y=q)u^;tdr-Z7A8q@82QX)UHxM%tM^wMAT(SLjw`LwPnEF{Lz$`QWx1Qm2H6ec() } + if (grid.isEmpty()) { + for (i in 0..8) { + grid.add("") + } + } + var turn by remember { mutableStateOf("X") } + var lastTurn by remember { mutableStateOf("O") } + + // Hidden flags for determining where we're at. + var status by remember{ mutableIntStateOf(0) } + var gameOver by remember{ mutableStateOf(false) } + var showClear by remember { mutableStateOf(true) } + + // Character pieces. + var player by rememberSaveable { mutableStateOf("X") } + var opponent by rememberSaveable { mutableStateOf("O") } + + // AI choices. + var opponentHuman by rememberSaveable { mutableStateOf(false) } + var opponentRandom by rememberSaveable { mutableStateOf(true) } + var opponentHard by rememberSaveable { mutableStateOf(false) } + var opponentEasy by rememberSaveable { mutableStateOf(false) } + var opponentAnnoying by rememberSaveable { mutableStateOf(false) } + var opponentShy by rememberSaveable { mutableStateOf(false) } + + // Being a goofball. + var mainText by remember { mutableStateOf("") } + var mainClicks by remember { mutableIntStateOf(0) } + // */ + + + /* Helper functions to change global variables in bulk. */ + + // Check if the game has ended. + fun checkStatus() { + if (status != 0) { + if (status == 1) { + msg = "Congratulations, $lastTurn won!" + } else if (status == 2) { + msg = "Tie, better luck next time!" + } + status = 0 + showClear = true + gameOver = true + } + } + + // Place a piece on the board, check for end game, and move to the next player's piece. + fun takeTurn(location: Int) { + lastTurn = turn + + if (!gameOver) { + grid[location] = turn + status = checkGrid(grid) + checkStatus() + turn = changeTurn(turn) + } + } + + // Set all the variables for starting the app near-fresh. + fun createGame() { + for (i in 0..8) { + grid[i] = "" + } + showClear = false + gameOver = false + turn = "X" + lastTurn = "O" + } + + // Toggle whether the primary player goes first or second. + fun togglePlayer() { + when (player) { + "X" -> { player = "O"; opponent = "X" } + "O" -> { player = "X"; opponent = "O" } + } + + if (!gameOver) { + createGame() + if (toastsEnabled) { + Toast.makeText( + context, + "Game has been cleared.", + Toast.LENGTH_SHORT + ).show() + } + } + + if (toastsEnabled) { + Toast.makeText( + context, + "Opponent is now $opponent.", + Toast.LENGTH_SHORT + ).show() + } + } + + // Sets all the radio buttons to false and returns true for the one being changed. + fun setRadiosFalse(): Boolean { + opponentHuman = false + opponentRandom = false + opponentHard = false + opponentEasy = false + opponentAnnoying = false + opponentShy = false + return true + } + // */ + + + /* AI logic. */ + if (turn == opponent && !gameOver) { + var play = -1 + if (opponentRandom) { + play = playWeightedMove(grid, -1, opponent) + } else if (opponentEasy) { + play = playWeightedMove(grid, 0, opponent) + } else if (opponentHard) { + play = playWeightedMove(grid, 1, opponent) + } else if (opponentAnnoying) { + play = playWeightedMove(grid, 2, opponent) + } else if (opponentShy) { + play = playWeightedMove(grid, 3, opponent) + } + if (!opponentHuman) { + takeTurn(play) + } + } + // */ + + + // Main layout object. + Column( + horizontalAlignment = Alignment.CenterHorizontally + , verticalArrangement = Arrangement.Center + , modifier = Modifier + .fillMaxSize() + ) { + + Spacer(modifier = Modifier.weight(0.1f)) + + /* Header text. */ + Column ( + horizontalAlignment = Alignment.CenterHorizontally, + verticalArrangement = Arrangement.Center + ){ + when (mainClicks) { + 0 -> mainText = "Let's play Tic-Tac-Toe!" + 1 -> mainText = "Ouch! Why'd you hit me!?" + 2 -> mainText = "Hey! Stop that!" + 3 -> mainText = "Alright wise guy..." + 4 -> mainText = "Play the game!" + 5 -> mainText = "I'm getting tired of you!" + 6 -> mainText = "Last chance, jerk!!" + 7 -> { + createGame() + opponentHard = setRadiosFalse() + while (!gameOver) { + takeTurn(playWeightedMove(grid, 0, player)) + } + opponentEasy = setRadiosFalse() + mainClicks += 1 + } + 8 -> mainText = "OK, take this! I hope easy bot won!" + 9 -> mainText = "We're done here, play the game!" + 10 -> mainText = "What are you, deaf?" + 11 -> mainText = "You're determined, fella." + 12 -> mainText = "Not much more here, I'm boring." + 13 -> mainText = "Seriously though, bye!" + 14 -> mainText = "Fine, keep clicking, I'll play for you." + 15 -> { + if (gameOver) { createGame() } + takeTurn(playWeightedMove(grid, -1, player)) + mainClicks = 14 + } + else -> mainClicks = 14 + } + Text( + text = mainText, + textAlign = TextAlign.Center, + fontSize = 24.sp, + modifier = Modifier.clickable { + mainClicks++ + } + ) + + if (lastTurn != turn && !gameOver) { + msg = "Player $turn, your turn!" + } + Text( + text = msg, + textAlign = TextAlign.Center, + fontSize = 20.sp, + modifier = Modifier + .padding(10.dp) + ) + } + Spacer(modifier = Modifier.size(10.dp)) + // */ + + /* The Grid */ + Column( + horizontalAlignment = Alignment.CenterHorizontally, + verticalArrangement = Arrangement.Center + ) { + + // OK, this is awesome, thanks Jetbrains Compose. + var count = 0 + for (row in 1..3) { + Row { + for (col in 1..3) { + val index = count + Button( + onClick = { + if (!gameOver && grid[index].isEmpty()) { + takeTurn(index) + } + }, modifier = Modifier + .size(69.dp) + ) { + Text( + text = grid[index], + fontSize = 28.sp, + textAlign = TextAlign.Center + ) + } + count++ + } + } + } + } + Spacer(modifier = Modifier.size(10.dp)) + // */ + + + /* Clear, restart, start new game button. */ + clearText = "Restart" + if (showClear) { + clearText = "Start New Game" + } + Row { + FilledTonalButton(onClick = { createGame() }) { + Text( + text = clearText, fontSize = 16.sp + ) + } + } + Spacer(modifier = Modifier.weight(0.05f)) + // */ + + + /* Allow player to go 2nd (play as O) */ + Row( + verticalAlignment = Alignment.CenterVertically, + modifier = Modifier.clickable { togglePlayer() } + ) { + Text( + text = "Primary user playing as $player.", + fontSize = 16.sp + ) + Spacer(modifier = Modifier.size(5.dp)) + Switch( + checked = (player == "X"), + onCheckedChange = { togglePlayer() } + ) + } + Spacer(modifier = Modifier.weight(0.05f)) + // */ + + + /* Opponent difficulty radio buttons. */ + // TBD: Make an array and build the radio buttons dynamically. + /* + MyRadioChoice { + selected: Boolean, + text: String + } + */ + Column ( + horizontalAlignment = Alignment.Start, + verticalArrangement = Arrangement.Bottom + ){ + Text( + text = stringResource(id = R.string.opponent_header), + fontSize = 16.sp + ) + Spacer(modifier = Modifier.size(5.dp)) + 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 { + 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 { + 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)) + // */ + + + /* Media links. */ + Column( + verticalArrangement = Arrangement.Bottom + ) { + + Row( + verticalAlignment = Alignment.CenterVertically + ) { + val text1 = stringResource(id = R.string.link1_text) + val uri1 = stringResource(id = R.string.link1_uri) + OutlinedButton( + onClick = { + uriHandler.openUri(uri1) + }, + modifier = Modifier + .padding(10.dp) + .weight(0.4f) + ) { + Text( + text = text1, + fontSize = 14.sp + ) + } + + Spacer(modifier = Modifier.weight(0.05f)) + + IconButton( + onClick = { activity?.finish() }, + modifier = Modifier.weight(0.1f) + ) { + Icon( + imageVector = Icons.Rounded.Close + , contentDescription = "Exit" + , modifier = Modifier.size(18.dp) + ) + } + + Spacer(modifier = Modifier.weight(0.05f)) + + val text2 = stringResource(id = R.string.link2_text) + val uri2 = stringResource(id = R.string.link2_uri) + OutlinedButton( + onClick = { + uriHandler.openUri(uri2) + }, + modifier = Modifier + .padding(10.dp) + .weight(0.4f) + ) { + Text( + text = text2, + fontSize = 14.sp + ) + } + } + + } + // */ + } +} + +/* Light Theme * / +@Preview( + name = "Normal" + , showBackground = true + , uiMode = Configuration.UI_MODE_NIGHT_NO + , device = Devices.PIXEL_3A + //, showSystemUi = true +) +// */ +/* Dark Theme */ +@Preview( + name = "Night" + , showBackground = true + , uiMode = Configuration.UI_MODE_NIGHT_YES + , device = Devices.PIXEL_3A + //, showSystemUi = true +) +// */ +@Composable +fun PreviewGame() { + TicTacToeTheme { + Surface { + Game() + } + } +} + +// Check whether any winning conditions have been met. +// Return values: +// 0: False, no victor yet. +// 1: Victory! +// 2: Game ended in a tie. +private fun checkGrid(grid: List): Int { + + // Left column + if (grid[0].isNotBlank() && grid[0] === grid[3] && grid[3] === grid[6]) { + return 1 + } + // Center column + if (grid[1].isNotBlank() && grid[1] == grid[4] && grid[4] === grid[7]) { + return 1 + } + // Right column + if (grid[2].isNotBlank() && grid[2] === grid[5] && grid[5] === grid[8]) { + return 1 + } + + // Top row + if (grid[0].isNotBlank() && grid[0] === grid[1] && grid[1] === grid[2]) { + return 1 + } + // Middle row + if (grid[3].isNotBlank() && grid[3] === grid[4] && grid[4] === grid[5]) { + return 1 + } + // Bottom row + if (grid[6].isNotBlank() && grid[6] === grid[7] && grid[7] === grid[8]) { + return 1 + } + + // Top left to bottom right diagonal + if (grid[0].isNotBlank() && grid[0] === grid[4] && grid[4] === grid[8]) { + return 1 + } + // Top right to bottom left diagonal + if (grid[2].isNotBlank() && grid[2] === grid[4] && grid[4] === grid[6]) { + return 1 + } + + var tie = true + for (item in grid) { + if (item.isBlank()) { + tie = false + break + } + } + if (tie) { return 2 } + + // No end game status yet. + return 0 +} + +// Change which player's turn it is. +private fun changeTurn(turn: String): String { + if (turn == "X") { + return "O" + } + return "X" +} + +/* Random Player * / +private fun playRandomMove(grid: MutableList): Int { + /* + var choice: Int + do { + choice = (0..8).random() + } + while (grid[choice].isNotEmpty()) + return choice + */ + return playWeightedMove(grid, -1, "X") +} +// */ + + +/* AI Players */ +// Behavior determines if the AI is: +// 0 - Plays to lose +// 1 - Plays to win +// 2 - Plays to tie +// * - Random, every open spot has the same weight. +// Returns the grid number which should get the AI's mark. +fun playWeightedMove(grid: MutableList, behavior: Int, piece: String) : Int { + val t = "playWeightedMove" + val d = false + + // Determine who's who. + val human: String = ( if (piece == "X") "O" else "X" ) + + // Custom weights depending on the AI's desire. + val played: Int = -100 + val side : Int + val corner: Int + val middle: Int + val causeWin: Int + val preventLoss: Int + when (behavior) { + // Easy, does not prevent human from winning and may try to win. + 0 -> { + causeWin = 100 + preventLoss = -1 + middle = 1 + corner = 1 + side = 1 + } + // Hard, will try to win for itself and prevent the human from winning. + 1 -> { + causeWin = 100 + preventLoss = 99 + middle = 4 + corner = 3 + side = 2 + } + // Annoying / stubborn, will not let you win but also will not try to win. + 2 -> { + causeWin = 99 + preventLoss = 100 + middle = 4 + corner = 3 + side = 2 + } + // Shy, refuses to complete the game unless it's the only move left. + 3 -> { + causeWin = -1 + preventLoss = -1 + middle = 1 + corner = 1 + side = 1 + } + // Random! No need for the other function anymore. ;) + else -> { + causeWin = 0 + preventLoss = 0 + middle = 0 + corner = 0 + side = 0 + } + } + + // Initialize a blank board's weights. + val weights: IntArray = intArrayOf( + corner, side, corner, side, middle, side, corner, side, corner + ) + + /* Check if any conditions are currently available. */ + + // Top Row, Win Conditions + if (grid[0] == piece && grid[1] == piece && grid[2].isBlank()) + weights[2] = causeWin + if (grid[0] == piece && grid[1].isBlank() && grid[2] == piece) + weights[1] = causeWin + if (grid[0].isBlank() && grid[1] == piece && grid[2] == piece) + weights[0] = causeWin + + // Top Row, Lose Conditions + if (grid[0] == human && grid[1] == human && grid[2].isBlank()) + weights[2] = preventLoss + if (grid[0] == human && grid[1].isBlank() && grid[2] == human) + weights[1] = preventLoss + if (grid[0].isBlank() && grid[1] == human && grid[2] == human) + weights[0] = preventLoss + + // Middle Row, Win Conditions + if (grid[3] == piece && grid[4] == piece && grid[5].isBlank()) + weights[5] = causeWin + if (grid[3] == piece && grid[4].isBlank() && grid[5] == piece) + weights[4] = causeWin + if (grid[3].isBlank() && grid[4] == piece && grid[5] == piece) + weights[3] = causeWin + + // Middle Row, Lose Conditions + if (grid[3] == human && grid[4] == human && grid[5].isBlank()) + weights[5] = preventLoss + if (grid[3] == human && grid[4].isBlank() && grid[5] == human) + weights[4] = preventLoss + if (grid[3].isBlank() && grid[4] == human && grid[5] == human) + weights[3] = preventLoss + + // Bottom Row, Win Conditions + if (grid[6] == piece && grid[7] == piece && grid[8].isBlank()) + weights[8] = causeWin + if (grid[6] == piece && grid[7].isBlank() && grid[8] == piece) + weights[7] = causeWin + if (grid[6].isBlank() && grid[7] == piece && grid[8] == piece) + weights[6] = causeWin + + // Bottom Row, Lose Conditions + if (grid[6] == human && grid[7] == human && grid[8].isBlank()) + weights[8] = preventLoss + if (grid[6] == human && grid[7].isBlank() && grid[8] == human) + weights[7] = preventLoss + if (grid[6].isBlank() && grid[7] == human && grid[8] == human) + weights[6] = preventLoss + + // Left Column, Win Conditions + if (grid[0] == piece && grid[3] == piece && grid[6].isBlank()) + weights[6] = causeWin + if (grid[0] == piece && grid[3].isBlank() && grid[6] == piece) + weights[3] = causeWin + if (grid[0].isBlank() && grid[3] == piece && grid[6] == piece) + weights[0] = causeWin + + // Left Column, Lose Conditions + if (grid[0] == human && grid[3] == human && grid[6].isBlank()) + weights[6] = preventLoss + if (grid[0] == human && grid[3].isBlank() && grid[6] == human) + weights[3] = preventLoss + if (grid[0].isBlank() && grid[3] == human && grid[6] == human) + weights[0] = preventLoss + + // Middle Column, Win Conditions + if (grid[1] == piece && grid[4] == piece && grid[7].isBlank()) + weights[7] = causeWin + if (grid[1] == piece && grid[4].isBlank() && grid[7] == piece) + weights[4] = causeWin + if (grid[1].isBlank() && grid[4] == piece && grid[7] == piece) + weights[1] = causeWin + + // Middle Column, Lose Conditions + if (grid[1] == human && grid[4] == human && grid[7].isBlank()) + weights[7] = preventLoss + if (grid[1] == human && grid[4].isBlank() && grid[7] == human) + weights[4] = preventLoss + if (grid[1].isBlank() && grid[4] == human && grid[7] == human) + weights[1] = preventLoss + + // Right Column, Win Conditions + if (grid[2] == piece && grid[5] == piece && grid[8].isBlank()) + weights[8] = causeWin + if (grid[2] == piece && grid[5].isBlank() && grid[8] == piece) + weights[5] = causeWin + if (grid[2].isBlank() && grid[5] == piece && grid[8] == piece) + weights[2] = causeWin + + // Right Column, Lose Conditions + if (grid[2] == human && grid[5] == human && grid[8].isBlank()) + weights[8] = preventLoss + if (grid[2] == human && grid[5].isBlank() && grid[8] == human) + weights[5] = preventLoss + if (grid[2].isBlank() && grid[5] == human && grid[8] == human) + weights[2] = preventLoss + + // Top Left Diagonal, Win Conditions + if (grid[0] == piece && grid[4] == piece && grid[8].isBlank()) + weights[8] = causeWin + if (grid[0] == piece && grid[4].isBlank() && grid[8] == piece) + weights[4] = causeWin + if (grid[0].isBlank() && grid[4] == piece && grid[8] == piece) + weights[0] = causeWin + + // Top Left Diagonal, Lose Conditions + if (grid[0] == human && grid[4] == human && grid[8].isBlank()) + weights[8] = preventLoss + if (grid[0] == human && grid[4].isBlank() && grid[8] == human) + weights[4] = preventLoss + if (grid[0].isBlank() && grid[4] == human && grid[8] == human) + weights[0] = preventLoss + + // Top Right Diagonal, Win Conditions + if (grid[2] == piece && grid[4] == piece && grid[6].isBlank()) + weights[6] = causeWin + if (grid[2] == piece && grid[4].isBlank() && grid[6] == piece) + weights[4] = causeWin + if (grid[2].isBlank() && grid[4] == piece && grid[6] == piece) + weights[2] = causeWin + + // Top Right Diagonal, Lose Conditions + if (grid[2] == human && grid[4] == human && grid[6].isBlank()) + weights[6] = preventLoss + if (grid[2] == human && grid[4].isBlank() && grid[6] == human) + weights[4] = preventLoss + if (grid[2].isBlank() && grid[4] == human && grid[6] == human) + weights[2] = preventLoss + + // */ + + // Set all the played pieces to a very low number. + for (i in 0..8) { + if (grid[i].isNotBlank()) { + weights[i] = played + } + } + + // Go through the weights, and put the indexes of the highest in a new array. + var highestIndexes: IntArray = intArrayOf() + var heaviest = played + 1 + if (d) Log.d(t, "*** Starting New Calculation ***") + for ((count, weight) in weights.withIndex()) { + if (d) Log.d(t, "count=$count, weight=$weight, heaviest=$heaviest") + if (weight > heaviest) { + heaviest = weight + highestIndexes = intArrayOf(count) + if (d) Log.d(t, "highestIndexes reset. " + highestIndexes.count().toString()) + } else if (weight == heaviest) { + highestIndexes += count + if (d) Log.d(t, "highestIndexes appended. " + highestIndexes.count().toString()) + } + } + + // In case there are multiple indexes with a tied weight, choose a random one. + return highestIndexes[highestIndexes.indices.random()] +} +// */ + diff --git a/app/src/main/java/com/hyperling/tictactoe/ui/theme/Color.kt b/app/src/main/java/com/hyperling/tictactoe/ui/theme/Color.kt new file mode 100644 index 0000000..47e3c85 --- /dev/null +++ b/app/src/main/java/com/hyperling/tictactoe/ui/theme/Color.kt @@ -0,0 +1,11 @@ +package com.hyperling.tictactoe.ui.theme + +import androidx.compose.ui.graphics.Color + +val Purple80 = Color(0xFFD0BCFF) +val PurpleGrey80 = Color(0xFFCCC2DC) +val Pink80 = Color(0xFFEFB8C8) + +val Purple40 = Color(0xFF6650a4) +val PurpleGrey40 = Color(0xFF625b71) +val Pink40 = Color(0xFF7D5260) \ No newline at end of file diff --git a/app/src/main/java/com/hyperling/tictactoe/ui/theme/Theme.kt b/app/src/main/java/com/hyperling/tictactoe/ui/theme/Theme.kt new file mode 100644 index 0000000..d390455 --- /dev/null +++ b/app/src/main/java/com/hyperling/tictactoe/ui/theme/Theme.kt @@ -0,0 +1,70 @@ +package com.hyperling.tictactoe.ui.theme + +import android.app.Activity +import android.os.Build +import androidx.compose.foundation.isSystemInDarkTheme +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.darkColorScheme +import androidx.compose.material3.dynamicDarkColorScheme +import androidx.compose.material3.dynamicLightColorScheme +import androidx.compose.material3.lightColorScheme +import androidx.compose.runtime.Composable +import androidx.compose.runtime.SideEffect +import androidx.compose.ui.graphics.toArgb +import androidx.compose.ui.platform.LocalContext +import androidx.compose.ui.platform.LocalView +import androidx.core.view.WindowCompat + +private val DarkColorScheme = darkColorScheme( + primary = Purple80, + secondary = PurpleGrey80, + tertiary = Pink80 +) + +private val LightColorScheme = lightColorScheme( + primary = Purple40, + secondary = PurpleGrey40, + tertiary = Pink40 + + /* Other default colors to override + background = Color(0xFFFFFBFE), + surface = Color(0xFFFFFBFE), + onPrimary = Color.White, + onSecondary = Color.White, + onTertiary = Color.White, + onBackground = Color(0xFF1C1B1F), + onSurface = Color(0xFF1C1B1F), + */ +) + +@Composable +fun TicTacToeTheme( + darkTheme: Boolean = isSystemInDarkTheme(), + // Dynamic color is available on Android 12+ + dynamicColor: Boolean = true, + content: @Composable () -> Unit +) { + val colorScheme = when { + dynamicColor && Build.VERSION.SDK_INT >= Build.VERSION_CODES.S -> { + val context = LocalContext.current + if (darkTheme) dynamicDarkColorScheme(context) else dynamicLightColorScheme(context) + } + + darkTheme -> DarkColorScheme + else -> LightColorScheme + } + val view = LocalView.current + if (!view.isInEditMode) { + SideEffect { + val window = (view.context as Activity).window + window.statusBarColor = colorScheme.primary.toArgb() + WindowCompat.getInsetsController(window, view).isAppearanceLightStatusBars = darkTheme + } + } + + MaterialTheme( + colorScheme = colorScheme, + typography = Typography, + content = content + ) +} \ No newline at end of file diff --git a/app/src/main/java/com/hyperling/tictactoe/ui/theme/Type.kt b/app/src/main/java/com/hyperling/tictactoe/ui/theme/Type.kt new file mode 100644 index 0000000..725dbd8 --- /dev/null +++ b/app/src/main/java/com/hyperling/tictactoe/ui/theme/Type.kt @@ -0,0 +1,34 @@ +package com.hyperling.tictactoe.ui.theme + +import androidx.compose.material3.Typography +import androidx.compose.ui.text.TextStyle +import androidx.compose.ui.text.font.FontFamily +import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.unit.sp + +// Set of Material typography styles to start with +val Typography = Typography( + bodyLarge = TextStyle( + fontFamily = FontFamily.Default, + fontWeight = FontWeight.Normal, + fontSize = 16.sp, + lineHeight = 24.sp, + letterSpacing = 0.5.sp + ) + /* Other default text styles to override + titleLarge = TextStyle( + fontFamily = FontFamily.Default, + fontWeight = FontWeight.Normal, + fontSize = 22.sp, + lineHeight = 28.sp, + letterSpacing = 0.sp + ), + labelSmall = TextStyle( + fontFamily = FontFamily.Default, + fontWeight = FontWeight.Medium, + fontSize = 11.sp, + lineHeight = 16.sp, + letterSpacing = 0.5.sp + ) + */ +) \ No newline at end of file diff --git a/app/src/main/res/drawable-v24/ic_launcher_foreground.xml b/app/src/main/res/drawable-v24/ic_launcher_foreground.xml new file mode 100644 index 0000000..2b068d1 --- /dev/null +++ b/app/src/main/res/drawable-v24/ic_launcher_foreground.xml @@ -0,0 +1,30 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/ic_icon_ttt_background.xml b/app/src/main/res/drawable/ic_icon_ttt_background.xml new file mode 100644 index 0000000..ca3826a --- /dev/null +++ b/app/src/main/res/drawable/ic_icon_ttt_background.xml @@ -0,0 +1,74 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/drawable/ic_launcher_background.xml b/app/src/main/res/drawable/ic_launcher_background.xml new file mode 100644 index 0000000..07d5da9 --- /dev/null +++ b/app/src/main/res/drawable/ic_launcher_background.xml @@ -0,0 +1,170 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/mipmap-anydpi-v26/ic_icon_ttt.xml b/app/src/main/res/mipmap-anydpi-v26/ic_icon_ttt.xml new file mode 100644 index 0000000..47f02d0 --- /dev/null +++ b/app/src/main/res/mipmap-anydpi-v26/ic_icon_ttt.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/mipmap-anydpi-v26/ic_icon_ttt_round.xml b/app/src/main/res/mipmap-anydpi-v26/ic_icon_ttt_round.xml new file mode 100644 index 0000000..47f02d0 --- /dev/null +++ b/app/src/main/res/mipmap-anydpi-v26/ic_icon_ttt_round.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml b/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml new file mode 100644 index 0000000..6f3b755 --- /dev/null +++ b/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml b/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml new file mode 100644 index 0000000..6f3b755 --- /dev/null +++ b/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/mipmap-hdpi/ic_icon_ttt.webp b/app/src/main/res/mipmap-hdpi/ic_icon_ttt.webp new file mode 100644 index 0000000000000000000000000000000000000000..6e8ce830be2d9ddac1f24aedb4992996d22d8495 GIT binary patch literal 866 zcmV-o1D*U*Nk&Fm0{{S5MM6+kP&iCZ0{{RoN5ByfU*$HoZB^O#KHNRjmgeJ({ z;R)|s6ObcGQY3kH4=f%1Z}pet6gUC+#mrQ2BiVKp^?7Km$v*|+AOTEVY_WRZg=5G1FM`Z+}+;ue+eK8s6#+NKoi;!5D-v$^(b_Dp zB&kdvB+QbkdT)QbFn#c>t*uJZ(bftSNuDKXK`4@>f&%YwlvMR#2cpVl97n(KB}p3s z0;ci54@@7-B_Rof1V{ulP%RiM_mE0M0Vy;Tp-Mn(4Z;lnv=P3tpHu~0NK&A{cT#n% ztySUoZ{t$)$#1zaoN6=lX(MSv2@^TM1oXS zPp*6D*1z|y(#!L|j44VmSdu~`sWO5l1dxVC7lIl}P$(dis>X5q<8|<7(u+I%mdx1g z7r*~!KmV&PJBFf&2}$>xw(Pj{x*Yk;JFn-1)9v2-ZDI9%@x32%4@35&*4`hPTsqYVTiQIcQEn&;zyLc*5 zELeBeoW3=it-JBp1lRJllULAI;=Ug4WOgDIyAt7_MIKubPjH{ zqeCtF(@2B0ygPOx;`UBWAx(|7NF8bsO|5zTpDyU%r757Pusc+f3|1Y@*`aO{IV7%0 zbx zxyzNaYp{)MTgmx`Yfb~yL;nG(yBnKGl2y&ogY<=8!uN0E*LT9{gZU2u)}M43`NC@h z?aCjrjYV%t&5A!KwMZ-DUShu|yy{kF{3>B*s_xX9d^<&>(!c@$fe-=^20}q)0AOKV zY3W!RmH`4%IQo~5*H{^p&OX6LnF0t1Q6;}7{Y1fqm=ecL`9ZSG+38g5?%)6z05AXm z&|m>0Admq#3;-}mz{YN!t=Qe&{(lu?z1bSk{|V6kx&#vc`|p8N?uxdP6Hj$0+Ft(G zoT5p!O=!?GY1V*vD7R2X6U1pe%5p*?Go4rOmzVJzaS<@!KCGodG9nS=ehI*nHcmG@ zw4r^JnCHgo`D2d51rHvqyDQ4-fPRvgy&qUJ7nC)?|NHM_R(8KdOe+fQXG|)L8&eQI SKN?gTWa|Z$5b`_9f06)ASgghX literal 0 HcmV?d00001 diff --git a/app/src/main/res/mipmap-hdpi/ic_icon_ttt_round.webp b/app/src/main/res/mipmap-hdpi/ic_icon_ttt_round.webp new file mode 100644 index 0000000000000000000000000000000000000000..06027e790e9d01ab0aee5bdaf1a846cbe757ecbe GIT binary patch literal 2390 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 IIjk)_1_g+t6#xJL literal 0 HcmV?d00001 diff --git a/app/src/main/res/mipmap-hdpi/ic_launcher.webp b/app/src/main/res/mipmap-hdpi/ic_launcher.webp new file mode 100644 index 0000000000000000000000000000000000000000..c209e78ecd372343283f4157dcfd918ec5165bb3 GIT binary patch literal 1404 zcmV-?1%vuhNk&F=1pok7MM6+kP&il$0000G0000-002h-06|PpNX!5L00Dqw+t%{r zzW2vH!KF=w&cMnnN@{whkTw+#mAh0SV?YL=)3MimFYCWp#fpdtz~8$hD5VPuQgtcN zXl<@<#Cme5f5yr2h%@8TWh?)bSK`O z^Z@d={gn7J{iyxL_y_%J|L>ep{dUxUP8a{byupH&!UNR*OutO~0{*T4q5R6@ApLF! z5{w?Z150gC7#>(VHFJZ-^6O@PYp{t!jH(_Z*nzTK4 zkc{fLE4Q3|mA2`CWQ3{8;gxGizgM!zccbdQoOLZc8hThi-IhN90RFT|zlxh3Ty&VG z?Fe{#9RrRnxzsu|Lg2ddugg7k%>0JeD+{XZ7>Z~{=|M+sh1MF7~ zz>To~`~LVQe1nNoR-gEzkpe{Ak^7{{ZBk2i_<+`Bq<^GB!RYG+z)h;Y3+<{zlMUYd zrd*W4w&jZ0%kBuDZ1EW&KLpyR7r2=}fF2%0VwHM4pUs}ZI2egi#DRMYZPek*^H9YK zay4Iy3WXFG(F14xYsoDA|KXgGc5%2DhmQ1gFCkrgHBm!lXG8I5h*uf{rn48Z!_@ z4Bk6TJAB2CKYqPjiX&mWoW>OPFGd$wqroa($ne7EUK;#3VYkXaew%Kh^3OrMhtjYN?XEoY`tRPQsAkH-DSL^QqyN0>^ zmC>{#F14jz4GeW{pJoRpLFa_*GI{?T93^rX7SPQgT@LbLqpNA}<@2wH;q493)G=1Y z#-sCiRNX~qf3KgiFzB3I>4Z%AfS(3$`-aMIBU+6?gbgDb!)L~A)je+;fR0jWLL-Fu z4)P{c7{B4Hp91&%??2$v9iRSFnuckHUm}or9seH6 z>%NbT+5*@L5(I9j@06@(!{ZI?U0=pKn8uwIg&L{JV14+8s2hnvbRrU|hZCd}IJu7*;;ECgO%8_*W Kmw_-CKmY()leWbG literal 0 HcmV?d00001 diff --git a/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp b/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp new file mode 100644 index 0000000000000000000000000000000000000000..b2dfe3d1ba5cf3ee31b3ecc1ced89044a1f3b7a9 GIT binary patch literal 2898 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 literal 0 HcmV?d00001 diff --git a/app/src/main/res/mipmap-mdpi/ic_icon_ttt.webp b/app/src/main/res/mipmap-mdpi/ic_icon_ttt.webp new file mode 100644 index 0000000000000000000000000000000000000000..f6ae4596b3be445e30a823bab1cf2038e8c24f63 GIT binary patch literal 794 zcmV+#1LgcuNk&Ez0{{S5MM6+kP&iBm0{{RoFTe{B*913`ZPn47D`sZq{4R82>>8~00Jn0fB*y(V3KKDT}h63UIJlxy%ph4 zx@jJxS<#V{k`hSZVwSpQ$&wPd0s9axKt!|RWtKLQQj&oh5Q0Q9FhC##Am9T$fInbK z25P_%5T}*Vnx>sf%#WuJj)~6 zy475H{mLLx1o7_YXcKZ?Vps z2O@w0_Wz$#QV&ZC!2j^$v3!yqzPSF+asK7Jcstex=9XkfYb%)j-Ao1I>shBi-P>}c zFapv6z7Cuj3?zd9!NH ze|MA4r0Z{alZgILfb?CyzENlL-Z?0ca~W!Y?4%sZA{&4c-XS43HjX-n1W8TGLyF8- z;a(vz21SO4QU-wnJf(&YZ<0q83PsdIQJ{-dj&l!Dh_j3+g*bhxv{ag=IXR_SY?A9c znx(&zk}~qu9e;R!5u(11Tw4PG)y9M(^7$Qqnl}J!89Pg7&S1i?<#Az~^QC36VSug8 z^%d-NaxevKF-n;+td5P2bYi<$_kj|2hV{h3p@IFcXl-|Iys^1o&w5*$S`U=~08=cZ zPtSTXQJ~X5PKZLBNp4Y;(%U;kTNVp+#Jz%RG>QxlC0^X(3q!*u7Xe@*^kcX{{th^J z*ZD>;nV0wYBE~AKgb)=BAK_)DmT($tZ@-{Gz@OdV3qW=ta33oT0l1l^jXnA37;k59 Yq^%`aOJuG!x1i3M8f2HpQ!kgkOER@}H2?qr literal 0 HcmV?d00001 diff --git a/app/src/main/res/mipmap-mdpi/ic_icon_ttt_foreground.webp b/app/src/main/res/mipmap-mdpi/ic_icon_ttt_foreground.webp new file mode 100644 index 0000000000000000000000000000000000000000..b0d8b1c6a83ee0812879190d9d6237ba0138d2f1 GIT binary patch literal 334 zcmV-U0kQs4Nk&FS0RRA3MM6+kP&iCE0RR9mYrq;1&%q|LZ71)OlL-vaQX>;FNI(Z= z&fy*#j3UW)GCv1Bh(`hj5WtyJ&ae#IwsEA`ci;Q(zs*nZ^IVz#Fwlx7AQ-_6{wpB+ z&kiG>8!;6K_hO|wV&^aB9n$r?WythN74Z448MC6>44?-WxWNd1@BzRJcJP7;n1M5p z1Y?*WKM_IJa0A)w^Aj1_>+26IjNIw4ms{QZLSL9c+I}3aZQC}R)VAH!sg3{tw2Rny z%GizQ{{#pD{VU@Qn>rkIDe2|;(&Z&+V<##2kaLEDTfHcHr+qT?bV}8-QG64cEO}wx zMS3AmCONWy?ut>cPXMsV5!D8O&P36<0rmRI4?F<1dK|~y88Bvyz!VLL+5{jnrr?cc gvK-PErl71vTen;6pYdtZ!MomM?u|{ij#tn&04eOBAOHXW literal 0 HcmV?d00001 diff --git a/app/src/main/res/mipmap-mdpi/ic_icon_ttt_round.webp b/app/src/main/res/mipmap-mdpi/ic_icon_ttt_round.webp new file mode 100644 index 0000000000000000000000000000000000000000..c8fea5291e4258ba636dee1ba45a808a090524a6 GIT binary patch literal 1642 zcmV-w29^0zNk&Fu1^@t8MM6+kP&iCh1^@srFTe{BHPMZ=ZISGJ7h25BTBgD77Be%W z#b7csvvrxpCWFb$Sg?ytS_T)pf<*lq7B2j=ec!+fzHK+nH@E zPTu$XYp%d{#~is`L$~0WHM4!l-L~!gm-A;EVba=WOdb6r?)yQujh}7*rd*TVYPZ?8 zb;y-%+q5m)wta78BeQMuS((ibu>E4&W_}bu+i&kV`vf3q!g*O-RoqP^G#%4}!Gy~k zxFI%xpGx#}B!71OH;5Ik5v~9*9T^G}3j1X4s@P=SseHM*@!>OvT{;~Z0EDZX1AH?L zBP!PveyE`N$A%Zf_yUeTo(WH7Ud6)93MwNS)6D$SlOBYpg9)gVs61s>5Ea8_&33_N ze&BAvOv(flmaCX-=UK!rR@m>sOC%7^%UKr5%_W?hD;IuYpq!Zo+qMESD!1*q`qptPK^Rbxaop$HW4K~R9O6Dv=tkWdMiZgtsrri!8#Ik9&SeJt>k}=Ma@%* zV{?=rHRQr{ATz~sda5cJsc0-}oIG9fFP+dpOYIY))I)*nJ$ijd5#tNEZcI83vBUCRV^u9d0(5oj;2_Fc; zEy7V_a=F|lb35S~{`{f$#Xj2G+xI`bi#fi0!SaKgBHV@J)v%b;>C~9x^Jl%;uV9tu zn3$S8m2a#dsWIoLPr^~YPfjU>2f{DHZ7!t79ACZ|9ONDm2oGXJ6-#^tO{cbwzo&ED? z%GmIS000+6beNZ1Fz(dNkuhwBFJE30aUfh{ATm?Z9_1hBjXGsZY@U%yu+Pcbf5kt3 z^kf{w7er7Q+x(ktV@}%`$Qh}Gp0I5J8{Rpz>q~)z-mOGTC8vEAv5n|;u}{uOCFG>7 z^XY%G_FVm~ULv@IiR3EI`<&NrhChGIJ{Njv*z@qNi$u!cWpD0xg;p~|q*idInG0!s zHlEj|h4Z^z8KmE-x^qNYW}Ca`-Jo4$h@^6MMfl4%7mAuDX>$ESpna0a*mPcpa`gZI zzq7x6zWdFLK(a33Q9l_20bVw9anmI26q*f+?ee~cjb``IYhyBt&fJ)Hnf>MnUu(Em%<4NoCp;bK?Ky-u5lLiH{n)0?Q)jHBr7O?T>Mc*Hx57pP zHE(FJ{^M9PXMYT3roXu?z|%_3m9lPJnux6bK6YFf=!(Haz<+NxNYV;M$<3`9y`Z>u o?40b{F{qI!Xn6C#dj<;^2798ZY4FE{FX8{%RUZ#-a)gJZ0kZ}uj{pDw literal 0 HcmV?d00001 diff --git a/app/src/main/res/mipmap-mdpi/ic_launcher.webp b/app/src/main/res/mipmap-mdpi/ic_launcher.webp new file mode 100644 index 0000000000000000000000000000000000000000..4f0f1d64e58ba64d180ce43ee13bf9a17835fbca GIT binary patch literal 982 zcmV;{11bDcNk&G_0{{S5MM6+kP&il$0000G0000l001ul06|PpNU8t;00Dqo+t#w^ z^1csucXz7-Qrhzl9HuHB%l>&>1tG2^vb*E&k^T3$FG1eQZ51g$uv4V+kI`0<^1Z@N zk?Jjh$olyC%l>)Xq;7!>{iBj&BjJ`P&$fsCfpve_epJOBkTF?nu-B7D!hO=2ZR}

C%4 zc_9eOXvPbC4kzU8YowIA8cW~Uv|eB&yYwAObSwL2vY~UYI7NXPvf3b+c^?wcs~_t{ ze_m66-0)^{JdOMKPwjpQ@Sna!*?$wTZ~su*tNv7o!gXT!GRgivP}ec?5>l1!7<(rT zds|8x(qGc673zrvYIz;J23FG{9nHMnAuP}NpAED^laz3mAN1sy+NXK)!6v1FxQ;lh zOBLA>$~P3r4b*NcqR;y6pwyhZ3_PiDb|%n1gGjl3ZU}ujInlP{eks-#oA6>rh&g+!f`hv#_%JrgYPu z(U^&XLW^QX7F9Z*SRPpQl{B%x)_AMp^}_v~?j7 zapvHMKxSf*Mtyx8I}-<*UGn3)oHd(nn=)BZ`d$lDBwq_GL($_TPaS{UeevT(AJ`p0 z9%+hQb6z)U9qjbuXjg|dExCLjpS8$VKQ55VsIC%@{N5t{NsW)=hNGI`J=x97_kbz@ E0Of=7!TQj4N+cqN`nQhxvX7dAV-`K|Ub$-q+H-5I?Tx0g9jWxd@A|?POE8`3b8fO$T))xP* z(X?&brZw({`)WU&rdAs1iTa0x6F@PIxJ&&L|dpySV!ID|iUhjCcKz(@mE z!x@~W#3H<)4Ae(4eQJRk`Iz3<1)6^m)0b_4_TRZ+cz#eD3f8V;2r-1fE!F}W zEi0MEkTTx}8i1{`l_6vo0(Vuh0HD$I4SjZ=?^?k82R51bC)2D_{y8mi_?X^=U?2|F{Vr7s!k(AZC$O#ZMyavHhlQ7 zUR~QXuH~#o#>(b$u4?s~HLF*3IcF7023AlwAYudn0FV~|odGH^05AYPEfR)8p`i{n zwg3zPVp{+wOsxKc>)(pMupKF!Y2HoUqQ3|Yu|8lwR=?5zZuhG6J?H`bSNk_wPoM{u zSL{c@pY7+c2kck>`^q1^^gR0QB7Y?KUD{vz-uVX~;V-rW)PDcI)$_UjgVV?S?=oLR zf4}zz{#*R_{LkiJ#0RdQLNC^2Vp%JPEUvG9ra2BVZ92(p9h7Ka@!yf9(lj#}>+|u* z;^_?KWdzkM`6gqPo9;;r6&JEa)}R3X{(CWv?NvgLeOTq$cZXqf7|sPImi-7cS8DCN zGf;DVt3Am`>hH3{4-WzH43Ftx)SofNe^-#|0HdCo<+8Qs!}TZP{HH8~z5n`ExcHuT zDL1m&|DVpIy=xsLO>8k92HcmfSKhflQ0H~9=^-{#!I1g(;+44xw~=* zxvNz35vfsQE)@)Zsp*6_GjYD};Squ83<_?^SbALb{a`j<0Gn%6JY!zhp=Fg}Ga2|8 z52e1WU%^L1}15Ex0fF$e@eCT(()_P zvV?CA%#Sy08_U6VPt4EtmVQraWJX` zh=N|WQ>LgrvF~R&qOfB$!%D3cGv?;Xh_z$z7k&s4N)$WYf*k=|*jCEkO19{h_(%W4 zPuOqbCw`SeAX*R}UUsbVsgtuG?xs(#Ikx9`JZoQFz0n*7ZG@Fv@kZk`gzO$HoA9kN z8U5{-yY zvV{`&WKU2$mZeoBmiJrEdzUZAv1sRxpePdg1)F*X^Y)zp^Y*R;;z~vOv-z&)&G)JQ{m!C9cmziu1^nHA z`#`0c>@PnQ9CJKgC5NjJD8HM3|KC(g5nnCq$n0Gsu_DXk36@ql%npEye|?%RmG)

FJ$wK}0tWNB{uH;AM~i literal 0 HcmV?d00001 diff --git a/app/src/main/res/mipmap-xhdpi/ic_icon_ttt.webp b/app/src/main/res/mipmap-xhdpi/ic_icon_ttt.webp new file mode 100644 index 0000000000000000000000000000000000000000..780212a967f61e9c198159cfa15104b5837d4039 GIT binary patch literal 1152 zcmV-`1b_QdNk&F^1ONb6MM6+kP&iC%1ONapU%(d-uLrlbZPm(J=ev9MfkG&Y=BS5E z!>{+=caSFF*0!x$nfw0#af!(2fz@)AFPSlCb`NgSB`9>x6}SM!#*`TZ?CTX&5GJ-`Yy~UV|Q5|SZMmP{-f#_g1V6qHLCeI`!AYcFklL`rANT{#~ z0RatkkpXFG$WamqLabJ?H8YSh?T=z_Xgv$nXj1ehy4tmH4TBifLckAH zID^{NKF(AhaX0_^>#rNQfF67g=`S%{j44Ky#1u=+vA_&{46vL2eb3-xOvR`oaxiOX z!~i`^5Xjo~6T^A^4v%{#2KU`17VUEKtsef@Z7r{9vE0h{bbB4z$J9*}kP?5qKb@eX zd=4?iVlLnFT*>ZEcE@b@?BQ_qkRMlTbl$p=Rm$JF6f|$o&#o`f4ZCJ$QPjnO42m`; z1cU4#L9g0h?o!`Bf2RITE292{pc}ec|4VERr=R^ZT7Nq}y!6WSZ@R19&F&c0K6=Ig z6FgnNUYX4_dvVbSXlgV)I7i!PruAQ^YsI~TCX4NVTwV{noUTI%hlE?(3rVW6?OEHl zy*pUXbY^Yawr$%sdOd5~w(VcgNUADp=1Wy2qW=>h{bcQErl2kd=RifyiERZ)*tBJ{ z%7w-O7$GxM=+Uiu`6N;D~x)d9~jH&x1Jal~`V zMU|47#gDmO^&6m+C5|`QhU#J<#A+p=SFJ5Q`EIRhc0PEe%(p);?7sKd>XT=dPwf)+ zzh9@CJv+8r-L`s_5Mucwi{~!@;LVDacCXpcUhAL@RDhMZuX`m(cpgcM$Hv7+;WyrQ67ynjkUL%%`I2}R z!gEOPleS=aM6glf3C#1gKz5Ngl}`o-JaCTmO?D%H(Ne_(W}hpkF|U>uvKA9Xw42F& zBb+6I+%<#+eoB!pHGUdQE_X`fb0E`Q9Y}zqTX>M4e}L*W&OmpR$U3;VdxwRFsNDGP SEr3hJxs$Vt>i-Ka{agw+Jt6V{ literal 0 HcmV?d00001 diff --git a/app/src/main/res/mipmap-xhdpi/ic_icon_ttt_foreground.webp b/app/src/main/res/mipmap-xhdpi/ic_icon_ttt_foreground.webp new file mode 100644 index 0000000000000000000000000000000000000000..d35904845fef217bcb8140c6252ea0c70c330ebc GIT binary patch literal 374 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 literal 0 HcmV?d00001 diff --git a/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp b/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp new file mode 100644 index 0000000000000000000000000000000000000000..1b9a6956b3acdc11f40ce2bb3f6efbd845cc243f GIT binary patch literal 3918 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 literal 0 HcmV?d00001 diff --git a/app/src/main/res/mipmap-xxhdpi/ic_icon_ttt_round.webp b/app/src/main/res/mipmap-xxhdpi/ic_icon_ttt_round.webp new file mode 100644 index 0000000000000000000000000000000000000000..fdb55ccad48509c8cb3903e249d16743bd20d51e GIT binary patch literal 4688 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 SW<*5M(lkv|v_wSY(G38UfEd64 literal 0 HcmV?d00001 diff --git a/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp b/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp new file mode 100644 index 0000000000000000000000000000000000000000..28d4b77f9f036a47549d47db79c16788749dca10 GIT binary patch literal 2884 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�(p-{x$&=IACIfoAR!za)F-^da-t3#0Dycnp zwO~NVXwXCl;jE<}>%@xz|=8fIJAB?>+E{7)|4l${4ngA3G|=r z2Dyv;VVWSgZx9Wj>qUjleGl3Ei9K4>h!(lPS%8VOG>Xu0%6VDz^O=bjJmuP7>DeUv zrbI}MlHB^^d?{zv6d=@_ZD2lg1&G7UjnVN{1}9WkaM3H~btX0GtSzB+tZ^qRgWo4m z!GmimlG$=wgXCnr6j@m<1gAL46#T~5Bnm=2{^@>|t&`9mkEPddj zAvG~@Tv~TAm2i%VW}R-g(Z0)z-Y|szHr@rk>4MAyG*Ma*7Yh#H7(!-5>DZ@8r;_dx z{prSe<>~099F8vsYd2xff7uAS%7{S)f(|@me3t2$iy&NEc7OUEchp@9A|X;;IA>8!oX+y(BKJ$EzV* znR$z;!L$s7uy@{OT~nG#B!NRraT8(X##Ho!0r_o@gg0CA-9H^;-uE&?$2$nHv_00o z%cbuUc-tCx$Uh&EZ4Nf4Zgqv)Y6>usG3>GeQnxx_Z6+PcbX-+ysbt1hQ`K1LDpOE? zrAhIZhSN9yVIAOa22gn577tbc&i3|3V8NWy&!tw##`}9*x}gtI^h1DzZRA>UuaJG) zaZ7j)dq!O}{?#8Y7~7i6fHh4{`pL?>-18|p!S75Y#^DM>-S3)vuZG+Q7l@ek zQP~#cBpWgg#mApc_sPYjpw8odQuRokmTkzcNl`^CcKB7e&;zViV;{Y{o^Y$%7i0m# z62%#1Lq!RC?}lK>%mp}T!3Xv;L*0v*>USLm``N%>w>@fwC+#T&Tx2bN4w(20JB}oU zuSa6v^kXi0xPs?pbaOHnyiqq6By1EZY9OZ^^QA>{q-Hsd&m`pbQ%8121aWG-F5xf zlZ%;B{;C>X19|`^_?dVyCq>n+41w7|!tUS!{9rHlbhX=SZO5CQ^;!Du_E7*`GiR^Q w)2!4MKjfSAeNZ5(O;wUb;g&xn`+c4)Vu zera0!7*nCDP@{(ySBN;=!ND!cyt-kAWn0sxq9UQ*k(ZQJhD z%-uR$o3+{YYU2Z<&&s>Y-9v4=Q}>S9x-o!b0RZXd`~TSHYG<=;J4Jkex~FJ2u6?~h zrf%AL3flj6TrW=3FJGrh+87>C(D{Mnk=&;E+?7`nlLjjm@ar&ue|^FmYF$GazKUI#G3)L zYhSFwYOFfXzgy)^$}vPNLTs5ijJE3*9I~;(yi97D*>rmEtg2cu~~5+cfCHhk4P zXElWBeGsZN5}i--K6Vcy_*odu(?cS_!eMW9-a$1Q8;cVXK%`*~9HlmS0ak>#xOCB4SI0AYX z4aYbP#BH47@O@I4w@|_`>Shr0Vpt2iSqREPHy%nE&e9Ok8Dm)ebWAYLb>=@PPpOo4 zF-xnQhpA?zh_f_+O1;^nSt(FpY7(#s#yRLF6s8CwxNr@iiRl)yP}$l{0?B+omKuVB&h4o3FI4+x0Bd7y3h8vWylR3|PY6q$ zOG%V_%mZ(4(g*{ID?I6}w;BTO*F$l*SKg*|JcKA7K5j$Ql>wZKplkhdj^ z5};R6lOK}vug~qSguqPf^u>R_lYvG|ev$=Gex~}i0tk;q0JjuMV(?FL$vJmdpvHFx zqW{0iK|=sS@=sfUaA*EI^WPD;$my@t*GK8k_aKu#UWCv8u`R?0Dpu=u-ArpV$|{$x zT+yladPGm#O{xv)h8XMo(mjMg26ei~elr}7uj&!-p_-2a5=l5CHy3TA3Ynlvx;DsH|rsKFTV?h3bvq9_%Nf zySnm0P60?3!4S67CkCuWT|>9#VE7ge%~l4405C9bjA7MRbZ;Q!9YYPT-hfN!7O(Zs?v?5(1(q_TFo!)nhZm~GSbVZB08fG+nY6ofW)q-zP07=$DwZ?K5%Km z5F7}gj3JOXg$$<8o#7t%bk>gCPr?k$g8@(QOD~^6bSDtoo3+9~B00r%uQ35b5AF4V z4_9FdSqcmY1r`ty3}6XYcm+N|P)F0|$n)6$gnB|Zsr}*J2z@$!JR%n#Vk?zuz94aT zls=!-jQGWF(^nXu!3{o1E0Vz@P8Wisi3XsTPZW_8 z)<*sqVf+9a*q!XH=KZ~s zd$UoZ{MU`_0RR9mufb~&U*al~Z6`Y9Y#>QM0T@LZ3Mjra zyZ78<7e-1oGZ6ira_1rTIR?DBu!dL{?f4b*C04&O2 zi5u|={Q`<08UbpWB2WoB(6LFz**x#Y3N4WeXnGgcaQL(M-488Tc3&*?8=sOs)9%9i z86V&fEC`TE#7ag0F*iU8A~+CeAS+0c{6Vb9?$}NbT&P>%7Gp!nUN@K|(|K$6UnuUn zE)Lv)0V6O21CRqS2owPz20I)i0D>gRrmbh&w(a+A|NXD&+Ba@R^nU_;_#gk{fBcXC zy{wN+Vf=^x@E`uefA|mo;g-euWJGsHW`BEUL=X56|KUIU=e1?BUa9FtNjKY-nof<3 z${v+;osD#^8^uFZ+DJ&7!*w&`(XU5?HT;MF@Sn}#zA9~{R1h~GmrpELP-3xdW=MUV zjl}I|<&)`-)ZJbeNTtOrcb-)F)f`Ix{b=VK{=s9&Fgza{#VsYxVqraKb) z@-EHC^GN3S5C7pm{D=SWAO6FC_zzW#h7yk~2$jWu>NRLJWZUdn13D7_;XlJP-za!F WHsuU0{`1&||M5Tm$N%`>b2k9_3hEsI literal 0 HcmV?d00001 diff --git a/app/src/main/res/mipmap-xxxhdpi/ic_icon_ttt_round.webp b/app/src/main/res/mipmap-xxxhdpi/ic_icon_ttt_round.webp new file mode 100644 index 0000000000000000000000000000000000000000..151a67f447e4b276221234fcc9803ca6edafbae2 GIT binary patch literal 6272 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 literal 0 HcmV?d00001 diff --git a/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp b/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp new file mode 100644 index 0000000000000000000000000000000000000000..aa7d6427e6fa1074b79ccd52ef67ac15c5637e85 GIT binary patch literal 3844 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

UmY2RIYtNPVDpE$%vda+HD#3m z&VuXJ{BK&Qe+rBa7eq}Q(bq|tn(RrJAk|ztj2(i{d>nmQnM?;HF2k&9sA6up5tmjl z7lySlzMbifH17-m-Lwa_F&e7nOH?ESi3#ckR3tsM+jsck3`oG!uMS}|eAwVXv>}qxwq?QY%QJ0}r@^;fhuUA9W z*BVl>TGo&N004@xSiwDUXUvp51sVmqO3m)=B55aPwf@0=e}cN+$-BdKxY`YrT_4)0 z_d10#i44Q*rFr8MC>*)v$EJvz``(pb{e&*6k+b zsMz%($|1+8hn8c2?P(l@;Rb&CsZeYoCI3?2!LqjbwPXW3z4G$Qfj=cT5Yb%vY0(AX oeb?AaKtwrnc|$|zzw9vfvn^aJJ!zd)XFXqqy0000001=f@-~a#s literal 0 HcmV?d00001 diff --git a/app/src/main/res/values/colors.xml b/app/src/main/res/values/colors.xml new file mode 100644 index 0000000..f8c6127 --- /dev/null +++ b/app/src/main/res/values/colors.xml @@ -0,0 +1,10 @@ + + + #FFBB86FC + #FF6200EE + #FF3700B3 + #FF03DAC5 + #FF018786 + #FF000000 + #FFFFFFFF + \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml new file mode 100644 index 0000000..64640c2 --- /dev/null +++ b/app/src/main/res/values/strings.xml @@ -0,0 +1,16 @@ + + Tic-Tac-Toe + + Choose your opponent: + Human - Someone next to you. + AI : Random - Fills any open spot. + AI : Hard - Your typical try-hard. + AI : Easy - Opportunist, may try to win. + AI : Stubborn - Won\'t let you win. + AI : Shy - Too scared to win. + + Website + https://hyperling.com + GitHub + https://github.com/Hyperling/TicTacToeAndroid + \ No newline at end of file diff --git a/app/src/main/res/values/themes.xml b/app/src/main/res/values/themes.xml new file mode 100644 index 0000000..f89af7e --- /dev/null +++ b/app/src/main/res/values/themes.xml @@ -0,0 +1,5 @@ + + + +