Tugas Pertemuan 11 - Unscramble App
Nama : I Gusti Agung Ngurah Adhi Sanjaya
NRP : 5025211056
Kelas : Pemrograman Perangkat Bergerak B
Dosen : Fajar Baskoro
Penerapan ViewModel dan State in Composepada Unscramble App
Aplikasi Unscramble App adalah aplikasi permainan game yang akan menampilkan kata acak. Objective kita dalah untuk memecahkan kata nya itu supaya terutut dan setiap kata yang benar akan mendapatkan 10 poin.
Terdapat 2 tombol, submit dan skip. Submit berfungsi sebagai tombol untuk mengirimkan jawaban yang di tebak, lalu skip untuk melewati soal dan tidak akan mendapatkan point.
Jika jawaban yang dikumpulkan tidak benar/salah, maka tidak akan mendapatkan point.
Berikut adalah codingan dari aplikasi ini :
VIEW MODEL
package com.example.unscramble.ui
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.setValue
import androidx.lifecycle.ViewModel
import com.example.unscramble.data.MAX_NO_OF_WORDS
import com.example.unscramble.data.SCORE_INCREASE
import com.example.unscramble.data.allWords
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.flow.update
// Game UI state
// Backing property to avoid state updates from other classes
class GameViewModel : ViewModel() {
// Game UI state
private val _uiState = MutableStateFlow(GameUiState())
val uiState: StateFlow<GameUiState> = _uiState.asStateFlow()
var userGuess by mutableStateOf("")
private set
// Set of words used in the game
private var usedWords: MutableSet<String> = mutableSetOf()
private lateinit var currentWord: String
init {
resetGame()
}
fun resetGame() {
usedWords.clear()
_uiState.value = GameUiState(currentScrambledWord = pickRandomWordAndShuffle())
}
fun updateUserGuess(guessedWord: String) {
userGuess = guessedWord
}
fun checkUserGuess() {
if(userGuess.equals(currentWord, ignoreCase = true)) {
// User's guess is correct, increase the score
val updatedScore = _uiState.value.score.plus(SCORE_INCREASE)
// Call updateGameState() to prepare the game for the next round
updateGameState(updatedScore)
} else {
// User's guess is wrong, show an error
_uiState.update { currentState ->
currentState.copy(isGuessedWordWrong = true)
}
//
}
updateUserGuess("")
}
fun skipWord() {
updateGameState(_uiState.value.score)
// Reset user guess
updateUserGuess("")
}
private fun updateGameState(updatedScore: Int) {
if (usedWords.size == MAX_NO_OF_WORDS) {
// Last round
_uiState.update { currentState ->
currentState.copy(
isGuessedWordWrong = false,
score = updatedScore,
isGameOver = true
)
}
} else {
// Normal round
_uiState.update { currentState ->
currentState.copy(
isGuessedWordWrong = false,
currentScrambledWord = pickRandomWordAndShuffle(),
currentWordCount = currentState.currentWordCount.inc(),
score = updatedScore,
)
}
}
}
private fun shuffleCurrentWord(word: String): String {
val tempWord = word.toCharArray()
// Scramble
tempWord.shuffle()
while (String(tempWord) == word){
tempWord.shuffle()
}
return String(tempWord)
}
private fun pickRandomWordAndShuffle(): String {
currentWord = allWords.random()
return if (usedWords.contains(currentWord)){
pickRandomWordAndShuffle()
} else {
usedWords.add(currentWord)
shuffleCurrentWord(currentWord)
}
}
}
DATA DARI KATA YANG AKAN DI RANDOM GENERATE :/*
* Copyright (C) 2023 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.example.unscramble.data
const val MAX_NO_OF_WORDS = 10
const val SCORE_INCREASE = 20
// Set with all the words for the Game
val allWords: Set<String> =
setOf(
"animal",
"auto",
"anecdote",
"alphabet",
"all",
"awesome",
"arise",
"balloon",
"basket",
"bench",
"best",
"birthday",
"book",
"briefcase",
"camera",
"camping",
"candle",
"cat",
"cauliflower",
"chat",
"children",
"class",
"classic",
"classroom",
"coffee",
"colorful",
"cookie",
"creative",
"cruise",
"dance",
"daytime",
"dinosaur",
"doorknob",
"dine",
"dream",
"dusk",
"eating",
"elephant",
"emerald",
"eerie",
"electric",
"finish",
"flowers",
"follow",
"fox",
"frame",
"free",
"frequent",
"funnel",
"green",
"guitar",
"grocery",
"glass",
"great",
"giggle",
"haircut",
"half",
"homemade",
"happen",
"honey",
"hurry",
"hundred",
"ice",
"igloo",
"invest",
"invite",
"icon",
"introduce",
"joke",
"jovial",
"journal",
"jump",
"join",
"kangaroo",
"keyboard",
"kitchen",
"koala",
"kind",
"kaleidoscope",
"landscape",
"late",
"laugh",
"learning",
"lemon",
"letter",
"lily",
"magazine",
"marine",
"marshmallow",
"maze",
"meditate",
"melody",
"minute",
"monument",
"moon",
"motorcycle",
"mountain",
"music",
"north",
"nose",
"night",
"name",
"never",
"negotiate",
"number",
"opposite",
"octopus",
"oak",
"order",
"open",
"polar",
"pack",
"painting",
"person",
"picnic",
"pillow",
"pizza",
"podcast",
"presentation",
"puppy",
"puzzle",
"recipe",
"release",
"restaurant",
"revolve",
"rewind",
"room",
"run",
"secret",
"seed",
"ship",
"shirt",
"should",
"small",
"spaceship",
"stargazing",
"skill",
"street",
"style",
"sunrise",
"taxi",
"tidy",
"timer",
"together",
"tooth",
"tourist",
"travel",
"truck",
"under",
"useful",
"unicorn",
"unique",
"uplift",
"uniform",
"vase",
"violin",
"visitor",
"vision",
"volume",
"view",
"walrus",
"wander",
"world",
"winter",
"well",
"whirlwind",
"x-ray",
"xylophone",
"yoga",
"yogurt",
"yoyo",
"you",
"year",
"yummy",
"zebra",
"zigzag",
"zoology",
"zone",
"zeal"
)
Jika jawaban yang dikumpulkan tidak benar/salah, maka tidak akan mendapatkan point.
Berikut adalah codingan dari aplikasi ini :
package com.example.unscramble.ui
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.setValue
import androidx.lifecycle.ViewModel
import com.example.unscramble.data.MAX_NO_OF_WORDS
import com.example.unscramble.data.SCORE_INCREASE
import com.example.unscramble.data.allWords
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.flow.update
// Game UI state
// Backing property to avoid state updates from other classes
class GameViewModel : ViewModel() {
// Game UI state
private val _uiState = MutableStateFlow(GameUiState())
val uiState: StateFlow<GameUiState> = _uiState.asStateFlow()
var userGuess by mutableStateOf("")
private set
// Set of words used in the game
private var usedWords: MutableSet<String> = mutableSetOf()
private lateinit var currentWord: String
init {
resetGame()
}
fun resetGame() {
usedWords.clear()
_uiState.value = GameUiState(currentScrambledWord = pickRandomWordAndShuffle())
}
fun updateUserGuess(guessedWord: String) {
userGuess = guessedWord
}
fun checkUserGuess() {
if(userGuess.equals(currentWord, ignoreCase = true)) {
// User's guess is correct, increase the score
val updatedScore = _uiState.value.score.plus(SCORE_INCREASE)
// Call updateGameState() to prepare the game for the next round
updateGameState(updatedScore)
} else {
// User's guess is wrong, show an error
_uiState.update { currentState ->
currentState.copy(isGuessedWordWrong = true)
}
//
}
updateUserGuess("")
}
fun skipWord() {
updateGameState(_uiState.value.score)
// Reset user guess
updateUserGuess("")
}
private fun updateGameState(updatedScore: Int) {
if (usedWords.size == MAX_NO_OF_WORDS) {
// Last round
_uiState.update { currentState ->
currentState.copy(
isGuessedWordWrong = false,
score = updatedScore,
isGameOver = true
)
}
} else {
// Normal round
_uiState.update { currentState ->
currentState.copy(
isGuessedWordWrong = false,
currentScrambledWord = pickRandomWordAndShuffle(),
currentWordCount = currentState.currentWordCount.inc(),
score = updatedScore,
)
}
}
}
private fun shuffleCurrentWord(word: String): String {
val tempWord = word.toCharArray()
// Scramble
tempWord.shuffle()
while (String(tempWord) == word){
tempWord.shuffle()
}
return String(tempWord)
}
private fun pickRandomWordAndShuffle(): String {
currentWord = allWords.random()
return if (usedWords.contains(currentWord)){
pickRandomWordAndShuffle()
} else {
usedWords.add(currentWord)
shuffleCurrentWord(currentWord)
}
}
}
/*
* Copyright (C) 2023 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.example.unscramble.data
const val MAX_NO_OF_WORDS = 10
const val SCORE_INCREASE = 20
// Set with all the words for the Game
val allWords: Set<String> =
setOf(
"animal",
"auto",
"anecdote",
"alphabet",
"all",
"awesome",
"arise",
"balloon",
"basket",
"bench",
"best",
"birthday",
"book",
"briefcase",
"camera",
"camping",
"candle",
"cat",
"cauliflower",
"chat",
"children",
"class",
"classic",
"classroom",
"coffee",
"colorful",
"cookie",
"creative",
"cruise",
"dance",
"daytime",
"dinosaur",
"doorknob",
"dine",
"dream",
"dusk",
"eating",
"elephant",
"emerald",
"eerie",
"electric",
"finish",
"flowers",
"follow",
"fox",
"frame",
"free",
"frequent",
"funnel",
"green",
"guitar",
"grocery",
"glass",
"great",
"giggle",
"haircut",
"half",
"homemade",
"happen",
"honey",
"hurry",
"hundred",
"ice",
"igloo",
"invest",
"invite",
"icon",
"introduce",
"joke",
"jovial",
"journal",
"jump",
"join",
"kangaroo",
"keyboard",
"kitchen",
"koala",
"kind",
"kaleidoscope",
"landscape",
"late",
"laugh",
"learning",
"lemon",
"letter",
"lily",
"magazine",
"marine",
"marshmallow",
"maze",
"meditate",
"melody",
"minute",
"monument",
"moon",
"motorcycle",
"mountain",
"music",
"north",
"nose",
"night",
"name",
"never",
"negotiate",
"number",
"opposite",
"octopus",
"oak",
"order",
"open",
"polar",
"pack",
"painting",
"person",
"picnic",
"pillow",
"pizza",
"podcast",
"presentation",
"puppy",
"puzzle",
"recipe",
"release",
"restaurant",
"revolve",
"rewind",
"room",
"run",
"secret",
"seed",
"ship",
"shirt",
"should",
"small",
"spaceship",
"stargazing",
"skill",
"street",
"style",
"sunrise",
"taxi",
"tidy",
"timer",
"together",
"tooth",
"tourist",
"travel",
"truck",
"under",
"useful",
"unicorn",
"unique",
"uplift",
"uniform",
"vase",
"violin",
"visitor",
"vision",
"volume",
"view",
"walrus",
"wander",
"world",
"winter",
"well",
"whirlwind",
"x-ray",
"xylophone",
"yoga",
"yogurt",
"yoyo",
"you",
"year",
"yummy",
"zebra",
"zigzag",
"zoology",
"zone",
"zeal"
)
Komentar
Posting Komentar