Java question on building HashMap for multiple enums - java

I'm making an RPG game in Java for a school assignment. In the game I take user input and the first word is the "command word", so I create an enum to convert the strings for user input to enum constants:
public enum CommandWord
{
GO("go"), QUIT("quit"), HELP("help"), BACK("back"), LOOK("look"), DROP("drop"), GRAB("grab"), USE("use"), UNKNOWN("?");
private String commandString;
/*
* Initialize with the corresponding command string.
* #param commandString the command string.
*/
CommandWord(String commandString) {
this.commandString = commandString;
}
public String toString()
{
return commandString;
}
Sometimes the second word is a direction following "go" so I have a second enum for directions with more constants:
UP("up"), DOWN("down"), NORTH("north"), SOUTH("south"), EAST("east"), WEST("west"), UNKNOWN("unknown");
I'm trying to come up with the best method for building a HashMap to store strings and the related enum constants. For command words I have this class:
public class CommandWords
{
// A mapping between a command word and the CommandWord
// that is associated with it
private HashMap<String, CommandWord> validCommands;
/**
* Constructor - initialise the command words.
*/
public CommandWords()
{
validCommands = new HashMap<>();
for (CommandWord command : CommandWord.values()) {
if(command != CommandWord.UNKNOWN) {
validCommands.put(command.toString(), command);
}
}
}
/**
* Searches the HashMap of valid commands for the supplied word.
* #param commandWord The word we're searching for.
* #return The CommandWord that is mapped to the supplied string commandWord,
* or UNKNOWN if it is not in valid command.
*/
public CommandWord getCommandWord(String commandWord)
{
CommandWord command = validCommands.get(commandWord);
if (command!= null) {
return command;
}
else {
return CommandWord.UNKNOWN;
}
}
}
Then I can take userinput and search for the command word, but I can't reuse it for directions, or items, characters etc. I looked at using a generic class but I can't call methods like .values() on it, is there a good way to do this so I can reuse the CommandWords class on different enums?

We have valueOf(String) method on Enum, you don't have to build that map.
For your case, you have a value, and you know which Enum type you would like to convert to. So, just use:
CommandWord.valueOf("QUIT");
Items.valueOf("GEM");
etc..
Enums must be determined at compile-time.

Related

Parse Java code between braces using Regex and groups

I am creating some java code that takes correctly written .java files as input, and i want to extract the text between braces using a regular expression. I want to use the Pattern and Matcher classes, and not for loops.
I believe its best to create a regex that groups the text in the whole class, and later another regex that will be aplied to the previous output and groups the text in methods.
I got close to getting the class text using the following regex on online regex testers:
\w\sclass.*\{((.*\s*)*)\}
but i'm pretty sure i am doing it wrong by using two groups instead of just one. Furthermore when i use this expression in Java i am actually getting nothing.
Here is an example file that i am using for debugging
package foo.bar;
import java.io.File;
public class Handy {
{
// static block, dont care!
}
/**
* Check if a string is Null and Empty
* #param str
* #return
*/
public static boolean isNullOrEmpty(String str) {
Boolean result = (str == null || str.isEmpty());
return result;
}
/**
* Mimics the String.format method with a smaller name
* #param format
* #param args
* #return
*/
public static String f(String format, Object... args)
{
return String.format(format, args);
}
}
With the example code above, i expect to get:
entire class text
{
// static block, dont care!
}
/**
* Check if a string is Null and Empty
* #param str
* #return
*/
public static boolean isNullOrEmpty(String str) {
Boolean result = (str == null || str.isEmpty());
return result;
}
/**
* Mimics the String.format method with a smaller name
* #param format
* #param args
* #return
*/
public static String f(String format, Object... args)
{
return String.format(format, args);
}
individual method text
Boolean result = (str == null || str.isEmpty());
return result;
return String.format(format, args);
I know how to use the Pattern and Matcher classes already, i just need the right regexes...
After some confusion in the comments section, i would like to share my solution for what i asked, even if it was not very clear.
This is not thoroughly tested code, but it works for my purpose. Some adjustments or improvements are very likely possible. I took some inspiration from the comments i read in this post, and others like this.
I feed each of the following methods the entire plain text found in a .java file, and from there i use Pattern and Matcher to extract what i want.
private static String patternMatcher(String content, String patternText, int groupIndex) {
Pattern pattern = Pattern.compile(patternText);
Matcher matcher = pattern.matcher(content);
if (matcher.find()) {
return matcher.group(groupIndex);
} else {
return "";
}
}
public static String getPackageName(String content) {
return patternMatcher(content, ".*package\\s+(.*)\\s*\\;", 1);
}
public static String getClassName(String content) {
return patternMatcher(content, ".*class\\s+(\\w+)[\\w\\s]+\\{", 1);
}
public static String getClassCode(String content) {
return patternMatcher(content, ".*class.*\\{((.*\\s*)*)\\}", 1);
}
public static String getMethodName(String code) {
String uncommentedCode = removeComments(code).trim();
return patternMatcher(uncommentedCode,
"(public|private|static|protected|abstract|native|synchronized) *([\\w<>.?, \\[\\]]*)\\s+(\\w+)\\s*\\([\\w<>\\[\\]._?, \\n]*\\)\\s*([\\w ,\\n]*)\\s*\\{",
3);
}
public static String removeComments(String content) {
return content.replaceAll("\\/\\*[\\s\\S]*?\\*\\/|([^:]|^)\\/\\/.*$", "$1 ").trim();
}
I double checked but i hope i didn't forget any escape character, be carefull with those.
Lots of people recomended that i used an actual code parsing library, like ANTLR, but i assumed it would take much longer for me to learn how to work with it, then it would take to do with with RegEx. Furthermore i wanted to improve my Regex skills, this exercise definitely taught me some things.

How to implement code before super without creating another method?

So I want to implement a code that would scramble the words!!
It is a homework assignment question.
Although we are not given the liberty of creating another Method in the class, nor are we allowed to create another field in the class. Everything that we want has to be enclosed within the Constructor parameters.
and then send the word as an argument for super(arg);
Although would it not be illegal and an error if I put any code before super???
Note: I also cannot create any variables outside the constructor.
Note2: ScrambledWordPuzzle is a contructor for class ScrambledWordPuzzle that extends another abstract class
Edit 2: Extra Info
Class to make changes:
public class ScrambledWordPuzzle extends AbstractWordPuzzle {
/**
* The solution to the puzzle
*/
private String solution;
/**
* Creates a scrambled word puzzle given the solution word.
*
* #param solutionWord
* the puzzle word
*/
public ScrambledWordPuzzle(String solutionWord) {
// COMPLETE THIS
// Hint: You need to scramble the letters of the solution word
// to generate the puzzle word and then set the puzzle word.
// The easiest way to scramble the letters is to put them
// into a list, use Collections.shuffle, and then convert the
// the shuffled list of letters back into a string.
super();
this.solution = solutionWord;
}
/**
* Get the solution for this reverse word puzzle.
*
* #return the solution for this reverse word puzzle
*/
#Override
public String getSolution() {
// COMPLETE THIS
return this.solution;
}
}
Abstract Class:
public abstract class AbstractWordPuzzle {
/**
* The puzzle word.
*/
private String puzzle;
/**
* Initializes this puzzle to the empty string.
*/
public AbstractWordPuzzle() {
// COMPLETE THIS
this.puzzle="";
}
/**
* Initializes this puzzle to the specified puzzle word.
*
* #param puzzleWord
* the puzzle word
*/
public AbstractWordPuzzle(String puzzleWord) {
// COMPLETE THIS
this.puzzle=puzzleWord;
}
/**
* Get the solution word. For word puzzles with more than one solution this
* method returns the solution that comes first in dictionary order.
*
* #return the solution word that comes first in dictionary order
*/
public abstract String getSolution();
/**
* Get the puzzle word
*
* #return the puzzle word
*/
public final String getPuzzleWord() {
// ALREADY IMPLEMENTED; DO NOT MODIFY
return this.puzzle;
}
/**
* Set the puzzle word for this puzzle.
*
* #param puzzleWord
* the puzzle word
*/
public final void setPuzzleWord(String puzzleWord) {
// COMPLETE THIS
this.puzzle=puzzleWord;
}
}
I need the code before super() because, if it is after the super code, I will not be able to call the variable or whatever it would be in the super(arg).
Ok, so no methods allowed. Then everything should be inline.
public ScrambledWordPuzzle(String solutionWord) {
super(new MyCollection(solutionWord.split("")).shuffle().toString());
}

How to recommend parameters in java?

Is there any possible way to recommend parameters when I use the method? (Just like annotations?)
I made lots of static final String parameter for url connection and I want to know whether I use right input parameter or not when I code.
Below is my example.
public void myRequest(String inputParameter) {
String requestURL = "";
static final String ex1 = "http://example.com/xml1";
static final String ex2 = "http://example.com/xml2";
static final String ex3 = "http://example.com/xml3";
static final String ex4 = "http://example.com/xml4";
static final String ex5 = "http://example.com/xml5";
static final String ex6 = "http://example.com/xml6";
static final String ex7 = "http://example.com/xml7";
// too many..
// ....
static final String ex125 = "http://example.com/xm125";
if(inputParameter.equals("ex1")) {
requestURL = ex1;
} else if(inputParameter.equals("ex2")) {
requestURL = ex2;
}
// just like this..
// .....
else if(inputParameter.equals("ex125")) {
requestURL = ex125;
}
String requestURL = inputParameter;
URL url = new URL(requestURL);
URLConnection urlConnection = url.openConnection();
// below codes are unnecessary.
}
and I will use that method in the "main" method
public static void main(String[] args) {
myRequest("ex1"); // this!!
}
The point is, when I write the method "myRequest()", IDE will tell me the information about parameter (when the cursor is between '(' and ')'). The only one, that I can be noticed, is "You should write String object." not "You can use ex1 which means loading ex1.xml, ex2 meaning ex2.xml or ... ex125 meaning xm125.xml"
If my hope comes true, the result seems like this.
(Writing the methods)
myRequest(|); // there is cursor between ( and )
"What xml should I request? Umm.. there is ex1 to ex125. Ok.. ex1 means.. my hometown history.. ex2 means my school history.. and Umm.. I should use ex4 ok!"
(And I write below method)
myRequest("ex4");
I want IDE to inform me what String Parameter should I use.
Is there any possible way?
Given your updates to the question, the answer is build around enums and maps.
In other words: you simply, never ever put down a list of constants like you do there; that are then "mapped" (by hard wiring in your code; as you do in your example) to some other incoming strings.
Instead: you could use an enum to hold those constants; and you could also add some method to that enum class that knows how to map incoming strings to the available enum constants.
But the main point is: you want to abandon "raw" strings. The IDE (respectively the compiler) can't help you with adding an "ext1" string as method parameter.
But when you have:
public enum ExUrls {
EX1("http://example.com/xml1"), EX2("...
... a private constructor that takes that url string)
then you do:
void someMethod(ExURls ex) {
and all of a sudden, the IDE will be able to suggest the all potential ExUrl constants to you!
I'm not sure if I got your question right but you can use javadocs.
Here is an example from oracle.
/**
* Returns an Image object that can then be painted on the screen.
* The url argument must specify an absolute {#link URL}. The name
* argument is a specifier that is relative to the url argument.
* <p>
* This method always returns immediately, whether or not the
* image exists. When this applet attempts to draw the image on
* the screen, the data will be loaded. The graphics primitives
* that draw the image will incrementally paint on the screen.
*
* #param url an absolute URL giving the base location of the image
* #param name the location of the image, relative to the url argument
* #return the image at the specified URL
* #see Image
*/
public Image getImage(URL url, String name) {
try {
return getImage(new URL(url, name));
} catch (MalformedURLException e) {
return null;
}
}
All you need to do is type /** and press enter on top of your function then you can add details. These will show up when you hover to its function call.
In your case maybe like this
/**
* This method is very amazing it will cure cancer
* (ex1 - hometown history),
* (ex2 - school history),
* (ex3 - blah blah),
* (ex4 - what is the meaning of life),
* ...
* (ex125 - choose this)
*
* #param inputParameter - (String) You can input ex1 up to ex125
*/
public void myRequest(String inputParameter) {
but if you're looking to restrict input to ex1-ex125 only you need something else.

Binary tree variable type issue

I'm having trouble with a method I wrote to insert string words into a binary tree. The below code is the method in question. Basically, the word is inserted if it is not yet in the tree (as a BinaryTreeNode), and if it is in the tree, its frequency (count variable within BinaryTreeNode) is increased by one. My problem is with the temporary variable searchWord. Defining it as a String creates a type mismatch and a statement that says getFrequency() is not defined for type String. The generic type T is only there as a placeholder - it too does not work. What should it therefore be defined as?
buildBinaryTree method:
public static void buildBinaryTree(String word) {
//if word is already in tree
if(wordTree.contains(word)) {
//find existing word node
T searchWord = wordTree.find(word); //problem here
//increment frequency by 1
searchWord.setFrequency(searchWord.getFrequency() + 1);
} else {
//add word to tree
System.out.println(word);
wordTree.addElement(word);
}
}
BinaryTreeNode constructor:
/**
* Creates a new tree node with the specified data.
* #param obj the element that will become a part of the new tree node
*/
BinaryTreeNode(T obj) {
element = obj;
left = null;
right = null;
frequency = 1;
}
Frequency get/set methods:
/**
* Gets the frequency.
* #return the frequency
*/
public int getFrequency() {
return frequency;
}
/**
* Sets the frequency.
* #param frequency the frequency to set
*/
public void setFrequency(int frequency) {
this.frequency = frequency;
}
After talking in chat, you should define a class that has both a String and int that you use as the type to place in the binary tree, to replace the type variable T. Then, you can define methods such as getString() to return the String, incrementFrequency() to add one to the frequency, etc. When you get an object out of the binary tree, it will be the right type to call these methods.

Searching through an ArrayList

Implement a method
public void search (String searchString) { }
to iterate through the notes ArrayList until it
finds a note that contains the searchString.
It should then print either the item found or
the message "String not found".
So far, I have:
import java.util.ArrayList;
import java.util.Iterator;
/**
* A class to maintain an arbitrarily long list of notes.
* Notes are numbered for external reference by a human user.
* In this version, note numbers start at 0.
*
* #author David J. Barnes and Michael Kolling.
* #version 2008.03.30
*/
public class Notebook
{
// Storage for an arbitrary number of notes.
private ArrayList<String> notes;
/**
* Perform any initialization that is required for the
* notebook.
*/
public Notebook()
{
notes = new ArrayList<String>();
}
/**
* Store a new note into the notebook.
* #param note The note to be stored.
*/
public void storeNote(String note)
{
notes.add(note);
}
/**
* #return The number of notes currently in the notebook.
*/
public int numberOfNotes()
{
return notes.size();
}
/**
* Show a note.
* #param noteNumber The number of the note to be shown.
*/
public void showNote(int noteNumber)
{
if(noteNumber < 0) {
// This is not a valid note number, so do nothing.
System.out.println("invalid index given");
}
else if(noteNumber < numberOfNotes()) {
// This is a valid note number, so we can print it.
System.out.println(notes.get(noteNumber));
}
else {
System.out.println("there are fewer items in the notebook");
// This is not a valid note number, so do nothing.
}
}
public void removeNote(int noteNumber)
{
if(noteNumber < 0) {
// This is not a valid note number, so do nothing.
System.out.println("invalid index given");
}
else if(noteNumber < numberOfNotes()) {
// This is a valid note number.
notes.remove(noteNumber);
}
else {
System.out.println("there are fewer items in the notebook");
// This is not a valid note number, so do nothing.
}
}
/* Edit note.
* I tried to improve the formatting of the code below, but I'm completely
* unable to figure out how on earth anything of that should make sense
* and therefore the indentation is completely without any meaning.
*/
public void search (String searchString)
{
for each notes in ArrayList {
if notes = searchString;
System.out.println("String found"); + searchString
return end
}
if}
System.out.println("String not found");
}
}
But it is not working, and I am not able to work it out.
Several problems:
Your search method is actually outside the class.
The body of your search method makes no sense at all.
If you're counting on the monkeys writing Shakespeare, you'll be waiting a while.
To iterate over the array list, you can use a 'for-each' loop:
for (String note: notes) {
// Do something with note
}
This is very basic syntax. Have you seen it before? If not, you should start by reading a very basic tutorial to Java before attempting this homework.
Fundamentally you need to look at each item in your ArrayList and test to see if it matches the search condition. In Pseudocode
for each note in notes
{
if note equals searchString then
print "Found " + searchString
return
end if
}
print "not found"
Given that basic outline, want to take a second stab at coding it in Java?
Basically you want to loop over the elements, and for each one check whether it equals the element you are searching for. You can use a for loop or a foreach loop to do the actual iteration.
should you be checking if the whole note matches your searchstring, or if the note contains your searchstring?
i.e. given notes "foobar","baz","spam", should a search on "foo" return "foobar" or not match on anything?
so in pseudocode:
for each note in notes
{
if searchstring in note
{
print "Found :"+note
}
}
check this website http://pleac.sourceforge.net/pleac_java/arrays.html it may be useful

Categories