I am creating the Sudoku game and I am trying to provide options to save, save as, and open games. I am using JFileChooser to do this. I am able to save (or "save as") but when I try to open a saved file, I get an error. I am new to programming and I'm hoping someone could spot the issue and educate me on how to read in the contents of the Sudoku board when I am saving (as well as how to deal with re-creating the Sudoku board when I open the file). I hear there is an easier way to deal with this using InputStream/OutputStream instead of Reader/Writer...
Here is my code for the inner class that implements this (I don't know if there's a way to post my entire class without exceeding the character limit for this text box.):
EDIT:
// this inner class provides a JMenuBar object at the top of
// the board
class MenuAtTop extends JMenuBar implements ActionListener{
// SudokuMain object we are dealing with
private SudokuMain main;
// the "File" menu
private JMenu fileMenu;
// the "New Game" option
private JMenuItem newGame;
// the "Open" option
private JMenuItem open;
// the "Save" option
private JMenuItem save;
// the "Save As" option
private JMenuItem saveAs;
// the "Reset" option
private JMenuItem reset;
// the "Quit" option
private JMenuItem quit;
// the ability to choose files
private JFileChooser choose;
// the saved file
// // compiler would not allow "static" keyword
private File fileSaved = null;
private Object opener;
// JDialog object to create a dialog box to prompt
// user for new game information
private JDialog createNewWin;
/**
* Constructs MenuAtTop object.
*
* #param m The SudokuMain object to be referred to.
*/
public MenuAtTop(final SudokuMain m) {
main = m;
opener = null;
choose = new JFileChooser();
// instantiate and bind to reference
fileMenu = new JMenu("File");
add(fileMenu);
// instantiate and bind to reference
newGame = new JMenuItem("New Game");
newGame.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_N,
ActionEvent.CTRL_MASK));
fileMenu.add(newGame);
newGame.addActionListener(this);
open = new JMenuItem("Open");
open.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_O,
ActionEvent.CTRL_MASK));
fileMenu.add(open);
// add action listener to "Open" option
open.addActionListener(this);
save = new JMenuItem("Save");
save.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_S,
ActionEvent.CTRL_MASK));
fileMenu.add(save);
// add action listener to "Save" option
save.addActionListener(this);
saveAs = new JMenuItem("Save As");
saveAs.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_A,
ActionEvent.CTRL_MASK));
fileMenu.add(saveAs);
// add action listener to "Save As" option
saveAs.addActionListener(this);
reset = new JMenuItem("Reset");
reset.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_R,
ActionEvent.CTRL_MASK));
fileMenu.add(reset);
// add action listener to "Reset" option
reset.addActionListener(this);
quit = new JMenuItem("Quit");
quit.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_Q,
ActionEvent.CTRL_MASK));
fileMenu.add(quit);
// add action listener to "Quit" option
quit.addActionListener(this);
}
public void actionPerformed(ActionEvent e) {
if(e.getSource().equals(newGame)) {
setEnabled(false);
// create dialog box prompting for the new board information
createNewWin = new Dialog1(main, "Create New Board", true);
// make it visible
createNewWin.setVisible(true);
fileSaved = null;
} else if(e.getSource().equals(open)) {
int returnVal = choose.showOpenDialog(main.win);
if(returnVal == JFileChooser.APPROVE_OPTION) {
boolean error = false;
File openFile = choose.getSelectedFile();
try {
FileInputStream fis = new FileInputStream(openFile);
ObjectInputStream ois = new ObjectInputStream(fis);
opener = ois.readObject();
SudokuBase sudoku = (SudokuBoard) opener;
ois.close();
} catch (Exception exc) {
exc.printStackTrace();
JOptionPane.showMessageDialog(main.win, "Error opening file.");
error = true;
}
// "opener" reads something and it is of type SudokuBase
if(opener != null && opener instanceof SudokuBase){
main.north.remove(main.rowColRegStates);
main.west.remove(main.symbols);
main.east.remove(main.view);
main.view = new SudokuView((SudokuBase) opener);
main.rowColRegStates = new ShowStates(main.view);
main.symbols = new SetSymbols(main.view);
main.north.add(main.rowColRegStates);
main.west.add(main.symbols);
main.east.add(main.view);
main.win.requestFocus();
fileSaved = openFile;
} else {
if(error) {
JOptionPane.showMessageDialog(main.win, "Incorrect file type.");
}
}
}
} else if(e.getSource().equals(save)) {
if(fileSaved == null) {
saveAsPrompt();
} else {
try {
FileOutputStream fos = new FileOutputStream(fileSaved);
ObjectOutputStream oos = new ObjectOutputStream(fos);
board.writeToStream(fos);
oos.writeObject(board);
oos.close();
} catch (Exception exc) {
JOptionPane.showMessageDialog(main.win, "Error saving file.");
}
}
} else if(e.getSource().equals(saveAs)) {
saveAsPrompt();
} else if(e.getSource().equals(reset)) {
int n = JOptionPane.showConfirmDialog(main.win,
"Any player values will" +
" be lost. Proceed?",
"Warning!", 2);
if(n == JOptionPane.OK_OPTION) {
main.board.reset();
main.view.repaint();
}
} else if(e.getSource().equals(quit)) {
closePrompt();
}
}
// This method prompts the user to choose a file to save to,
// and then saves the file.
private int saveAsPrompt() {
boolean saveError;
int rtn = choose.showSaveDialog(main.win);
if(rtn == JFileChooser.APPROVE_OPTION) {
saveError = false;
File fileSaveAs = choose.getSelectedFile();
try {
board.writeToStream(new FileOutputStream(fileSaveAs));
} catch (Exception e) {
JOptionPane.showMessageDialog(main.win, "Error saving file.");
saveError = true;
}
if(!saveError) {
fileSaved = fileSaveAs;
}
}
return rtn;
}
// This method prompts the user whether they want to save before
// closing, only if changes occurred.
private void closePrompt() {
if(true) {
int n = JOptionPane.showConfirmDialog(main.win, "Save game?");
if(n == JOptionPane.YES_OPTION) {
int saved = saveAsPrompt();
if(saved != JFileChooser.CANCEL_OPTION){
main.win.dispose();
}
} else if(n == JOptionPane.NO_OPTION) {
main.win.dispose();
}
}
else { // no changes were made
main.win.dispose();
}
}
}
Here's the class that holds the data (it is extended by SudokuBoard):
// Allow short name access to following classes
import java.util.Observable;
import java.io.InputStream;
import java.io.OutputStream;
public abstract class SudokuBase extends Observable {
// rows per region
private int rows;
// columns per region
private int columns;
// size of a region (rows * columns)
private int size;
// array of each element of entire sudoku board
private int[] grid;
// the masked 8-bit "given" value constant
private static final int GIVEN_MASK = 0x00000100;
// the bitwise complement of the masked "given" constant,
// which produces an unmasked constant
private static final int GIVEN_UNMASK = ~ GIVEN_MASK;
/**
* Enumerated type to store constants that indicate the "State" of
* a specified row, column, or region.
*/
public enum State {COMPLETE, INCOMPLETE, ERROR};
/**
* Constructs SudokuBase object.
*
* #param layoutRows The number of rows per region.
* #param layoutColumns The number of columns per region.
*/
public SudokuBase(int layoutRows, int layoutColumns) {
rows = layoutRows;
columns = layoutColumns;
size = columns * rows;
grid = new int[size*size];
}
/**
* Gets the number of rows per region.
*
* #return The rows per region.
*/
public int getRowsPerRegion() {
return rows;
}
/**
* Gets the number of columns per region.
*
* #return The columns per region.
*/
public int getColumnsPerRegion() {
return columns;
}
/**
* Gets the size of the region (rows * columns).
*
* #return The size of the region.
*/
public int getBoardSize() {
return size;
}
// gets the index of the specified row and column for the grid
private int getIndex(int row, int col) {
// handle invalid arguments
if(row < 0 || row >= size || col < 0 || col >= size) {
String msg = "Error in location";
throw new IllegalArgumentException(msg);
}
return row * size + col;
}
/**
* Gets the value of the element at the specified row
* and column on the grid.
*
* #param row The specified row.
* #param col The specified column.
* #return The value of the element at the specified row and column.
*/
public int getValue(int row, int col) {
return grid[getIndex(row, col)] & GIVEN_UNMASK;
}
/**
* Sets the desired value at the specified row and column.
*
* #param row The specified row.
* #param col The specified column.
* #param value The specified value to be set.
*/
public void setValue(int row, int col, int value) {
// handle invalid argument
if(value < 0 || value > size) {
String msg = "Value out of range: " + value;
throw new IllegalArgumentException(msg);
}
// handle attempt to set a value for a "given" location
if(isGiven(row, col)) {
String msg = "Cannot set given location: " + row + ", " + col;
throw new IllegalStateException(msg);
}
grid[getIndex(row, col)] = value;
setChanged();
notifyObservers();
}
/**
* This method checks the status of the "givens" bit.
*
* #param row The specified row.
* #param col The specified column.
* #return Whether or not the specified location is a "given" value.
*/
public boolean isGiven(int row, int col) {
return (grid[getIndex(row, col)] & GIVEN_MASK) == GIVEN_MASK;
}
/**
* This method sets non-zero values on the Sudoku board with the
* "givens" bit.
*/
public void fixGivens() {
for(int i = 0; i < grid.length; i++)
if(grid[i] != 0)
grid[i] |= GIVEN_MASK;
setChanged();
notifyObservers();
}
/**
* This abstract method gets the "State" (COMPLETE, INCOMPLETE,
* or ERROR) of the specified row.
*
* #param n The specified row.
* #return The "State" of the row.
*/
public abstract State getRowState(int n);
/**
* This abstract method gets the "State" (COMPLETE, INCOMPLETE,
* or ERROR) of the specified column.
*
* #param n The specified column.
* #return The "State" of the column.
*/
public abstract State getColumnState(int n);
/**
* This abstract method gets the "State" (COMPLETE, INCOMPLETE,
* or ERROR) of the specified region.
*
* #param n The specified region.
* #return The "State" of the region.
*/
public abstract State getRegionState(int n);
/**
* Represents the Sudoku board as a grid of appropriate characters.
*
* #return The string representation of the Sudoku board.
*/
public String toString() {
String board = "";
for(int i = 0; i < size; i ++) {
for(int j = 0; j < size; j ++)
board += charFor(i, j) + " ";
board += "\n";
}
return board;
}
// this method provides a character for all possible values encountered on the
// Sudoku board, to be utilized in "toString()"
private String charFor(int i, int j) {
int v = getValue(i, j);
// negative value (invalid)
if(v < 0) {
return "?";
} else if(v == 0) { // blank or zero value
return ".";
} else if(v < 36) { // value from 1 to (size * size)
return Character.toString(Character.forDigit(v, 36)).toUpperCase();
} else { // non-numeric input or v >= size * size (both invalid)
return "?";
}
}
/**
* This method reads from an input stream.
*
* #param is The input stream to read from.
*/
protected void readFromStream(InputStream is) {
}
/**
* This method writes to an output stream.
*
* #param os The output stream to write to.
*/
protected void writeToStream(OutputStream os) {
try {
ObjectOutputStream oos = new ObjectOutputStream(os);
oos.close();
} catch(IOException e) {
}
}
/**
* Gets the "raw" value directly, not having checked whether there is an
* unfixed error message.
*
* #param row The row where the raw value is located.
* #param col The column where the raw value is located.
* #return The raw value.
*/
protected int getRawValue(int row, int col) {
return grid[getIndex(row, col)];
}
/**
* Sets the raw value directly, not having checked whether there is an
* unfixed error message.
*
* #param row The row where the raw value is to be located.
* #param col The column where the raw value is to be located.
*/
protected void setRawValue(int row, int col, int value) {
grid[getIndex(row, col)] = value;
}
protected void reset() {
for(int row = 0; row < rows; row++) {
for(int col = 0; col < columns; col++) {
if(!isGiven(row, col)) {
grid[getIndex(row, col)] = 0;
}
}
}
}
}
Well I cannot give a full answer and I do not want to browse the full source code. But a few pointers for you to find some solution:
Never catch Exceptions like that while developing an application:
} catch (Exception e) {
JOptionPane.showMessageDialog(main.win, "Error saving file.");
saveError = true;
}
With this, you completely loose the chance to detect errors. At least add the following line to your exception handling:
e.printStackTrace();
Normally you would log the exception and so on, but with that you see the source of your error at the console. Better than nothing.
To your more specific problem:
You seem to write an Object to a file holding all the configuration. In your read method something goes wrong. Probably you do not read the same object as you write or something like that. Hard to say without any code. Try to get the exception stack trace and figure out what the problem is. If you cannot figure it out, edit your question with more specific information and I will try to give better directions.
EDIT:
Here is a small example showing serialization of objects for a Sudoku like game:
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
public class SerializationExample {
public static void main(String args[]) throws IOException, ClassNotFoundException {
final File target = new File(System.getProperty("java.io.tmp"), "mySerializedObject.txt");
Map<Integer, Integer> initialState = new HashMap<Integer, Integer>();
initialState.put(1, 1);
initialState.put(21, 3);
// ...
GameState state = new GameState(10, initialState);
state.setField(2, 2);
state.setField(3, 8);
System.out.println("Game state before writing to file: " + state);
ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream(target));
out.writeObject(state);
out.close();
ObjectInputStream in = new ObjectInputStream(new FileInputStream(target));
Object gameStateReadFromFile = in.readObject();
GameState readGameState = (GameState)gameStateReadFromFile;
System.out.println("Read from file: " + readGameState);
}
private static class GameState implements Serializable {
private int[] fields;
private int boardSize;
private int[] fixedFields;
public GameState(int boardSize, Map<Integer, Integer> initialState) {
this.boardSize = boardSize;
this.fields = new int[boardSize * boardSize];
this.fixedFields = new int[this.fields.length];
for (Entry<Integer, Integer> entry : initialState.entrySet()) {
this.fixedFields[entry.getKey()] = entry.getValue();
}
}
public void setField(int index, int value) {
this.fields[index] = value;
}
#Override
public String toString() {
StringBuilder builder = new StringBuilder();
builder.append("\nFixed fields: ");
appendArray(builder, this.fixedFields);
builder.append("\nSet fields: ");
appendArray(builder, this.fields);
return builder.toString();
}
private void appendArray(StringBuilder builder, int[] fieldArray) {
for (int i = 0; i < fieldArray.length; ++i) {
if (fieldArray[i] != 0) {
builder.append("row ").append(i / this.boardSize).append(" column ").append(i % this.boardSize)
.append(" has value ")
.append(fieldArray[i]).append(",");
}
}
}
}
}
Related
So basically, the idea is as follows:
The program must extend JTextPane
The program must detect when user typed an abbreviation in the extended JTextPane.
If the user keeps his caret at the last position of the abbreviation, and presses CTRL + ENTER, the program must replace that abbreviation with a definition.
My question is, how would that be done, would somebody be able to make a demo to demonstrate that?
I am aware that keyListener is not the best approach here.
Update A few hours later:
I managed to get it working finally.
I will write down my working demo down below, I hope it will save you the headache that I had to go through while working on it.
GIF Demonstration:
import java.awt.event.ActionEvent;
import java.awt.event.InputEvent;
import java.awt.event.KeyEvent;
import java.util.ArrayList;
import javax.swing.AbstractAction;
import javax.swing.ActionMap;
import javax.swing.InputMap;
import javax.swing.JFrame;
import javax.swing.JTextPane;
import javax.swing.KeyStroke;
import javax.swing.WindowConstants;
import javax.swing.text.BadLocationException;
import javax.swing.text.Document;
/**
* JTextPane with capability to:
* -To keep the correct amount of tabs on new line when user types Enter
* -Dynamically add abbreviations
* -To replace abbreviation with its definition when user keeps caret at last letter of the abbreviation and taps CTRL + ENTER
* -To set position of the caret for each abbreviation after it is replaced by its definition
*/
public class AbbreviationJTextPane extends JTextPane {
public static void main(String[] args) {
JFrame frame = new JFrame();
// Create abbreviation JTextPane
AbbreviationJTextPane abbreviationPane = new AbbreviationJTextPane();
// Add abbreviations
abbreviationPane.addAbbreviation("sysout", "System.out.println();", 19); // 19 sets caret between parenthesis ( )
abbreviationPane.addAbbreviation("/**", "/*\n * \n * \n * /", 6); // 6 sets caret on second line after *
abbreviationPane.addAbbreviation("sob", "short of breath", 15);
// Add abbreviation JTextPane to JFrame
frame.add(abbreviationPane);
frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
frame.pack();
frame.setTitle("Demo on abbreviation with CTRL + ENTER capability for JTextPane");
frame.setSize(720, 250);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
private AbbreviationList abbreviations = new AbbreviationList();
public void addAbbreviation(String abbreviation, String definition, int setCaretPositionBack) {
abbreviations.add(new AbbreviationParameter(setCaretPositionBack, abbreviation, definition));
}
public AbbreviationJTextPane() {
// Add key detection functional
InputMap im = getInputMap();
ActionMap am = getActionMap();
// Add ENTER Listener - Replaces the way ENTER key works - new line will keep the same amount of tabs as on previous line
im.put(KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0), "onEnter");
am.put("onEnter", new AbstractAction() {
#Override
public void actionPerformed(ActionEvent e) {
onEnter();
}
});
// Add CTRL + ENTER Listener
im.put(KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, InputEvent.CTRL_DOWN_MASK), "onCTRL_ENTER");
am.put("onCTRL_ENTER", new AbstractAction() {
#Override
public void actionPerformed(ActionEvent e) {
onCtrlEnter();
}
});
}
// ====================== LISTENERS
/**
* Overrides the way tapping Enter key functions.
* New line "\n" will keep the same amount of tabs "\t" as on previous line
*/
private void onEnter() {
newLineWithTabs();
}
/**
* Overrides the way tapping CTRL + ENTER functions
*/
private void onCtrlEnter() {
// The method below must be called like this to avoid bugs where expanding does
// not work on new line
expandAbbreviation(" ");
expandAbbreviation("\n");
expandAbbreviation("\t");
}
// ====================== FUNCTIONAL
/**
* Inserts a new line.
* New line "\n" will keep the same amount of tabs "\t" as on previous line
*/
private void newLineWithTabs() {
try {
// Get the entire text in the document
String text = getDocument().getText(0, getCaretPosition());
// Get the end index of the text
int end = text.length();
// Insert relevant amount of tabs on each new line:
String tabs = getTabsFromLine(text, end);
// Replace all new lines in definition with relevant amount of tabs
String definition = "\n".replace("\n", "\n"+tabs);
// Insert the definition into the document at the start index
getDocument().insertString(end, definition, null);
} catch (BadLocationException e) {
e.printStackTrace();
}
}
/**
* This method is used to expand an abbreviation in the document based on the
* given word.
*
* #param lastIndexOf - a String representing the word that the abbreviation is
* being searched from
*/
private void expandAbbreviation(String lastIndexOf) {
try {
// Get the caret position in the document
int caretPosition = getCaretPosition();
Document doc = getDocument();
// Get the entire text in the document
String text = doc.getText(0, caretPosition);
// Get the start index of the word that is being searched
int start = text.lastIndexOf(lastIndexOf) + 1;
// Get the end index of the text
int end = text.length();
// Get the word that is being searched
String word = text.substring(start, end);
// Check if the abbreviations list contains the word and the caret position is
// at the end of the document
if (abbreviations.containsAbbreviation(word) && caretPosition == end) {
// Get the definition of the word from the abbreviations list
AbbreviationParameter inputParameter = abbreviations.getObjectForAbbreviation(word);
// If input parameter is null, this means that no such abbreviation exists in
// the list
if (inputParameter == null) {
return;
}
// Get definition from inputParameter
String definition = inputParameter.definition;
// Insert relevant amount of tabs on each new line:
String tabs = getTabsFromLine(text, end);
// Replace all new lines in definition with relevant amount of tabs
definition = definition.replace("\n", "\n"+tabs);
// Remove the word from the document
doc.remove(start, end - start);
// Insert the definition into the document at the start index
doc.insertString(start, definition, null);
// Set caret onto the appropriate index
setCaretPosition(start + inputParameter.caretPosition);
}
} catch (BadLocationException e) {
// No need to print anything as BadLocationException error will keep happening
// e.printStackTrace();
}
}
// ====================== UTILITY METHODS
/**
* Gets the tabs from line.
*
* #param text - the entire text in the document
* #param end - the end index of the text
* #return the tabs from line, string will be "" if there are no tabs at all
*/
private String getTabsFromLine(String text, int end) {
// Count all tabs in the line where caret is at present
int tabsCount = countCharacter(getLineAtIndex(text, end), '\t');
// Create String containing the amount of tabs necessary
StringBuilder tabs = new StringBuilder();
for(int iTab = 0; iTab < tabsCount; iTab++) {
tabs.append("\t");
}
return tabs.toString();
}
/**
* Returns the full line of a given index in a string.
*
* #param input the input string
* #param index the index in the input string
* #return the full line of the given index
*/
public static String getLineAtIndex(String input, int index) {
// Find the start index of the line
int start = input.lastIndexOf("\n", index) + 1;
// Find the end index of the line
int end = input.indexOf("\n", index);
if (end == -1) {
end = input.length();
}
// Return the substring from the start to the end of the line
return input.substring(start, end);
}
/**
* Count the number of a specified character in a string.
*
* #param s the input string
* #param c the character to count
* #return the number of occurrences of the character in the string
*/
public static int countCharacter(String s, char c) {
int count = 0;
for (int i = 0; i < s.length(); i++) {
if (s.charAt(i) == c) {
count++;
}
}
return count;
}
/**
* Count the number of occurrences of a specified string in another string.
*
* #param input the input string
* #param target the string to count
* #return the number of occurrences of the target string in the input string
*/
public static int countString(String input, String target) {
int count = 0;
int index = 0;
while ((index = input.indexOf(target, index)) != -1) {
count++;
index += target.length();
}
return count;
}
}
/**
* Constructor class for abbreviations, their definition, and expected caret
* location after use
*
*/
class AbbreviationParameter {
/**
* This value is meant to indicate how many chars forward the caret should be
* placed onto after definition is placed.
*/
final int caretPosition;
final String abbreviation;
final String definition;
public AbbreviationParameter(int caretPosition, String abbreviation, String definition) {
this.caretPosition = caretPosition;
this.abbreviation = abbreviation;
this.definition = definition;
}
/**
* Gets the definition.
*
* #return the definition
*/
public String getDefinition() {
return definition;
}
}
/**
* List with all abbreviations and their values
*/
class AbbreviationList extends ArrayList<AbbreviationParameter> {
private static final long serialVersionUID = -7332763119043404932L;
/**
* Checks if list contains given abbreviation.
*
* #param abbreviation - the abbreviation
* #return true, if successful
*/
public boolean containsAbbreviation(String abbreviation) {
ArrayList<AbbreviationParameter> list = this;
for (AbbreviationParameter stringInputParameter : list) {
if (stringInputParameter.abbreviation.equals(abbreviation)) {
return true;
}
}
return false;
}
/**
* Gets the object for abbreviation.
*
* #param abbreviation - the abbreviation
* #return the {#link #AbbreviationList} object for abbreviation given if match is found, will return null if no such abbreviation is found
*/
public AbbreviationParameter getObjectForAbbreviation(String abbreviation) {
ArrayList<AbbreviationParameter> list = this;
for (AbbreviationParameter stringInputParameter : list) {
if (stringInputParameter.abbreviation.equals(abbreviation)) {
return stringInputParameter;
}
}
return null;
}
}
I'm using some code from my university's lecturer for a new project and everything seems to be working except for that one little piece, where I want to import "data.Frame" and I just don't know what's missing so my code would function. If anyone knows the solution or could give me an alternative so I could import the needed "Frame" - would be awesome!
I'm using eclipse!
The code is:
import java.io.FileWriter;
import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Set;
import data.Frame; // HERE IS THE PROBLEM!
/**
* Compares the annotations of two or more annotators and groups them together,
* before they are written to a csv file.
*/
public class ComparisonWriter
{
private String content;
private final int A1 = 1;
private final int A2 = 2;
private final int A3 = 3;
// private final int A4 = 4;
private int numberOfAnnotators = 3;
String outputFileName = "data/200Saetze/Gruppe 1/comparison_buchpreis2_alle.csv";
String inputA1 = "data/200Saetze/Gruppe 1/Daniela/buchpreis2.xml";
String inputA2 = "data/200Saetze/Gruppe 1/Inga/buchpreis2.xml";
String inputA3 = "data/200Saetze/Gruppe 1/Stefan/buchpreis2.xml";
public ComparisonWriter()
{
content = "SatzID;Annotator;Frame;SE;exact;partial;Source;Annotator;SourceString;" +
"exact;exact ohne leer;exact ohne leer (SE);partial;koreferent;SourceFlag;exact;Target;Annotator;" +
"TargetString;exact;exact ohne leer;exact ohne leer (SE);partial;koreferent;TargetFlag;;FrameFlag";
AnnotationReader annotationReaderA1 = new AnnotationReader(inputA1);
Map<String, List<Frame>> seAnnotator1 = annotationReaderA1.getAllSubjectiveExpressions();
AnnotationReader annotationReaderA2 = new AnnotationReader(inputA2);
Map<String, List<Frame>> seAnnotator2 = annotationReaderA2.getAllSubjectiveExpressions();
AnnotationReader annotationReaderA3 = new AnnotationReader(inputA3);
Map<String, List<Frame>> seAnnotator3 = annotationReaderA3.getAllSubjectiveExpressions();
Set<String> sentences = seAnnotator1.keySet();
for (String sentence : sentences)
{
//add leading zeros
content += "\n\n" + sentence + ";" + annotationReaderA1.sentenceStrings.get(sentence);
//add the annotations in a sorted order
Map<Integer, List<Frame>> allFramesInSentence = new HashMap<Integer, List<Frame>>();
allFramesInSentence.put(A1, seAnnotator1.get(sentence));
allFramesInSentence.put(A2, seAnnotator2.get(sentence));
allFramesInSentence.put(A3, seAnnotator3.get(sentence));
// allFramesInSentence.put(A4, seAnnotator4.get(sentence));
//
//get the one with the most annotations
int largest = getIndexOfLargestList(allFramesInSentence);
if(largest == 0)
continue;
for (int i = 0; i < allFramesInSentence.get(largest).size(); i++)
{
Frame frame = allFramesInSentence.get(largest).get(i);
content += "\n\n;A" + largest + ";" + frame;
frame.setConsidered(true);
findOverlappingAnnotations(allFramesInSentence, largest, frame);
}
//Check, if there are not considered annotations in one of the frame lists for that sentence.
for (int a = 1; a <= 4; a++)
{
List<Frame> frameList = allFramesInSentence.get(a);
if(a != largest && frameList != null)
{
for (Frame frame : frameList)
{
if(frame.isConsidered() == false)
{
content += "\n\n;A" + a + ";" + frame;
frame.setConsidered(true);
findOverlappingAnnotations(allFramesInSentence, a, frame);
}
}
}
}
}
writeContentToFile(content, outputFileName, false);
}
/**
* Find overlapping annotations.
* #param frames - list of frames, potentially overlapping with the given one.
* #param largest
* #param frame - frame in question.
*/
private void findOverlappingAnnotations(Map<Integer, List<Frame>> frames,
int largest, Frame frame)
{
for (int a = 1; a <= 4; a++)
{
//If j is not the current largest frame list and there are annotated frames
//in from this annotator (a)
if(a != largest && frames.get(a) != null)
{
for (Frame compareFrame : frames.get(a))
{
addOverlappingAnnotations2Conent(frame, a, compareFrame);
}
}
}
}
/**
* Add overlapping Annotations (measured by matching ids) to the content attribute.
* #param frame
* #param a - Annotator index
* #param compareFrame
*/
private void addOverlappingAnnotations2Conent(Frame frame, int a,
Frame compareFrame)
{
List<String> terminalIDs = compareFrame.getTerminalIDs();
for (String id : terminalIDs)
{
if(compareFrame.isConsidered())
break;
if(frame.getTerminalIDs().contains(id))
{
//Write it to the content
content += "\n;A" + a + ";" + compareFrame;
compareFrame.setConsidered(true);
break;
}
}
}
/**
* Get the index of the largest frame list in the map.
* #param frames - a map with all the frames for each annotator (key: annotator)
* #return The index of the largest frame list.
*/
private int getIndexOfLargestList(Map<Integer, List<Frame>> frames)
{
int size = 0;
int largest = 0;
for(int a = 0; a <= numberOfAnnotators; a++)
{
if(frames.get(a) != null)
{
if(frames.get(a).size() > size)
largest = a;
}
}
return largest;
}
You basically need Frame class in your classpath. If you have this class in some jar, then add that jar to your classpath.
You need to get a copy of the source code or class file for the Frame class and add it to your project. The source code should be in a file called Frame.java.
I am sorry if the code is long.
Block and Tuple are self defined classes. Their attributes are protected. Block contains a ArrayList of Tuples. Tuple has attribute int Key and String value
I have ArrayList[] bucketLstS and Block[] bucketBlocksS
ArrayList[] bucketLstS = new ArrayList[Setting.memorySize - 1];
Block[] bucketBlocksS = new Block[Setting.memorySize - 1];
for (int i = 0; i < bucketBlocksS.length; i++) {
bucketLstS[i] = new ArrayList<Tuple>();
bucketBlocksS[i] = new Block();
}
//Get individual relS keys
RelationLoader sLoader = relS.getRelationLoader();
while (sLoader.hasNext()) {
Block[] blocks = sLoader.loadNextBlocks(1);
for (Block b : blocks) {
numIO++;
if (b != null) {
for (Tuple t : b.tupleLst) {
//Hash the key to determine which Bucket
bucketIdx = t.key % (Setting.memorySize - 2);
//System.out.println(bucketBlocksS[bucketIdx].getNumTuples());
//check if the block is already full
if (bucketBlocksS[bucketIdx].getNumTuples() >= Setting.blockFactor) {
bucketLstS[bucketIdx].add(bucketBlocksS[bucketIdx]);
bucketBlocksS[bucketIdx] = new Block();
blkNum++;
}
bucketBlocksS[bucketIdx].insertTuple(t);
}
}
}
}//end while
The question is that I need to loop into each Block, so that I can access each Tuple's Key and value I tried this:
for (int i = 0; i < bucketLstS.length; i++) {
System.out.println(i + " " + bucketLstS[i]);
for (int j = 0; j < bucketLstS[i].size(); j++) {
//Access a Block in Block Array
System.out.println(j + " " + bucketLstS[i].get(j));
}
}
But then I am stuck. The output is like:
0 [project2.Block#558fee4f, project2.Block#5c66b06b, project2.Block#59c87031, project2.Block#763dcf03, project2.Block#53e20a9a, project2.Block#1d262f7c, project2.Block#35f784d7, project2.Block#d325aef, project2.Block#64f007ad]
0 project2.Block#558fee4f
1 project2.Block#5c66b06b
2 project2.Block#59c87031
3 project2.Block#763dcf03
4 project2.Block#53e20a9a
5 project2.Block#1d262f7c
6 project2.Block#35f784d7
7 project2.Block#d325aef
8 project2.Block#64f007ad
But how to I get into the Tuple of a Block to get to the key?
(To obtain key, can use Tuple.key)
Following is the Class for Block
import java.util.ArrayList;
public class Block {
/**
* List of tuples contained in this block
*/
protected ArrayList<Tuple> tupleLst;
public Block(){
this.tupleLst=new ArrayList<Tuple>(Setting.blockFactor);
}
/**
* Insert a tuple t to this block
* #param t is a tuple to be inserted to this block
* #return true if tuple t is successfully inserted into this block and false if the block is full
*/
//One tupleLst can store up to "10" tuples
public boolean insertTuple(Tuple t){
if(tupleLst.size()<Setting.blockFactor){
tupleLst.add(t);
return true;
}
return false;
}
/**
* #return number of tuples stored in this block
*/
public int getNumTuples(){
return tupleLst.size();
}
/**
* Print this block
* #param printTuple is a flag to indicate whether the details of the tuples are printed
*/
public void print(boolean printTuple){
System.out.println("[BlockSize: "+getNumTuples()+"]");
if(printTuple){
for(Tuple t:tupleLst){
System.out.println(t);
}
}
}
I started refactoring this program I was working on and hit a major road block... I have one class that acts as a nucleus, with about 6 other smaller (but still important) classes working together to run the program... I took one method [called 'populate()'] out the nucleus class and made an entirely new class with it [called 'PopulationGenerator'], but when I try to create an object of the newly created class anywhere in the nucleus class I get stuck in a never ending loop of that new class
I've never had this issue when trying to create objects before... Here's the nucleus class before refactoring:
public class Simulator
{
// Constants representing configuration information for the simulation.
// The default width for the grid.
private static final int DEFAULT_WIDTH = 120;
// The default depth of the grid.
private static final int DEFAULT_DEPTH = 80;
// The probability that a fox will be created in any given grid position.
private static final double FOX_CREATION_PROBABILITY = 0.02;
// The probability that a rabbit will be created in any given grid position.
private static final double RABBIT_CREATION_PROBABILITY = 0.08;
// List of animals in the field.
private List<Animal> animals;
// The current state of the field.
private Field field;
// The current step of the simulation.
private int step;
// A graphical view of the simulation.
private SimulatorView view;
/**
* Construct a simulation field with default size.
*/
public Simulator()
{
this(DEFAULT_DEPTH, DEFAULT_WIDTH);
}
/**
* Create a simulation field with the given size.
* #param depth Depth of the field. Must be greater than zero.
* #param width Width of the field. Must be greater than zero.
*/
public Simulator(int depth, int width)
{
if(width <= 0 || depth <= 0) {
System.out.println("The dimensions must be greater than zero.");
System.out.println("Using default values.");
depth = DEFAULT_DEPTH;
width = DEFAULT_WIDTH;
}
animals = new ArrayList<Animal>();
field = new Field(depth, width);
// Create a view of the state of each location in the field.
view = new SimulatorView(depth, width);
view.setColor(Rabbit.class, Color.orange);
view.setColor(Fox.class, Color.blue);
// Setup a valid starting point.
reset();
}
/**
* Run the simulation from its current state for a reasonably long period,
* (4000 steps).
*/
public void runLongSimulation()
{
simulate(4000);
}
/**
* Run the simulation from its current state for the given number of steps.
* Stop before the given number of steps if it ceases to be viable.
* #param numSteps The number of steps to run for.
*/
public void simulate(int numSteps)
{
for(int step = 1; step <= numSteps && view.isViable(field); step++) {
simulateOneStep();
}
}
/**
* Run the simulation from its current state for a single step.
* Iterate over the whole field updating the state of each
* fox and rabbit.
*/
public void simulateOneStep()
{
step++;
// Provide space for newborn animals.
List<Animal> newAnimals = new ArrayList<Animal>();
// Let all rabbits act.
for(Iterator<Animal> it = animals.iterator(); it.hasNext(); ) {
Animal animal = it.next();
animal.act(newAnimals);
if(! animal.isAlive()) {
it.remove();
}
}
// Add the newly born foxes and rabbits to the main lists.
animals.addAll(newAnimals);
view.showStatus(step, field);
}
/**
* Reset the simulation to a starting position.
*/
public void reset()
{
step = 0;
animals.clear();
populate();
// Show the starting state in the view.
view.showStatus(step, field);
}
/**
* Randomly populate the field with foxes and rabbits.
*/
private void populate()
{
Random rand = Randomizer.getRandom();
field.clear();
for(int row = 0; row < field.getDepth(); row++) {
for(int col = 0; col < field.getWidth(); col++) {
if(rand.nextDouble() <= FOX_CREATION_PROBABILITY) {
Location location = new Location(row, col);
Fox fox = new Fox(true, field, location);
animals.add(fox);
}
else if(rand.nextDouble() <= RABBIT_CREATION_PROBABILITY) {
Location location = new Location(row, col);
Rabbit rabbit = new Rabbit(true, field, location);
animals.add(rabbit);
}
// else leave the location empty.
}
}
}
}
EDIT:
Here's this same class AFTER refactoring ...
import java.util.Random;
import java.util.List;
import java.util.ArrayList;
import java.util.Iterator;
import java.awt.Color;
/**
* A simple predator-prey simulator, based on a rectangular field
* containing rabbits and foxes.
*
* Update 10.40:
* Now *almost* decoupled from the concrete animal classes.
*
* #TWiSTED_CRYSTALS
*/
public class Simulator
{
// Constants representing configuration information for the simulation.
// The default width for the grid.
private static final int DEFAULT_WIDTH = 120;
// The default depth of the grid.
private static final int DEFAULT_DEPTH = 80;
// The current state of the field.
private Field field;
// The current step of the simulation.
private int step;
// A graphical view of the simulation.
private SimulatorView view;
//Population Generator class... coupled to fox and rabbit classes
private PopulationGenerator popGenerator;
// Lists of animals in the field. Separate lists are kept for ease of iteration.
private List<Animal> animals;
/**
* Construct a simulation field with default size.
*/
public Simulator()
{
this(DEFAULT_DEPTH, DEFAULT_WIDTH);
}
/**
* Create a simulation field with the given size.
* #param depth Depth of the field. Must be greater than zero.
* #param width Width of the field. Must be greater than zero.
*/
public Simulator(int depth, int width)
{
if(width <= 0 || depth <= 0) {
System.out.println("The dimensions must be greater than zero.");
System.out.println("Using default values.");
depth = DEFAULT_DEPTH;
width = DEFAULT_WIDTH;
}
animals = new ArrayList<Animal>();
field = new Field(depth, width);
// Create a view of the state of each location in the field.
//
// view.setColor(Rabbit.class, Color.orange); // PG
// view.setColor(Fox.class, Color.blue); // PG
// Setup a valid starting point.
reset();
}
/**
* Run the simulation from its current state for a reasonably long period,
* (4000 steps).
*/
public void runLongSimulation()
{
simulate(4000);
}
/**
* Run the simulation from its current state for the given number of steps.
* Stop before the given number of steps if it ceases to be viable.
* #param numSteps The number of steps to run for.
*/
public void simulate(int numSteps)
{
for(int step = 1; step <= numSteps && view.isViable(field); step++) {
simulateOneStep();
}
}
/**
* Run the simulation from its current state for a single step.
* Iterate over the whole field updating the state of each
* fox and rabbit.
*/
public void simulateOneStep()
{
step++;
// Provide space for animals.
List<Animal> newAnimals = new ArrayList<Animal>();
// Let all animals act.
for(Iterator<Animal> it = animals.iterator(); it.hasNext(); ) {
Animal animal = it.next();
animal.act(newAnimals);
if(! animal.isAlive()) {
it.remove();
}
}
animals.addAll(newAnimals);
}
/**
* Reset the simulation to a starting position.
*/
public void reset()
{
PopulationGenerator popGenerator = new PopulationGenerator();
step = 0;
animals.clear();
popGenerator.populate();
// Show the starting state in the view.
view.showStatus(step, field);
}
public int getStep()
{
return step;
}
}
... and the new class
import java.util.ArrayList;
import java.util.Random;
import java.util.List;
import java.awt.Color;
public class PopulationGenerator
{
// The default width for the grid.
private static final int DEFAULT_WIDTH = 120;
// The default depth of the grid.
private static final int DEFAULT_DEPTH = 80;
// The probability that a fox will be created in any given grid position.
private static final double FOX_CREATION_PROBABILITY = 0.02;
// The probability that a rabbit will be created in any given grid position.
private static final double RABBIT_CREATION_PROBABILITY = 0.08;
// Lists of animals in the field. Separate lists are kept for ease of iteration.
private List<Animal> animals;
// The current state of the field.
private Field field;
// A graphical view of the simulation.
private SimulatorView view;
/**
* Constructor
*/
public PopulationGenerator()
{
animals = new ArrayList<Animal>();
field = new Field(DEFAULT_DEPTH, DEFAULT_WIDTH);
}
/**
* Randomly populate the field with foxes and rabbits.
*/
public void populate()
{
// Create a view of the state of each location in the field.
view = new SimulatorView(DEFAULT_DEPTH, DEFAULT_WIDTH);
view.setColor(Rabbit.class, Color.orange); // PG
view.setColor(Fox.class, Color.blue); // PG
Simulator simulator = new Simulator();
Random rand = Randomizer.getRandom();
field.clear();
for(int row = 0; row < field.getDepth(); row++) {
for(int col = 0; col < field.getWidth(); col++) {
if(rand.nextDouble() <= FOX_CREATION_PROBABILITY) {
Location location = new Location(row, col);
Fox fox = new Fox(true, field, location);
animals.add(fox);
}
else if(rand.nextDouble() <= RABBIT_CREATION_PROBABILITY) {
Location location = new Location(row, col);
Rabbit rabbit = new Rabbit(true, field, location);
animals.add(rabbit);
}
// else leave the location empty.
}
}
view.showStatus(simulator.getStep(), field);
}
}
here's the Field class that the PopulationGenerator calls... I havent changed this class in any way
import java.util.Collections;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Random;
/**
* Represent a rectangular grid of field positions.
* Each position is able to store a single animal.
*
* #TWiSTED_CRYSTALS
*/
public class Field
{
// A random number generator for providing random locations.
private static final Random rand = Randomizer.getRandom();
// The depth and width of the field.
private int depth, width;
// Storage for the animals.
private Object[][] field;
/**
* Represent a field of the given dimensions.
* #param depth The depth of the field.
* #param width The width of the field.
*/
public Field(int depth, int width)
{
this.depth = depth;
this.width = width;
field = new Object[depth][width];
}
/**
* Empty the field.
*/
public void clear()
{
for(int row = 0; row < depth; row++) {
for(int col = 0; col < width; col++) {
field[row][col] = null;
}
}
}
/**
* Clear the given location.
* #param location The location to clear.
*/
public void clear(Location location)
{
field[location.getRow()][location.getCol()] = null;
}
/**
* Place an animal at the given location.
* If there is already an animal at the location it will
* be lost.
* #param animal The animal to be placed.
* #param row Row coordinate of the location.
* #param col Column coordinate of the location.
*/
public void place(Object animal, int row, int col)
{
place(animal, new Location(row, col));
}
/**
* Place an animal at the given location.
* If there is already an animal at the location it will
* be lost.
* #param animal The animal to be placed.
* #param location Where to place the animal.
*/
public void place(Object animal, Location location)
{
field[location.getRow()][location.getCol()] = animal;
}
/**
* Return the animal at the given location, if any.
* #param location Where in the field.
* #return The animal at the given location, or null if there is none.
*/
public Object getObjectAt(Location location)
{
return getObjectAt(location.getRow(), location.getCol());
}
/**
* Return the animal at the given location, if any.
* #param row The desired row.
* #param col The desired column.
* #return The animal at the given location, or null if there is none.
*/
public Object getObjectAt(int row, int col)
{
return field[row][col];
}
/**
* Generate a random location that is adjacent to the
* given location, or is the same location.
* The returned location will be within the valid bounds
* of the field.
* #param location The location from which to generate an adjacency.
* #return A valid location within the grid area.
*/
public Location randomAdjacentLocation(Location location)
{
List<Location> adjacent = adjacentLocations(location);
return adjacent.get(0);
}
/**
* Get a shuffled list of the free adjacent locations.
* #param location Get locations adjacent to this.
* #return A list of free adjacent locations.
*/
public List<Location> getFreeAdjacentLocations(Location location)
{
List<Location> free = new LinkedList<Location>();
List<Location> adjacent = adjacentLocations(location);
for(Location next : adjacent) {
if(getObjectAt(next) == null) {
free.add(next);
}
}
return free;
}
/**
* Try to find a free location that is adjacent to the
* given location. If there is none, return null.
* The returned location will be within the valid bounds
* of the field.
* #param location The location from which to generate an adjacency.
* #return A valid location within the grid area.
*/
public Location freeAdjacentLocation(Location location)
{
// The available free ones.
List<Location> free = getFreeAdjacentLocations(location);
if(free.size() > 0) {
return free.get(0);
}
else {
return null;
}
}
/**
* Return a shuffled list of locations adjacent to the given one.
* The list will not include the location itself.
* All locations will lie within the grid.
* #param location The location from which to generate adjacencies.
* #return A list of locations adjacent to that given.
*/
public List<Location> adjacentLocations(Location location)
{
assert location != null : "Null location passed to adjacentLocations";
// The list of locations to be returned.
List<Location> locations = new LinkedList<Location>();
if(location != null) {
int row = location.getRow();
int col = location.getCol();
for(int roffset = -1; roffset <= 1; roffset++) {
int nextRow = row + roffset;
if(nextRow >= 0 && nextRow < depth) {
for(int coffset = -1; coffset <= 1; coffset++) {
int nextCol = col + coffset;
// Exclude invalid locations and the original location.
if(nextCol >= 0 && nextCol < width && (roffset != 0 || coffset != 0)) {
locations.add(new Location(nextRow, nextCol));
}
}
}
}
// Shuffle the list. Several other methods rely on the list
// being in a random order.
Collections.shuffle(locations, rand);
}
return locations;
}
/**
* Return the depth of the field.
* #return The depth of the field.
*/
public int getDepth()
{
return depth;
}
/**
* Return the width of the field.
* #return The width of the field.
*/
public int getWidth()
{
return width;
}
}
your problem is not in the Field class but below it. The Simulator constructor calls reset() which creates a new PopulationGenerator object, then calls populate() on that object. The populate() method calls Simulator simulator = new Simulator(); which creates a new Simulator object which continues the cycle. Solution: don't create a new Simulator object in PopulationGenerator, but instead pass the existing simulator to PopulationGenerator through its constructor or through a setSimulator(...) method.
e.g.,
class PopulationGenerator {
// ... etc...
private Simulator simulator; // null to begin with
// pass Simulator instance into constructor.
// Probably will need to do the same with SimulatorView
public PopulationGenerator(Simulator simulator, int depth, int width) {
this.simulator = simulator; // set the instance
// ... more code etc...
}
public void populate() {
// don't re-create Simulator here but rather use the instance passed in
}
}
I've posted my program for review on code review (stackexchange).
Everything worked fine, After I came home I was told to use a IDE.
I opened my source with Eclipse IDE, and then I started getting (both on the IDE, or without) this error upon run:
Exception in thread "main" java.lang.NullPointerException
at games.Spin.rand(Spin.java:68)
at games.Spin.<init>(Spin.java:10)
at games.GameHandler.<init>(GameHandler.java:8)
at Mains.startGame(Mains.java:16)
at Mains.main(Mains.java:9)
Why is it doing that? My mate has reviewed my code, and could not find anything wrong with it?.
I am very new to java, tried at attempting going deeper in OO.
My code is located at code review thread (3 classes):
https://codereview.stackexchange.com/questions/28197/improving-my-java-object-oriented-review
What is wrong with it? Why is it giving me that exception?
Line 68: return r.nextInt(x);
public int rand(int x) {
return r.nextInt(x);
}
That's how I create r object:
/**
* Creating new Random object.
**/
private Random r = new Random();
Mains.java:
import games.GameHandler;
import java.util.Scanner;
import java.io.*;
public class Mains {
public static void main (String[] args) {
//Start the game
startGame();
}
private static void startGame() {
//Declares
GameHandler handler = new GameHandler();
Scanner console = new Scanner(System.in);
boolean game = true;
String input = "";
//Print program welcome text
handler.printStart();
//While in game...
while (game) {
//Getting input ready for new commands from the player
input = console.nextLine();
//Checking if input was set.
if (input != null) {
//Selecting the game you want to play.
handler.selectGame(input);
//If game was selected.. then.. let's start playing.
while (handler.inGame) {
//Use will say something.
input = console.nextLine();
//If it was "exit", it will go back and select another game.
if (input.equals("exit")) {
handler.exitGame();
} else {
//Play again.
handler.continueGame(input);
}
}
}
}
}
}
GameHandler.java:
package games;
import java.io.*;
public class GameHandler {
private String[] games = {"Spin", "Tof"};
private String[] navigation = {"Back", "Start"};
private Spin spin = new Spin();
private boolean spinGame = false;
private boolean tofGame = false;
public boolean inGame = false;
/**
* Method printStart
*
* Will welcome the player to the program.
*/
public void printStart() {
this.print(0, "Welcome to the program!");
this.print(0, "Please select a game: " + this.availableGames());
}
/**
* Method available games
*
* This will print all the games that are located in the games array in one row.
**/
private String availableGames() {
String names = "";
for (int i = 0; i < games.length; i++) {
names = (names + games[i]);
if (i < games.length -1) {
names = (names + ", ");
}
}
return names;
}
/**
* Method selectGame
*
* This will select the given game.
* #param command The entered command.
**/
public void selectGame(String command) {
if (this.inArray(command))
{
if (command.equalsIgnoreCase("spin")) {
this.startGame("spin");
} else if (command.equalsIgnoreCase("tof")) {
this.startGame("tof");
}
} else {
this.print(0, "Could not find game!");
}
}
/**
* Method inArray
*
* This will check if the entered game name is exisiting in the games array.
* If yes, will return a boolean true, else false.
*
* #param value The entered game name.
* #return boolean true/false.
**/
private boolean inArray(String value) {
int returning = 0;
for (String s : games) {
if (value.equalsIgnoreCase(s)) {
returning = 1;
}
}
if (returning == 1) {
return true;
} else {
return false;
}
}
/**
* Method startGame
*
* Will start the game, and print instructions.
* will set the game boolean to true.
**/
private void startGame(String game) {
switch (game) {
case "spin":
this.print(0, "Welcome to spin game!");
this.print(0, "Please click on any key to spin!");
spinGame = true;
break;
case "tof":
break;
}
inGame = true;
}
/**
* Method continueGame
*
* Will continue the game, either spin again, or print new question or even answer.
* #param command The entered command.
**/
public void continueGame(String command) {
while (inGame) {
if (spinGame) {
this.spinWheel();
// Break out of the loop.
break;
}
}
}
/**
* Method exitGame
*
* Exit the game..
**/
public void exitGame() {
spinGame = false;
tofGame = false;
this.printStart();
}
/**
* Method spinWheel
*
* This will spin the wheel.
**/
private void spinWheel() {
this.print(0, spin.spinWheel());
}
/**
* Method print
*
* Prints text using System.out
* #param type printing type (Println/print).
* #param message The message
**/
private void print(int type, String message) {
switch (type) {
case 0:
System.out.println(message);
break;
case 1:
System.out.print(message);
break;
}
}
}
Spin.java:
package games;
import java.util.Random;
public class Spin {
/**
* The base auth we are going to work with..
**/
private int auth = this.rand(1000) / 5;
/**
* Creating new Random object.
**/
private Random r = new Random();
/**
* Method spinWheel
*
* Spins the damn wheel..
* #return spinned value + if you won or not.
**/
public String spinWheel() {
return this.spinWheel(this.rand(100));
}
/**
* spinWheel
*
* Returning results.
**/
private String spinWheel(int number) {
int result = this.Calculate(this.rand(number));
if (result < 101) {
return "You have won the game!" + result;
} else {
return "You've lost the game!" + result;
}
}
/**
* Method calculate
*
* Calculates the spin.
* #return the spinned number.
**/
private int Calculate(int Number) {
int var = this.rand(101);
int holder = (var * Number) / 2;
return holder + this.auth;
}
/**
* Shortcut for nextInt of Random
**/
public int rand(int x) {
return r.nextInt(x);
}
}
rand is invoked before the Random instance r is initialised. Switch the order or these 2 statements
private int auth = this.rand(1000) / 5;
private Random r = new Random();
should be
private Random r = new Random();
private int auth = this.rand(1000) / 5;
Make the assignment of r the first thing in your Spinwheel class definition, i.e. put it before it is used in this.rand(1000):
public class Spin {
/**
* Creating new Random object.
**/
private Random r = new Random();
/**
* The base auth we are going to work with..
**/
private int auth = this.rand(1000) / 5;
r is null, so you can't call any instance method on r. Make sure you intialize r before using it.
More specifically, in this line:
private int auth = this.rand(1000) / 5;
you're calling the rand() method before r has been initialized (it's initialized right after).
This is the line causing the NullPointerException:
private int auth = this.rand(1000) / 5;
Since this line comes before the initialization for r, you are invoking rand before r was initialized. In that case r is null in rand and that's your exception.
This is obvious from your stack trace:
at games.Spin.rand(Spin.java:68)
at games.Spin.<init>(Spin.java:10)
Note that the exception is happening in the initializer. From there, it's easy to back out what is going on.
You need to initialize r first, that is, move the initialization line for r before the initialization line for auth. Thus:
private Random r = new Random();
private int auth = this.rand(1000) / 5;
This is because r is being used before it is instantiated within statement private int auth = this.rand(1000) / 5; . So , JVM is seeing r as null , which is leading to NPE. To get rid of this problem within Spin class declare the fields as follows:
private Random r = new Random();
private int auth = this.rand(1000) / 5;