patternjavaMinor
Simulating character selection with JOptionPane
Viewed 0 times
selectionwithcharactersimulatingjoptionpane
Problem
I am writing a program to simulate some parts of the popular game Hearthstone by Blizzard Entertainment in Java. The first thing that happens in any game is the selection of the character each player will play as, called the "hero." I decided to use
```
//A recreation of the game Hearthstone in Java
//Created 04/17/16 by Trevor B.
//Last updated 04/26/16
import java.util.*;
import javax.swing.*;
public class Hearthstone {
public static void main(String[] args) {
String redName, blueName;
String redClass = null, blueClass = null;
String redHero = null, blueHero = null;
boolean redTurn, blueTurn; //for later
/////////////////////////
Scanner keyboard = new Scanner(System.in);
Random randomizer = new Random(); //for later
//Welcome message
System.out.println("Hearthstone (Redux)\nBy Trevor B.\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~");
//Assigning players
System.out.print("Red player, enter your name: ");
redName = keyboard.nextLine();
System.out.print("Blue player, enter your name: ");
blueName = keyboard.nextLine();
//Picking hero
while(redClass == null || redClass == "Choose one") {
String[] heroes = {
"Choose one",
"Druid",
"Hunter",
"Mage",
"Paladin",
"Priest",
"Rogue",
"Shaman",
"Warlock",
"Warrior"
};
redClass = (String) JOptionPane.showInputDialog(null, redName + ", pick your class", "Red class", JOptionPane.QUESTION_MESSAGE, null, heroes, heroes[0]);
if(redClass == null || redClass == "Choose one") {
System.
JOptionPane to create dialog boxes for this selection for the two players with the below code (which can also be found on GitHub here.```
//A recreation of the game Hearthstone in Java
//Created 04/17/16 by Trevor B.
//Last updated 04/26/16
import java.util.*;
import javax.swing.*;
public class Hearthstone {
public static void main(String[] args) {
String redName, blueName;
String redClass = null, blueClass = null;
String redHero = null, blueHero = null;
boolean redTurn, blueTurn; //for later
/////////////////////////
Scanner keyboard = new Scanner(System.in);
Random randomizer = new Random(); //for later
//Welcome message
System.out.println("Hearthstone (Redux)\nBy Trevor B.\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~");
//Assigning players
System.out.print("Red player, enter your name: ");
redName = keyboard.nextLine();
System.out.print("Blue player, enter your name: ");
blueName = keyboard.nextLine();
//Picking hero
while(redClass == null || redClass == "Choose one") {
String[] heroes = {
"Choose one",
"Druid",
"Hunter",
"Mage",
"Paladin",
"Priest",
"Rogue",
"Shaman",
"Warlock",
"Warrior"
};
redClass = (String) JOptionPane.showInputDialog(null, redName + ", pick your class", "Red class", JOptionPane.QUESTION_MESSAGE, null, heroes, heroes[0]);
if(redClass == null || redClass == "Choose one") {
System.
Solution
Assignement
I don't like multiple assignment per line. I find it difficult to discern what is value, what is a variable and add a little bit of mental compute time to read the code. Not a big deal, but I suggest you to keep one variable assignment per line.
String equality
The way you are doing
So the lesson is to always use the method
Enum
If you don't know what an
So what can be an enum here ? Well the Hero class is a really good one! Let's see how I would do it :
What is
Player class
You should introduce a
Refactoring
Let's start with choosing the alternate hero. What do you have is something like :
What is common each time you want to make the user choose an alternate hero ? The choices of hero is always depending on the class you have, that's one thing. Which player is choosing will always change depending on who's turn is it to choose and that's it. So let's make a method with those two things as parameters!
Let's tackle the hero selection. What is common between what the red player and the blue player have to do ? The classes are the same for both of them so we should re-use our new
I don't like multiple assignment per line. I find it difficult to discern what is value, what is a variable and add a little bit of mental compute time to read the code. Not a big deal, but I suggest you to keep one variable assignment per line.
String equality
The way you are doing
String equality works but it's not the right way to do it. When you do redClass == "Paladin" what you are really comparing is address of object in memory. What is the trap in Java is that String are most of the time a constant and thus share the same address but let's try to break String equality :String redClass = new String("Paladin");
System.out.println("Paladin" == redClass); //Output false
System.out.println("Paladin".equals(redClass));//Output trueSo the lesson is to always use the method
equals if you want to check for equality and use == if you want to make sure you have the same object.Enum
If you don't know what an
Enum is you should really learn it! Here is the Java tutorial for enum : https://docs.oracle.com/javase/tutorial/java/javaOO/enum.html.So what can be an enum here ? Well the Hero class is a really good one! Let's see how I would do it :
public enum Classes {
Druid("Malfurion Stormrage"),
Hunter("Rexxar", "Alleria Windrunner"),
Mage("Jaina Proudmoor", "Medivh","Khadgar"),
Paladin("Uther Lightbringer", "Lady Liadrin"),
Priest("Anduin Wrynn"),
Rogue("Valeera Sanguinar"),
Shaman("Thrall"),
Warlock("Gul'dan"),
Warrior("Garrosh Hellscream", "Magni Bronzebeard");
private String[] heroNames;
Classes(String... heroNames) {
this.heroNames = heroNames;
}
public String [] getHeroNames() {
return this.heroNames;
}
}What is
heroNames ? It's a small hack in my code that I'll present to you later to keep the abstraction at one level. Ideally, you should have a sub-enum or class to represent hero!Player class
You should introduce a
Player to represent what is particular to one player. From reading your code there is a pattern in the naming that help to find what belongs to the player. [red]Class, [blue]Class, [red]Name, [blue]Name do you see the pattern ? Here is what I used for the Player class :public class Player {
private String name;
private Classes heroClass;
private String heroName;
private String color;
public Player(String color) {
this.color = color;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Classes getHeroClass() {
return heroClass;
}
public void setHeroClass(Classes heroClass) {
this.heroClass = heroClass;
}
public String getHeroName() {
return heroName;
}
public void setHeroName(String heroName) {
this.heroName = heroName;
}
public String getColor() {
return color;
}
}Refactoring
Let's start with choosing the alternate hero. What do you have is something like :
String alternateHeroResponse = null;
while(alternateHeroResponse == null || alternateHeroResponse == "Choose one") {
String[] alternateHeroResponseChoices = {
"Choose one",
"Uther Lightbringer",
"Lady Liadrin"
};
alternateHeroResponse = (String) JOptionPane.showInputDialog(null, redName + ", which hero do you want to use?", "Red hero", JOptionPane.QUESTION_MESSAGE, null, alternateHeroResponseChoices, alternateHeroResponseChoices[0]);
if(alternateHeroResponse == null || alternateHeroResponse == "Choose one") {
System.err.println(redName + " did not pick a hero!");
}
else {
redHero = alternateHeroResponse;
}What is common each time you want to make the user choose an alternate hero ? The choices of hero is always depending on the class you have, that's one thing. Which player is choosing will always change depending on who's turn is it to choose and that's it. So let's make a method with those two things as parameters!
private static String chooseAlternateHero(Player player, String[] heroNames) {
String alternateHeroResponse = null;
while (alternateHeroResponse == null) {
alternateHeroResponse = (String) JOptionPane.showInputDialog(null,
player.getName() + ", which hero do you want to use?", player.getColor() + " hero",
JOptionPane.QUESTION_MESSAGE, null, heroNames, "Choose one");
if (alternateHeroResponse == null) {
System.err.println(player.getName() + " did not pick a hero!");
}
}
return alternateHeroResponse;
}Let's tackle the hero selection. What is common between what the red player and the blue player have to do ? The classes are the same for both of them so we should re-use our new
Enum Classes for it. Since our Enum contaCode Snippets
String redClass = new String("Paladin");
System.out.println("Paladin" == redClass); //Output false
System.out.println("Paladin".equals(redClass));//Output truepublic enum Classes {
Druid("Malfurion Stormrage"),
Hunter("Rexxar", "Alleria Windrunner"),
Mage("Jaina Proudmoor", "Medivh","Khadgar"),
Paladin("Uther Lightbringer", "Lady Liadrin"),
Priest("Anduin Wrynn"),
Rogue("Valeera Sanguinar"),
Shaman("Thrall"),
Warlock("Gul'dan"),
Warrior("Garrosh Hellscream", "Magni Bronzebeard");
private String[] heroNames;
Classes(String... heroNames) {
this.heroNames = heroNames;
}
public String [] getHeroNames() {
return this.heroNames;
}
}public class Player {
private String name;
private Classes heroClass;
private String heroName;
private String color;
public Player(String color) {
this.color = color;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Classes getHeroClass() {
return heroClass;
}
public void setHeroClass(Classes heroClass) {
this.heroClass = heroClass;
}
public String getHeroName() {
return heroName;
}
public void setHeroName(String heroName) {
this.heroName = heroName;
}
public String getColor() {
return color;
}
}String alternateHeroResponse = null;
while(alternateHeroResponse == null || alternateHeroResponse == "Choose one") {
String[] alternateHeroResponseChoices = {
"Choose one",
"Uther Lightbringer",
"Lady Liadrin"
};
alternateHeroResponse = (String) JOptionPane.showInputDialog(null, redName + ", which hero do you want to use?", "Red hero", JOptionPane.QUESTION_MESSAGE, null, alternateHeroResponseChoices, alternateHeroResponseChoices[0]);
if(alternateHeroResponse == null || alternateHeroResponse == "Choose one") {
System.err.println(redName + " did not pick a hero!");
}
else {
redHero = alternateHeroResponse;
}private static String chooseAlternateHero(Player player, String[] heroNames) {
String alternateHeroResponse = null;
while (alternateHeroResponse == null) {
alternateHeroResponse = (String) JOptionPane.showInputDialog(null,
player.getName() + ", which hero do you want to use?", player.getColor() + " hero",
JOptionPane.QUESTION_MESSAGE, null, heroNames, "Choose one");
if (alternateHeroResponse == null) {
System.err.println(player.getName() + " did not pick a hero!");
}
}
return alternateHeroResponse;
}Context
StackExchange Code Review Q#126755, answer score: 5
Revisions (0)
No revisions yet.