问题
I have an app that counts the score in a basketball match. There are three buttons for each team to increase the score (+3, +2, free throw).
I want to create a button to return back in case the user click a button for mistake. Without creating three separate buttons for each score (+3,+2,+1). But i don't really know how to transform this in Java code.
Something like: Score=score-lastNumberAdded. Sorry for my english. This is the code:
XML
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_weight="1"
android:layout_width="0dp"
android:layout_height="match_parent"
android:orientation="vertical">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:padding="4dp"
android:text="Team A"
android:textSize="14sp"
android:textColor="#616161"
android:fontFamily="sans-serif-medium"
android:layout_marginTop="16dp"
android:layout_marginBottom="16dp" />
<TextView
android:id="@+id/team_a_score"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:padding="4dp"
android:text="0"
android:textSize="56sp"
android:textColor="#000000"
android:fontFamily="sans-serif-light"
android:layout_marginBottom="24dp"/>
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="8dp"
android:text="+3 Points"
android:onClick="addThreeforTeamA" />
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="8dp"
android:text="+2 Points"
android:onClick="addTwoforTeamA" />
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="8dp"
android:text="+1 Point"
android:onClick="addOneforTeamA" />
</LinearLayout>
<View
android:layout_width="1dp"
android:layout_height="wrap_content"
android:background="@android:color/darker_gray"
android:layout_marginTop="16dp"
android:layout_marginBottom="50dp"/>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_weight="1"
android:layout_width="0dp"
android:layout_height="match_parent"
android:orientation="vertical">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:padding="4dp"
android:text="Team B"
android:textSize="14sp"
android:textColor="#616161"
android:fontFamily="sans-serif-medium"
android:layout_marginTop="16dp"
android:layout_marginBottom="16dp" />
<TextView
android:id="@+id/team_b_score"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:padding="4dp"
android:text="0"
android:textSize="56sp"
android:textColor="#000000"
android:fontFamily="sans-serif-light"
android:layout_marginBottom="24dp" />
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="8dp"
android:text="+3 Points"
android:onClick="addThreeforTeamB" />
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="8dp"
android:text="+2 Points"
android:onClick="addTwoforTeamB" />
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="8dp"
android:text="+1 Point"
android:onClick="addOneforTeamB" />
</LinearLayout>
</LinearLayout>
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:text="Reset"
android:onClick="reset" />
</RelativeLayout>
JAVA
package com.example.android.courtcounter;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.TextView;
public class MainActivity extends AppCompatActivity {
int scoreTeamA=0;
int scoreTeamB=0;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
/**
* Displays the given score for Team A.
*/
public void displayForTeamA(int score) {
TextView scoreView = (TextView) findViewById(R.id.team_a_score);
scoreView.setText(String.valueOf(score));
}
/**
* Displays the given score for Team B.
*/
public void displayForTeamB(int score) {
TextView scoreView = (TextView) findViewById(R.id.team_b_score);
scoreView.setText(String.valueOf(score));
}
public void addThreeforTeamA(View v) {
scoreTeamA+=3;
displayForTeamA(scoreTeamA);
}
public void addTwoforTeamA(View v) {
scoreTeamA+=2;
displayForTeamA(scoreTeamA);
}
public void addOneforTeamA(View v) {
scoreTeamA+=1;
displayForTeamA(scoreTeamA);
}
public void addThreeforTeamB(View v) {
scoreTeamB+=3;
displayForTeamB(scoreTeamB); }
public void addTwoforTeamB(View v) {
scoreTeamB+=2;
displayForTeamB(scoreTeamB); }
public void addOneforTeamB(View v) {
scoreTeamB+=1;
displayForTeamB(scoreTeamB); }
public void reset(View v) {
scoreTeamA=0;
scoreTeamB=0;
displayForTeamA(scoreTeamA);
displayForTeamB(scoreTeamB); }
}
回答1:
Undo problems beg for a Stack
to be used since it's a Last In First Out (LIFO) and efficient data structure. That means, in your case, every time a new score is added it will be sitting at the top. The score before that will be sitting just below it and so on and so forth. Therefore, when you start to undo you simply pop()
off the top element, subtract it from the score, and re-display the score.
Since a stack is incredibly easy to implement and because you can add couple minor modifications to aid in your program, I see this as one of those times you take it upon yourself to create your own light-weight ScoreStack
; like so:
public class ScoreStack {
private class ScoreNode {
int score;
ScoreNode next;
ScoreNode(int score, ScoreNode next) {
this.score = score;
this.next = next;
}
}
private int score = 0;
private ScoreNode root = null;
public void push(int score) {
root = new ScoreNode(score, root);
this.score += score;
}
public int pop() {
if (root == null) {
return 0;
}
int score = root.score;
root = root.next;
this.score -= score;
return score;
}
public void reset() {
root = null;
}
@Override
public String toString() {
return String.valueOf(score);
}
}
With this you're able to keep track of the ever-changing score, provide a simple means for obtaining the current score in String
format, and do it all with relative ease and efficiency. Of course, this changes your design slightly so here's an example.
public void addOneforTeamA(View v) {
aTeamStack.push(1);
displayForTeamA();
}
public void undoLastForA() {
aTeamStack.pop();
displayForTeamA();
}
public void displayForTeamA() {
((TextView) findViewById(R.id.team_a_score)).setText(aTeamStack);
}
Unrelated
Additionally, you have a number of improvements you could consider. It could be a sign the design could be better when you're providing the same functionality in methods which only differ by signature. For example,
displayForTeamA()
and its counterpart for TeamB
could be displayScore(int id, String score)
; like so:
public void displayScore(int id, String score) {
((TextView) findViewById(id)).setText(score);
}
and called like:
displayScore(R.id.team_a_score, aTeamStack);
This is true for all of the team specific methods you have. That is, with a little effort towards design you can achieve a cleaner result.
回答2:
Set an additional variable for each team, updating its values each time a button is pressed. This version would only be able to undo the very last action. If you want to be able to undo all previous added values, you would have to use a list of all previously added values.
Example for team A:
int lastAddA=0;
public void addThreeforTeamA(View v) {
scoreTeamA+=3;
lastAddA = 3;
displayForTeamA(scoreTeamA);
}
public void undoLastTeamA(View v) {
scoreTeamA-=lastAddA;
lastAddA = 0;//Reset to default
displayForTeamA(scoreTeamA);
}
来源:https://stackoverflow.com/questions/40052574/how-can-i-do-a-return-back-button-in-java