Skip to content
This repository has been archived by the owner on Jul 25, 2022. It is now read-only.

Commit

Permalink
Added feature logging the high score.
Browse files Browse the repository at this point in the history
The highest score is stored persistently. A new menu entry allows to display the current high score.

The design allows to extend the score information with low effort.

Fixes #4.
  • Loading branch information
dhebbeker committed Mar 18, 2018
2 parents 13a4e38 + 517369b commit ad1cc55
Show file tree
Hide file tree
Showing 10 changed files with 190 additions and 4 deletions.
1 change: 1 addition & 0 deletions app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -60,4 +60,5 @@ dependencies {
testImplementation 'junit:junit:4.12'
androidTestImplementation 'com.android.support.test:runner:1.0.1'
androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.1'
compile "com.google.code.gson:gson:2.8.2"
}
11 changes: 11 additions & 0 deletions app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,17 @@
android:name="android.support.PARENT_ACTIVITY"
android:value="info.hebbeker.david.memorex.MainActivity" />
</activity>
<activity
android:name=".DisplayHighScore"
android:label="High scores"
android:parentActivityName=".MainActivity"
tools:ignore="UnusedAttribute">

<!-- The meta-data tag is required if you support API level 15 and lower -->
<meta-data
android:name="android.support.PARENT_ACTIVITY"
android:value=".MainActivity" />
</activity>
</application>

</manifest>
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package info.hebbeker.david.memorex;

import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.text.Html;
import android.widget.TextView;

import java.io.Serializable;

public class DisplayHighScore extends AppCompatActivity
{

@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_display_high_score);
final Serializable currentHighScore = getIntent().getSerializableExtra(MainActivity.HIGH_SCORE_DATA);
final String aboutText = getResources().getString(R.string.high_score_display, currentHighScore.toString());
final TextView textView = findViewById(R.id.textViewHighScore);
textView.setText(Html.fromHtml(aboutText));
}
}
8 changes: 6 additions & 2 deletions app/src/main/java/info/hebbeker/david/memorex/Game.java
Original file line number Diff line number Diff line change
Expand Up @@ -68,12 +68,16 @@ private void nextLevel()
gameBoardInterface.queueDisplaySymbolSequence(symbolSequence);
}

void putPlayerInput(final Symbol symbol)
void putPlayerInput(final Symbol symbol, final HighScoreContainer highScoreContainer)
{
// if input symbol is not correct, notify user and reset board game
if (symbol != currentSymbol.next())
{
gameBoardInterface.notifyUser("Game Over (" + symbolSequence.size() + ")");
// end current game
final int completedLevel = symbolSequence.size() - 1;
final Score score = new Score(completedLevel);
highScoreContainer.setNewHighScore(score);
gameBoardInterface.notifyUser("Game Over (" + completedLevel + ")");
gameBoardInterface.clearBoard();
}
// if sequence is complete, notify user and start next level
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
package info.hebbeker.david.memorex;

import android.content.SharedPreferences;

import com.google.gson.Gson;
import com.google.gson.JsonSyntaxException;

import java.io.IOException;

class HighScoreContainer
{
final private SharedPreferences sharedPref;
final private String highScorePreferenceKey = "HighScoreStorage";
final private Gson gson = new Gson();
private Score currentHighScore;

HighScoreContainer(final SharedPreferences sharedPref)
{
this.sharedPref = sharedPref;
loadHighScore();
}

private void loadHighScore()
{
try
{
String highScoreSerializedObject = this.sharedPref.getString(highScorePreferenceKey, "");
currentHighScore = gson.fromJson(highScoreSerializedObject, Score.class);
if (currentHighScore == null) // this may be overcautious
{
throw new IOException("Getting stored high score failed!");
}
}
catch (JsonSyntaxException|IOException e)
{
e.printStackTrace();
currentHighScore = new Score(0);
saveHighScore();
}
}

boolean setNewHighScore(final Score newScore)
{
final boolean isNewHighScore = newScore.isGreaterThan(currentHighScore);
if (isNewHighScore)
{
currentHighScore = newScore;
saveHighScore();
}
return isNewHighScore;
}

private void saveHighScore()
{
SharedPreferences.Editor editor = sharedPref.edit();
String highScoreSerializedObject = gson.toJson(currentHighScore);
editor.putString(highScorePreferenceKey, highScoreSerializedObject);
editor.apply();
}

public Score getCurrentHighScore()
{
return currentHighScore;
}
}
15 changes: 13 additions & 2 deletions app/src/main/java/info/hebbeker/david/memorex/MainActivity.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package info.hebbeker.david.memorex;

import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.preference.PreferenceManager;
Expand All @@ -16,10 +17,12 @@

public class MainActivity extends AppCompatActivity implements GameBoardInterface, View.OnClickListener
{
static final String HIGH_SCORE_DATA = MainActivity.class.getPackage().getName() + "HIGH_SCORE_DATA";
private final SymbolButton[] symbols = new SymbolButton[4];
private final Game game = new Game(this, symbols);
private View startGameButton;
private View startGameButton = null;
private Toast notification = null;
private HighScoreContainer highScoreContainer = null;

@Override
protected void onCreate(final Bundle savedInstanceState)
Expand All @@ -28,6 +31,7 @@ protected void onCreate(final Bundle savedInstanceState)
setContentView(R.layout.activity_main);

startGameButton = findViewById(R.id.startButton);
highScoreContainer = new HighScoreContainer(getSharedPreferences("info.hebbeker.david.memorex.PREFERENCE_SCORE_FILE_KEY", Context.MODE_PRIVATE));

symbols[0] = findViewById(R.id.button1);
symbols[1] = findViewById(R.id.button2);
Expand Down Expand Up @@ -55,7 +59,7 @@ public void signalSymbol2Game(View view)
{
SymbolButton pressedButton = (SymbolButton) view;
pressedButton.signalSymbol(); // signal symbol to user
game.putPlayerInput(pressedButton); // signal symbol to game
game.putPlayerInput(pressedButton, highScoreContainer); // signal symbol to game
}

public void startGame(@SuppressWarnings("unused") final View view)
Expand Down Expand Up @@ -154,6 +158,13 @@ public void run()
}).start();
}

public void showHighScore(@SuppressWarnings("unused") final MenuItem menuItem)
{
Intent intent = new Intent(this, DisplayHighScore.class);
intent.putExtra(HIGH_SCORE_DATA, highScoreContainer.getCurrentHighScore());
startActivity(intent);
}

public void showAbout(@SuppressWarnings("unused") final MenuItem menuItem)
{
Intent intent = new Intent(this, DisplayAboutActivity.class);
Expand Down
37 changes: 37 additions & 0 deletions app/src/main/java/info/hebbeker/david/memorex/Score.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package info.hebbeker.david.memorex;

import java.io.Serializable;

/**
* Does contain information about a score.
* \todo Add the following attributes: username, speed, date, points
*/
class Score implements Serializable
{
/**
* Completed level.
* <p>
* If the player fails at level 2, the completed level is 1. If he fails at level 1, the
* completed level is 0.
*/
private final int level;

Score(final int level)
{
this.level = level;
}

/**
* @return true if this score is greater than other score
*/
boolean isGreaterThan(final Score otherScore)
{
return this.level > otherScore.level;
}

@Override
public String toString()
{
return "Level=" + level;
}
}
23 changes: 23 additions & 0 deletions app/src/main/res/layout/activity_display_high_score.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="info.hebbeker.david.memorex.DisplayHighScore">

<TextView
android:id="@+id/textViewHighScore"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_marginBottom="8dp"
android:layout_marginLeft="11dp"
android:layout_marginRight="11dp"
android:layout_marginTop="8dp"
android:autoLink="web|email|map"
android:text="@string/high_score_display"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</android.support.constraint.ConstraintLayout>
9 changes: 9 additions & 0 deletions app/src/main/res/menu/main_menu.xml
Original file line number Diff line number Diff line change
@@ -1,11 +1,20 @@
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">

<item
android:icon="@android:drawable/ic_menu_myplaces"
android:onClick="showHighScore"
android:title="@string/show_high_score"
android:titleCondensed="high score" />
<item
android:icon="@android:drawable/ic_menu_info_details"
android:onClick="showAbout"
android:title="@string/about_this_app"
android:titleCondensed="About" />

<!-- “Settings” should be below all other items (except Help & Feedback)
https://material.io/guidelines/patterns/settings.html#settings-placement
-->
<item
android:icon="@android:drawable/ic_menu_preferences"
android:onClick="showSettings"
Expand Down
2 changes: 2 additions & 0 deletions app/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@
<string name="title_activity_settings">Settings</string>
<string name="preference_speed_list" translatable="false">speed_list</string>
<string name="preference_switch_sound" translatable="false">switch_preference_sound</string>
<string name="show_high_score">Show high score</string>
<string name="high_score_display">Current high score is: %1$s</string>
<string-array name="pref_speed_titles">
<item>Slow</item>
<item>Medium</item>
Expand Down

0 comments on commit ad1cc55

Please sign in to comment.