How to dynamically add brackets to a boolean expression? - java

I'm writing a program in Java that is supposed to function as a truth table generator for a boolean expression. However, I'm having a lot of trouble with the brackets. The errors start when a pair of brackets enclose the entire expression (produces a runtime error), or if there aren't enough brackets in the expression (producing the wrong result).
Here's all my code:
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.util.*;
import java.lang.Math;
public class BooleanAlgebra
{
public static void main(String[] args)
{
new BooleanAlgebra();
}
private JFrame frame;
private JPanel panel;
private JTextField textField;
private JButton and;
private JButton or;
private JButton not;
private JButton nor;
private JButton nand;
private JButton xor;
private JButton xnor;
private JPanel panel2;
private JButton generate;
private JButton close;
private ArrayList<Character> variables;
private char[] chars;
public BooleanAlgebra()
{
frame = new JFrame("Boolean Algebra");
frame.setSize(new Dimension(800, 800));
textField = new JTextField("(x+y)");
and = new JButton("AND [ x & y ]");
or = new JButton("OR [ x + y ]");
not = new JButton("NOT [ ! x ]");
nor = new JButton("NOR [ ! ( x + y ) ]");
nand = new JButton("NAND [ ! ( x & y ) ]");
xor = new JButton("XOR [ ( x & ! y ) + ( ! x & y ) ]");
xnor = new JButton("XNOR [ ( x & y ) + ( ! x & ! y ) ]");
generate = new JButton("Generate Table");
close = new JButton("Exit");
ButtonHandler buttons = new ButtonHandler();
and.addActionListener(buttons);
or.addActionListener(buttons);
not.addActionListener(buttons);
nor.addActionListener(buttons);
nand.addActionListener(buttons);
xor.addActionListener(buttons);
xnor.addActionListener(buttons);
generate.addActionListener(buttons);
close.addActionListener(buttons);
panel2 = new JPanel();
panel2.setLayout(new GridLayout(1, 2));
panel2.add(generate);
panel2.add(close);
panel = new JPanel();
panel.setLayout(new GridLayout(9, 1));
panel.add(textField);
panel.add(and);
panel.add(or);
panel.add(not);
panel.add(nor);
panel.add(nand);
panel.add(xor);
panel.add(xnor);
panel.add(panel2);
frame.add(panel);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
private boolean isLetter(char a)
{
if((a > 64 && a < 91) || (a > 96 && a < 123))
{
return true;
}
return false;
}
private void generate()
{
chars = ("(" + textField.getText() + ")").toCharArray();
variables = new ArrayList<Character>();
for(int i = 0; i < chars.length; i++)
{
if(isLetter(chars[i]))
{
if(!variables.contains(chars[i]))
{
variables.add(chars[i]);
}
}
}
Collections.sort(variables);
String[] heads = new String[variables.size() + 1];
for(int i = 0; i < heads.length - 1; i++)
{
heads[i] = variables.get(i).toString();
}
heads[heads.length - 1] = textField.getText();
int row = (int)Math.pow(2, variables.size());
int column = variables.size() + 1;
int count = 0;
int max = 1;
Integer[][] array = new Integer[row][column];
for(int a = column - 2; a >= 0; a--)
{
for(int b = 0; b < row; b++)
{
if(count < max)
{
array[b][a] = 0;
count++;
}
else if(count >= max)
{
array[b][a] = 1;
count++;
if(count == max * 2)
{
count = 0;
}
}
}
max = max * 2;
}
for(int i = 0; i < row; i++)
{
array[i][column - 1] = 0;
}
int[][] arrayCopy = new int[row][column];
for(int i = 0; i < row; i++)
{
for(int j = 0; j < column; j++)
{
arrayCopy[i][j] = array[i][j];
}
}
for(int i = 0; i < row; i++)
{
array[i][column - 1] = calculate(arrayCopy[i]);
}
JTable table = new JTable(array, heads);
JFrame frame2 = new JFrame(textField.getText());
frame2.add(new JScrollPane(table));
frame2.pack();
frame2.setVisible(true);
table.setEnabled(false);
}
private int calculate(int[] array)
{
Stack<Character> ops = new Stack<Character>();
Stack<Integer> values = new Stack<Integer>();
for(int i = 0; i < chars.length; i++)
{
char s = chars[i];
if (s == '(') ;
else if (s == '+') ops.push(s);
else if (s == '&') ops.push(s);
else if (s == '!') ops.push(s);
else if (s == ')')
{
char operation = ops.pop();
int v = values.pop();
if (operation == '+') v = or(values.pop(), v);
else if (operation == '&') v = and(values.pop(), v);
else if (operation == '!') v = not(v);
values.push(v);
}
else if(isLetter(s))
{
values.push(array[variables.indexOf(s)]);
}
}
return values.pop();
}
private int and(int a, int b)
{
if(a == 1 && b == 1)
{
return 1;
}
return 0;
}
private int or(int a, int b)
{
if(a == 0 && b == 0)
{
return 0;
}
return 1;
}
private int not(int a)
{
if(a == 1)
{
return 0;
}
return 1;
}
public class ButtonHandler implements ActionListener
{
public void actionPerformed(ActionEvent event)
{
if(event.getSource() == and)
{
textField.setText(textField.getText() + "(x&y)");
textField.requestFocus(true);
}
if(event.getSource() == or)
{
textField.setText(textField.getText() + "(x+y)");
textField.requestFocus(true);
}
if(event.getSource() == not)
{
textField.setText(textField.getText() + "(!x)");
textField.requestFocus(true);
}
if(event.getSource() == nor)
{
textField.setText(textField.getText() + "!(x+y)");
textField.requestFocus(true);
}
if(event.getSource() == nand)
{
textField.setText(textField.getText() + "!(x&y)");
textField.requestFocus(true);
}
if(event.getSource() == xor)
{
textField.setText(textField.getText() + "(x&(!y))+(((!x)&y))");
textField.requestFocus(true);
}
if(event.getSource() == xnor)
{
textField.setText(textField.getText() + "(x&y)+(((!x)&(!y)))");
textField.requestFocus(true);
}
if(event.getSource() == generate)
{
generate();
}
if(event.getSource() == close)
{
System.exit(0);
}
}
}
}
I need help making this work without the user having to input the brackets correctly themselves (I want the program to fix up the expression, or somehow evaluate it without waiting for a close bracket like I did here).
To test the code and see the errors, input the following when running it:
(x+y) --> runtime error because brackets surround the whole expression
x+y+z --> incorrect output table
x+y --> works
x&y --> works
!!x --> incorrect output table
Please explain this to me. Thanks!

In your generate method you have declared the following thing:
chars = ("(" + textField.getText() + ")").toCharArray();
However, from your GUI there is actually an entry coming with braces, like (x+y) which basically change the value of chars to ((x+y)).
In calculate you pop however on closing ) characters which on the second brace returns an EmptyStackException. If you remove the braces either from the text-fields in general or from the line quoted above your table should print out fine.
Regarding the input-failure at (!!x): You pop only a single operation from the stack ignoring if there are multiple operations available.
As you asked for how to solve your issue that only one operator is used:
You can try to break down an equation like a && b || (c && d) && !e into its own segments and evaluate each term and combine all those terms at the end to a result similar to an earlier post I did which presents a simple rule engine in plain Java. Note however, that I did not guarantee binding-strength correctness nor did I include braces in this sample - therefore its just a very basic demo of a rule engine!
Following OO principley, you could create an Expression class which And, Or, Not, Term, ... are children of and include a boolean evaluate() method which propagates the call down to the respective term and its binding.
The equation from above therefore could be expressed with a more code like approach similar to this f.e:
Expression terms = new Or(
new And(new Term("a", ...), new Term("b", ...)),
new And(new Term("c", ...),
new And(new Term("d", ...), new Not(new Term("e", ...))
)
);
boolean value = terms.evaluate();
To obtain a structure like the one from above, you basically start with an empty stack and iterate through all tokens from the equation. The stack will hold currently open expressions. Therefore, you start by retrieving the first character and decide if it is an operand (( or !) or a letter. If an expression was found you can create a new class representation for it and add it to the stack otherwise create a term object based on the letter and assign the corresponding array[variables.indexOf(s)] value which is either 0 or 1 (false or true) to the term.
Then check if there is an element on the stack (peek will return the topmost element from the stack without removing it) and if so add the term to the operand otherwise store it temporarily so you can add it till you hit the operand and add it thereafter. If an operand has all of its fields filled you need to pop it from the stack and assign it (if not already done) to the new topmost element on the stack. This way you achieve nested structure.
However, you have to also consider the binding-order of operations. A brace binds stronger than an and-operation which further binds stronger than an or-operation. Therefore, on hitting a new operation you also need to check the topmost element on the stack if the binding order is stronger than the binding order of the current element. F.e. while iterating through the sample from above the stack currently holds the And operation for a and b and we are currently processing the Or operation. As this binds weaker than And we need to pop this element from the stack and assign it to the left element of the Or operation and push it onto the stack.
This is similar for braces. However, they can have multiple expressions contained and need to be popped from the stack only if a closing brace was parsed.
I hope this gives you enough insights to continue your journey.

Related

Java Connect4 Game with GUI bug issues

http://imgur.com/a/V7LPP
Grid images are in the link
I have 2 main issues with my current connect4 code, sometimes the "AI" places 2 discs in one turn and the player can't fill the entire board without the "AI" entering an infinite loop. Any help is appreciated.
/**
* Auto Generated Java Class.
*/
import java.awt.Dimension;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.BoxLayout;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
public class EmptyFrame1 implements ActionListener
{
//Array of JButtons
static JButton [] mnuBtn = new JButton[2];
static JButton [] btnArray = new JButton[7];
static JLabel [][] board = new JLabel[6][7];
static int [][] numBoard = new int[6][7];
static int choice = 0;
static int playerColour = 1;
static int computerColour = 2;
static int computerTurn = 0;
static ImageIcon emptyGrid = new ImageIcon("EmptyGrid.png");
static ImageIcon yellowGrid = new ImageIcon("YellowGrid.png");
static ImageIcon redGrid = new ImageIcon("RedGrid.png");
static JPanel pnlBoard;
static boolean validTurn;
static int pieceCount = 42;
public EmptyFrame1()
{
JFrame game = new JFrame("Connect 4");
//mainFrame panel to hold all components
JPanel mainFrame = new JPanel();
pnlBoard = new JPanel();
pnlBoard.setLayout(new GridLayout(7,6));
//Change mainFrame layout to vertical BoxLayout
mainFrame.setLayout(new BoxLayout(mainFrame, BoxLayout.Y_AXIS));
//For every single button
//Set the button text to its index value, add an action listener and add it to the pnlButtons
for (int i = 0; i < btnArray.length; i++)
{
btnArray[i] = new JButton("place");
btnArray[i].addActionListener(this);
pnlBoard.add(btnArray[i]);
}//end for
for (int r = 0; r < board.length; r++)
{
for (int c = 0; c < board[r].length; c++)
{
board[r][c] = new JLabel(emptyGrid);
board[r][c].setPreferredSize(new Dimension(69, 69));
pnlBoard.add(board[r][c]);
}//end for
}//end for
//Add all the panels to the mainFrame panel
mainFrame.add(pnlBoard);
//add mainFrame to the JFrame
game.add(mainFrame);
game.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); // Added this for security
game.pack();
game.setVisible(true);
game.setResizable(false);
}
//*Action listener for all buttons*
public void actionPerformed(ActionEvent e)
{
for (int i = 0; i < btnArray.length; i++)
{
//if the current button was triggered, set the choice to the button index
if (btnArray[i] == e.getSource())
{
choice = i;
colCheck(choice, 1);
//System.out.println("User turn used");
pieceCount--;
for (int j = 0; j < btnArray.length; j++)
{
if (numBoard[0][j] == 0) btnArray[j].setEnabled(true);
}
if (pieceCount > 0)
{
validTurn = false;
while(!validTurn)
{
computerTurn = (int) (Math.random() * 7);
System.out.print(computerTurn + " ");
validTurn = colCheck(computerTurn, 2);
//System.out.println("CPU tried to move");
}
}
System.out.println();
setGrid();
pieceCount--;
System.out.println(pieceCount);
validTurn = false;
}//end if
}//end for
pnlBoard.repaint();
}//end actionPerformed
public static boolean colCheck(int choice, int currentTurn)
{
int row = -1;
for (int r = 5; r >= 0; r--)
{
if (numBoard[r][choice] == 0)
{
row = r;
break;
}
}
//System.out.println("Row That CPU Chooses: " + row);
if (row > -1)
{
numBoard[row][choice] = currentTurn;
if (row == 0)
{
btnArray[choice].setEnabled(false);
return false;
}
return true;
}
return false;
}
public static void setGrid()
{
for (int r = 0; r < numBoard.length; r++)
{
for (int c = 0; c < numBoard[r].length; c++)
{
if (numBoard [r][c] == 0)
{
board[r][c].setIcon(emptyGrid);
}
else if (numBoard [r][c] == 1)
{
board[r][c].setIcon(redGrid);
}
else if (numBoard [r][c] == 2)
{
board[r][c].setIcon(yellowGrid);
}
}
}
}
/**
* Inner helper class that defines the graphics
*/
public static void main(String[] args)
{
new EmptyFrame1();
}
//end constructor
Some problems and suggestions:
Your colCheck method and the while (!validTurn) { loop in the actionPerformed method is where the problem is located.
This method should not set numBoard value or disable buttons. In other words, it should not have any "side effects".
Instead it should only check for validity and then return a boolean value, nothing more or less
You should have another method that is called first, one that checks if no valid columns are available, if the game is effectively over. This should be called before the while loop above and should prevent the while loop from entering. This will end your endless loop problem because it's looping because no valid columns can be found for the computer turn.
You should have another method for setting the numBoard state and for enabling and disabling JButtons.
Change your colCheck to this to see where the loop is coming from:
public static boolean colCheck(int choice, int currentTurn) {
int row = -1;
for (int r = 5; r >= 0; r--) {
if (numBoard[r][choice] == 0) {
row = r;
break;
}
}
// System.out.println("Row That CPU Chooses: " + row);
if (row > -1) {
numBoard[row][choice] = currentTurn;
if (row == 0) {
btnArray[choice].setEnabled(false);
System.out.printf("debug 1 row %d %n", row);
return false;
}
System.out.printf("debug 2 row %d %n", row);
return true;
}
System.out.printf("debug 3 row %d %n", row);
return false;
}
Other issues not directly related to your problem at hand, but which should be addressed
You're grossly over-using the static modifier, and in fact none of your fields should be static. All should be private instance fields.
You've got your program logic code, the model, mixed in the same class as the GUI, the view, making it hard to debug problems and enhance the program. Much better if you could make your model a completely separate class, one that is "view-agnostic" meaning that it is testable on its own and can work with any view, be it a command line or Swing or Android UI.
Your question depends on images, EmptyGrid.png, YellowGrid.png.... that we have no access to, preventing us from testing it.
You're using magic numbers, such as 0, 1, 2 for position values, and need to avoid doing this.
Instead use an enum for empty, user and computer
This is Java not Javascript. You'll want to be clear on the difference because they're two completely different languages.

how to get calculator to accept new numbers after equal sign is pressed? java

i am doing an exercise to create a simple calculator in java.
i want the calculator to keep taking numbers after the equal sign is pressed. so if i press "10+10 =" the result will be 20, and if I want to press "+1 = " and the result will be 21. or if I want to subtract as well.
my code is below. im sure the change has to be made to the "equals" portion of the code but i am unsure where/how to begin.
public int getDisplayValue()
{
return displayValue;
}
public void numberPressed(int number)
{
currentValue = (currentValue * 10) + number;
displayValue = currentValue;
}
private void applyPreviousOperation()
{
if (previousOp == '+')
{
heldValue = heldValue + currentValue;
displayValue = heldValue;
}
else if (previousOp == '-')
{
heldValue = heldValue - currentValue;
displayValue = heldValue;
}
else {
heldValue = currentValue;
}
}
public void plus()
{
applyPreviousOperation();
previousOp = '+';
currentValue = 0;
}
public void minus()
{
applyPreviousOperation();
previousOp = '-';
currentValue = 0;
}
public void equals()
{
applyPreviousOperation();
previousOp = ' ';
currentValue = 0;
heldValue = 0;
}
public void clear()
{
displayValue = 0;
previousOp = ' ';
}
}
You need to define your question more clearly.
what's the calculator flow should be. You describe an operation that contradicts a simple a+b.
It really matters how you input the numbers, If for example the very first operation is texted "a+b" ,"a-b" .... than you can keep it as currentValue.
than next opperations will be calculated against currentValue.
Have a variable called defaultOperand. When the equals button is pressed, update the defaultOperand variable with the output of the operation. It becomes the default left side operand. If an operation is inputted without a left side operand, then use the value in the defaultOperand as the default left hand operand.

How can I organize my Java code?

The title is not my entire question. I know HOW to organize code, theoretically, but i would like some specific, USEFUL, pointers. Please read on before griping.
I'm a beginner to java and OOP (object oriented programming) and I would really like to learn how to better organize my code! Over the course of a month or two, I made a calculator program with little functions I thought of here and there with a few small jokes built into it. After looking at it a second time I realized that it is extremely poorly formatted and almost incomprehensible.If I may, I would like to ask some more experienced programmers to point me in the right direction on what I should do to fix it (for example, what things can I turn into objects, Where can I compartmentalize, etc).
Please note that this is my FIRST time posting on a forum like this so if i need to clarify something for you to help me, I've done something wrong, I'm asking for too much, please tell me so i can resolve it and i can get help. Please dont just mark this as invalid and file it away to oblivion (as often happens in stackoverflow). Also, before anyone asks, NO this is NOT homework, it is the product of my own crack at teaching myself java (probably why its not working too well).
Here is the source code:
// This is the original Calculator code without objects in a single class. not really efficient...
package randomClasses;
import java.awt.*;
import java.awt.event.*;
import java.text.DecimalFormat;
import javax.swing.*;
#SuppressWarnings("serial")
public class CalcClass
extends JFrame
implements ActionListener {
JPanel[] row = new JPanel[6];
JButton[] button = new JButton[21];
String[] buttonString = {"7", "8", "9", "+", "4", "5", "6", "-", "1", "2", "3", "*", ".", "/", "C", "v", "+/-", "=", "0", "Parabola", "x^y"};
int[] dimW = {300, 45, 100, 90, 180};
int[] dimH = {35, 40};
Dimension displayDimension = new Dimension(dimW[0], dimH[0]);
Dimension regularDimension = new Dimension(dimW[1], dimH[1]);
Dimension rColumnDimension = new Dimension(dimW[2], dimH[1]);
Dimension zeroButDimension = new Dimension(dimW[3], dimH[1]);
Dimension parabolaDimension = new Dimension(dimW[4], dimH[0]);
//formatting variables
int var = 0;
double x = 0;
String stor = "";
boolean initial = true;
//variables for Parabola function
int countEquals_parab = 0;
double Angle = 0;
double Vi = 0;
double Vx = 0;
double Vy = 0;
double T_max = 0;
double Y_displ = 0;
double X_displ = 0;
double h = 0;
double k = 0;
double a_parab = 0;
boolean parabComplete = true;
boolean parabola = false;
DecimalFormat df = new DecimalFormat("#######.#####");
//variables for addressing illegal typing issues
boolean typeNum = true;
boolean typeDot = true;
JFrame frame; //for parabolaInstructions
//original calculator variables
boolean[] function = new boolean[5];
double[] temporary = {0, 0}; //store on screen values
double result = 0; //store result
public JTextArea display = new JTextArea(1, 20);
Font font = new Font("Times new Roman", Font.BOLD, 14);
CalcClass() {
super("CalcClass");
setDesign();
setSize(380, 300);
setResizable(false);
setDefaultCloseOperation(EXIT_ON_CLOSE);
GridLayout grid = new GridLayout(6, 5);
setLayout(grid);
for(int i = 0; i < 5; i++) {
function[i] = false;
}
FlowLayout f1 = new FlowLayout(FlowLayout.CENTER);
FlowLayout f2 = new FlowLayout(FlowLayout.CENTER, 1, 1);
for(int i = 0; i < 6; i++) {
row[i] = new JPanel();
}
row[0].setLayout(f1);
for(int i = 1; i < 6; i++) {
row[i].setLayout(f2);
}
for(int i = 0; i < 21; i++) {
button[i] = new JButton();
button[i].setText(buttonString[i]);
button[i].setFont(font);
button[i].addActionListener(this);
}
display.setFont(font);
display.setEditable(false);
display.setPreferredSize(displayDimension);
for(int i = 0; i < 14; i++) {
button[i].setPreferredSize(regularDimension);
}
for(int i = 14; i < 18; i++) {
button[i].setPreferredSize(rColumnDimension);
}
button[18].setPreferredSize(zeroButDimension);
button[19].setPreferredSize(parabolaDimension);
button[20].setPreferredSize(rColumnDimension);
row[0].add(display);
add(row[0]);
for(int i = 0; i < 4; i++) {
row[1].add(button[i]);
}
row[1].add(button[14]);
add(row[1]);
for(int i = 4; i < 8; i++) {
row[2].add(button[i]);
}
row[2].add(button[15]);
add(row[2]);
for(int i = 8; i < 12; i++) {
row[3].add(button[i]);
}
row[3].add(button[16]);
add(row[3]);
row[4].add(button[18]);
for(int i = 12; i < 14; i++) {
row[4].add(button[i]);
}
row[4].add(button[17]);
add(row[4]);
row[5].add(button[19]);
row[5].add(button[20]);
add(row[5]);
setVisible(true);
}
public void getSqrt() {
stor = "";
initial = true;
try {
double value = Double.parseDouble(display.getText());
if(value == -100) {
format("John's Girlfriend");
} else {
value = Math.sqrt(Double.parseDouble(display.getText())); //create a value for variable, and use Maths square root to find the value
format(Double.toString(value)); //Sets display to new value
}
} catch(NumberFormatException e) {
}
typeDot = false;
typeNum = false;
}
public void getPosNeg() {
stor = "";
initial = true;
try {
double value = Double.parseDouble(display.getText()); //again creating a variable for current value
if(value != 0) { //if value is not equal to zero
value = (-1) * value; //multiplied by -1 to change the sign
format(Double.toString(value)); //Sets display to new value
} else {
}
} catch(NumberFormatException e) {
}
}
public void getResult() {
temporary[1] = Double.parseDouble(display.getText());
String temp0 = Double.toString(temporary[0]);
String temp1 = Double.toString(temporary[1]);
try {
if(temp0.contains("-")) {
String[] temp00 = temp0.split("-", 2);
temporary[0] = (Double.parseDouble(temp00[1]) * -1);
}
if(temp1.contains("-")) {
String[] temp11 = temp1.split("-", 2);
temporary[1] = (Double.parseDouble(temp11[1]) * -1);
}
} catch(ArrayIndexOutOfBoundsException e) {
}
try {
functions();
clear();
format(Double.toString(result));//display has a result
for(int i = 0; i < 5; i++) {
function[i] = false; //set all functions to false
}
} catch(NumberFormatException e) {
}
typeNum = false;
}
public void functions() {
if(function[2] == true) { //multiplication
result = temporary[0] * temporary[1];
} else if(function[3] == true) { //division
result = temporary[0] / temporary[1];
} else if(function[0] == true) { //addition
result = temporary[0] + temporary[1];
} else if(function[1] == true) { //subtraction;
result = temporary[0] - temporary[1];
} else if(function[4] == true) {
result = Math.pow(temporary[0], temporary[1]);
} else {
result = temporary[1];
}
}
double a_quadratic = 0;
double b = 0;
double c = 0;
double x1 = 0;
double x2 = 0;
double discr = 0;
int countEquals_quadratic = 0;
public void quadraticFormula() {
if(countEquals_parab == 0) {
a_quadratic = Double.parseDouble(display.getText());
clear();
display.setText("b = ");
}
if(countEquals_parab == 1) {
b = Double.parseDouble(display.getText());
display.setText("c = ");
}
if(countEquals_parab == 2) {
c = Double.parseDouble(display.getText());
discr = (Math.pow(b, 2) - 4 * a_quadratic * c); //stores the value of the discriminant
if(discr >= 0) {
x1 = (-b + Math.sqrt(b * b - 4 * a_quadratic * c)) / (2 * a_quadratic);
x2 = (-b - Math.sqrt(b * b - 4 * a_quadratic * c)) / (2 * a_quadratic);
}
}
}
public void parabolaButton() {
double G = 9.81;
if(countEquals_parab == 0) {
Vi = Double.parseDouble(display.getText());
clear();
display.setText("Angle of release: ");
}
if(countEquals_parab == 1) {
Angle = Double.parseDouble(display.getText());
if((Angle > 90.0) || (Angle < 0.0)) {
display.setText("Sorry, not a valid angle");
countEquals_parab = 3;
} else {
Angle = (Math.PI / 180.0) * Angle; //converting degrees into radians
Vx = Vi * Math.cos(Angle); //Calculating x component
Vy = Vi * Math.sin(Angle); //Calculating y component
//Finding time
T_max = Vy / G; //time to max height
//Calculating vertex coordinates
Y_displ = (Vy * Vy / (2 * G));
X_displ = Vx * T_max;
//finding a
a_parab = (-Y_displ) / (X_displ * X_displ);
display.setText("The equation of the parabola is \ny = " + df.format(a_parab) + "(x - " + df
.format(h) + ")^2 + " + df.format(k));
}
}
if(countEquals_parab == 2) {
display.setText("Time to get to max height = " + df.format(T_max));
}
if(countEquals_parab == 3) {
clearFunction();
countEquals_parab = -1;
parabola = false;
parabComplete = true;
}
countEquals_parab++;
}
public void var() {
var++;
if(var > 8) {
var = 1;
}
if(var == 1) {
format("x");
}
}
public final void setDesign() {
try {
UIManager.setLookAndFeel("com.sun.java.swing.plaf.nimbus.NimbusLookAndFeel");
} catch(Exception e) {
}
}
public void format(String get) {
//get stores the incoming values temporarily
//get is transferred to a new value for permanent storage
//print the permanent storage value
//new number is added, stored temporarily in get
//get is added to permanent storage
//print permanent storage value
double spaceFix = 0;
if(initial == true) {
stor = get;
initial = false;
} else if(initial == false) {
stor = stor + get;
}
spaceFix = stor.length() / 4;
int numberOfSpaces = 56 - stor.length() + (int) spaceFix;
String format = String.format("%" + numberOfSpaces + "s", stor);
display.setText(format);
}
#Override
public void actionPerformed(ActionEvent ae) {
if(ae.getSource() == button[0]) {
numberButtons("7");
}
if(ae.getSource() == button[1]) {
numberButtons("8");
}
if(ae.getSource() == button[2]) {
numberButtons("9");
}
if(ae.getSource() == button[3]) {
operatorButtons(0); //add function[0]
}
if(ae.getSource() == button[4]) {
numberButtons("4");
}
if(ae.getSource() == button[5]) {
numberButtons("5");
}
if(ae.getSource() == button[6]) {
numberButtons("6");
}
if(ae.getSource() == button[7]) {
operatorButtons(1); //subtract function[1]
}
if(ae.getSource() == button[8]) {
numberButtons("1");
}
if(ae.getSource() == button[9]) {
numberButtons("2");
}
if(ae.getSource() == button[10]) {
numberButtons("3");
}
if(ae.getSource() == button[11]) {
operatorButtons(2); //multiplication function[2]
}
if(ae.getSource() == button[12]) {
if(typeDot == false) {
} else {
numberButtons(".");
typeDot = false;
}
}
if(ae.getSource() == button[13]) {
operatorButtons(3); //divide function[3]
}
if(ae.getSource() == button[14]) {
clearFunction();
parabola = false;
parabComplete = true;
}
if(ae.getSource() == button[15]) {
getSqrt();
}
if(ae.getSource() == button[16]) {
getPosNeg();
}
if((ae.getSource() == button[17]) && display.getText().equals("")) {
} else if((ae.getSource() == button[17]) && (parabola == false)) {
getResult();
} else if((ae.getSource() == button[17]) && (parabola == true)) {
parabolaButton();
}
if(ae.getSource() == button[18]) {
numberButtons("0");
}
if(ae.getSource() == button[19]) {
clearFunction();
parabolaInstructions();
parabola = true;
parabComplete = false;
display.setText("Initial velocity: ");
}
if(ae.getSource() == button[20]) {
operatorButtons(4);//powerFunction();
}
}
public void parabolaInstructions() {
//Create the dialog.
final JDialog dialog = new JDialog(frame, "How to use the Parabola function");
//Add contents to it. It must have a close button,
//since some L&Fs (notably Java/Metal) don't provide one
//in the window decorations for dialogs.
JLabel label = new JLabel("<html><p align=center>" + "Step 1: Type in the initial velocity and press the \"=\" button<br>" + "Step 2: Type in the angle of Release (make sure that it is between 0 and 90)<br>" + "Step 3: Press the \"=\" button to scroll through the results<br>" + "Step 4: Profit");
label.setHorizontalAlignment(JLabel.CENTER);
Font font = label.getFont();
label.setFont(label.getFont().deriveFont(font.PLAIN, 14.0f));
JButton closeButton = new JButton("Ok");
closeButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
dialog.setVisible(false);
dialog.dispose();
}
});
JPanel closePanel = new JPanel();
closePanel.setLayout(new BoxLayout(closePanel, BoxLayout.LINE_AXIS));
closePanel.add(Box.createHorizontalGlue());
closePanel.add(closeButton);
closePanel.setBorder(BorderFactory.
createEmptyBorder(0, 0, 5, 5));
JPanel contentPane = new JPanel(new BorderLayout());
contentPane.add(label, BorderLayout.CENTER);
contentPane.add(closePanel, BorderLayout.PAGE_END);
contentPane.setOpaque(true);
dialog.setContentPane(contentPane);
//Show it.
dialog.setSize(new Dimension(400, 200));
dialog.setLocationRelativeTo(frame);
dialog.setVisible(true);
}
public void numberButtons(String i) {
if(typeNum == false) {
display.setText("");
format(i);
} else {
format(i);
}
typeNum = true;
}
public void operatorButtons(int funct) {
if(display.getText().equals("")) {
} else {
temporary[0] = Double.parseDouble(display.getText());
function[funct] = true;
clear();
}
}
public void clearFunction() {
clear();
try {
for(int i = 0; i < 5; i++) {
function[i] = false;
}
for(int i = 0; i < 2; i++) {
temporary[i] = 0;
}
} catch(NullPointerException e) {
}
//For parabola()
Vi = 0;
Vx = 0;
Vy = 0;
T_max = 0;
Y_displ = 0;
X_displ = 0;
h = 0;
k = 0;
a_parab = 0;
}
public void clear() {
display.setText("");
stor = "";
typeDot = true;
initial = true;
}
public static void main(String[] arguments) {
CalcClass c = new CalcClass();
}
}
Ok so now you've seen my mess... I sort-of know what I should do and YES I did some research but I feel it would be much easier to learn organization through example or a nice push than it would be from reading articles that tell you ultra-hypothetical or loosely-analogous examples of what objects are. Note: I tried using methods to organize and my class looks much better than what it did (I also made the whole thing an object to be called upon at the bottom which is pretty much useless).
If you use eclipse, try:
Window > Prefferences > Java > Editor > Save Actions
Check "perform the selected actions on save", "Additional Actions" and click "Configure".
Using eclipse's Save Actions can be really useful in real life coding, but you will probably learn some neat java tricks going through the Save Actions wizard.
Java is an Object Oriented language. You need to take advantage of that fact.
Use classes to separate your code into different logical / structural components. Learn how to use OOP. Follow SOLID design and use design patterns.
Another important thing is to know your language. Start by reading basic classes javadocs and relevant sections of the java spec. I would begin with deeply understanding the different types of java (class, interface, enum and inner / nested / anonymous types) and the different modifiers (private, public, protected, static, abstract, final, default).
Some other eclipse's short cuts:
CTRL-A, CTRL-I ("indentation") will fix your code indentation.
CTRL-SHIFT-O ("organize imports") will omit redundant imports.
You might consider taking a look at Code Complete, which deals with the issues that you're concerned with here, and otherwise is just a classic in our field that every serious developer should read.
In general, when you're organizing code you should do so with a few things in mind: readability and atomicity. These two factors apply to code on every level of an application, from variable naming, routines, methods, classes, packages, and so on.
Readability is a simple idea: can a human being read this code and understand it? To gauge the readability of the code all you have to do is read it! Do variable names help the reader understand what something is? Are routines and classes properly formatted and not needlessly complex? Have you removed all code that isn't being used? Is your code written in a logical progression?
Atomicity is the idea that everything should have one purpose. A function or method should (usually) do one thing and one thing only. A class should usually be a logical grouping of related methods and fields serving some type of unique purpose, and NOT a mish-mash of unrelated stuff. A package should also contain a set of related files. Same with a project, and so on.
The main benefit of atomicity is that once you get into more involved applications it's actually much easier to debug and isolate issues in your code because you know where stuff is. For instance: I have a database access error! Good thing I have a package that's specifically defined for my database access objects.
I know when I was just getting started in the field this was something that threw me off too. It might not be until you do a lot of coding within more significant apps that you really start to understand best practices and why people build stuff a certain way.
Thanks to everyone who contributed to my problem, I completely scrapped this garbage and made it 1000 times better. I knew from the beginning it was poorly made and I wanted to fix it, I just didn't know where to start. After reading all the advice that was given, watching a few tutorials and brushing up on some simple java concepts (modifiers, jswing, etc), I ended up making a new one that is in MVC format (Yay, order and efficiency). Now all my new variables are actually meaningful (Thanks #maaartinus for helping me realize that many of my variables were poorly named and made my whole program unnecessarily complicated). Also, I tried to work on SRP (Not 100% sure if I completely did it but with the program organized it will be easy to change things) and I plan on adding units later for good practice (Thank you, #Robert Snyder). This new GUI is ugly but that can always be changed later and since It is now in MVC format the job will be easier.
Here is what I did (not finished and far from perfect but a step in the right direction):
CalcGui.java
package com.Calculator;
import java.awt.BorderLayout;
import java.awt.FlowLayout;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JTextField;
public class CalcGui extends JFrame {
private static final long serialVersionUID = 1L;
private String[] operatorsList = { "+", "-", "*", "/", "^" };
// Row 1
private JTextField firstNumber = new JTextField(10);
private JComboBox<String> operator = new JComboBox<>(operatorsList);
private JTextField secondNumber = new JTextField(10);
private JButton calculateButton = new JButton("Calculate");
private JTextField calcSolution = new JTextField(20);
// Row 2
private JLabel sqrtSymbol = new JLabel("√");
private JTextField sqrtNumber = new JTextField(10);
private JButton sqrtCalcButton = new JButton("Calculate");
private JTextField sqrtCalcSolution = new JTextField(20);
// Row 3
private JLabel quadraticLabel1 = new JLabel("A = ");
private JTextField quadraticFirstNumber = new JTextField(5);
private JLabel quadraticLabel2 = new JLabel("B = ");
private JTextField quadraticSecondNumber = new JTextField(5);
private JLabel quadraticLabel3 = new JLabel("C = ");
private JTextField quadraticThirdNumber = new JTextField(5);
private JButton quadraticCalcButton = new JButton("Calculate");
private JLabel quadraticTextBefore = new JLabel("x =");
private JTextField firstQuadraticCalcSolution = new JTextField(3);
private JLabel quadraticTextMiddle = new JLabel("and x =");
private JTextField secondQuadraticCalcSolution = new JTextField(3);
CalcGui() {
JPanel calcPanel = new JPanel(new BorderLayout());
FlowLayout Default = new FlowLayout(FlowLayout.LEFT);
JPanel row1 = new JPanel(Default);
JPanel row2 = new JPanel(Default);
JPanel row3 = new JPanel(Default);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setSize(650, 150);
row1.add(firstNumber);
row1.add(operator);
row1.add(secondNumber);
row1.add(calculateButton);
row1.add(calcSolution);
row2.add(sqrtSymbol);
row2.add(sqrtNumber);
row2.add(sqrtCalcButton);
row2.add(sqrtCalcSolution);
row3.add(quadraticLabel1);
row3.add(quadraticFirstNumber);
row3.add(quadraticLabel2);
row3.add(quadraticSecondNumber);
row3.add(quadraticLabel3);
row3.add(quadraticThirdNumber);
row3.add(quadraticCalcButton);
row3.add(quadraticTextBefore);
row3.add(firstQuadraticCalcSolution);
row3.add(quadraticTextMiddle);
row3.add(secondQuadraticCalcSolution);
calcPanel.add(row1, BorderLayout.NORTH);
calcPanel.add(row2, BorderLayout.CENTER);
calcPanel.add(row3, BorderLayout.SOUTH);
this.add(calcPanel);
}
// basic calculations methods
public double getFirstNumber() {
return Double.parseDouble(firstNumber.getText());
}
public String getOperator() {
return (String) operator.getSelectedItem();
}
public double getSecondNumber() {
return Double.parseDouble(secondNumber.getText());
}
public void setCalcSolution(double solution) {
calcSolution.setText(Double.toString(solution));
}
void addCalculateListener(ActionListener listenForCalcButton) {
calculateButton.addActionListener(listenForCalcButton);
}
void displayErrorMessage(String errorMessage) {
JOptionPane.showMessageDialog(this, errorMessage);
}
// Square root function methods
public double getSqrtNumber() {
return Double.parseDouble(sqrtNumber.getText());
}
public void setSqrtCalcSolution(double solution) {
sqrtCalcSolution.setText(Double.toString(solution));
}
void addSqrtCalcListener(ActionListener listenForSqrtCalcButton) {
sqrtCalcButton.addActionListener(listenForSqrtCalcButton);
}
// Quadratic formula Methods
public double getQuadraticFirstNumber() {
return Double.parseDouble(quadraticFirstNumber.getText());
}
public double getQuadraticSecondNumber() {
return Double.parseDouble(quadraticSecondNumber.getText());
}
public double getQuadraticThirdNumber() {
return Double.parseDouble(quadraticThirdNumber.getText());
}
public void setFirstQuadraticCalcSolution(double solution) {
firstQuadraticCalcSolution.setText(Double.toString(solution));
}
public void setSecondQuadraticCalcSolution(double solution) {
secondQuadraticCalcSolution.setText(Double.toString(solution));
}
void addQuadraticCalcListener(ActionListener listenForQuadraticCalcButton) {
quadraticCalcButton.addActionListener(listenForQuadraticCalcButton);
}
}
CalcModel.java
package com.Calculator;
public class CalcModel {
private double calcValue;
public void calculate(double firstNumber, double secondNumber,
String operator) {
if (operator.equals("+")) {
calcValue = firstNumber + secondNumber;
}
if (operator.equals("-")) {
calcValue = firstNumber - secondNumber;
}
if (operator.equals("*")) {
calcValue = firstNumber * secondNumber;
}
if (operator.equals("/")) {
calcValue = firstNumber / secondNumber;
}
if (operator.equals("^")) {
calcValue = Math.pow(firstNumber, secondNumber);
}
}
public double getCalcValue() {
return calcValue;
}
}
SqrtCalcModel.java
package com.Calculator;
public class SqrtCalcModel {
private double sqrtCalcValue;
public void sqrt(double number) {
sqrtCalcValue = Math.sqrt(number);
}
public double getSqrtCalcValue() {
return sqrtCalcValue;
}
}
QuadraticCalcModel.java
package com.Calculator;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
public class QuadraticCalcModel {
private double firstQuadraticCalcValue;
private double secondQuadraticCalcValue;
public void quadraticFormula(double a, double b, double c) {
double discriminant = (b * b) - (4 * a * c);
if (discriminant >= 0) {
firstQuadraticCalcValue = (Math.sqrt((b * b) - (4 * a * c)) + (-b))
/ (2 * a);
secondQuadraticCalcValue = (Math.sqrt((b * b) - (4 * a * c)) - (-b))
/ (2 * a);
}
else {
JFrame parent = new JFrame();
JOptionPane.showMessageDialog(parent,
"This function has no real roots.");
}
}
public double getFirstQuadraticValue() {
return firstQuadraticCalcValue;
}
public double getSecondQuadraticValue() {
return secondQuadraticCalcValue;
}
}
CalculatorControler.java
package com.Calculator;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
public class CalculatorController {
private CalcGui theGui;
private CalcModel theCalcModel;
private SqrtCalcModel theSqrtCalcModel;
private QuadraticCalcModel theQuadraticCalcModel;
public CalculatorController(CalcGui theGui, CalcModel theCalcModel,
SqrtCalcModel theSqrtCalcModel,
QuadraticCalcModel theQuadraticCalcModel) {
this.theGui = theGui;
this.theCalcModel = theCalcModel;
this.theSqrtCalcModel = theSqrtCalcModel;
this.theQuadraticCalcModel = theQuadraticCalcModel;
this.theGui.addCalculateListener(new CalcListener());
this.theGui.addSqrtCalcListener(new SqrtCalcListener());
this.theGui.addQuadraticCalcListener(new QuadraticCalcListener());
}
class CalcListener implements ActionListener {
public void actionPerformed(ActionEvent e) {
double firstNumber, secondNumber = 0;
String operator;
try {
firstNumber = theGui.getFirstNumber();
operator = theGui.getOperator();
secondNumber = theGui.getSecondNumber();
theCalcModel.calculate(firstNumber, secondNumber, operator);
theGui.setCalcSolution(theCalcModel.getCalcValue());
}
catch (NumberFormatException ex) {
System.out.println(ex);
theGui.displayErrorMessage("You Need to Enter 2 Numbers");
}
}
}
class SqrtCalcListener implements ActionListener {
public void actionPerformed(ActionEvent e) {
double number = 0;
try {
number = theGui.getSqrtNumber();
theSqrtCalcModel.sqrt(number);
theGui.setSqrtCalcSolution(theSqrtCalcModel.getSqrtCalcValue());
}
catch (NumberFormatException ex) {
System.out.println(ex);
theGui.displayErrorMessage("You Need to enter a Number");
}
}
}
class QuadraticCalcListener implements ActionListener {
public void actionPerformed(ActionEvent e) {
double a, b, c = 0;
try {
a = theGui.getQuadraticFirstNumber();
b = theGui.getQuadraticSecondNumber();
c = theGui.getQuadraticThirdNumber();
theQuadraticCalcModel.quadraticFormula(a, b, c);
theGui.setFirstQuadraticCalcSolution(theQuadraticCalcModel
.getFirstQuadraticValue());
theGui.setSecondQuadraticCalcSolution(theQuadraticCalcModel
.getSecondQuadraticValue());
}
catch (NumberFormatException ex) {
System.out.println(ex);
theGui.displayErrorMessage("You need to enter 3 numbers.");
}
}
}
}
MVCCalculator.java
package com.Calculator;
public class MVCCalculator {
public static void main(String[] args) {
CalcGui theGui = new CalcGui();
CalcModel theCalcModel = new CalcModel();
SqrtCalcModel theSqrtCalcModel = new SqrtCalcModel();
QuadraticCalcModel theQuadraticCalcModel = new QuadraticCalcModel();
new CalculatorController(theGui, theCalcModel, theSqrtCalcModel,
theQuadraticCalcModel);
theGui.setVisible(true);
}
}

How can I parse ASCII Art to HTML using Java or Javascript? [closed]

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
Questions asking for code must demonstrate a minimal understanding of the problem being solved. Include attempted solutions, why they didn't work, and the expected results. See also: Stack Overflow question checklist
Closed 9 years ago.
Improve this question
I saw that the Neo4j API uses ASCII Art very cleverly with its API:
http://jaxenter.com/getting-started-with-neo4j-the-java-graph-database-47955.html
I want to try something similar, but with ASCI Art to HTML. How can ASCII art be parsed, so for example, given an ASCII Art input something like:
--------------------------------
I I
I ------- ------- I
I I I I I I
I I A I I B I I
I I I I I I
I ------- ------- I
I I
I I
--------------------------------
: could result in HTML output something like:
<div>
<div style='display:inline;'>
A
</div>
<div style='display:inline;'>
B
</div>
</div>
Update
The question was closed citing that I need to "demonstrate a minimal understanding of the problem being solved.". I do have an understanding of the problem to be solved. The problem is that I want to solve is to make templated HTML easier to understand in source code for the following web framework:
https://github.com/zubairq/coils
: although the solution could be applied to any web framework. I have since seen someone attempt to make an initial version in C++ here:
https://github.com/h3nr1x/asciidivs2html/blob/master/asciidivs2html.cpp
: very impressive! If you can get it to work in Java or Clojure then if we can get the question reopened I will nominate a bounty so you can get more points for the solution :)
I ran the Java solution provided by #meewok and here is the result:
$ java AsciiToDIVs.RunConverter
Created a box(ID=0,X=0,Y=0,width=33,height=10)
Created a box(ID=1,X=2,Y=4,width=8,height=5,parent=0)
Created a char(Char=A,X=4,Y=7,parent=1)
Created a box(ID=2,X=2,Y=21,width=8,height=5,parent=0)
Created a char(Char=B,X=4,Y=24,parent=2)
<div><div><div>A</div></div><div><div>B</div></div></div>
Methodology
A solution to implement is the following:
create an in memory 2D array (array of arrays) which is similar to a chessboard.
Then i will create an algorith that when it detects "-" characters, i initialize acall to a method to detect the remaining corners ( top right, bottom left, bottom right) following the characters and where they end.
Example ( quick pseudocode ):
while(selectedCell==I)
selectedCell=selectedCell.goDown();
Using such a strategy you can map out your boxes and which boxes are contained within which.
Remaining would be to print this info as html..
Quick and Dirty Implementation
Since I was in the mood I spent an hour+ to quickly cook up a toy implementation.
The below is non-optimized in respect to that I do not make use of Iterators to go over Cells, and would need refactoring to become a serious framework.
Cell.java
package AsciiToDIVs;
public class Cell {
public char Character;
public CellGrid parentGrid;
private int rowIndex;
private int colIndex;
public Cell(char Character, CellGrid parent, int rowIndex, int colIndex)
{
this.Character = Character;
this.parentGrid = parent;
this.rowIndex = rowIndex;
this.colIndex = colIndex;
}
public int getRowIndex() {
return rowIndex;
}
public int getColIndex() {
return colIndex;
}
}
CellGrid.java
package AsciiToDIVs;
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Iterator;
public class CellGrid {
private ArrayList<ArrayList<Cell>> CellGridData;
public CellGrid(String asciiFile) throws IOException {
readDataFile(asciiFile);
}
public ArrayList<FoundObject> findBoxes(FoundBoxObject parent)
{
int startRowIndex = 0, startColIndex = 0,
parentRowLimit = Integer.MAX_VALUE,
parentColLimit = Integer.MAX_VALUE,
startingColIndex = 0;
if(parent != null)
{
startRowIndex = parent.getRowIndex()+1;
startColIndex = startingColIndex = parent.getColIndex()+1;
parentRowLimit = parent.getRowIndex() + parent.getHeight();
parentColLimit = parent.getColIndex() + parent.getWidth();
}
ArrayList<FoundObject> results = new ArrayList<FoundObject>();
Cell currentCell;
if(startRowIndex>=CellGridData.size())
return null;
for(; startRowIndex<CellGridData.size() && startRowIndex<parentRowLimit; startRowIndex++ )
{
startColIndex = startingColIndex;
for(; startColIndex< CellGridData.get(startRowIndex).size() && startColIndex<parentColLimit; startColIndex++)
{
FoundBoxObject withinBox = checkWithinFoundBoxObject(results, startRowIndex, startColIndex);
if(withinBox !=null)
startColIndex+=withinBox.getWidth();
currentCell = getCell(startRowIndex, startColIndex);
if(currentCell!=null)
{
if(currentCell.Character == '-') // Found a TOP-CORNER
{
int boxHeight = getConsecutiveIs(startRowIndex+1, startColIndex) + 1;
if(boxHeight>1)
{
int boxWidth = getConsecutiveDashes(startRowIndex, startColIndex);
FoundBoxObject box = new FoundBoxObject(startRowIndex, startColIndex, boxWidth, boxHeight, parent);
results.add(box);
findBoxes(box);
startColIndex+=boxWidth;
}
}
//This is a character
else if(currentCell.Character != '-' && currentCell.Character != 'I' && currentCell.Character != ' '
&& currentCell.Character != '\n' && currentCell.Character != '\n' && currentCell.Character != '\t')
{
FoundCharObject Char = new FoundCharObject(startRowIndex, startColIndex, parent, currentCell.Character);
results.add(Char);
}
}
}
}
if(parent!=null)
parent.containedObjects = results;
return results;
}
public static String printDIV(ArrayList<FoundObject> objects)
{
String result = "";
Iterator<FoundObject> it = objects.iterator();
FoundObject fo;
while(it.hasNext())
{
result+="<div>";
fo = it.next();
if(fo instanceof FoundCharObject)
{
FoundCharObject fc = (FoundCharObject)fo;
result+=fc.getChar();
}
if(fo instanceof FoundBoxObject)
{
FoundBoxObject fb = (FoundBoxObject)fo;
result+=printDIV(fb.containedObjects);
}
result+="</div>";
}
return result;
}
private FoundBoxObject checkWithinFoundBoxObject(ArrayList<FoundObject> results, int rowIndex, int colIndex)
{
Iterator<FoundObject> it = results.iterator();
FoundObject f;
FoundBoxObject fbox = null;
while(it.hasNext())
{
f = it.next();
if(f instanceof FoundBoxObject)
{
fbox = (FoundBoxObject) f;
if(rowIndex >= fbox.getRowIndex() && rowIndex <= fbox.getRowIndex() + fbox.getHeight())
{
if(colIndex >= fbox.getColIndex() && colIndex <= fbox.getColIndex() + fbox.getWidth())
{
return fbox;
}
}
}
}
return null;
}
private int getConsecutiveDashes(int startRowIndex, int startColIndex)
{
int counter = 0;
Cell cell = getCell(startRowIndex, startColIndex);
while( cell!=null && cell.Character =='-')
{
counter++;
cell = getCell(startRowIndex, startColIndex++);
}
return counter;
}
private int getConsecutiveIs(int startRowIndex, int startColIndex)
{
int counter = 0;
Cell cell = getCell(startRowIndex, startColIndex);
while( cell!=null && cell.Character =='I')
{
counter++;
cell = getCell(startRowIndex++, startColIndex);
}
return counter;
}
public Cell getCell(int rowIndex, int columnIndex)
{
ArrayList<Cell> row;
if(rowIndex<CellGridData.size())
row = CellGridData.get(rowIndex);
else return null;
Cell cell = null;
if(row!=null){
if(columnIndex<row.size())
cell = row.get(columnIndex);
}
return cell;
}
public Iterator<ArrayList<Cell>> getRowGridIterator(int StartRow) {
Iterator<ArrayList<Cell>> itRow = CellGridData.iterator();
int CurrentRow = 0;
while (itRow.hasNext()) {
// Itrate to Row
if (CurrentRow++ < StartRow)
itRow.next();
}
return itRow;
}
private void readDataFile(String asciiFile) throws IOException {
CellGridData = new ArrayList<ArrayList<Cell>>();
ArrayList<Cell> row;
FileInputStream fstream = new FileInputStream(asciiFile);
BufferedReader br = new BufferedReader(new InputStreamReader(fstream));
String strLine;
// Read File Line By Line
int rowIndex = 0;
while ((strLine = br.readLine()) != null) {
CellGridData.add(row = new ArrayList<Cell>());
// System.out.println (strLine);
for (int colIndex = 0; colIndex < strLine.length(); colIndex++) {
row.add(new Cell(strLine.charAt(colIndex), this, rowIndex,colIndex));
// System.out.print(strLine.charAt(i));
}
rowIndex++;
// System.out.println();
}
// Close the input stream
br.close();
}
public String printGrid() {
String result = "";
Iterator<ArrayList<Cell>> itRow = CellGridData.iterator();
Iterator<Cell> itCol;
Cell cell;
while (itRow.hasNext()) {
itCol = itRow.next().iterator();
while (itCol.hasNext()) {
cell = itCol.next();
result += cell.Character;
}
result += "\n";
}
return result;
}
}
FoundBoxObject.java
package AsciiToDIVs;
import java.util.ArrayList;
public class FoundBoxObject extends FoundObject {
public ArrayList<FoundObject> containedObjects = new ArrayList<FoundObject>();
public static int boxCounter = 0;
public final int ID = boxCounter++;
public FoundBoxObject(int rowIndex, int colIndex, int width, int height, FoundBoxObject parent) {
super(rowIndex, colIndex, width, height);
if(parent!=null)
System.out.println("Created a box(" +
"ID="+ID+
",X="+rowIndex+
",Y="+colIndex+
",width="+width+
",height="+height+
",parent="+parent.ID+")");
else
System.out.println("Created a box(" +
"ID="+ID+
",X="+rowIndex+
",Y="+colIndex+
",width="+width+
",height="+height+
")");
}
}
FoundCharObject.java
package AsciiToDIVs;
public class FoundCharObject extends FoundObject {
private Character Char;
public FoundCharObject(int rowIndex, int colIndex,FoundBoxObject parent, char Char) {
super(rowIndex, colIndex, 1, 1);
if(parent!=null)
System.out.println("Created a char(" +
"Char="+Char+
",X="+rowIndex+
",Y="+colIndex+
",parent="+parent.ID+")");
else
System.out.println("Created a char(" +
",X="+rowIndex+
",Y="+colIndex+")");
this.Char = Char;
}
public Character getChar() {
return Char;
}
}
FoundObject.java
package AsciiToDIVs;
public class FoundObject {
private int rowIndex;
private int colIndex;
private int width = 0;
private int height = 0;
public FoundObject(int rowIndex, int colIndex, int width, int height )
{
this.rowIndex = rowIndex;
this.colIndex = colIndex;
this.width = width;
this.height = height;
}
public int getRowIndex() {
return rowIndex;
}
public int getColIndex() {
return colIndex;
}
public int getWidth() {
return width;
}
public int getHeight() {
return height;
}
}
Main Method
public static void main(String args[])
{
try {
CellGrid grid = new CellGrid("ascii.txt");
System.out.println(CellGrid.printDIV(grid.findBoxes(null)));
//System.out.println(grid.printGrid());
} catch (IOException e) {
e.printStackTrace();
}
}
Update
The 'printDIV' should be like this (more '' were being printed than needed).
public static String printDIV(ArrayList<FoundObject> objects)
{
String result = "";
Iterator<FoundObject> it = objects.iterator();
FoundObject fo;
while(it.hasNext())
{
fo = it.next();
if(fo instanceof FoundCharObject)
{
FoundCharObject fc = (FoundCharObject)fo;
result+=fc.getChar();
}
if(fo instanceof FoundBoxObject)
{
result+="<div>";
FoundBoxObject fb = (FoundBoxObject)fo;
result+=printDIV(fb.containedObjects);
result+="</div>";
}
}
return result;
}
Here's a fairly simple solution in JavaScript, tested via Node. Of course, you'll need to adjust the input and output methods.
var s = "\n\
--------------------------------\n\
I I\n\
I ------- ------- I\n\
I I I I I I\n\
I I A I I B I I\n\
I I I I I I\n\
I ------- ------- I\n\
I I\n\
I I\n\
--------------------------------\n\
";
var lines = s.split('\n');
var outer_box_top_re = /--+/g;
var i;
for (i=0; i<lines.length; i++) {
while ((res = outer_box_top_re.exec(lines[i])) != null) {
L = res.index
R = outer_box_top_re.lastIndex
process_box(i, L, R)
}
}
function process_box(T, L, R) {
console.log('<div top="' + T + '" left="' + L + '" right="' + R + '">')
blank_out(T, L, R)
var i = T;
while (1) {
i += 1;
if (i >= lines.length) {
console.log('Fell off bottom of ascii-art without finding bottom of box');
process.exit(1);
}
var line = lines[i];
if (line[L] == 'I' && line[R-1] == 'I') {
// interior
// Look for (the tops of) sub-boxes.
// (between L+1 and R-2)
var inner_box_top_re = /--+/g;
// Inner and outer need to be separate so that
// inner doesn't stomp on outer's lastIndex.
inner_box_top_re.lastIndex = L+1;
while ((res = inner_box_top_re.exec(lines[i])) != null) {
sub_L = res.index;
sub_R = inner_box_top_re.lastIndex;
if (sub_L > R-1) { break; }
process_box(i, sub_L, sub_R);
}
// Look for any other content (i.e., a box label)
content = lines[i].substring(L+1, R-1);
if (content.search(/[^ ]/) != -1) {
console.log(content);
}
blank_out(i, L, R);
}
else if (line.substring(L,R).match(/^-+$/)) {
// bottom
blank_out(i, L, R);
break;
}
else {
console.log("line " + i + " doesn't contain a valid continuation of the box");
process.exit(1)
}
}
console.log('</div>')
}
function blank_out(i, L, R) {
lines[i] = (
lines[i].substring(0,L)
+ lines[i].substring(L,R).replace(/./g, ' ')
+ lines[i].substring(R)
);
}
What you want is the idea of 2-dimensional parsing, which detects 2D entities and verifies they have legitimate relationships.
See http://mmi.tudelft.nl/pub/siska/TSD%202DVisLangGrammar.pdf‎
What will be difficult is defining the sets of possible "ASCII Art" constraints.
Do only want to to recognize letters? Made only of the same-letter characters?
"cursive" letters? boxes? (Your example has boxes whose sides aren't made of the same
ASCII character). Boxes with arbitrary thick walls? Nested boxes? Diagrams with (thin/fat) arrows? Kilroy-was-here-nose-over-the-wall?
Pictures of Mona Lisa in which character pixels provide density relations?
What exactly do you mean by "ASCII art"?
The real problem is defining the range of things you intend to recognize. If
you limit that range, your odds of success go way up (see the referenced paper).
The problem here has little to to do specifically with Java or Javascript. This is far more related
to algorithms. Pick a limited class of art, choose the right algorithms, and then what you have is a coding problem which should be relatively easy to solve. No limits, no algorithms --> no amount of Javascript will save you.

Return the index of clicked button?

I have got an array of 30 buttons []. I have a variable buttonClicked. When I press the button how can I get the index and store the index number in the buttonClicked?
Thanks :)
JButton [] buttons = new JButton[30];
for(int i = 1; i <= 30; i++)
{
int btnNumber = (i > 10 && i <= 20) ? (31 - i) : i;
System.out.printf("i = %d, btnNumber = %d%n", i, btnNumber);
buttons[btnNumber - 1] = new JButton("label " + btnNumber);
//buttons[btnNumber - 1].setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
buttons[btnNumber - 1].setBorder(BorderFactory.createEtchedBorder());
buttons[btnNumber - 1].setOpaque(true);
buttons[btnNumber - 1].setBackground(Color.white);
//Puts the player 1 piece on button 1,3,5,7,9 and player 2 piece on button 2,4,6,8,10
if ((btnNumber - 1) < 10)
{
if (((btnNumber - 1) % 2) == 0)
{
buttons[btnNumber - 1].setIcon(piece1);
}
else
{
buttons[btnNumber - 1].setIcon(piece2);
}
}
centerPanel.add(buttons[btnNumber - 1]);
}
//Below is what I am attempting to do, I know is not correct.
public void move()
{
Move = dice.getDiceResult();
int buttonClicked = 0;
if(playerOneTurn =true)
{
buttonclicked + diceResult();
}
//revised
public class MyActionListener implements ActionListener {
Dice dice;
private boolean playerOneTurn = true;
private boolean playerTwoTurn = false;
#Override
public void actionPerformed(ActionEvent e)
{
String num = e.getActionCommand();
int index = Integer.parseInt(num);
int move = dice.getDiceResult();
int positionLanding = 0;
if(playerOneTurn = true)
{
positionLanding = index + move;
positionLanding.setIcon("piece1");//how can I set the image Icon to this position?
}
}
}
1) putClientProperty
buttons[i][j].putClientProperty("column", i);
buttons[i][j].putClientProperty("row", j);
buttons[i][j].addActionListener(new MyActionListener());
and getClientProperty
public class MyActionListener implements ActionListener {
#Override
public void actionPerformed(ActionEvent e) {
JButton btn = (JButton) e.getSource();
System.out.println("clicked column " + btn.getClientProperty("column")
+ ", row " + btn.getClientProperty("row"));
}
2) ActionCommand
You can find the button in ActionEvent.getSource(). To find the index it is just a matter of iterating through the array, looking for that particular button.
The prettiest way is using Component.setName. Then you don't even need to maintain variables with your components - you can go straight off of the name
I prefer the strategy suggested by aioobe, but here is another way.
buttons[btnNumber - 1] = new JButton("label " + btnNumber);
buttons[btnNumber - 1].setActionCommand("" + btnNumber);
// ...
// ...later.. in the actionPerformed() method
String num = actionEvent.getActionCommand();
int index = Integer.parseInt(num);
// ..proceed..

Categories

Resources