diff --git a/app/build.gradle b/app/build.gradle index 699bdf44..95bc4626 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -48,7 +48,7 @@ android { jvmTarget = '1.8' } buildFeatures { - viewBinding = true + dataBinding = true } } diff --git a/app/src/main/java/com/example/android/unscramble/ui/game/GameFragment.kt b/app/src/main/java/com/example/android/unscramble/ui/game/GameFragment.kt index 1fd9861c..e4925bc4 100644 --- a/app/src/main/java/com/example/android/unscramble/ui/game/GameFragment.kt +++ b/app/src/main/java/com/example/android/unscramble/ui/game/GameFragment.kt @@ -20,19 +20,20 @@ import android.os.Bundle import android.view.LayoutInflater import android.view.View import android.view.ViewGroup +import androidx.databinding.DataBindingUtil import androidx.fragment.app.Fragment +import androidx.fragment.app.viewModels import com.example.android.unscramble.R import com.example.android.unscramble.databinding.GameFragmentBinding +import com.google.android.material.dialog.MaterialAlertDialogBuilder /** * Fragment where the game is played, contains the game logic. */ class GameFragment : Fragment() { - private var score = 0 - private var currentWordCount = 0 - private var currentScrambledWord = "test" + private val viewModel: GameViewModel by viewModels() // Binding object instance with access to the views in the game_fragment.xml layout private lateinit var binding: GameFragmentBinding @@ -42,39 +43,43 @@ class GameFragment : Fragment() { // first fragment override fun onCreateView( - inflater: LayoutInflater, container: ViewGroup?, - savedInstanceState: Bundle? + inflater: LayoutInflater, container: ViewGroup?, + savedInstanceState: Bundle? ): View { // Inflate the layout XML file and return a binding object instance - binding = GameFragmentBinding.inflate(inflater, container, false) + binding = DataBindingUtil.inflate(inflater, R.layout.game_fragment, container, false) + return binding.root } override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) - + binding.gameViewModel = viewModel + binding.maxNoOfWords = MAX_NO_OF_WORDS // Setup a click listener for the Submit and Skip buttons. binding.submit.setOnClickListener { onSubmitWord() } binding.skip.setOnClickListener { onSkipWord() } // Update the UI - updateNextWordOnScreen() - binding.score.text = getString(R.string.score, 0) - binding.wordCount.text = getString( - R.string.word_count, 0, MAX_NO_OF_WORDS) + binding.lifecycleOwner = viewLifecycleOwner + } /* - * Checks the user's word, and updates the score accordingly. - * Displays the next scrambled word. - */ + * Checks the user's word, and updates the score accordingly. + * Displays the next scrambled word. + */ private fun onSubmitWord() { - currentScrambledWord = getNextScrambledWord() - currentWordCount++ - score += SCORE_INCREASE - binding.wordCount.text = getString(R.string.word_count, currentWordCount, MAX_NO_OF_WORDS) - binding.score.text = getString(R.string.score, score) - setErrorTextField(false) - updateNextWordOnScreen() + val playerWord = binding.textInputEditText.text.toString() + + if (viewModel.isUserWordCorrect(playerWord)) { + setErrorTextField(false) + if (!viewModel.nextWord()) { + showFinalScoreDialog() + } + } else { + setErrorTextField(true) + } + } /* @@ -82,20 +87,11 @@ class GameFragment : Fragment() { * Increases the word count. */ private fun onSkipWord() { - currentScrambledWord = getNextScrambledWord() - currentWordCount++ - binding.wordCount.text = getString(R.string.word_count, currentWordCount, MAX_NO_OF_WORDS) - setErrorTextField(false) - updateNextWordOnScreen() - } - - /* - * Gets a random word for the list of words and shuffles the letters in it. - */ - private fun getNextScrambledWord(): String { - val tempWord = allWordsList.random().toCharArray() - tempWord.shuffle() - return String(tempWord) + if (viewModel.nextWord()) { + setErrorTextField(false) + } else { + showFinalScoreDialog() + } } /* @@ -103,8 +99,8 @@ class GameFragment : Fragment() { * restart the game. */ private fun restartGame() { + viewModel.reinitializeData() setErrorTextField(false) - updateNextWordOnScreen() } /* @@ -127,10 +123,16 @@ class GameFragment : Fragment() { } } - /* - * Displays the next scrambled word on screen. - */ - private fun updateNextWordOnScreen() { - binding.textViewUnscrambledWord.text = currentScrambledWord + private fun showFinalScoreDialog() { + MaterialAlertDialogBuilder(requireContext()).setTitle(getString(R.string.congratulations)) + .setMessage(getString(R.string.you_scored, viewModel.score.value)) + .setCancelable(true) + .setNegativeButton(getString(R.string.exit)) { _, _ -> + exitGame() + } + .setPositiveButton(getString(R.string.play_again)) { _, _ -> + restartGame() + } + .show() } } diff --git a/app/src/main/java/com/example/android/unscramble/ui/game/GameViewModel.kt b/app/src/main/java/com/example/android/unscramble/ui/game/GameViewModel.kt new file mode 100644 index 00000000..aed97101 --- /dev/null +++ b/app/src/main/java/com/example/android/unscramble/ui/game/GameViewModel.kt @@ -0,0 +1,74 @@ +package com.example.android.unscramble.ui.game + +import androidx.lifecycle.LiveData +import androidx.lifecycle.MutableLiveData +import androidx.lifecycle.ViewModel + +class GameViewModel : ViewModel() { + + private val _currentWordCount = MutableLiveData(0) + val currentWordCount: LiveData get() = _currentWordCount + private val _currentScrambledWord = MutableLiveData() + private var wordsList: MutableList = mutableListOf() + private lateinit var currentWord: String + + val currentScrambledWord: LiveData get() = _currentScrambledWord + + private val _score = MutableLiveData(0) + val score: LiveData get() = _score + + init{ + getNextWord() + } + + override fun onCleared() { + super.onCleared() + } + + private fun getNextWord() { + currentWord = allWordsList.random() + val tempWord = currentWord.toCharArray() + tempWord.shuffle() + + while (tempWord.toString().equals(currentWord, false)) { + tempWord.shuffle() + } + + if (wordsList.contains(currentWord)) { + getNextWord() + } else { + _currentScrambledWord.value = String(tempWord) + _currentWordCount.value = (_currentWordCount.value)?.inc() + wordsList.add(currentWord) + } + } + + fun nextWord(): Boolean { + return if (_currentWordCount.value!! < MAX_NO_OF_WORDS){ + getNextWord() + true + } + else { + false + } + } + + private fun increaseScore(){ + _score.value = (_score.value)?.plus(SCORE_INCREASE) + } + + fun isUserWordCorrect(playerWord: String): Boolean{ + if(playerWord.equals(currentWord, true)){ + increaseScore() + return true + } + return false + } + + fun reinitializeData(){ + _score.value = 0 + _currentWordCount.value = 0 + wordsList.clear() + getNextWord() + } +} \ No newline at end of file diff --git a/app/src/main/res/layout/game_fragment.xml b/app/src/main/res/layout/game_fragment.xml index e06c6181..e4ae2335 100644 --- a/app/src/main/res/layout/game_fragment.xml +++ b/app/src/main/res/layout/game_fragment.xml @@ -14,107 +14,120 @@ ~ limitations under the License. --> - + xmlns:tools="http://schemas.android.com/tools"> - + + + + + + android:layout_height="match_parent"> -