I'm trying to clean my code to make it run under 'sections'.
There's one called intro(), another one called second() and so on..
The issue comes when I switch from the first section of code (intro()) to the next one (second()) which should run a cleaning code first, but doesn't really!
The code basically writes text on a list which should look like a chat, so the intro() is the first part of text then it should clear the chat and start writing other text inside second().
This is my code, take a look:
int counter;
boolean introDone = false;
//Intro
public void intro(){
write(answers[counter], buttonText[counter]);
}
public void second(){
write("So these are the rules:", R.string.go);
}
public void hello(View view){
Toast toast = Toast.makeText(this, Integer.toString(counter), Toast.LENGTH_SHORT);
toast.show();
if(counter <= 2){
intro();
}else if(counter == 3){
clear();
}else if (counter > 2 && counter < 5) {
second();}
counter++;
}
}
This did the trick:
//Intro
public void intro(){
write(answers[counter], buttonText[counter]);
}
public void second(){
write("So these are the rules:", R.string.go);
}
public void hello(View view) {
Toast toast = Toast.makeText(this, Integer.toString(counter), Toast.LENGTH_SHORT);
toast.show();
if (counter <= 2) {
intro();
} else if(counter == 3) {
introDone = true;
}
if (introDone) {
clear();
introDone = false;
}
if (counter > 2 && counter < 5) {
second();
}
counter++;
}
}
How is the variable counter and the variable introDone initialized?
I assume that the variable counter have the value 0 at the start of the program, and the variable introDone is false. If that is the case, then the code into second section isn't executed. Example:
public void hello(View view){
// --> here, counter=0 and introDone=false
Toast toast = Toast.makeText(this, Integer.toString(counter), Toast.LENGTH_SHORT);
toast.show();
intro(); // --> counter is still 0, so the variable introDone is still false
second(); // --> because introDone=false then the code is not executed
counter++;
}
I'm going to assume that the boolean introDone variable is never true. In your intro() method you have it wrapped with an if statement to check if the counter is 2 or less. It is hard to tell without the full source, but I would guess that if you changed your code to this:
//Intro
public void intro(){
//if (counter <= 2) {
// write(answers[counter], buttonText[counter]);
//}else{
introDone = true;
//}
}
public void second(){
if(introDone) {
listViewMother.setAdapter(null); //THIS SHOULD CLEAN THE LIST, BUT INSTEAD WHEN I RUN THE CODE IT LOOKS LIKE IT JUST IGNORES IT
if (counter > 2 && counter < 5) {
write("So these are the rules:", R.string.go);
}
}
}
public void hello(View view){
Toast toast = Toast.makeText(this, Integer.toString(counter), Toast.LENGTH_SHORT);
toast.show();
intro();
second();
counter++;
}
everything would work fine.
From there you could look at the logic around how you increment the counter variable and see if that was the issue.
This example will run call intro() and second() 10 times.
public void hello(View view){
Toast toast = Toast.makeText(this, Integer.toString(counter), Toast.LENGTH_SHORT);
toast.show();
for (int counter = 0; counter < 10; counter++) {
intro();
second();
}
}
Related
Working on a one tutorial. Decided to implement the method logic to decrement or increment the array index. Somehow, it is still going outside the size of my array. Why is it happening?
mTrueButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Toast toast = Toast.makeText(getApplicationContext(),"You are right!", Toast.LENGTH_SHORT);
toast.setGravity(Gravity.CENTER_VERTICAL, 0, 0);
toast.show();
mTextView = (TextView) findViewById(R.id.question_text_view);
mTextView.setText(mQuestionBank[mIndex].getQuestionId());
updateQuestionTrue();
}
});
mFalseButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Toast toast = Toast.makeText(getApplicationContext(),"Nope...", Toast.LENGTH_SHORT);
toast.setGravity(Gravity.CENTER_VERTICAL, 0, 0);
toast.show();
mTextView = (TextView) findViewById(R.id.question_text_view);
mTextView.setText(mQuestionBank[mIndex].getQuestionId());
updateQuestionFalse();
}
});
Here is the wrong logic method. Could you explain me, why it is going outside the size of my array?
private void updateQuestionTrue() {
mIndex++;
if(mIndex == mQuestionBank.length) {
mIndex = 0;
}
}
private int updateQuestionFalse() {
mIndex--;
if(mIndex == 0) {
mQuestionBank[0].getQuestionId();
}
return 0;
}
You should ensure that your index will always be in a valid range based on the length of your array. You can try the following
private void updateQuestionTrue() {
if(mIndex + 1 >= mQuestionBank.length) {
mIndex = 0;
}
else
mIndex++;
}
private int updateQuestionFalse() {
if(mIndex - 1 <= 0) {
//mIndex = mQuestionBank.length - 1; //too loop back around
mIndex = 0; //or to keep the index at 0 once you are as far back as possible
}
else
mIndex--;
return mIndex;
}
You can also use my personal favorite, ternary operator
private void updateQuestionTrue() {
mIndex = mIndex + 1 >= mQuestionBank.length ? 0 : ++mIndex;
}
private int updateQuestionFalse() {
return (mIndex = mIndex - 1 <= 0 ? 0 : --mIndex);
}
Just as updateQuestionTrue() sets mIndex to 0 when it would otherwise equal mQuestionBank.length, updateQuestionFalse() should set mIndex to mQuestionBank.length - 1 when it would otherwise be less than 0. In this way, it will loop to the end when you go back before the start, just as it loops to the start when you go off the end.
I'm not sure what mQuestionBank[0].getQuestionId(); does in your code, though.
I am new to android and java and im trying my best to do a simple game called rockpaper scissor.
I am wondering why does my code cScore = 0; wont appear at the same time with yScore=0. I need to press again the rock button to reset the cScore back to 0.
Please help, any kind of suggestions will do.
thanks.
public class MainActivity extends AppCompatActivity {
TextView youOutput, compOutput, youScore, compScore;
int yScore=0, cScore=0, cPicked;
Random abc = new Random();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
youOutput =(TextView)findViewById(R.id.youOutput);
compOutput = (TextView)findViewById(R.id.compOutput);
youScore = (TextView)findViewById(R.id.youScore);
compScore = (TextView)findViewById(R.id.compScore);
}
public void rockButton(View view) {
youOutput.setText("Rock");
cPicked = 1+abc.nextInt(3);
if (cPicked == 1) {
compOutput.setText("Rock");
compScore.setText(Integer.toString(cScore));
youScore.setText(Integer.toString(yScore));
} else if(cPicked == 2) {
compOutput.setText("Paper");
cScore++;
if(cScore == 10){
cScore = 0;
yScore = 0;
Toast.makeText(this, "Computer won", Toast.LENGTH_LONG).show();
}else
compScore.setText(Integer.toString(cScore));
youScore.setText(Integer.toString(yScore));
} else {
compOutput.setText("Scissor");
yScore++;
if(yScore == 10){
cScore = 0;
yScore = 0;
Toast.makeText(this, "You won", Toast.LENGTH_LONG).show();
}else
compScore.setText(Integer.toString(cScore));
youScore.setText(Integer.toString(yScore));
}
}
Add curly brackets in last else block and else block in if (cPicked == 2)
if (cPicked == 1) {
compOutput.setText("Rock");
compScore.setText(Integer.toString(cScore));
youScore.setText(Integer.toString(yScore));
} else if (cPicked == 2) {
compOutput.setText("Paper");
cScore++;
if (cScore == 10) {
cScore = 0;
yScore = 0;
Toast.makeText(this, "Computer won", Toast.LENGTH_LONG).show();
//added curly brackets
} else {
compScore.setText(Integer.toString(cScore));
youScore.setText(Integer.toString(yScore));
}
} else {
compOutput.setText("Scissor");
yScore++;
if (yScore == 10) {
cScore = 0;
yScore = 0;
Toast.makeText(this, "You won", Toast.LENGTH_LONG).show();
//added curly brackets
} else {
compScore.setText(Integer.toString(cScore));
youScore.setText(Integer.toString(yScore));
}
}
I have found that my method called checkForErrors takes around 80x longer to run on the first execution only, and I can't seem to figure out why.
D/guess: adhl
D/checkerror: checking for errors took 4760743ns // first run
D/validity: checking guess validity took 7141114ns
D/guess: agkl
D/checkerror: checking for errors took 61035ns // every other run takes around this long
D/validity: checking guess validity took 732422ns
I have looked through the code and I don't see anything that would take longer on the first run only so I'm stumped.
Button on click listener:
submitBtn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
String Guess = guess_txt.getText().toString();
Log.d("guess", Guess);
if(checkGuessValidity(Guess)){ // <--
submitValidGuess(Guess);
int bulls = game.getBullsAndHits()[0];
int hits = game.getBullsAndHits()[1];
if(!game.gameWon) //if game is not won, submit the guess with bulls and hits
guessSubmittedListener.guessSubmitted(Guess, bulls, hits);
else //if game is won, call gameWon() method
gameEnd();
}
if((game.getCurrentTry() > game.getMaxTries()) && (!Guess.equals(game.getHiddenWord()))) gameEnd(); //if user is out of tries, call gameLost method
triesLeft.setText("Tries Left: " + (game.getMaxTries() - game.getCurrentTry() + 1)); //update tries left on main fragment
guess_txt.setText("");
}
});
checkGuessValidity:
public boolean checkGuessValidity(String Guess){
long start = System.nanoTime();
long start2 = System.nanoTime();
ErrorList Status = checkForErrors(Guess); // <--
long end2 = System.nanoTime();
Log.d("checkerror", "checking for errors took " + (end2 - start2) + "ns");
. . . more code . . .
checkForErrors:
public ErrorList checkForErrors(String Guess){
if(Guess.length() != game.getHiddenWordLength()) return ErrorList.Wrong_Length;
else if(!isValidInput(Guess)) return ErrorList.Invalid_Characters;
else if(!isIsogram(Guess)) return ErrorList.Not_Isogram;
else if(!isLowercase(Guess)) return ErrorList.Not_Lowercase;
else return ErrorList.OK;
}
isValidInput, isIsogram and isLowercase:
public boolean isIsogram(String Guess){
Map<Character, Boolean> map = new HashMap();
for(int i = 0; i < Guess.length(); i++){
if(map.get(Guess.charAt(i)) == null) //if the value for the key (character) is null (has not been changed since map initialization)
map.put(Guess.charAt(i), true); //then set it to true (indicating that it has been seen)
else { //else (if the value at the character HAS been changed since initialization, ie. it has been seen)
Log.d("Character repeated", "" + Guess.charAt(i));
return false; //return false
}
}
return true; //if loop completes no duplicates were found and guess is an isogram
}
public boolean isLowercase(String Guess){
if(Guess.equals(Guess.toLowerCase())) return true;
else return false;
}
public boolean isValidInput(String Guess){
char[] chars = Guess.toCharArray();
for(int i = 0; i < chars.length; i++){
if(!isLatinLetter(chars[i])) return false;
}
return true;
}
public static boolean isLatinLetter(char c) {
return (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z');
}
It doesn't seem like any of the methods should be impacted by when they are run, so I don't know why it takes extra long on the first execution. I'm still a beginner to programming so please excuse any poor formatting or horribly optimized code :p .
edit: CPU usage graph: https://prnt.sc/ftjokq
I am using a menu option to set the time for a game. By default the time is set to 10 seconds. The user can set the time by clicking on the menu and then selecting a choice. I am using a custom view, so the method for changing the time is in a different class than the view.
When the user clicks on the menu option a dialog appears with a EditText as its view. The user enter a number between 5 and 60. I have to wait an entire game cycle for the time to change, so it should change on the next game..
but it does not..
It will only change if I try and change the time again.
Ex)
I change the time to 5 seconds the first time I play, expecting it to change to 5 seconds the next game cycle. In the next game cycle it does not change to 5. It will stay at the previous time. I change the time again to 30 seconds. Next game cycle, the timer now appears to have 5 seconds. If I change the time again to 40, it will appear 30.
This is where I am changing the time, on each newgame();
static int timeRemaining = 10;
public void newGame() {
timeLeft = timeRemaining; // start the countdown
// do other stuff
This is where I ask the user for input, and change the variable timeRemaining. Keep in mind they are in different classes.
#Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
if (id == R.id.action_settings) {
AlertDialog.Builder dialog;
dialog = new AlertDialog.Builder(this);
final EditText input = new EditText(this);
dialog.setTitle("Enter the time limit");
dialog.setView(input);
dialog.setPositiveButton("Done", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
getInput = input.getText().toString();
try{
result = Integer.parseInt(getInput);
}catch(InputMismatchException e){
CannonView.timeRemaining = 10;
Toast.makeText((Context) getApplicationContext(), "Enter an integer", Toast.LENGTH_SHORT).show();
}
if(result < 5){
Toast.makeText((Context) getApplicationContext(), "Invalid input", Toast.LENGTH_SHORT).show();
} else if (result > 60) {
Toast.makeText((Context) getApplicationContext(), "Invalid input", Toast.LENGTH_SHORT).show();
}
Toast.makeText((Context) getApplicationContext(), "Time set changed next game", Toast.LENGTH_SHORT).show();
}
});
AlertDialog box = dialog.create();
box.show();
if(result < 5 || result > 60){
CannonView.timeRemaining = 10;
return true;
}else{
CannonView.timeRemaining = result;
return true;
}
}
return super.onOptionsItemSelected(item);
}
I change the timeRemaining here, but it does not update until I change it again. Any suggestions?
I think the error is you do not put the follwing in the onClickListener
if(result < 5 || result > 60)
CannonView.timeRemaining = 10;
else CannonView.timeRemaining = result;
It should be like this
dialog.setPositiveButton("Done", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
// your original code
if(result < 5 || result > 60)
CannonView.timeRemaining = 10;
else CannonView.timeRemaining = result;
});
Hi im trying to get a button to flash, I have tried to change the background with a loop, but not having much luck any suggestions thanks
int count = 0;
while (count < 10000) { // test: boolean test within (..)
if (count % 2 != 0) {
helpt.setBackgroundColor(getResources().getColor(R.color.Blue));
}
else {
helpt.setBackgroundColor(getResources().getColor(R.color.Red));
}
count = count + 1;
}
This will change the colour every one second:
int count = 0; //Declare as instance variable
Activity activity; //Declare as instance variable
//Inside onCreate()
activity = this;
new Timer().schedule(new TimerTask() {
#Override
public void run() {
activity.runOnUiThread(new Runnable() {
public void run() {
if (count < 10000) {
if (count % 2 != 0) {
helpt.setBackgroundColor(getResources()
.getColor(android.R.color.black));
} else {
helpt.setBackgroundColor(getResources()
.getColor(android.R.color.white));
}
count = count + 1;
}
}
});
}
}, 0, 1000);
You dont have any form of delay, of course you wouldn't see it flash. It will run through that loop very quickly. Also for standards you should be using a for loop, not a while. For is explicityly for when you know how many times you are going to run.