This question already has answers here:
What is a NullPointerException, and how do I fix it?
(12 answers)
Closed 5 years ago.
Can someone explain why I'm getting this error and how to solve it? Also try to keep it simple. I'm new to coding. (Also i know the answer to the question exists, but i don't know how to implement it to my code)
It gives NullPointerException error when rows are deleted. Also when the blocks move down, the blocks are still counted as 0 so new blocks go through them. (i guess its only the top row, other rows are working as intended) But the actual error is more important: (but i'd be happy if you help to solve this too)
package application;
import java.util.*;
import javafx.application.Application;
import javafx.application.Platform;
import javafx.event.EventHandler;
import javafx.scene.*;
import javafx.scene.input.*;
import javafx.scene.layout.Pane;
import javafx.scene.paint.Color;
import javafx.scene.shape.*;
import javafx.scene.text.Text;
import javafx.stage.Stage;
public class Tetris extends Application {
public static final int MOVE_AMOUNT = 25;
public static final int SIZE = 25;
public static int XLIMIT = SIZE * 10;
public static int YLIMIT = SIZE * 24;
public static int[][] GRID = new int[XLIMIT/SIZE][YLIMIT/SIZE];
private static Pane group = new Pane();
private static Shape object;
private static Scene scene = new Scene(group, XLIMIT, YLIMIT);
public static void main(String[] args) { launch(args); }
#Override public void start(Stage stage) throws Exception {
for(int[] a: GRID){
Arrays.fill(a, 0);
}
for(int i = 0; i <= XLIMIT; i+= SIZE){
Line a = new Line(i, 0, i, YLIMIT);
group.getChildren().add(a);
}
for(int i = 0; i <= YLIMIT; i+= SIZE){
Line a = new Line(0, i, XLIMIT, i);
group.getChildren().add(a);
}
for(int i = 0; i <= YLIMIT; i+= SIZE){
Text a = new Text("" + i);
a.setY(i);
group.getChildren().add(a);
}
for(int i = SIZE; i < XLIMIT; i+= SIZE){
Text a = new Text("" + i);
a.setY(10);
a.setX(i);
group.getChildren().add(a);
}
Shape a = TetrisHolder.createRect();
group.getChildren().addAll(a.a, a.b, a.c, a.d);
moveOnKeyPress(scene, a.a, a.b, a.c, a.d);
object = a;
stage.setScene(scene);
stage.show();
Timer myTimer=new Timer();
TimerTask task =new TimerTask() {
#Override
public void run() {
Platform.runLater(new Runnable(){
public void run(){
CheckDown(object);
}
});
}
};
myTimer.schedule(task,0,300);
}
private void moveOnKeyPress(Scene scene, Rectangle rect, Rectangle rect2, Rectangle rect3, Rectangle rect4) {
scene.setOnKeyPressed(new EventHandler<KeyEvent>() {
#Override public void handle(KeyEvent event) {
Shape shape = new Shape(rect, rect2, rect3, rect4);
switch (event.getCode()) {
case RIGHT:
TetrisHolder.CheckRight(shape);
break;
case DOWN:
CheckDown(shape);
break;
case LEFT:
TetrisHolder.CheckLeft(shape);
break;
case UP:
//TetrisHolder.CheckTurn(shape);
break;
}
}
});
}
private void CheckTurn(Shape shape){
}
private void DeleteRows(Pane pane){
ArrayList<Node> rects = new ArrayList<Node>();
ArrayList<Integer> lines = new ArrayList<Integer>();
int full = 0;
for(int i = 0; i < GRID[0].length; i++){
for(int j = 0; j < GRID.length; j++){
if(GRID[j][i] == 1)
full++;
}
if(full == GRID.length)
lines.add(i/*+lines.size()*/);
full = 0;
}
for(Node node: pane.getChildren()) {
if(node instanceof Rectangle) {
rects.add(node);
}
}
if(lines.size() > 0)
do{
for(Node node: rects){
Rectangle a = (Rectangle)node;
if(a.getY() == lines.get(0)*SIZE){
GRID[(int)a.getX()/SIZE][(int)a.getY()/SIZE] = 0;
pane.getChildren().remove(node);
}
if(a.getY() < lines.get(0)*SIZE){
GRID[(int)a.getX()/SIZE][(int)a.getY()/SIZE] = 0;
a.setY(a.getY() + SIZE);
GRID[(int)a.getX()/SIZE][(int)a.getY()/SIZE] = 1;
}
}
lines.remove(0);
rects.clear();
for(Node node: pane.getChildren()) {
if(node instanceof Rectangle) {
rects.add(node);
}
}
} while(lines.size() > 0);
}
private void CheckDown(Shape shape){
if((shape.c.getY() == YLIMIT - SIZE) || checkA(shape) || checkB(shape) || checkC(shape) || checkD(shape)){
GRID[(int)shape.a.getX()/SIZE][(int)shape.a.getY()/SIZE] = 1;
GRID[(int)shape.b.getX()/SIZE][(int)shape.b.getY()/SIZE] = 1;
GRID[(int)shape.c.getX()/SIZE][(int)shape.c.getY()/SIZE] = 1;
GRID[(int)shape.d.getX()/SIZE][(int)shape.d.getY()/SIZE] = 1;
DeleteRows(group);
Shape a = TetrisHolder.createRect();
object = a;
group.getChildren().addAll(a.a, a.b, a.c, a.d);
moveOnKeyPress(shape.a.getScene(), a.a, a.b, a.c, a.d);
}
if(shape.c.getY() + MOVE_AMOUNT < YLIMIT){
int checka = GRID[(int)shape.a.getX()/SIZE][((int)shape.a.getY()/SIZE) + 1];
int checkb = GRID[(int)shape.b.getX()/SIZE][((int)shape.b.getY()/SIZE) + 1];
int checkc = GRID[(int)shape.c.getX()/SIZE][((int)shape.c.getY()/SIZE) + 1];
int checkd = GRID[(int)shape.d.getX()/SIZE][((int)shape.d.getY()/SIZE) + 1];
if(checka == 0 && checka == checkb && checkb == checkc && checkc == checkd){
shape.a.setY(shape.a.getY() + MOVE_AMOUNT);
shape.b.setY(shape.b.getY() + MOVE_AMOUNT);
shape.c.setY(shape.c.getY() + MOVE_AMOUNT);
shape.d.setY(shape.d.getY() + MOVE_AMOUNT);
}
}
}
private boolean checkA(Shape shape){
return (GRID[(int)shape.a.getX()/SIZE][((int)shape.a.getY()/SIZE) + 1] == 1);
}
private boolean checkB(Shape shape){
return (GRID[(int)shape.b.getX()/SIZE][((int)shape.b.getY()/SIZE) + 1] == 1);
}
private boolean checkC(Shape shape){
return (GRID[(int)shape.c.getX()/SIZE][((int)shape.c.getY()/SIZE) + 1] == 1);
}
private boolean checkD(Shape shape){
return (GRID[(int)shape.d.getX()/SIZE][((int)shape.d.getY()/SIZE) + 1] == 1);
}
}
The error:
Exception in thread "JavaFX Application Thread" java.lang.NullPointerException
at application.Tetris.moveOnKeyPress(Tetris.java:70)
at application.Tetris.CheckDown(Tetris.java:147)
at application.Tetris.access$1(Tetris.java:137)
at application.Tetris$1$1.run(Tetris.java:60)
at com.sun.javafx.application.PlatformImpl.lambda$null$173(PlatformImpl.java:295)
at java.security.AccessController.doPrivileged(Native Method)
at com.sun.javafx.application.PlatformImpl.lambda$runLater$174(PlatformImpl.java:294)
at com.sun.glass.ui.InvokeLaterDispatcher$Future.run(InvokeLaterDispatcher.java:95)
Why are you getting the scene from a shape if you still have a reference to a static scene at the top?
I'd say try switching the following out at line 70:
scene.setOnKeyPressed(new EventHandler<KeyEvent>() {
to this:
this.scene.setOnKeyPressed(new EventHandler<KeyEvent>() {
You are trying to access a shape which is null.
In your case, if you look at line 70, you are trying to perform scene.setOnKeyPressed, but scene is null.
You are calling in 2 places the moveOnKeyPress method.
Where your problem is calling this method at line 147, where you do shape.a.getScene(). That call to getScene() is null.
Furthermore, if you look where you call CheckDown, you have them in 2 places, but your problematic call is at line 60.
Not sure what you do at line 48 (Shape a = TetrisHolder.createRect();), but I suspect there might be something wrong with setting up the scene
What I did here is translate your stacktrace:
at application.Tetris.moveOnKeyPress(Tetris.java:70)
at application.Tetris.CheckDown(Tetris.java:147)
at application.Tetris.access$1(Tetris.java:137)
at application.Tetris$1$1.run(Tetris.java:60)
Related
So here's my problem :
I have two arrays, I want to count how many values are on the exact same position [i] on both arrays, and how many values are the same on both arrays but for different [i]
I tried the usual loop with for and the size of an array but it displays strange values that are far from what expected
package stackOverflow;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Arrays;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JTextField;
public class mainStack extends JFrame implements ActionListener {
JButton jbr,jbv,jbb,jbo,jbn,jbj;
JTextField l11b;
String a;
int tabRef[]= {0,1,2,3};
int correctAndSameCase=0;
int correctButDiffCase=0;
mainStack(){
this.setLayout(null);
jbr = new JButton("Rouge");
jbr.setBounds(0,80,85,30);
add(jbr);
jbv = new JButton("Vert");
jbv.setBounds(125, 80, 85, 30);
add(jbv);
jbb = new JButton("Bleu");
jbb.setBounds(0, 120, 85, 30);
add(jbb);
jbj = new JButton("Jaune");
jbj.setBounds(125, 120, 85, 30);
add(jbj);
jbo = new JButton("Orange");
jbo.setBounds(0, 160, 85,30);
add(jbo);
jbn = new JButton("Noir");
jbn.setBounds(125,160, 85,30);
add(jbn);
jbr.addActionListener(this);
jbv.addActionListener(this);
jbb.addActionListener(this);
jbj.addActionListener(this);
jbo.addActionListener(this);
jbn.addActionListener(this);
setLayout(null);
setSize(800,800);
setVisible(true);
}
private int index = 0;
private int p=0;
private int tabAnswer[][] = new int[3][4];
private int i;
public void actionPerformed(ActionEvent e) {
if (e.getSource().equals(jbr)) {
tabAnswer[p][index] = 0;
} else if (e.getSource().equals(jbv)) {
tabAnswer[p][index] = 1;
} else if (e.getSource().equals(jbj)) {
tabAnswer[p][index] = 2;
} else if (e.getSource().equals(jbb)) {
tabAnswer[p][index] = 3;
} else if (e.getSource().equals(jbo)) {
tabAnswer[p][index] = 4;
} else if (e.getSource().equals(jbn)) {
tabAnswer[p][index] = 5;
}
index++;
if (index >= tabAnswer[p].length) {
System.out.println(Arrays.toString(tabAnswer[p]));
for(i=0 ; i<tabRef.length;i++) {
if(tabAnswer[p][i]==tabRef[i]) {
correctAndSameCase++;
}else if(tabAnswer[p][i]==tabRef[0] & tabAnswer[p][i]!=tabRef[i] || tabAnswer[p][i]==tabRef[1] & tabAnswer[p][i]!=tabRef[i] || tabAnswer[p][i]==tabRef[2]& tabAnswer[p][i]!=tabRef[i] ||tabAnswer[p][i]==tabRef[3] & tabAnswer[p][i]!=tabRef[i]) {
correctButDiffCase++;
}
}
index = 0;
p++;
System.out.println(correctAndSameCase+" number are on the same case on both arrays");
System.out.println(correctButDiffCase+" number are on different case on both arrays");
if(p>=3) {
p=0;
}
correctAndSameCase=0;
correctButDiffCase=0;
}
}
public static void main(String[] args) {
mainStack t= new mainStack();
}
Here for tabAnswer {5,4,3,2} correctAndSameCase should be 0 and correctButDiffCase should be 2 but in stead it gives me 0 and 1 as answer.
EDIT: I can see that the problem is in the condition to set the value to correctButDiffCasebut i don't know how to fix it
here a short code snippet that counts these two values.
But I didn't know, if you want to count some special cases (see TODOs).
public static void main(String[] args) throws Exception {
List<Integer> tabRef = Arrays.asList(10, 5, 3, 5, 2, 6);
List<Integer> tabRef2 = Arrays.asList(12, 8, 3, 5, 6, 2);
int matchesOnSameIndex = 0;
int matchesButDifferentIndex = 0;
for (int i = 0; i < tabRef.size(); i++) {
//compare on same index, if other list has element on this index
if (tabRef2.size() > i) {
if (tabRef.get(i) == tabRef2.get(i)) {
//same element on same index
matchesOnSameIndex++;
}
}
//check if value exists in other list
if (tabRef2.contains(tabRef.get(i))) {
//if yes, check if it is not at same position
if (tabRef2.size() > i) {
if (tabRef2.get(i) != tabRef.get(i)) {
//not same index
//TODO must count multiple times, if element exists multiple times?
matchesButDifferentIndex++;
}else {
//TODO must count, if also exists on other index?
}
}else {
//same position not existing, so must be on other position
matchesButDifferentIndex++;
}
}
}
System.out.println("matchesOnSameIndex: "+matchesOnSameIndex);
System.out.println("matchesButDifferentIndex: "+matchesButDifferentIndex);
}
your code to count the occurences seem fine (although a bit messy).
I wrote a junit test using your code and there is no issue:
#Test
public void testArrayCheck() {
int[] tabRef = {0,1,2,3};
int tabAnswer[][] = new int[3][4];
int[] tabAnswerPos0 = {0,0,0,0};
tabAnswer[0] = tabAnswerPos0;
int p = 0;
int correctAndSameCase = 0;
int correctButDiffCase = 0;
Set<Integer> setArrayValues = new HashSet<Integer>();
for(int i=0 ; i<tabRef.length;i++) {
if(tabAnswer[p][i]==tabRef[i]) {
correctAndSameCase++;
}else if(tabAnswer[p][i]==tabRef[0] && tabAnswer[p][i]!=tabRef[i]
|| tabAnswer[p][i]==tabRef[1] && tabAnswer[p][i]!=tabRef[i]
|| tabAnswer[p][i]==tabRef[2] && tabAnswer[p][i]!=tabRef[i]
||tabAnswer[p][i]==tabRef[3] && tabAnswer[p][i]!=tabRef[i]) {
if (!setArrayValues.contains(tabAnswer[p][i])) {
correctButDiffCase++;
setArrayValues.add(tabAnswer[p][i]);
}
}
}
System.out.println(correctAndSameCase+" number are on the same case on both arrays");
System.out.println(correctButDiffCase+" number are on different case on both arrays");
}
1 number are on the same case on both arrays
1 number are on different case on both arrays
Are you sure that tabAnswers has the values {5,4,3,2}?
So I looked this error up before posting and understand it has something to do with trying to refer to an array value outside of the bounds of an array, but what confuses me is that my class still runs as if the error never happened (My guess for this is the differing threads), and that no one thing in my code seems to be causing the error (I followed the stack-trace all the way through); it's just annoying to see the error pop up every so often and I would like to know how to fix it.
My class is a text based grid display that allows for keyboard input (I don't extend the JFrame class because I don't want anyone to be able to resize the display other than by changing the "width" and "height" fields). I hooked it up to another class with a main method that uses the display to play a top-view text-based platformer game to make the error more visible. As I move around, every so often I get an error similar to this one:
Exception in thread "AWT-EventQueue-0" java.lang.ArrayIndexOutOfBoundsException: -1
at javax.swing.text.CompositeView.getView(CompositeView.java:160)
at javax.swing.text.Utilities.getNextVisualPositionFrom(Utilities.java:1030)
at javax.swing.text.CompositeView.getNextEastWestVisualPositionFrom(CompositeView.java:757)
at javax.swing.text.CompositeView.getNextVisualPositionFrom(CompositeView.java:479)
at javax.swing.plaf.basic.BasicTextUI$RootView.getNextVisualPositionFrom(BasicTextUI.java:1588)
at javax.swing.plaf.basic.BasicTextUI.getNextVisualPositionFrom(BasicTextUI.java:1127)
at javax.swing.text.DefaultEditorKit$NextVisualPositionAction.actionPerformed(DefaultEditorKit.java:1690)
at javax.swing.SwingUtilities.notifyAction(SwingUtilities.java:1663)
at javax.swing.JComponent.processKeyBinding(JComponent.java:2882)
at javax.swing.JComponent.processKeyBindings(JComponent.java:2929)
at javax.swing.JComponent.processKeyEvent(JComponent.java:2845)
at java.awt.Component.processEvent(Component.java:6310)
at java.awt.Container.processEvent(Container.java:2236)
at java.awt.Component.dispatchEventImpl(Component.java:4889)
at java.awt.Container.dispatchEventImpl(Container.java:2294)
at java.awt.Component.dispatchEvent(Component.java:4711)
at java.awt.KeyboardFocusManager.redispatchEvent(KeyboardFocusManager.java:1954)
at java.awt.DefaultKeyboardFocusManager.dispatchKeyEvent(DefaultKeyboardFocusManager.java:806)
at java.awt.DefaultKeyboardFocusManager.preDispatchKeyEvent(DefaultKeyboardFocusManager.java:1074)
at java.awt.DefaultKeyboardFocusManager.typeAheadAssertions(DefaultKeyboardFocusManager.java:945)
at java.awt.DefaultKeyboardFocusManager.dispatchEvent(DefaultKeyboardFocusManager.java:771)
at java.awt.Component.dispatchEventImpl(Component.java:4760)
at java.awt.Container.dispatchEventImpl(Container.java:2294)
at java.awt.Window.dispatchEventImpl(Window.java:2746)
at java.awt.Component.dispatchEvent(Component.java:4711)
at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:758)
at java.awt.EventQueue.access$500(EventQueue.java:97)
at java.awt.EventQueue$3.run(EventQueue.java:709)
at java.awt.EventQueue$3.run(EventQueue.java:703)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:80)
at java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:90)
at java.awt.EventQueue$4.run(EventQueue.java:731)
at java.awt.EventQueue$4.run(EventQueue.java:729)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:80)
at java.awt.EventQueue.dispatchEvent(EventQueue.java:728)
at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:201)
at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:116)
at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:105)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:101)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:93)
at java.awt.EventDispatchThread.run(EventDispatchThread.java:82)
This is my class:
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import javax.swing.JFrame;
import javax.swing.JTextPane;
import javax.swing.text.MutableAttributeSet;
import javax.swing.text.SimpleAttributeSet;
import javax.swing.text.StyleConstants;
import javax.swing.text.StyledDocument;
public class TextDisplay {
private int width;
private int height;
private int fontSize;
private double fontSpacing;
private char lastChar = 0;
private int lastKeyPress = 0;
private int lastKeyRelease = 0;
private JFrame mainframe;
private JTextPane field;
public TextDisplay(int width, int height) {
this.width = width;
this.height = height;
createGUI(false);
clearDisplay();
}
public TextDisplay(int width, int height, boolean visibility) {
this.width = width;
this.height = height;
createGUI(visibility);
clearDisplay();
}
private void createGUI(boolean visibility) {
mainframe = new JFrame();
if ((this.width < 1) || (this.height < 1)) {
throw new IllegalArgumentException();
}
mainframe.setResizable(false);
mainframe.setDefaultCloseOperation(3);
field = new JTextPane();
field.addKeyListener(new KeyListener() {
public void keyTyped(KeyEvent e) {
lastChar = e.getKeyChar();
}
public void keyPressed(KeyEvent e) {
lastKeyPress = e.getKeyCode();
}
public void keyReleased(KeyEvent e) {
lastKeyRelease = e.getKeyCode();
}
});
field.setEditable(false);
setFont(70, 0.0);
clearDisplay();
mainframe.add(field);
if (visibility) {
mainframe.setVisible(true);
}
}
public int getLastKeyPress() {
return lastKeyPress;
}
public int getLastKeyRelease() {
return lastKeyRelease;
}
public char getLastKeyTyped() {
return lastChar;
}
public void clearLastKeyPress() {
lastKeyPress = 0;
}
public void clearLastKeyRelease() {
lastKeyRelease = 0;
}
public void clearLastKeyTyped() {
lastChar = 0;
}
private int calcWindowWidth() {
FontMetrics fm = field.getFontMetrics(new Font("Consolas", 0, this.fontSize));
return 12 + fm.charWidth(' ') * this.width;
}
private int calcWindowHeight() {
FontMetrics fm = field.getFontMetrics(new Font("Consolas", 0, this.fontSize));
double s = this.fontSpacing;
int fh = fm.getHeight();
int h = this.height;
double tf = Math.signum(s) * -4;
int pixels = 40 + fh * h;
double spacingPixels = roundB(fh * s * (h - 1));
int oddPixels = (int) roundB(tf * Math.floor(8 * s / tf) - 8 * s);
int extraPixels = (int) spacingPixels;
return pixels + extraPixels - oddPixels;
}
public static double roundB(double value) {
return Math.round(value * 100000000000.0) / 100000000000.0;
}
public void refresh() {
mainframe.setVisible(false);
mainframe.setVisible(true);
}
public void dispose() {
mainframe.dispose();
}
public boolean isDisplayable() {
return mainframe.isDisplayable();
}
public void setVisible(boolean visibility) {
mainframe.setVisible(visibility);
}
public void setTitle(String name) {
mainframe.setTitle(name);
}
public int getFontSize() {
return this.fontSize;
}
public double getFontSpacing() {
return this.fontSpacing;
}
public void setFontSize(int fontSize) {
setFont(fontSize, this.fontSpacing);
}
public void setFontSpacing(double fontSpacing) {
setFont(this.fontSize, fontSpacing);
}
public void setFont(int fontSize, double fontSpacing) {
this.fontSize = fontSize;
this.fontSpacing = roundB(fontSpacing);
mainframe.setSize(calcWindowWidth(), calcWindowHeight());
StyledDocument doc = field.getStyledDocument();
MutableAttributeSet mas = new SimpleAttributeSet();
StyleConstants.setLineSpacing(mas, (float) this.fontSpacing);
StyleConstants.setFontSize(mas, this.fontSize);
StyleConstants.setFontFamily(mas, "Consolas");
doc.setParagraphAttributes(0, 1000, mas, true);
field.setStyledDocument(doc);
}
public void setDefaultCloseOperation(int operation) {
mainframe.setDefaultCloseOperation(operation);
}
public void clearDisplay() {
StringBuilder display = new StringBuilder();
for (int row = 0; row < this.height; row++) {
for (int col = 0; col < this.width; col++) {
display.append(' ');
}
display.append('\n');
}
field.setText(display.toString());
}
public void setDisplay(char[][] charMap) {
StringBuilder display = new StringBuilder();
if (charMap.length != this.height) {
throw new IllegalArgumentException("rows = " + charMap.length + ", this.height = " + this.height);
}
for (int row = 0; row < charMap.length; row++) {
if (charMap[row].length != this.width) {
throw new IllegalArgumentException(
"row = " + row + ", length = " + charMap[row].length + ", this.width = " + this.width);
}
char[] arrayOfChar;
int j = (arrayOfChar = charMap[row]).length;
for (int i = 0; i < j; i++) {
char c = arrayOfChar[i];
display.append(c);
}
display.append('\n');
}
field.setText(display.toString());
}
public void setDisplay(String[] lines) {
StringBuilder display = new StringBuilder();
if (lines.length != this.height) {
throw new IllegalArgumentException("rows = " + lines.length + ", this.height = " + this.height);
}
for (int i = 0; i < lines.length; i++) {
String string = lines[i];
if (string.length() != this.width) {
throw new IllegalArgumentException(
"row = " + i + ", length = " + string.length() + ", this.width = " + this.width);
}
display.append(string + '\n');
}
field.setText(display.toString());
}
public String[] getDisplay() {
return field.getText().split("\n");
}
public char[][] getDisplayCharMap() {
String[] display = getDisplay();
char[][] charMap = new char[this.height][this.width];
for (int row = 0; row < this.height; row++) {
charMap[row] = display[row].toCharArray();
}
return charMap;
}
public void setCharAt(char character, int row, int col) {
char[][] display = getDisplayCharMap();
if ((row >= this.height) || (col >= this.width) || (row < 0) || (col < 0)) {
throw new IllegalArgumentException("row = " + row + ", this.height = " + this.height + ", col = " + col
+ ", this.width = " + this.width);
}
display[row][col] = character;
setDisplay(display);
}
public char getCharAt(int row, int col) {
char[][] display = getDisplayCharMap();
if ((row >= this.height) || (col >= this.width) || (row < 0) || (col < 0)) {
throw new IllegalArgumentException("row = " + row + ", col = " + col);
}
return display[row][col];
}
public void output(String text, int row, int col) {
char[][] display = getDisplayCharMap();
if ((row >= this.height) || (col >= this.width) || (row < 0) || (col < 0)) {
throw new IllegalArgumentException("row = " + row + ", col = " + col);
}
char[] arrayOfChar = text.toCharArray();
for (char c : arrayOfChar) {
display[row][col] = c;
col++;
if (col >= this.width) {
col = 0;
row++;
}
if (row >= this.height) {
row = 0;
}
}
setDisplay(display);
}
public int getWidth() {
return this.width;
}
public int getHeight() {
return this.height;
}
}
This is the class I used with the main method:
import java.awt.event.KeyEvent;
public class Main {
volatile static int key;
public static void main(String[] args) {
TextDisplay display = new TextDisplay(10, 5);
display.setDisplay(new String[] {"OXXXXXXXXO","X X","X X","X X","OXXXXXXXXO"});
display.setVisible(true);
int x = 1;
int y = 1;
boolean gameRunning = true;
display.setCharAt('P', y, x);
while (gameRunning) {
key = display.getLastKeyPress();
if (key != 0) {
display.setCharAt(' ', y, x);
switch (key) {
case KeyEvent.VK_LEFT:
if (display.getCharAt(y, x - 1) == ' ') x--;
break;
case KeyEvent.VK_UP:
if (display.getCharAt(y - 1, x) == ' ') y--;
break;
case KeyEvent.VK_RIGHT:
if (display.getCharAt(y, x + 1) == ' ') x++;
break;
case KeyEvent.VK_DOWN:
if (display.getCharAt(y + 1, x) == ' ') y++;
break;
}
display.setCharAt('P', y, x);
display.clearLastKeyPress();
}
}
}
}
I can live with the error, but its quite annoying; could someone help me fix this?
EDIT: Figured this was impractical, so I just extended JFrame and wrapped any time I was changing the display with invokeLater. When I did this the error disappeared. Thanks to tsolakp for the help.
You are changing Swing UI state from main thread inside your while loop.
Keep in mind that after calling setVisible on display object the Event Dispatch Thread is started and you cannot modify UI directly after that call.
Swing does not guarantee proper operation in this type of usage.
Try to wrap all calls to display' variable aftersetVisiblecall withinvokeLater`.
1) Here is the code the uses invokeLater:
public static void main(String[] args) {
TextDisplay display = new TextDisplay(10, 5);
display.setDisplay(new String[] {"OXXXXXXXXO","X X","X X","X X","OXXXXXXXXO"});
display.setVisible(true);
Helper helper = new Helper(display);
boolean gameRunning = true;
while (gameRunning) {
SwingUtilities.invokeLater( () -> helper.check() );
}
}
private static class Helper{
int x = 1;
int y = 1;
TextDisplay display = null;
public Helper(TextDisplay display){
this.display = display;
display.setCharAt('P', y, x);
}
public void check(){
int key = display.getLastKeyPress();
if (key != 0) {
display.setCharAt(' ', y, x);
switch (key) {
case KeyEvent.VK_LEFT:
if (display.getCharAt(y, x - 1) == ' ') x--;
break;
case KeyEvent.VK_UP:
if (display.getCharAt(y - 1, x) == ' ') y--;
break;
case KeyEvent.VK_RIGHT:
if (display.getCharAt(y, x + 1) == ' ') x++;
break;
case KeyEvent.VK_DOWN:
if (display.getCharAt(y + 1, x) == ' ') y++;
break;
}
display.setCharAt('P', y, x);
display.clearLastKeyPress();
}
}
}
2) You dont really need to while loop at all. Just listen to key events. I just poster the approach with invokeLater so that you could familiarize how it can be used:
public static void main(String[] args) {
TextDisplay display = new TextDisplay(10, 5);
Helper helper = new Helper(display);
display.setDisplay(new String[] {"OXXXXXXXXO","X X","X X","X X","OXXXXXXXXO"});
display.addKeyListener(helper);
display.setVisible(true);
}
private static class Helper extends KeyAdapter{
int x = 1;
int y = 1;
TextDisplay display = null;
public Helper(TextDisplay display){
this.display = display;
display.setCharAt('P', y, x);
}
public void keyPressed(KeyEvent e) {
int key = e.getKeyCode();
if (key != 0) {
display.setCharAt(' ', y, x);
switch (key) {
case KeyEvent.VK_LEFT:
if (display.getCharAt(y, x - 1) == ' ') x--;
break;
case KeyEvent.VK_UP:
if (display.getCharAt(y - 1, x) == ' ') y--;
break;
case KeyEvent.VK_RIGHT:
if (display.getCharAt(y, x + 1) == ' ') x++;
break;
case KeyEvent.VK_DOWN:
if (display.getCharAt(y + 1, x) == ' ') y++;
break;
}
display.setCharAt('P', y, x);
}
}
}
and add this method to your TextDisplay:
public void addKeyListener(KeyListener kl){
field.addKeyListener(kl);
}
The problem asks for an acm graphics program that reads a txt file like this:
R
FUN
SALES
RECEIPT
MERE#FARM
DOVE###RAIL
MORE#####DRAW
HARD###TIED
LION#SAND
EVENING
EVADE
ARE
D
and makes a crossword puzzle, with blank squares on letters, black squares on '#', and nothing on empty spaces. The problem also asks that "if the square is at the beginning of a word running across, down, or both, the square should contain a number that is assigned sequentially through the puzzle."
I have the square drawing working, but I'm stuck on drawing the numbers correctly. There is something wrong with how I'm detecting null space and black squares. Can someone tell me what I'm doing wrong, please?
Here is the code:
import acm.program.*;
import java.io.*;
import java.util.*;
import acm.graphics.*;
import java.awt.*;
public class Crossword extends GraphicsProgram {
public void run() {
String fileName = "crosswordfile.txt";
makeCrosswordPuzzle(fileName);
}
private static final int sqCon = 15; // constant for square x and y dimensions
private int y = 0;
public void makeCrosswordPuzzle(String fileName) {
BufferedReader rd;
int y = 0; // y value for the square being added during that loop. increments by sqCon after every line
int wordNumber = 1; // variable for numbers added to certain boxes. increments every time the program adds a number
try {
rd = new BufferedReader(new FileReader(fileName));
String line = rd.readLine(); //reads one line of the text document at a time and makes it a string
while (line != null) {
int x = 0;
for (int i = 0; i < line.length(); i++) {
char lineChar = line.charAt(i);// the character being examined for each loop
GRect whiteSq = new GRect(sqCon,sqCon); //GRect for blank squares
GRect blackSq = new GRect(sqCon,sqCon);//GRect for black squares
blackSq.setFilled(true);
blackSq.setFillColor(Color.BLACK);
if (lineChar == '#'){
add (blackSq,x,y);
}
if (Character.isLetter(lineChar)) {
add (whiteSq, x, y);
// if the element above or to the left of the current focus is null or blackSq, place the number and then increment wordNumber
GObject above = getElementAt(x+sqCon/2,y-sqCon/2);
GObject left = getElementAt(x-sqCon/2, y+sqCon/2);
GLabel wordNumberLabel = new GLabel(Integer.toString(wordNumber));
if (above == null || left == null || above == blackSq || left == blackSq) {
add(wordNumberLabel,x,y+sqCon);
wordNumber++;
}
}
x += sqCon;
}
line = rd.readLine();
y += sqCon;
}
rd.close();
}
catch (IOException e) {
throw new ErrorException(e);
}
}
}
Edited to add:
I copied your code over to my Eclipse and ran it. Here's the result.
You did fine on the upper half, but you missed the down numbers on the lower half.
Here's the same code, reformatted so it's easier to read.
import java.awt.Color;
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import acm.graphics.GLabel;
import acm.graphics.GObject;
import acm.graphics.GRect;
import acm.program.GraphicsProgram;
import acm.util.ErrorException;
public class Crossword extends GraphicsProgram {
private static final long serialVersionUID = -7971434624427958742L;
public void run() {
// String fileName = "crosswordfile.txt";
String fileName = "C:/Eclipse/eclipse-4.2-work/com.ggl.testing/crosswordfile.txt";
makeCrosswordPuzzle(fileName);
}
private static final int sqCon = 15; // constant for square x and y
// dimensions
private int y = 0;
public void makeCrosswordPuzzle(String fileName) {
BufferedReader rd;
int y = 0; // y value for the square being added during that loop.
// increments by sqCon after every line
int wordNumber = 1; // variable for numbers added to certain boxes.
// increments every time the program adds a number
try {
rd = new BufferedReader(new FileReader(fileName));
String line = rd.readLine(); // reads one line of the text document
// at a time and makes it a string
while (line != null) {
int x = 0;
for (int i = 0; i < line.length(); i++) {
char lineChar = line.charAt(i);// the character being
// examined for each loop
GRect whiteSq = new GRect(sqCon, sqCon); // GRect for blank
// squares
GRect blackSq = new GRect(sqCon, sqCon);// GRect for black
// squares
blackSq.setFilled(true);
blackSq.setFillColor(Color.BLACK);
if (lineChar == '#') {
add(blackSq, x, y);
}
if (Character.isLetter(lineChar)) {
add(whiteSq, x, y);
// if the element above or to the left of the current
// focus is null or blackSq, place the number and then
// increment wordNumber
GObject above = getElementAt(x + sqCon / 2, y - sqCon
/ 2);
GObject left = getElementAt(x - sqCon / 2, y + sqCon
/ 2);
GLabel wordNumberLabel = new GLabel(
Integer.toString(wordNumber));
if (above == null || left == null || above == blackSq
|| left == blackSq) {
add(wordNumberLabel, x, y + sqCon);
wordNumber++;
}
}
x += sqCon;
}
line = rd.readLine();
y += sqCon;
}
rd.close();
} catch (IOException e) {
throw new ErrorException(e);
}
}
}
I followed the advice of my own comment. I created the crossword puzzle answer, numbered the crossword puzzle answer, and finally drew the crossword puzzle answer.
Here's the applet result:
I kept a List of crossword puzzle cells. That way, I could determine the length and the width of the puzzle by the number of characters on a row and the number of rows of the input text file. I didn't have to hard code the dimensions.
For each crossword cell, I kept track of whether or not it was a letter, and whether or not it was a dark space.
When determining where to put the numbers, I followed 2 rules.
An across number is placed where the cell left of the cell is empty or dark, and there are three or more letters across.
A down number is placed where the cell above the cell is empty or dark, there are three or more letters down, and there is no across number.
You can see in the code that I had to do some debug printing to get the crossword puzzle clue numbering correct. I broke the process into many methods to keep each method as simple as possible.
Finally, I drew the crossword puzzle answer from the information in the List.
Here's the code:
import java.awt.Color;
import java.awt.Point;
import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import acm.graphics.GLabel;
import acm.graphics.GRect;
import acm.program.GraphicsProgram;
import acm.util.ErrorException;
public class Crossword extends GraphicsProgram {
private static final boolean DEBUG = false;
private static final long serialVersionUID = -7971434624427958742L;
private List<CrosswordCell> crosswordCellList;
#Override
public void run() {
this.crosswordCellList = new ArrayList<CrosswordCell>();
// String fileName = "crosswordfile.txt";
String fileName = "C:/Eclipse/eclipse-4.2-work/" +
"com.ggl.testing/crosswordfile.txt";
try {
readCrosswordAnswer(fileName);
if (DEBUG) printCrosswordAnswer();
numberCrosswordCells();
if (DEBUG) printCrosswordAnswer();
drawCrosswordAnswer();
} catch (FileNotFoundException e) {
throw new ErrorException(e);
} catch (IOException e) {
throw new ErrorException(e);
}
}
private void readCrosswordAnswer(String fileName)
throws FileNotFoundException, IOException {
BufferedReader reader =
new BufferedReader(new FileReader(fileName));
String line = "";
int row = 0;
while ((line = reader.readLine()) != null) {
for (int column = 0; column < line.length(); column++) {
CrosswordCell cell = new CrosswordCell(column, row);
char lineChar = line.charAt(column);
if (lineChar == '#') {
cell.setDarkCell(true);
} else if (Character.isLetter(lineChar)) {
cell.setLetter(true);
}
crosswordCellList.add(cell);
}
row++;
}
reader.close();
}
public void printCrosswordAnswer() {
for (CrosswordCell cell : crosswordCellList) {
System.out.println(cell);
}
}
private void numberCrosswordCells() {
int clueNumber = 1;
for (CrosswordCell cell : crosswordCellList) {
if (cell.isLetter()) {
clueNumber = testCell(cell, clueNumber);
}
}
}
private int testCell(CrosswordCell cell, int clueNumber) {
Point p = cell.getLocation();
CrosswordCell leftCell = getLeftCell(p.x, p.y);
List<CrosswordCell> acrossList = getRightCells(p.x, p.y);
if (DEBUG) {
System.out.print(p);
System.out.println(", " + leftCell + " " +
acrossList.size());
}
if ((leftCell == null) && (acrossList.size() >= 3)) {
cell.setClueNumber(clueNumber++);
} else {
CrosswordCell aboveCell = getAboveCell(p.x, p.y);
List<CrosswordCell> downList = getBelowCells(p.x, p.y);
if (DEBUG) {
System.out.print(p);
System.out.println(", " + aboveCell + " " +
downList.size());
}
if ((aboveCell == null) && (downList.size() >= 3)) {
cell.setClueNumber(clueNumber++);
}
}
return clueNumber;
}
private CrosswordCell getAboveCell(int x, int y) {
int yy = y - 1;
return getCell(x, yy);
}
private CrosswordCell getLeftCell(int x, int y) {
int xx = x - 1;
return getCell(xx, y);
}
private List<CrosswordCell> getBelowCells(int x, int y) {
List<CrosswordCell> list = new ArrayList<CrosswordCell>();
for (int i = y; i < (y + 3); i++) {
CrosswordCell cell = getCell(x, i);
if (cell != null) {
list.add(cell);
}
}
return list;
}
private List<CrosswordCell> getRightCells(int x, int y) {
List<CrosswordCell> list = new ArrayList<CrosswordCell>();
for (int i = x; i < (x + 3); i++) {
CrosswordCell cell = getCell(i, y);
if (cell != null) {
list.add(cell);
}
}
return list;
}
private CrosswordCell getCell(int x, int y) {
for (CrosswordCell cell : crosswordCellList) {
Point p = cell.getLocation();
if ((p.x == x) && (p.y == y)) {
if (cell.isDarkCell()) {
return null;
} else if (cell.isLetter()){
return cell;
} else {
return null;
}
}
}
return null;
}
private void drawCrosswordAnswer() {
int sqCon = 32;
for (CrosswordCell cell : crosswordCellList) {
Point p = cell.getLocation();
if (cell.isDarkCell()) {
drawDarkCell(p, sqCon);
} else if (cell.isLetter()) {
drawLetterCell(cell, p, sqCon);
}
}
}
private void drawDarkCell(Point p, int sqCon) {
GRect blackSq = new GRect(sqCon, sqCon);
blackSq.setFilled(true);
blackSq.setFillColor(Color.BLACK);
add(blackSq, p.x * sqCon, p.y * sqCon);
}
private void drawLetterCell(CrosswordCell cell, Point p, int sqCon) {
GRect whiteSq = new GRect(sqCon, sqCon);
add(whiteSq, p.x * sqCon, p.y * sqCon);
if (cell.getClueNumber() > 0) {
String label = Integer.toString(cell.getClueNumber());
GLabel wordNumberLabel = new GLabel(label);
add(wordNumberLabel, p.x * sqCon + 2, p.y * sqCon + 14);
}
}
class CrosswordCell {
private boolean darkCell;
private boolean isLetter;
private int clueNumber;
private Point location;
public CrosswordCell(int x, int y) {
this.location = new Point(x, y);
this.clueNumber = 0;
this.darkCell = false;
this.isLetter = false;
}
public boolean isDarkCell() {
return darkCell;
}
public void setDarkCell(boolean darkCell) {
this.darkCell = darkCell;
}
public boolean isLetter() {
return isLetter;
}
public void setLetter(boolean isLetter) {
this.isLetter = isLetter;
}
public int getClueNumber() {
return clueNumber;
}
public void setClueNumber(int clueNumber) {
this.clueNumber = clueNumber;
}
public Point getLocation() {
return location;
}
#Override
public String toString() {
StringBuilder builder = new StringBuilder();
builder.append("CrosswordCell [location=");
builder.append(location);
builder.append(", clueNumber=");
builder.append(clueNumber);
builder.append(", darkCell=");
builder.append(darkCell);
builder.append(", isLetter=");
builder.append(isLetter);
builder.append("]");
return builder.toString();
}
}
}
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 8 years ago.
Improve this question
I'm not sure what's going on, but in the console I have a red 'stop' square that i can click to stop my program from running (Eclipse IDE) and my program is just running and the square stays red..?
EDIT:
my maze:
WWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWW
WSOOOOOOOOOOOOOOWOOOOOOOOOOOOOOOOOWOOOOOOOOOOOOOOOWOOOOOOW
WWOOOOOOOOOOOOOWWWWWWWWWWWWWOOOOOOOOOOWWWWWWWWWWWWWOOOOOOW
WWWWWWOOOOOOOOOOOOWWWWWWWOOOOOOOOOOOOWWWWWWWWWWWWWWWWOOOOW
WOOOOOOWWWWWWWWWWWWWWOOOOOOOOOOOWWWWWWWWOOOOOOOOOOOOOOOWWW
WOOOOWWWWWWWOOOOOOWWWWOOOOOOWWWWWWWWWWWOOOOWWWWWWWWWOWWWWW
WOOOWWWWWWWWWWWWOOWWWWWWWWWWWWOOOOOOOOOOOOWWWWWWWWWOOOOOWW
WOOWWWWWWWWWWWWWOOWWWWWWWWWWWWWWWWWOOOOOOOWWWWWWWWWWWWOOOW
WOWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWOOOOOOOWWWWWWWWWWWOOW
WOWWWWWWWWWWWWWOOOOOOOOOOOOOOOOOOOOOOOOOOOOWWWWWWWWWWWWOOW
WOOOOOOOOOOOOOOOOWWWWOOOOOOOOWWWWWWWOOOOOOWWWWWWWWWWWWWWFW
WWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWW
EDIT: here is my code:
import java.io.File;
import java.io.FileNotFoundException;
import java.util.HashSet;
import java.util.Scanner;
import java.util.Stack;
import java.awt.Point;
public class MazeExplorer {
static Point startPoint = new Point();
static Point finishPoint = new Point();
final static int mazeHeight = 12;
final static int mazeWidth = 58;
static char[][] mazePoints = new char[mazeHeight][mazeWidth];
Stack<Point> pointsNotTraversed = new Stack<Point>();
Point pt = new Point();
static HashSet<Point> previousLocations = new HashSet<Point>();
static Stack<Point> nextPoints = new Stack<Point>();
public static void main(String[] args) throws FileNotFoundException{
System.out.println("Please enter the file name of your Maze");
Scanner console = new Scanner(System.in);
File f = new File(console.nextLine());
Scanner sc = new Scanner(f);
if(!sc.hasNextLine()){
System.out.println("Sorry, please enter a file name with the extension, that contains a maze!");
}
System.out.println("So, you want to know if your maze is solvable.....?");
for (int row = 0; row < mazeHeight && sc.hasNext(); row++) {
final String mazeRow = sc.next(); //Get the next row from the scanner.
mazePoints[row] = mazeRow.toCharArray(); //Convert the row into a char[].
}
//identify the finish point
for(int i = 0; i < mazeHeight; i++){
for(int j = 0; j<mazeWidth; j++){
if(mazePoints[i][j] == 'F'){
finishPoint = new Point(i, j);
}
}
}
// Identify the start point
for(int i = 0; i< mazeHeight; i++){
for(int j = 0; j < mazeWidth; j++){
if(mazePoints[i][j] == 'S'){
startPoint = new Point(i , j);
}
}
}
isTraversable(startPoint);
}
public static boolean isTraversable(Point current){
boolean isSolvable = false;
nextPoints.push(current);
do {
if(current.y < 11) {
if((mazePoints[current.y + 1][current.x] != ' ') && (mazePoints[current.y + 1][current.x] != 'W') ){ // below direction
nextPoints.push(new Point(current.y + 1, current.x));
mazePoints[current.y + 1][current.x] = ' ';
isTraversable(nextPoints.pop());
}
}
if(current.y > 0){
if (mazePoints[current.y - 1][current.x] != ' ' && mazePoints[current.y - 1][current.x] != 'W' ){ //up dir
nextPoints.push(new Point(current.y - 1, current.x));
mazePoints[current.y - 1][current.x] = ' '; //'X' marks where you've already been
isTraversable(nextPoints.pop());
}
}
if(current.x < 57){
if(mazePoints[current.y][current.x + 1] != ' ' && mazePoints[current.y][current.x + 1] != 'W'){ // to the right
nextPoints.push(new Point(current.y, current.x + 1));
mazePoints[current.y][current.x + 1] = ' ';
isTraversable(nextPoints.pop());
}
}
if(current.x > 0){
if(mazePoints[current.y][current.x - 1] != ' ' && mazePoints[current.y][current.x - 1] != 'W') { // to the left
nextPoints.push(new Point(current.y, current.x - 1));
mazePoints[current.y][current.x - 1] = ' ';
isTraversable(nextPoints.pop());
}
}
if(current.equals(finishPoint)){
isSolvable = true;
System.out.println("MAZE IS SOLVABLE, YAHOOOOOO!!!!");
}
} while(!current.equals('F') && !nextPoints.isEmpty());
return isSolvable;
}
}
As I suggested before, you just need to reconfigure your recursive method. I took the liberty of doing this but if you ever want to learn how to program you'll want to try and solve problems like these on your own. Or try to understand the logic of your solution before you start coding.
Your main problem is that you don't know what direction you want to go in with the method before you just jumped in and that was causing all sorts of errors with different things not being compatible with each other.
import java.io.File;
import java.io.FileNotFoundException;
import java.util.HashSet;
import java.util.Scanner;
import java.util.Stack;
import java.awt.Point;
public class TestCode {
static Point startPoint = new Point();
static Point finishPoint = new Point();
final static int mazeHeight = 12;
final static int mazeWidth = 58;
static char[][] mazePoints = new char[mazeHeight][mazeWidth];
Stack<Point> pointsNotTraversed = new Stack<Point>();
Point pt = new Point();
static HashSet<Point> previousLocations = new HashSet<Point>();
static Stack<Point> nextPoints = new Stack<Point>();
public static void main(String[] args) throws FileNotFoundException{
System.out.println("Please enter the file name of your Maze");
Scanner console = new Scanner(System.in);
File f = new File(console.nextLine());
Scanner sc = new Scanner(f);
if(!sc.hasNextLine()){
System.out.println("Sorry, please enter a file name with the extension, that contains a maze!");
}
System.out.println("So, you want to know if your maze is solvable.....?");
for (int row = 0; row < mazeHeight && sc.hasNext(); row++) {
final String mazeRow = sc.next(); //Get the next row from the scanner.
mazePoints[row] = mazeRow.toCharArray(); //Convert the row into a char[].
}
//identify the finish point
for(int i = 0; i < mazeHeight; i++){
for(int j = 0; j<mazeWidth; j++){
if(mazePoints[i][j] == 'F'){
finishPoint = new Point(i, j);
}
}
}
// Identify the start point
for(int i = 0; i< mazeHeight; i++){
for(int j = 0; j < mazeWidth; j++){
if(mazePoints[i][j] == 'S'){
startPoint = new Point(i , j);
}
}
}
System.out.println(isTraversable(startPoint));
}
public static boolean isTraversable(Point current){
mazePoints[current.x][current.y] = ' ';
if(current.y < 56 && current.y > 0 && current.x > 0 && current.x < 11){
if (mazePoints[current.x - 1][current.y] == 'O'){ // Up dir
Point upPoint = new Point(current.x-1, current.y);
nextPoints.push(upPoint);
}
if(mazePoints[current.x+1][current.y] == 'O'){ // Down dir
Point downPoint = new Point(current.x+1, current.y);
nextPoints.push(downPoint);
}
if(mazePoints[current.x][current.y + 1] == 'O'){ // to the right
Point rightPoint = new Point(current.x, current.y+1);
nextPoints.push(rightPoint);
}
if(mazePoints[current.x][current.y - 1] == 'O'){ // to the left
Point leftPoint = new Point(current.x, current.y-1);
nextPoints.push(leftPoint);
}
if(mazePoints[current.x - 1][current.y] == 'F' ||
mazePoints[current.x + 1][current.y] == 'F' ||
mazePoints[current.x][current.y - 1] == 'F' ||
mazePoints[current.x][current.y + 1] == 'F'){
System.out.println("MAZE IS SOLVABLE, YAHOOOOOO!!!!");
return true;
}
}
if(nextPoints.isEmpty()){
return false;
}
else{
current = nextPoints.pop();
}
return(isTraversable(current));
}
}
With the maze input:
WWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWW
WSOOOOOOOOOOOOOOWOOOOOOOOOOOOOOOOOWOOOOOOOOOOOOOOOWOOOOOOW
WWOOOOOOOOOOOOOWWWWWWWWWWWWWOOOOOOOOOOWWWWWWWWWWWWWOOOOOOW
WWWWWWOOOOOOOOOOOOWWWWWWWOOOOOOOOOOOOWWWWWWWWWWWWWWWWOOOOW
WOOOOOOWWWWWWWWWWWWWWOOOOOOOOOOOWWWWWWWWOOOOOOOOOOOOOOOWWW
WOOOOWWWWWWWOOOOOOWWWWOOOOOOWWWWWWWWWWWOOOOWWWWWWWWWOWWWWW
WOOOWWWWWWWWWWWWOOWWWWWWWWWWWWOOOOOOOOOOOOWWWWWWWWWOOOOOWW
WOOWWWWWWWWWWWWWOOWWWWWWWWWWWWWWWWWOOOOOOOWWWWWWWWWWWWOOOW
WOWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWOOOOOOOWWWWWWWWWWWOOW
WOWWWWWWWWWWWWWOOOOOOOOOOOOOOOOOOOOOOOOOOOOWWWWWWWWWWWWOOW
WOOOOOOOOOOOOOOOOWWWWOOOOOOOOWWWWWWWOOOOOOWWWWWWWWWWWWWOFW
WWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWW
Yields the following output:
So, you want to know if your maze is solvable.....?
MAZE IS SOLVABLE, YAHOOOOOO!!!!
true
I imported the file a different way, but you can change that back to whatever method you use previously.
Might be that you've started multiple programs and you have the "Show Console When Standard Output Changes" Not sure, but that explains one scenario. If you start task manager and find the program there you could try terminating it that way.
If it's stuck running and never completes you could try running your program in the Eclipse debugger, without any breakpoints.
Open the Debug tab (Open in from Window > Show View > Debug), suspend the thread by right clicking 'Thread [main] (Running)' and selecting 'Suspend'.
Then work your way up from the bottom of the stack, hopefully this will narrow it down enough for you to find where it blocks.
import java.util.Scanner;
import java.util.Stack;
public class test5 {
private int numRows;
private int numCols;
public test5(){
Scanner input = new Scanner(System.in);
System.out.println("Enter number of rows: ");
numRows = input.nextInt();
System.out.println("Enter number of cols: ");
numCols = input.nextInt();
Stack<Point>stack = new Stack<Point>();
stack.push(new Point(0,0));
while(!stack.isEmpty()){
if(currentPath(stack.pop(),stack)){
System.out.println("Maze is solvable");
}
}
}
public static void main(String[]args){
new test5();
}
private boolean currentPath(Point point, Stack<Point>stack){
int currentRow = point.getRow();
int currentCol = point.getCol();
while(currentRow!=numRows-1 || currentCol!=numCols-1){
boolean canGoRight = canGoRight(currentRow,currentCol);
boolean canGoUp = canGoUp(currentRow,currentCol);
boolean canGoDown = canGoDown(currentRow,currentCol);
if(canGoRight){
if(canGoUp){
stack.push(new Point(currentRow-1,currentCol));
}
if(canGoDown){
stack.push(new Point(currentRow+1,currentCol));
}
currentCol = currentCol+1;
}
else{
if(canGoUp){
if(canGoDown){
stack.push(new Point(currentRow+1,currentCol));
}
currentRow = currentRow-1;
}
else if(canGoDown){
currentRow = currentRow+1;
}
else{
return false;
}
}
}
return true;
}
private boolean canGoUp(int row, int col){
return row-1>=0;
}
private boolean canGoRight(int row, int col){
return col+1<numCols;
}
private boolean canGoDown(int row, int col){
return row+1<numRows;
}
class Point{
private int row;
private int col;
public Point(int row, int col){
this.row = row;
this.col = col;
}
public int getRow(){
return row;
}
public int getCol(){
return col;
}
}
}
I know that there are lots of examples out there on this, but they all feel a little dated (even the sun docs) so I'm asking here to make sure what I'm doing is up to date. How would I go about talking to javascript from inside a java applet? Something simple like how to call alert() is all I'm looking for. Bonus points for a way to check if the browser has javascript enabled (this applet may be used in a school setting where having javascript turned off is a real possibility). All help is greatly appreciated, thanks in advance...
Code:
import java.applet.*;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import netscape.javascript.JSObject;
public class TeamProject extends Applet implements ActionListener, MouseListener {
char[][] charValues = new char[10][10];
Table aTable;
boolean allowUserInput = false;
Button BtnStart;
Button randomChangeBtn;
boolean guessMode;
JSObject jso;
public void init() {
//setup buttons
BtnStart = new Button("add row/column");
BtnStart.addActionListener((ActionListener)this); //cast
randomChangeBtn = new Button("change one value");
randomChangeBtn.addActionListener((ActionListener)this);
//add button
this.add(BtnStart);
//add image to Image objects
Image imgO = getImage(getCodeBase(), "images/not.gif");
Image imgX= getImage(getCodeBase(), "images/cross.gif");
//setup table
aTable = new Table(100, 100, 75, 55, 5, 5, imgX, imgO);
//setBackground(Color.LIGHT_GRAY);
super.resize(700, 700);
//add mouse listener
addMouseListener(this);
//initially guessMode will be false
guessMode = false;
//to talk to javascript
jso = JSObject.getWindow(this);
}
public void paint(Graphics g) {
g.setColor(Color.black);
aTable.draw(g);
}
//Mouse listener methods
public void mousePressed (MouseEvent e) {
if(!guessMode){
if ((allowUserInput)) { //&&(aTable.isDrawable(e.getX(), e.getY())))
aTable.swapSquareValue(e.getX(), e.getY());
repaint();
}
} else {
System.out.println("guessed row = " + e.getY() + " guessed col = " + e.getX());
aTable.checkGuess(e.getX(), e.getY());
//repaint();
}
}
public void mouseClicked (MouseEvent e) {}
public void mouseEntered (MouseEvent e) {}
public void mouseReleased (MouseEvent e) {}
public void mouseExited (MouseEvent e) {}
//Button action listener
public void actionPerformed(ActionEvent e) {
if (e.getSource() == BtnStart) {
aTable.addRow();
aTable.addColumn();
this.remove(BtnStart);
this.add(randomChangeBtn);
repaint();
} else if (e.getSource() == randomChangeBtn) {
//aTable.addRow();
aTable.randomChangeFunc();
repaint();
guessMode = true;
}
allowUserInput = true;
System.out.println(aTable.toString());
}
}
and my Table class:
import java.awt.*;
import java.util.Random;
public class Table {
private char[][]values = new char[10][10]; //probably better to use array of integer values(0 or 1)
Image imgO;
Image imgX;
private int Rows;
private int Columns;
private int BoxWidth ;
private int BoxHeight;
public Point Pos = new Point();
private int tableHeight;
private int tableWidth;
private int changedRow;
private int changedCol;
//constructor
public Table(int x, int y, int width, int height, int col, int rows, Image X, Image O) {
Rows = rows;
Columns = col;
BoxWidth = width;
BoxHeight = height;
Pos.x = x;
Pos.y = y;
imgX = X;
imgO = O;
tableHeight = Rows*BoxHeight;
tableWidth = Columns*BoxWidth;
this.setValues();
}
//draw table
public void draw(Graphics g) {
//draw vertical table lines
for (int i = 0 ; i <= Columns ; i++)
g.drawLine(i*BoxWidth + Pos.x, Pos.y, i*BoxWidth + Pos.x, tableHeight+Pos.y);
//draw horizontal table line
for(int i = 0 ; i <= Rows ; i++)
g.drawLine(Pos.x, i*BoxHeight + Pos.y, tableWidth+Pos.x, i*BoxHeight + Pos.y);
//draw values
drawValues(g);
}
public void swapSquareValue(int x, int y) {
if (this.isDrawable(x, y)) {
int col = this.getColumn(x)-1;
int row = this.getRow(y)-1;
if(values[row][col] == 'X')
values[row][col] = 'O';
else if(values[row][col] == 'O')
values[row][col] = 'X';
else
System.out.println("ERROR SWAPPING SQUARE VALUE");
} else
System.out.println("says not drawable");
}
public char getValue(int col, int row) {
return values[row][col];
}
//return true if (x,y) is a point in the table
public boolean isDrawable(int x, int y) {
if((this.getRow(y)!=-1)||(this.getColumn(x)!=-1))
return true;
else
return false;
}
public void addRow() {
Rows++;
tableHeight = (Rows*BoxHeight);
int numOfXs = 0;
for (int c=0; c < Columns; c++) {
numOfXs = 0;
for(int r = 0; r < Rows - 1; r++) {
if(values[r][c] == 'X'){
numOfXs++;
System.out.println("in column " + c + "new x found at " + r + " " + c + ", numOfXs = " + numOfXs);
}
if(numOfXs % 2 == 0) {
values[Rows - 1][c] = 'O';
} else{
values[Rows - 1][c] = 'X';
}
}//end inner for
System.out.println("end of column " + c);
}//end outer for
}// end function
public void addColumn() {
Columns++;
tableWidth = (Columns*BoxWidth);
int numOfXs = 0;
for (int r=0; r < Rows; r++) {
numOfXs = 0;
for(int c = 0; c < Columns - 1; c++) {
if(values[r][c] == 'X') {
numOfXs++;
System.out.println("in row " + r + "new x found at " + r + " " + c + ", numOfXs = " + numOfXs);
}
if(numOfXs % 2 == 0) {
values[r][Columns - 1] = 'O';
}
else {
values[r][Columns - 1] = 'X';
}
}//end inner for
System.out.println("end of row " + r);
}
}
//does not add or remove values
public void setColumn(int col) {
Columns = col;
tableWidth = (Columns*BoxWidth);
}
//does not add or remove values
public void setRows(int row) {
Rows = row;
tableHeight = (row*BoxHeight);
}
public String toString() {
String ValueString = "Displaying charValues[" + Rows + "][" + Columns + "]\n";
for (int r=0; r < Rows; r++) {
for (int c=0; c < Columns; c++) {
ValueString += (char)values[r][c];
}
ValueString += "\n"; //next line
}
return ValueString;
}
private void drawValues(Graphics g) {
Point drawPoint = new Point();
for (int r=0; r < Rows; r++)
for (int c=0; c < Columns; c++) {
drawPoint.x = Pos.x+BoxWidth*c;
drawPoint.y = Pos.y+BoxHeight*r;
//g.setColor(Color.white);
//g.fillRect(drawPoint.x+1, drawPoint.y+1, BoxWidth-1, BoxHeight-1);
if (values[r][c] == 'X') {
g.drawImage(imgX,drawPoint.x+1, drawPoint.y+1, BoxWidth-1, BoxHeight-1, null);
} else {
g.drawImage(imgO,drawPoint.x+1, drawPoint.y+1, BoxWidth-1, BoxHeight-1, null);
}
//System.out.print((char)values[r][c]);
}
g.setColor(Color.black);
}
//fills array with random values
private void setValues() {
for (int r=0; r < Rows; r++)
for (int c=0; c < Columns; c++) {
values[r][c] = this.randomChar();
}
}
//randomly return 'X' or 'O'
private char randomChar() {
char randomValue;
Random RandomGen = new Random();
if (RandomGen.nextInt(2)==0)
randomValue = 'O';
else
randomValue ='X';
return randomValue;
}
private int getColumn(int x) {
int offsetx=0;
for (int i = 0 ; i < Columns ; i++) {
offsetx = i*BoxWidth;
if((x>Pos.x+offsetx)&& (x<Pos.x+offsetx+BoxWidth))
return i+1;
}
return -1;
}
private int getRow(int y) {
int offsety=0;
for (int i = 0 ; i < Rows ; i++) {
offsety = i*BoxHeight;
if((y>Pos.y+offsety)&& (y<Pos.x+offsety+BoxHeight))
return i+1;
}
return -1;
}
public void randomChangeFunc() {
//get random row and column
Random rand=new Random();
int randRow = rand.nextInt(Rows);
int randCol = rand.nextInt(Columns);
System.out.println("randRow = " + randRow + " randCol = " + randCol);
/*THIS SHOULD BE HANDLED BY swapSquareValue(randCol,randRow)
/*BUT GETTING ERRORS (notDrawable). THE FOLLOWING CODE IS A WORK-AROUND
*/
if(values[randRow][randCol] == 'X')
values[randRow][randCol] = 'O';
else if(values[randRow][randCol] == 'O')
values[randRow][randCol] = 'X';
else
System.out.println("ERROR SWAPPING SQUARE VALUE");
//set globals
changedRow = randRow;
changedCol = randCol;
}
public void checkGuess(int guessCol, int guessRow){
int gCol = this.getColumn(guessCol)-1;
int gRow = this.getRow(guessRow)-1;
System.out.println("gCol = " + gCol + " gRow = " + gRow);
if(gCol == changedCol && gRow == changedRow) {
System.out.println("CORRECT!!!");
} else
System.out.println("incorrect :(");
}
}
Changing my javac command to:
javac -classpath /usr/lib/Java6u1/jre/lib/plugin.jar TeamProject.java
ignores my "Table" class and I get errors where I mention that. Any ideas?
Look at this article. If you try calling JS from applet on this page it definitely works, because there are js exception after update action from applet :)
import netscape.javascript.JSObject
public void init()
{
jso = JSObject.getWindow(this);
}
public void actionPerformed(ActionEvent e) {
if(jso != null )
try {
jso.call("updateWebPage", new String[] {txt.getText()});
}
catch (Exception ex) {
ex.printStackTrace();
}
}
EDIT:
For the classpath problem you need to add plugin.jar to your classpath which is located in %JAVA_HOME%\jre\lib\plugin.jar
EDIT2:
I think that your problem is that a class Table isn't compiled too:
try javac -classpath /usr/lib/Java6u1/jre/lib/plugin.jar TeamProject.java Table.java or use wildcards like *.java.
Maybe you should consider use IDE like Eclipse or Netbeans to compile and run project instead of struggling with command line tools.
As requested a sample which calls alert on the page it is embedded in (tested in Opera 10.01, FF 3.5.4, IE6).
Note the MAYSCRIPT in the applet tag, this MUST be present to enable java-javascript communication. As per default access to JSObject is disabled due to security reasons.
HTML:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>Test</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
</head>
<body>
<applet code="HelloWWW.class" width="300px" height="100px" MAYSCRIPT></applet>
</body>
</html>
Java (compile with javac -cp .;[pathtojre]/jre/lib/plugin.jar HelloWWW.java)
import java.awt.*;
import java.applet.*;
import java.awt.event.*;
import netscape.javascript.*;
public class HelloWWW extends Applet implements ActionListener {
Button runButton;
public void init() {
runButton = new Button("Run: alert(\"Hello WWW\")");
add(runButton);
runButton.addActionListener(this);
}
public void actionPerformed(ActionEvent evt) {
if (evt.getSource() == runButton) {
try {
//get JSOBject
JSObject jso = JSObject.getWindow(this);
//call alert with parameter passed as Object array
jso.call("alert", new Object[]{"Hello WWW"});
} catch (JSException e) {
e.printStackTrace();
}
runButton.setLabel("Did it!");
repaint();
}
}
}
Also check Java-to-Javascript Communication and Mozilla Dev: JSObject for further info.