Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
55 changes: 32 additions & 23 deletions app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -13,51 +13,60 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/

apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-kapt'
apply plugin: 'kotlin-android-extensions'
apply plugin: "androidx.navigation.safeargs.kotlin"
plugins{
id 'com.android.application'
id 'kotlin-android'
id 'kotlin-kapt'
id "androidx.navigation.safeargs"
}

android {
compileSdkVersion 28
compileSdkVersion 34
defaultConfig {
applicationId "com.example.android.guesstheword"
minSdkVersion 19
targetSdkVersion 28
minSdkVersion 21
targetSdkVersion 34
versionCode 1
versionName "1.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
testInstrumentationRunner 'androidx.test.runner.AndroidJUnitRunner'
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}

dataBinding {
enabled = true
buildFeatures {
dataBinding true
}

compileOptions {
sourceCompatibility = JavaVersion.VERSION_17
targetCompatibility = JavaVersion.VERSION_17
}
kotlinOptions {
jvmTarget = JavaVersion.VERSION_17
}
namespace 'com.example.android.guesstheword'
}

dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
implementation 'androidx.appcompat:appcompat:1.0.2'
implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
implementation 'androidx.appcompat:appcompat:1.7.0'
implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
implementation 'androidx.legacy:legacy-support-v4:1.0.0'
testImplementation 'junit:junit:4.12'
androidTestImplementation 'androidx.test:runner:1.1.1'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.1.1'
testImplementation 'junit:junit:4.13.2'
androidTestImplementation 'androidx.test:runner:1.6.2'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.6.1'

// KTX
implementation 'androidx.core:core-ktx:1.0.1'
implementation 'androidx.core:core-ktx:1.13.1'

// Navigation
implementation "android.arch.navigation:navigation-fragment-ktx:1.0.0-rc02"
implementation "android.arch.navigation:navigation-ui-ktx:1.0.0-rc02"
implementation "androidx.navigation:navigation-fragment-ktx:2.8.1"
implementation "androidx.navigation:navigation-ui-ktx:2.8.1"

// TODO (01) Add lifecycle-extensions gradle
// Lifecycles
implementation 'androidx.lifecycle:lifecycle-extensions:2.2.0'
}
7 changes: 3 additions & 4 deletions app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,7 @@
-->

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="com.example.android.guesstheword">
xmlns:tools="http://schemas.android.com/tools">

<application
android:allowBackup="true"
Expand All @@ -30,8 +29,8 @@
<!-- Screen locked to landscape for easier play -->
<!-- configChanges attribute makes the following actions NOT cause a config change -->
<!-- screenOrientation attribute sets the default animation-->
<activity android:name=".MainActivity">

<activity android:name=".MainActivity"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,16 @@
package com.example.android.guesstheword.screens.game

import android.os.Bundle
import android.text.format.DateUtils
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.databinding.DataBindingUtil
import androidx.databinding.Observable
import androidx.fragment.app.Fragment
import androidx.navigation.fragment.NavHostFragment.findNavController
import androidx.lifecycle.Observer
import androidx.lifecycle.ViewModelProvider
import androidx.navigation.fragment.NavHostFragment.Companion.findNavController
import com.example.android.guesstheword.R
import com.example.android.guesstheword.databinding.GameFragmentBinding

Expand All @@ -31,114 +35,48 @@ import com.example.android.guesstheword.databinding.GameFragmentBinding
*/
class GameFragment : Fragment() {

// The current word
private var word = ""

// The current score
private var score = 0

// The list of words - the front of the list is the next word to guess
private lateinit var wordList: MutableList<String>

private lateinit var gameViewModel: GameViewModel
private lateinit var binding: GameFragmentBinding

override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?): View? {

// Inflate view and obtain an instance of the binding class
binding = DataBindingUtil.inflate(
inflater,
R.layout.game_fragment,
container,
false
inflater,
R.layout.game_fragment,
container,
false
)

// TODO (04) Create and initialize a GameViewModel, using ViewModelProviders; Add a log
// statement
gameViewModel = ViewModelProvider(this)[GameViewModel::class.java]

resetList()
nextWord()

binding.correctButton.setOnClickListener { onCorrect() }
binding.skipButton.setOnClickListener { onSkip() }
updateScoreText()
updateWordText()
return binding.root
binding.gameViewModel = gameViewModel
binding.setLifecycleOwner(this)

}
gameViewModel.eventGameFinished.observe(viewLifecycleOwner) { hasFinished ->
if (hasFinished) {
gameFinished()
gameViewModel.onGameFinished()
}
}

/**
* Resets the list of words and randomizes the order
*/
private fun resetList() {
wordList = mutableListOf(
"queen",
"hospital",
"basketball",
"cat",
"change",
"snail",
"soup",
"calendar",
"sad",
"desk",
"guitar",
"home",
"railway",
"zebra",
"jelly",
"car",
"crow",
"trade",
"bag",
"roll",
"bubble"
)
wordList.shuffle()
return binding.root
}

/**
* Called when the game is finished
*/
private fun gameFinished() {
val action = GameFragmentDirections.actionGameToScore(score)
val action = GameFragmentDirections.actionGameToScore()
action.setScore(gameViewModel.score.value ?: 0)
findNavController(this).navigate(action)
}

/**
* Moves to the next word in the list
*/
private fun nextWord() {
//Select and remove a word from the list
if (wordList.isEmpty()) {
gameFinished()
} else {
word = wordList.removeAt(0)
}
updateWordText()
updateScoreText()
}

/** Methods for buttons presses **/

private fun onSkip() {
score--
nextWord()
}

private fun onCorrect() {
score++
nextWord()
}

/** Methods for updating the UI **/

private fun updateWordText() {
binding.wordText.text = word
binding.wordText.text = gameViewModel.word.value

}

private fun updateScoreText() {
binding.scoreText.text = score.toString()
binding.scoreText.text = gameViewModel.score.toString()
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,5 +16,130 @@

package com.example.android.guesstheword.screens.game

// TODO (02) Create the GameViewModel class, extending ViewModel
// TODO (03) Add init and override onCleared; Add log statements to both
import android.os.CountDownTimer
import android.text.format.DateUtils
import android.util.Log
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import androidx.lifecycle.map

class GameViewModel : ViewModel() {

companion object {
// These represent different important times
// This is when the game is over
const val DONE = 0L

// This is the number of milliseconds in a second
const val ONE_SECOND = 1000L

// This is the total time of the game
const val COUNTDOWN_TIME = 5000L
}

private var timer: CountDownTimer

private var _currentTime = MutableLiveData<Long>()
val currentTime: LiveData<Long>
get() = _currentTime

val currentTimeString = currentTime.map { time ->
DateUtils.formatElapsedTime(time)
}

// The current word
private var _word = MutableLiveData<String>()
val word: LiveData<String>
get() = _word

// The current score with backing property
private var _score = MutableLiveData<Int>()
val score: LiveData<Int>
get() = _score

private var _eventGameFinished = MutableLiveData<Boolean>()
val eventGameFinished: LiveData<Boolean>
get() = _eventGameFinished

init {
_eventGameFinished.value = false
Log.i("GameViewModel", "GameViewModel was created.")
resetList()
_word.value = ""
nextWord()
_score.value = 0

timer = object : CountDownTimer(COUNTDOWN_TIME, ONE_SECOND) {
override fun onTick(millisUntilFinished: Long) {
_currentTime.value = (millisUntilFinished/ ONE_SECOND)
}

override fun onFinish() {
_currentTime.value = DONE
_eventGameFinished.value = true
}

}

timer.start()
}

// The list of words - the front of the list is the next word to guess
private lateinit var wordList: MutableList<String>

private fun resetList() {
wordList = mutableListOf(
"queen",
"hospital",
"basketball",
"cat",
"change",
"snail",
"soup",
"calendar",
"sad",
"desk",
"guitar",
"home",
"railway",
"zebra",
"jelly",
"car",
"crow",
"trade",
"bag",
"roll",
"bubble"
)
wordList.shuffle()
}

private fun nextWord() {
//Select and remove a word from the list
if (wordList.isEmpty()) {
resetList()
}
_word.value = wordList.removeAt(0)
}

override fun onCleared() {
super.onCleared()
timer.cancel()
Log.i("GameViewModel", "GameViewModel was cleared.")
}

fun onSkip() {
_score.value = score.value?.minus(1)
nextWord()
}

fun onCorrect() {
_score.value = score.value?.plus(1)
nextWord()
}

fun onGameFinished() {
_eventGameFinished.value = false
}
}
Loading