I am following a tutorial I found on youtube on creating a basic RPG with a GUI. The tutorial is very helpful in giving directions on how to handle panels and frames, but the way they handle user decisions seems very impractical. They have a switch case that uses the player's location, and then another switch case within that then handles the actions depending on what button the user enters. Im not saying that it doesn't get the job done, but it leads me to have a LONG switch case. I was wondering what would be the best approach to have a cleaner and more manageable code.
snippet of the code:
//depending on your position, you are given different action options
switch(position) {
//if you are in town, these are your options
case "townGate":
switch(yourOption) {
//talk to the guard
case "c1": talkGaurd(); break;
//attack the guard
case "c2": attackGuard(); break;
}
break;
//if you are talking to the guard, these are your options
case "talkingToGaurd":
switch(yourOption) {
//leave to the outside of the gate
case "c1": townGate(); break;
}
break;
//if you are attacking the guard, these are your options
case "attackingGuard":
switch(yourOption) {
//leave the the outside of the gate
case "c1": townGate(); break;
}
break;
}
Related
So I have a POJO with a question, and in my recycler I wanna show a question itself with answers and correct answer should have the background color.
When I try to add background color, items get colored based on some serious magic.
First few items do not get any color, and closer to the bottom of the recycler here is what happens.
enter image description here
The further the better, when I scroll from the bottom to the top, items at the top get the color as well.
public void bind(Question question) {
int correctAnswerNumber = question.getCorrectAnswer();
switch (correctAnswerNumber) {
case 1:
answer1.setBackground(AppCompatResources.getDrawable(context, R.drawable.correct_answer_border));
break;
case 2:
answer2.setBackground(AppCompatResources.getDrawable(context, R.drawable.correct_answer_border));
break;
case 3:
answer3.setBackground(AppCompatResources.getDrawable(context, R.drawable.correct_answer_border));
break;
case 4:
answer4.setBackground(AppCompatResources.getDrawable(context, R.drawable.correct_answer_border));
break;
}
}
The context here is passed from the activity, and I have to ideas what to do.
I tried to remove the logic to the constructor, change the context, address items through holder, didn't change much.
You have a classic case of "stale state from a recycled view item".
Your Problem
You only set the background for a correct answer. When that item view is recycled and used for an incorrect answer, you are not updating it and it keeps the old background that was set on it.
The Solution
Always explicitly set the full state of a recycler item view. In this case, set the background for whatever it should be when it's not a correct answer.
public void bind(Question question) {
int correctAnswerNumber = question.getCorrectAnswer();
// Reset all backgrounds to default before setting the current correct one
answer1.setBackground(getDefaultBackgroundBorder());
answer2.setBackground(getDefaultBackgroundBorder());
answer3.setBackground(getDefaultBackgroundBorder());
answer4.setBackground(getDefaultBackgroundBorder());
switch (correctAnswerNumber) {
case 1:
answer1.setBackground(AppCompatResources.getDrawable(context, R.drawable.correct_answer_border));
break;
case 2:
answer2.setBackground(AppCompatResources.getDrawable(context, R.drawable.correct_answer_border));
break;
case 3:
answer3.setBackground(AppCompatResources.getDrawable(context, R.drawable.correct_answer_border));
break;
case 4:
answer4.setBackground(AppCompatResources.getDrawable(context, R.drawable.correct_answer_border));
break;
}
}
I'm making a method wherein it has several choices and each of those choices , once selected, need to have the "cancel" button go back to the main menu.
Main Menu:
public static void start(){
String[] choices = {"1. Routines for Triangles","2. Routines for Temperatures","3. Routines for Geometric Figures","4. String Manipulations",
"5. Miscellaneous Simple Games.","6. Quit"};
String menu = (String) JOptionPane.showInputDialog(null,"choose","Main menu",JOptionPane.QUESTION_MESSAGE,null,choices,choices[0])
while (menu != null){
switch (menu){
case "1. Routines for Triangles":
triangleRoutines(); //one sub menu
break;
case "2. Routines for Temperatures":
break;
case "3. Routines for Geometric Figures":
break;
case "4. String Manipulations":
break;
case "5. Miscellaneous Simple Games.":
break;
case "6. Quit":
break;
}
}
}
A sub menu:
private static void triangleRoutines(){
String[] stringArray = {"Determine the Type of Triangle", "Determine a Valid Triangle", "Determine the Area of the Sides of a Triangle", "Determine a Pythagorean Triple",
};
String reply = (String) JOptionPane.showInputDialog(null, "Choose what you want to do today", "Triangle Processes", JOptionPane.QUESTION_MESSAGE,
null, stringArray, stringArray[0]);
switch (reply){
case "Determine the Type of Triangle":
break;
case "Determine a Valid Triangle":
break;
case "Determine the Area of the Sides of a Triangle":
break;
case "Determine a Pythagorean Triple":
break;
}
}
When a JOptionPane.showInputDialog() dialog is Canceled or Closed without a selection being made then a null is returned. you need to handle this null and act upon it accordingly but you will need to decide what you want to do when it does happen. Close the application, re-display the Main Menu dialog and force the Quit menu option to be selected, etc.
To always keep your Main Menu available place it within the while loop, for example:
String[] choices = {"1. Routines for Triangles", "2. Routines for Temperatures",
"3. Routines for Geometric Figures", "4. String Manipulations",
"5. Miscellaneous Simple Games.", "6. Quit"};
String menu = "";
while (!menu.equals("6. Quit")) {
menu = (String) JOptionPane.showInputDialog(null, "<html>Choose A Menu Item:<br><br></html>", "Main Menu",
JOptionPane.QUESTION_MESSAGE, null, choices, choices[0]);
if (menu == null) {
//continue; //uncomment and delete line below to force menu item 6 to be selected to quit Main Menu.
break; //Quit the Main Menu
}
switch (menu) {
case "1. Routines for Triangles":
triangleRoutines(); //one sub menu
break;
case "2. Routines for Temperatures":
break;
case "3. Routines for Geometric Figures":
break;
case "4. String Manipulations":
break;
case "5. Miscellaneous Simple Games.":
break;
case "6. Quit":
// This case is not really required unless you want to
// do some cleanup of sorts before quiting.
break;
}
}
Utilize the same technique for your methods which contain sub-menus but add a menu option to: Return To Main Menu and perhaps one more additional option to: Quit Application if desired.
The best approach would be to implement the Command design pattern.
However, if the point is that the triangleRoutines needs to return to the previous menu, then given the overall current approach, I think making a modification on where the menu is presented would work. I'm not positive that is the OP's question, but I believe so.
See the comments in the example code for additional details.
Not tested, but something like:
private static void triangleRoutines() {
...
// if the program is done, can return null
// if cancel, then return anything but null
return "";
}
Then
do {
// get the menu from the top level
String menu = (String) JOptionPane.showInputDialog(null,"choose","Main menu",JOptionPane.QUESTION_MESSAGE,null,choices,choices[0])
switch (menu){
case "1. Routines for Triangles":
// if cancel, then will return empty string, and then
// re-present the main menu
triangleRoutines(); //one sub menu
break;
...
case "6. Quit":
menu = null;
break;
} //switch
} while (menu != null);
Thus, in the triangleRoutines() one can "cancel" and it will return an empty String, which is not null, so it will present the top level menu again. If one wants to exit from the submenu triangleRoutines() then return null, and the program will exit.
Again, I might have misunderstood the specific question.
I've tried quite a few different tactics to achieve my desired result, but nothing is making these buttons do what they're 'sposed to... Basically I have 14 buttons. Four with the text "X", digitOne, digitTwo, digitThree and digitFour. Then, there are 10 with "1", "2", etc, named "one", "two", etc. All the buttons are tied to the same OnClickListener that will use a switch statement to determine which button was pressed, then find the soonest display button (buttons initially marked "X"), and change that buttons text to the entered digit. What I want to happen is:
Say someone clicks the "5" button. If its the first button pressed, the first "digit" button will change from displaying "X" to "5", and so-on, so-forth. This is not what is happening... In fact, nomatter what I've tried, nothing is happening. Not even an error... An error would be nice, at least I'd know where my logical flaw is -_-. Here's the code:
The button declarations:
one=(Button)findViewById(R.id.button1);
two=(Button)findViewById(R.id.Button2);
three=(Button)findViewById(R.id.Button3);
four=(Button)findViewById(R.id.Button4);
five=(Button)findViewById(R.id.Button5);
six=(Button)findViewById(R.id.Button6);
seven=(Button)findViewById(R.id.Button7);
eight=(Button)findViewById(R.id.Button8);
nine=(Button)findViewById(R.id.Button9);
zero=(Button)findViewById(R.id.Button0);
add=(Button)findViewById(R.id.buttonAdd);
digitOne=(Button)findViewById(R.id.Number1);
digitTwo=(Button)findViewById(R.id.Number2);
digitThree=(Button)findViewById(R.id.Number3);
digitFour=(Button)findViewById(R.id.Number4);
one.setOnClickListener(listener);
two.setOnClickListener(listener);
three.setOnClickListener(listener);
four.setOnClickListener(listener);
five.setOnClickListener(listener);
six.setOnClickListener(listener);
seven.setOnClickListener(listener);
eight.setOnClickListener(listener);
nine.setOnClickListener(listener);
zero.setOnClickListener(listener);
The OnClickListener private inner class (I guess that's what you'd call it. It's inside Activity class):
private OnClickListener listener = new OnClickListener(){
public void onClick(View button) {
switch(button.getId()){
case R.id.Button0:
addANumber(0);
break;
case R.id.button1:
addANumber(1);
break;
case R.id.Button2:
addANumber(2);
break;
case R.id.Button3:
addANumber(3);
break;
case R.id.Button4:
addANumber(4);
break;
case R.id.Button5:
addANumber(5);
break;
case R.id.Button6:
addANumber(6);
break;
case R.id.Button7:
addANumber(7);
break;
case R.id.Button8:
addANumber(8);
break;
case R.id.Button9:
addANumber(9);
break;
}
}
};
And finally, the "addANumber" method being called:
public void addANumber(int i){
if(digitOne.getText()=="X"){
digitOne.setText(i);
}else if(digitTwo.getText()=="X"){
digitTwo.setText(i);
}else if(digitThree.getText()=="X"){
digitThree.setText(i);
}else if(digitFour.getText()=="X"){
digitFour.setText(i);
}
}
I've done this before... I know I'm missing something so blatantly stupid it deserves a smack in the head...
Before all:
digitOne.getText()=="X" should be "X".equals(digitOne.getText())
you need checking for string equality in terms of content, not in term of reference.
Nothing happens because with == none of your if condition is evaluated to true and addANumber() simply results as an empty method
This is a fairly simple question I am sure, but I can't seem to figure out a way around this little thing. First, here is my code:
switch (event.getAction() & MotionEvent.ACTION_MASK) {
case MotionEvent.ACTION_DOWN:
Log.w("Platformer", "primary down");
break;
case MotionEvent.ACTION_UP:
Log.w("Platformer", "primary up");
break;
case MotionEvent.ACTION_POINTER_1_DOWN:
Log.w("Platformer", "secondary down");
break;
case MotionEvent.ACTION_POINTER_1_UP:
Log.w("Platformer", "secondary up");
break;
}
All I wanted it to do was when I pressed down, it would show me in the log whether the primary or secondary pointer was down, and when I release, do the same thing. The problem is, it always works on the down, but on up, whatever the 1st finger that comes up is, regardless of if it was the primary or secondary pointer originally, it returns that the secondary pointer was removed. Any idea around this? I am guessing it is something simple, but I don't know where to look truthfully. Thanks in advance.
WWaldo
ACTION_UP means that the gesture is over, that is, all pointers are up.
ACTION_POINTER_UP means that a non-primary pointer is up, you'll have to check the event to figure out which, i.e.:
int pointerIndex = (event.getAction() & MotionEvent.ACTION_POINTER_INDEX_MASK) >>
MotionEvent.ACTION_POINTER_INDEX_SHIFT;
int pointerId = event.getPointerId(pointerIndex)
ACTION_POINTER_1_UP and ACTION_POINTER_2_UP are deprecated now.
You should note that this is extremely buggy on Android versions less than Gingerbread. I find that if I lift the first of two touches and place it back down, the pointers swap index and ID. Very frustrating.
Use getPointerId to get which pointer is being selected.
Edit
To answer the question in the comment, try:
for (int i = 0; i < ev.getPointerCount(); i++) {
switch (ev.getAction() & MotionEvent.ACTION_MASK) {
case MotionEvent.ACTION_DOWN:
case MotionEvent.ACTION_POINTER_DOWN:
Log.d(TAG,"down "+ ev.getPointerId(i));
break;
case MotionEvent.ACTION_MOVE:
Log.d(TAG,"move "+ ev.getPointerId(i));
break;
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_POINTER_UP:
Log.d(TAG,"up "+ ev.getPointerId(i));
break;
}
}
I am a self taught programmer, so I do not know the proper ways to do things. I have made simple games like asteroids and snake, but in those games, you can easily modify the variables within the keyevent functions. Here is how I did it in my simple Asteroids game:
/*
* key listener events
*/
public void keyReleased(KeyEvent k){
int keyCode = k.getKeyCode();
switch(keyCode){
case KeyEvent.VK_LEFT:
turnLeft = false;
break;
case KeyEvent.VK_RIGHT:
turnRight = false;
break;
case KeyEvent.VK_UP:
accel = false;
break;
case KeyEvent.VK_1:
cls = true;
break;
case KeyEvent.VK_ENTER:
break;
case KeyEvent.VK_SPACE:
fire = false;
}
}
public void keyTyped(KeyEvent K){}
public void keyPressed(KeyEvent k){
int keyCode = k.getKeyCode();
switch(keyCode){
case KeyEvent.VK_LEFT:
turnLeft = true;
break;
case KeyEvent.VK_RIGHT:
turnRight = true;
break;
case KeyEvent.VK_UP:
accel = true;
break;
case KeyEvent.VK_1:
cls = false;
break;
case KeyEvent.VK_ENTER:
clearAllBullets();
break;
case KeyEvent.VK_SPACE:
fire = true;
}
}
If I were to make a more advanced game (with a main menu, options, main game, etc.) How should I do the key/mouse input?
Also, if I were to go into the single-player, should I put all of the gameplay code into one class? Is there a way to put the single player code into a separate class and somehow have the key input still modify the variables and such?
Thank you for your time!
P.S. Any links or source is extremely appreciated. :D
"Is there a way to put the single player code into a separate class and somehow have the key input still modify the variables and such?"
Yes, there is way to encapsulate all event-based behaviours- http://en.wikipedia.org/wiki/Mediator_pattern but, it can make yor code very complicated, so firstly try to implement your game in more "normal" way.
Anyway - you will need other classes, to present domain model of your game (Player, Gameboard, UserInterfaces etc...)