# 剪刀石頭布遊戲 app 參考
```kotlin=
package tw.josephku.rpsnow
import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.foundation.Image
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.layout.wrapContentWidth
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.Button
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Surface
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableIntStateOf
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import tw.josephku.rpsnow.ui.theme.RPSNowTheme
enum class Choice {
ROCK, PAPER, SCISSORS
}
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
RPSNowTheme {
// A surface container using the 'background' color from the theme
Surface(
modifier = Modifier.fillMaxSize(),
color = MaterialTheme.colorScheme.background
) {
RPSNow()
}
}
}
}
}
@Composable
fun choiceButton(bvlaue: String, onClick: () -> Unit) {
// buttons generator
Button(
modifier = Modifier
.height(130.dp)
.width(130.dp)
.padding(5.dp),
onClick = onClick,
shape = RoundedCornerShape(14.dp)
) {
Text(text = bvlaue)
}
}
@Composable
fun displayChoice(player: String, action: String) {
//player and android choices display
Text(
text = player,
fontSize = 16.sp,
modifier = Modifier
.fillMaxWidth()
.wrapContentWidth(Alignment.CenterHorizontally)
)
Text(
text = action,
fontSize = 32.sp,
modifier = Modifier
.fillMaxWidth()
.wrapContentWidth(Alignment.CenterHorizontally),
fontWeight = FontWeight.Bold
)
}
@Composable
fun RPSNow() {
//main compose
val image = painterResource(id = R.drawable.rpsnow_banner)
var playerChoiceName by remember { mutableStateOf("--") }
var computerChoiceName by remember { mutableStateOf("--") }
var playerWins by remember { mutableIntStateOf(0) }
var computerWins by remember { mutableIntStateOf(0) }
var records by remember { mutableStateOf("0 / 0") }
Column {
//main column
Image(
painter = image,
contentDescription = null
)
Text(
text = "Records",
fontSize = 30.sp,
modifier = Modifier
.fillMaxWidth()
.wrapContentWidth(Alignment.CenterHorizontally)
.padding(top = 16.dp)
)
Text(
text = records,
fontSize = 50.sp,
modifier = Modifier
.fillMaxWidth()
.wrapContentWidth(Alignment.CenterHorizontally),
fontWeight = FontWeight.Bold
)
Row(modifier = Modifier.padding(top = 85.dp)) {
Column(
Modifier
.fillMaxWidth(0.5f)
.wrapContentWidth(Alignment.CenterHorizontally)
) {
displayChoice("Your Choice", playerChoiceName)
}
Column(
Modifier
.fillMaxWidth()
.wrapContentWidth(Alignment.CenterHorizontally)
) {
displayChoice("Computer's Choice", computerChoiceName)
}
}
Row(modifier = Modifier.padding(top = 70.dp)) {
Choice.entries.forEach { choice ->
choiceButton(bvlaue = choice.name) {
playerChoiceName = choice.name
val computerChoice = Choice.entries.random()
computerChoiceName = computerChoice.name
val result = (choice.ordinal - computerChoice.ordinal + 3) % 3
when (result) {
0 -> {}
1 -> { playerWins++ }
else -> { computerWins++ }
}
records = "$playerWins / $computerWins"
}
}
}
}
}
@Preview(showBackground = true)
@Composable
fun DefaultPreview() {
RPSNowTheme {
RPSNow()
}
}
```
[Banner 圖](https://slack-files.com/T06ARGM2N-F070MND4L4F-c7943aebdc)
**Apktool**
https://apktool.org
macOS 安裝
```
$ brew install apktool
```
Windows 安裝
```
$ choco install apktool
```
Usage:
```
$ apktool d -f app-debug.apk
```
Revise strings.xml
```
$ apktool b app-debug -o new.apk
```
```
$ keytool -genkey -v -keystore my-test-key.jks -keyalg RSA -keysize 2048 -validity 10000 -alias my-alias
```
```
$ keytool -genkey -v -keystore my-test-key.jks -keyalg RSA -keysize 2048 -validity 10000 -alias my-alias
```
```
$ zipalign -v -p 4 new.apk new-align.apk
```
```
$ apksigner sign --ks my-test-key.jks --ks-pass pass:12345678 -out new-final.apk new-align.apk
```
zipalign 與 apksigner 在 $ANDROID_HOME/build-tool 中
**ApkLeaks**
https://github.com/dwisiswant0/apkleaks
macOS 安裝
```
$ brew install apkleaks
```
PyPi 安裝
```
$ pip3 install apkleaks
```
Usage:
```
$ apkleaks -f app-debug.apk
```