I am trying to create a calculator in Java.
here is all my code:
import java.util.Scanner;
public class Calculator {
public static void main (String[] args) throws java.lang.Exception{
Calculator.Calculating();
}
public static void Calculating() {
String usersCalc;
Scanner userInput = new Scanner( System.in );
System.out.println("Enter your calculation: ");
usersCalc = userInput.next();
//splits when sees plus
String[] parts = usersCalc.split("+");
//everything left to splitter
String part1 = parts[0];
//everything right to splitter
String part2 = parts[1];
int result;
int answerOne = Integer.parseInt(part1);
int answerTwo = Integer.parseInt(part2);
switch (usersCalc){
case '+':
result = answerOne + answerTwo;
break;
case '-':
result = part1 - part2;
break;
case '/':
result = part1 / part2;
break;
case'*':
result = part1 * part2;
break;
}
}
}
I am trying to do it so that the user enters a string like "2+2" and then I split it on symbol and then put it through a switch statement and it calculates it for me. however the code still has errors which I can't resolve.
any ideas?
errors
Cannot switch on a value of type String for source level below 1.7. Only convertible int values or enum variables are permitted
Try with contains() to check if it's +, -, * or /. Then split it and calculate it.
This is a common task for java interview: "Calculate value from string expression"
Here is the algorithm (Pseudo):
Check that expression is valid
Build a thee structure with two types of nodes - math operation and number
Recursively calculate the result
because usersCalc is a String so use "+" in place of '+'
You code have many errors:
In the switch case you are not using correct data for calculation. using part1 and part2 instead of answerOne and answerTwo Integer values.
You are passing String in the switch and using char for case statements.
For division, you should check the second value is not zero. Otherwise it will throw exception at runtime..
You can use regex for splitting the input. Then find the operator and pass it to the switch-statement.
import java.util.Scanner;
public class Calculator {
public static void main (String[] args) throws java.lang.Exception{
Calculator.Calculating();
}
public static void Calculating() {
String usersCalc;
Scanner userInput = new Scanner( System.in );
System.out.println("Enter your calculation: ");
usersCalc = userInput.next();
//splits when sees plus
String[] parts = usersCalc.split("[+-/*]");
char operator = usersCalc.contains("+") ? '+' : usersCalc.contains("-") ? '-' : usersCalc.contains("*") ? '*' : '/';
//everything left to splitter
String part1 = parts[0];
//everything right to splitter
String part2 = parts[1];
int result = -1;
int answerOne = Integer.parseInt(part1);
int answerTwo = Integer.parseInt(part2);
switch (operator){
case '+':
result = answerOne + answerTwo;
break;
case '-':
result = answerOne - answerTwo;
break;
case '/':
if (answerTwo == 0) {
System.out.println("Invalid input.");
return;
}
result = answerOne / answerTwo;
break;
case'*':
result = answerOne * answerTwo;
break;
}
System.out.println(result);
}
}
split the string by checking all possible operators
String[] parts = usersCalc.split("[+,-,*,/]");
check if userCalc contains the operator and do the same like
if (usersCalc.contains("+"))
result = answerOne + answerTwo;
else if (usersCalc.contains("-"))
result = answerOne - answerTwo;
......
Your error is propably because you try to compile with a version <1.7 (guessing from your error).
To use String with switch you need at least 1.7.
That won't resolve all your problems as other answers mention it you use String in the switch and char for the cases.
Also even with the switch statement it wont work because in "usersCalc" is still the complete calculation (e.g. 2+2) and not just the "+"
public class Calc extends MouseAdapter implements ActionListener
{
JButton[] b=new JButton[28];
static JTextField tf,tf2;
JFrame jf;
static double val1=0,val2=0,result=0;
static int operator=0,plus=1,minus=1,mul=1,div=1,rem=1,no=0,sqrt=0,hit=0,dot=0,pp=0,mp=0,mulp=0,divp=0,remp=0; //mp,pp,remp,mulp,divp all the used for operator Precedence
String str[]={"MC","MR","MS","M+","M-","<-","CE","C","+/-","sqrt","7","8","9","/","%","4","5","6","*","1/x","1","2","3","-","=","0",".","+"};
public Calc(String s)
{
jf=new JFrame(s);
JPanel p=new JPanel();
p.setBackground(new Color(213, 219, 255));
jf.add(p);
JMenuBar mb=new JMenuBar();
jf.setJMenuBar(mb);
JMenu view=new JMenu("View");
mb.add(view);
JMenu edit=new JMenu("Edit");
mb.add(edit);
JMenu help=new JMenu("Help");
mb.add(help);
JMenuItem viewHelp=new JMenuItem("View Help");
help.add(viewHelp);
JMenuItem about=new JMenuItem("About Us");
help.add(about);
mb.setBorder(BorderFactory.createEmptyBorder(1, 1, 1, 1));
mb.setCursor(new Cursor(Cursor.HAND_CURSOR));
mb.setFont(new Font("Time_New_Roaman", 0, 11));
tf=new JTextField();
tf2=new JTextField();
tf.setBackground(new Color(242, 248, 255));
tf2.setBackground(new Color(242, 248, 255));
tf2.setBounds(10,10,190,20);
tf.setBounds(10,29,190,30);
tf.setBorder(BorderFactory.createCompoundBorder(BorderFactory.createEmptyBorder(-1, 1, 1, 1),BorderFactory.createLineBorder(new Color(153,153,153))));
tf2.setBorder(BorderFactory.createCompoundBorder(BorderFactory.createEmptyBorder(1, 1, -1, 1),BorderFactory.createLineBorder(new Color(153,153,153))));
tf.setFont(new Font("Time_New_Roaman",0,20));
tf2.setFont(new Font("Time_New_Roaman",0,14));
tf.setHorizontalAlignment(tf.RIGHT);
tf2.setHorizontalAlignment(tf2.RIGHT);
p.add(tf);
p.add(tf2);
tf2.setCaretColor(Color.WHITE);
for(int i=0,x=10,y=32,h=27,w=34;i<str.length;i++)
{
int temp=0;
if(i==24)
h=62;
if(i==25)
{
w=73;
temp=39;
}
if(i%5==0)
{
y+=35;
x=10;
}
if(str[i]=="<-")
{
str[i]=""+(char)8592;
}if(str[i]=="sqrt")
{
str[i]="\u221A";
}if(str[i]=="+/-")
{
str[i]="\u00B1";
}
b[i]=new JButton(str[i]);
b[i].setFont(new Font("Arial",0,12));
if(str[i]=="1/x")
{b[i].setFont(new Font("Lucida Calligraphy",0, 12)); }
b[i].setBounds(x,y,w,h);
b[i].setMargin(new Insets(1,4,1,4));
if(str[i]==""+(char)8592||str[i]=="=")
{
b[i].setFont(new Font("Arial",1,20));
}
p.add(b[i]);
if(str[i]=="1"||str[i]=="2"||str[i]=="3"||str[i]=="4"||str[i]=="5"||str[i]=="6"||str[i]=="7"||str[i]=="8"||str[i]=="9"||str[i]=="0"||str[i]==".")
{
b[i].setBackground(new Color(234, 245, 248));
b[i].setFont(new Font("Arial",0,15));
}
b[i].addActionListener(this);
b[i].addMouseListener(this);
x+=39+temp;
h=27;
w=34;
}
p.setLayout(null);
Toolkit t=jf.getToolkit();
Dimension screensize=t.getScreenSize();
int width = screensize.width*8/10;
int height = screensize.height*8/10;
jf.setBounds(width/2,height/4,width,height);
jf.setDefaultCloseOperation(jf.EXIT_ON_CLOSE);
jf.setSize(215,330);
jf.setResizable(false);
jf.setVisible(true);
}
public void actionPerformed(ActionEvent e)
{
if(e.getSource()==b[10]||e.getSource()==b[11]||e.getSource()==b[12]||e.getSource()==b[15]||e.getSource()==b[16]||e.getSource()==b[17]||e.getSource()==b[20]||e.getSource()==b[21]||e.getSource()==b[22]||e.getSource()==b[25])
{hit=1;sqrt=1;pp=1;mp=1;mulp=1;divp=1;remp=1;}
if(e.getSource()==b[0]) //For MC Button
{}
if(e.getSource()==b[1]) //For MR Button
{}
if(e.getSource()==b[2]) //For MS Button
{}
if(e.getSource()==b[3]) //For M+ Button
{}
if(e.getSource()==b[4]) //For M- Button
{}
if(e.getSource()==b[5]) //For Backspace Button
{
no=1;
String s=tf.getText();
tf.setText("");
for(int i=0;i<s.length()-1;i++)
{tf.setText(tf.getText()+s.charAt(i));}
if(s.length()-1==0)
tf.setText("0");
}
if(e.getSource()==b[6]) //For CE Button
{
dot=0;no=1;
tf.setText("0");
}
if(e.getSource()==b[7]) //For C Button
{
tf.setText("0");
tf2.setText("");
val1=0;val2=0;hit=0;sqrt=0;plus=1;minus=1;mul=1;div=1;rem=1;dot=0;pp=0;mp=0;mulp=0;divp=0;remp=0;no=1;
tf.setFont(new Font("Time_New_Roaman",0,20));
}
if(e.getSource()==b[8]) //For +/- Button
{}
if(e.getSource()==b[9]) //For Sqrt Button
{
dot=0;no=1;
tf2.setText("");
if(sqrt==1)
{
double t;
double num=Double.parseDouble(tf.getText());
double squareRoot = num/2;
do {
t = squareRoot;
squareRoot =(t+(num/t))/2;
}while((t-squareRoot)!=0);
tf2.setText("sqrt("+num+")");
tf.setText(""+squareRoot);
}
}
if(e.getSource()==b[10]) //For 7 Button
{
if(no==1)
{ tf.setText(""); }
tf.setText(tf.getText().concat("7"));
no=0;
}
if(e.getSource()==b[11]) //For 8 Button
{
if(no==1)
{tf.setText("");}
tf.setText(tf.getText().concat("8"));
no=0;
}
if(e.getSource()==b[12]) //For 9 Button
{if(no==1)
{tf.setText("");}
tf.setText(tf.getText().concat("9"));
no=0;
}
if(e.getSource()==b[13]) //For / Button
{
no=1;dot=0;
if(div==2 && divp==1)
{
tf2.setText(tf2.getText()+tf.getText()+"/");
serve();
minus=1;plus=1;mul=1;rem=1;
}
if(div==1 && divp==1)
{
div=2;
val1=Double.parseDouble(tf.getText());
tf2.setText(tf.getText()+"/");
operator=4;
tf.setText("");
}divp=0;
}
if(e.getSource()==b[14]) //For % Button
{
no=1;dot=0;
if(rem==1 && remp==1)
{
val2=Double.parseDouble(tf.getText());
tf2.setText(tf2.getText()+tf.getText()+"%");
result=(val1*val2)/100;
tf.setText(""+result);
plus=1;mul=1;div=1;minus=1;
}
remp=0;
}
if(e.getSource()==b[15]) //For 4 Button
{
if(no==1)
{tf.setText("");}
tf.setText(tf.getText().concat("4"));
no=0;
}
if(e.getSource()==b[16]) //For 5 Button
{
if(no==1)
{tf.setText("");}
tf.setText(tf.getText().concat("5"));
no=0;
}
if(e.getSource()==b[17]) //For 6 Button
{
if(no==1)
{tf.setText("");}
tf.setText(tf.getText().concat("6"));
no=0;
}
if(e.getSource()==b[18]) //For * Button
{
no=1;dot=0;
if(mul==2 && mulp==1)
{
tf2.setText(tf2.getText()+tf.getText()+"*");
serve();
minus=1;plus=1;div=1;rem=1;
}
if(mul==1 && mulp==1)
{
mul=2;
val1=Double.parseDouble(tf.getText());
tf2.setText(tf.getText()+"*");
operator=3;
tf.setText("");
}mulp=0;
}
if(e.getSource()==b[19]) //For 1/x Button
{}
if(e.getSource()==b[20]) //For 1 Button
{
if(no==1)
{tf.setText("");}
tf.setText(tf.getText().concat("1"));
no=0;
}
if(e.getSource()==b[21]) //For 2 Button
{
if(no==1)
{tf.setText("");}
tf.setText(tf.getText().concat("2"));
no=0;
}
if(e.getSource()==b[22]) //For 3 Button
{
if(no==1)
tf.setText("");
tf.setText(tf.getText().concat("3"));
no=0;
}
if(e.getSource()==b[23]) //For - Button
{
no=1;dot=0;
if(minus==2 && mp==1)
{
tf2.setText(tf2.getText()+tf.getText()+"-");
serve();
plus=1;mul=1;div=1;rem=1;
}
if(minus==1 && mp==1)
{
minus=2;
val1=Double.parseDouble(tf.getText());
tf2.setText(tf.getText()+"-");
operator=2;
tf.setText("");
}mp=0;
}
if(e.getSource()==b[24]) //For = Button
{
no=1;dot=0;mp=1;mulp=1;pp=1;divp=1;remp=1;plus=1;minus=1;mul=1;div=1;rem=1;
if(hit==1)
{
val2=Double.parseDouble(tf.getText());
tf2.setText(tf.getText()+val2);
switch(operator)
{
case 1: result=val1+val2;
break;
case 2: result=val1-val2;
break;
case 3: result=val1*val2;
break;
case 4: result=val1/val2;
break;
default: result=0;
}
tf.setText(""+result);
tf2.setText("");
val1=0;
val2=0;
}
else
{tf.setText(""+result);}
}
if(e.getSource()==b[25]) //For 0 Button
{
//dot=0;
if(no==1)
{tf.setText("");}
tf.setText(tf.getText().concat("0"));
no=0;
}
if(e.getSource()==b[26]) //For dot (.) Button
{
if(no==1)
tf.setText("");
if(dot==0)
{
dot=1;
tf.setText(tf.getText().concat("."));
}
if(dot==1)
{tf.setText(tf.getText());}
no=0;
}
if(e.getSource()==b[27]) //For + Button
{
no=1;dot=0;
if(plus==2 && pp==1)
{
tf2.setText(tf2.getText()+tf.getText()+"+");
serve();
minus=1;mul=1;div=1;rem=1;
}
if(plus==1 && pp==1)
{
plus=2;
val1=Double.parseDouble(tf.getText());
tf2.setText(tf.getText()+"+");
operator=1;
tf.setText("");
}pp=0;
}
if(tf.getText()!="") // For converting Font When Text is out of range
{
int count=0,i;
String s=tf.getText();
char ch[]=s.toCharArray();
//double d=Double.parseDouble(tf.getText());
for(i=0;i<ch.length;i++)
{
//d/=10;
count++;
}
if(count>=15&&count<20)
{
tf.setFont(new Font("Time_New_Roaman",1,16));
}if(count>=20)
{
tf.setFont(new Font("Time_New_Roaman",1,14));
}
}
}
public void mouseEntered(MouseEvent me)
{
for(int i=0;i<b.length;i++)
{
if(me.getSource()==b[i])
{
b[i].setBackground(new Color(255,204,153));
}
}
}
public void mouseExited(MouseEvent me)
{
for(int i=0;i<b.length;i++)
{
if(me.getSource()==b[i])
{
b[i].setBackground(UIManager.getColor("control"));
if(me.getSource()==b[10]||me.getSource()==b[11]||me.getSource()==b[12]||me.getSource()==b[15]||me.getSource()==b[16]||me.getSource()==b[17]||me.getSource()==b[20]||me.getSource()==b[21]||me.getSource()==b[22]||me.getSource()==b[25]||me.getSource()==b[26])
{
b[i].setBackground(new Color(234, 245, 248));
}
}
}
}
void serve()
{
val2=Double.parseDouble(tf.getText());
if(operator==1)
{
result=val1+val2;
pp=0;mp=1;mulp=1;divp=1;remp=1;
}
else if(operator==2)
{
result=val1-val2;
mp=0;mulp=1;pp=1;divp=1;remp=1;
}
else if(operator==3)
{
result=val1*val2;
mulp=0;pp=1;mp=1;divp=1;remp=1;
}
else if(operator==4)
{
result=val1/val2;
mulp=1;pp=1;mp=1;divp=0;remp=1;
}
tf.setText("");
tf.setText(""+result);
val1=Double.parseDouble(tf.getText());
}
public static void main(String... args)
{
new Calc("PariGanak");
Timer time=new Timer();
time.schedule(new TimerTask(){
public void run()
{
tf.setText("0");
no=1;
}
},100);
}
}
Related
The goal of the current program is to create a line, of varying thickness, between two points in a window frame. So far, so good.
Next, I would like the program to recognize that the user has made a selection from the JComboBox.
This post, and the code, have been updated. (a) the itemStateChanged method was removed. It was not executed, and so, did not need to be in the program. (b) the actionPerformed method was updated to update whenever any of the objects were modified. (c) the color choice was implemented in perhaps one of the ugliest switch/case statements ever. (there must be a better way). And (d) I implemented the suggestion from Itamar Green, regarding the definition of the JComboBox. Thank you.
What don't I know?
Notes: Java 8.111. O/S: Windows 8.1. IDE: Ecilpse Java EE 4.6.0
All responses towards improving the code or the question are gratefully accepted.
import java.awt.*;
import javax.swing.*;
import java.awt.event.*;
public class ThickPen extends JApplet implements ActionListener
{
private static final long serialVersionUID = 1L;
JLabel xStartLabel = new JLabel("X Start");
JLabel yStartLabel = new JLabel("Y Start");
JLabel xStopLabel = new JLabel("X Stop");
JLabel yStopLabel = new JLabel("Y Stop");
JLabel thickLabel = new JLabel("Thickness");
JComboBox<String> myColour;
String theColour = "black";
TextField xStartField = new TextField(4);
int xStart = 0;
TextField yStartField = new TextField(4);
int yStart = 0;
TextField xStopField = new TextField(4);
int xStop = 0;
TextField yStopField = new TextField(4);
int yStop = 0;
TextField thicknessField = new TextField(4);
int thick = 0;
String[] colourString = {"black","blue","cyan","darkgray","gray","green",
"lightGray","magenta","orange","pink","red","white","yellow"};
int theIndex = 0;
public void init()
{
setSize(550,500);
Container content = getContentPane();
setLayout(new FlowLayout());
xStartField.addActionListener(this);
yStartField.addActionListener(this);
xStopField.addActionListener(this);
yStopField.addActionListener(this);
thicknessField.addActionListener(this);
add(xStartLabel);
add(xStartField);
add(yStartLabel);
add(yStartField);
add(xStopLabel);
add(xStopField);
add(yStopLabel);
add(yStopField);
add(thickLabel);
add(thicknessField);
myColour = new JComboBox<String>(colourString);
// JComboBox<String> myColour = new JComboBox<String>(colourString);
myColour.setSelectedIndex(0); // start with black
myColour.addActionListener(this);
add(myColour);
content.setBackground(Color.white);
content.setForeground(Color.black);
}
public void paint(Graphics g)
{
super.paint(g);
Dimension d = getSize();
int fullWidth = d.width;
int fullHeight = d.height;
int deltaX = 0;
int deltaY = 0;
boolean xAxis = false;
System.out.println("So far Start x y: "+xStart+" "+yStart+" color: "+theColour);
if (xStart < 1 || xStart > fullWidth
|| yStart < 1 || yStart > fullHeight
|| xStop < 1 || xStop > fullWidth
|| yStop < 1 || yStop > fullHeight
|| thick < 1 || thick > fullHeight || thick > fullWidth) {
String outStr = "Start and stop numbers must be within this window frame";
String outStr2 = "Current width: "+fullWidth+" height: "+fullHeight;
g.setColor(Color.white);
g.fillRoundRect(d.width/4, d.height/4, 300, 40, 4, 4);
g.setColor(Color.red);
g.drawString(outStr, d.width/4+10, d.height/4+15);
g.drawString(outStr2, d.width/4+10, d.height/4+30);
g.drawString("The index: "+theIndex, d.width/4, 300);
} else {
g.drawString("", d.width/4, 260);
deltaX = Math.abs(xStart - xStop); // determine absolute delta of two Xs
deltaY = Math.abs(yStart - yStop); // determine absolute delta of two Ys
if (deltaX > deltaY) // make line thickness based on x axis if
xAxis = false; // the x axis has the most 'room'.
else // else, use the y axis.
xAxis = true;
pickAColour(g, theColour);
drawMyLine(g, xStart, yStart, xStop, yStop, thick, xAxis);
}
g.drawString("The index: "+theIndex, d.width/4, 300);
g.drawString("The color "+ theColour, d.width/4, 330);
}
public void drawMyLine(Graphics g, int xStart, int yStart,
int xStop, int yStop, int thick, boolean xAxis)
{
int count = 0;
while (count < thick)
{
g.drawLine(xStart, yStart, xStop, yStop);
count++;
if (xAxis) {
xStart++;
xStop++;
} else {
yStart++;
yStop++;
}
}
}
public void pickAColour(Graphics g, String theColour)
{
switch (theColour) {
case "black" :
g.setColor(Color.black);
break;
case "blue" :
g.setColor(Color.blue);
break;
case "cyan" :
g.setColor(Color.cyan);
break;
case "darkgray" :
g.setColor(Color.darkGray);
break;
case "gray" :
g.setColor(Color.gray);
break;
case "green" :
g.setColor(Color.green);
break;
case "lightGray" :
g.setColor(Color.lightGray);
break;
case "magenta" :
g.setColor(Color.magenta);
break;
case "orange" :
g.setColor(Color.orange);
break;
case "pink" :
g.setColor(Color.pink);
break;
case "red" :
g.setColor(Color.red);
break;
case "white" :
g.setColor(Color.white);
break;
case "yellow" :
g.setColor(Color.yellow);
break;
} // end of case statement
} // end of pickAColour
public void actionPerformed (ActionEvent ae)
{
Object source=ae.getSource();
// xStart
// if (source==xStartField)
// {
try {
xStart=Integer.parseInt(
xStartField.getText());
}
catch (NumberFormatException x) {
xStart= -1;
}
// }
// yStart
// else if (source==yStartField)
// {
try {
yStart=Integer.parseInt(
yStartField.getText());
}
catch (NumberFormatException x) {
yStart= -1;
}
// }
// xStop
// else if (source==xStopField)
// {
try {
xStop=Integer.parseInt(
xStopField.getText());
}
catch (NumberFormatException x) {
xStop= -1;
}
// }
// yStop
// else if (source==yStopField)
// {
try {
yStop=Integer.parseInt(
yStopField.getText());
}
catch (NumberFormatException x) {
yStop= -1;
}
// }
// thickness
// else if (source==thicknessField)
// {
try {
thick=Integer.parseInt(
thicknessField.getText());
}
catch (NumberFormatException x) {
thick= -1;
}
// } else {
if (source==myColour) {
JComboBox<String> cb = (JComboBox<String>)ae.getSource();
// String theColour = (String)cb.getSelectedItem(); ///can;
// Integer theIndex = (int)cb.getSelectedIndex();
theColour = (String)cb.getSelectedItem();
theIndex = (int)cb.getSelectedIndex();
}
// }
repaint();
} // end of ActionEvent
} // end of class
Simply put this
myColour = new JComboBox<String>(colourString);
instead of this
JComboBox<String> myColour = new JComboBox<String>(colourString);
in your init method.
The problem is the difference between the myColour defined here (in member section)
JComboBox<String> myColour;
and the one created in the init(). You are initializing the one in the Init but not the one in the member section, so when you are trying to use myColour in actionPreformed, Java is trying to call methods from a reference with no object.
I am making a tic tac toe game in java, between human-computer.
I need a Check to ensure that the player has made a valid move, e.g. that the player is not trying to make a move in a square that is already occupied.
I tried to write a method and call it from the chick() method, or to make if statment within win() but It didn't work.
import javax.swing.*;
import java.awt.event.*;
import java.awt.*;
public class XOGAMEMAIN extends JFrame implements ActionListener {
private JButton [][]buttons = new JButton[3][3];
private JButton XButton = new JButton("play with X ");
private JButton OButton = new JButton("play with O");
private JButton CButton = new JButton("let computer start with X");
private JButton C1Button = new JButton("let computer start with O");
private JLabel statusLabel = new JLabel(" ");
private XOGAMEAI game = null;
private int human = 0;
private int computer = 0;
private boolean isPlay = false;
private String []chars=new String[]{"","X","O"};
private void setStatus(String s) {
statusLabel.setText(s);
}
private void setButtonsEnabled(boolean enabled) {
for(int i=0;i<3;i++)
for(int j=0;j<3;j++) {
buttons[i][j].setEnabled(enabled);
if(enabled) buttons[i][j].setText(".");
}
}
public XOGAMEMAIN() {
setTitle(" X/O Game ");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setResizable(false);
JPanel centerPanel = new JPanel(new GridLayout(3,3));
Font font = new Font("Arial",Font.BOLD, 32);
for(int i=0;i<3;i++)
for(int j=0;j<3;j++) {
buttons[i][j] = new JButton(".");
buttons[i][j].setFont(font);
buttons[i][j].addActionListener(this);
buttons[i][j].setFocusable(false);
centerPanel.add(buttons[i][j]);
}
XButton.addActionListener(this);
OButton.addActionListener(this);
CButton.addActionListener(this);
C1Button.addActionListener(this);
JPanel northPanel = new JPanel();
northPanel.add(statusLabel);
JPanel southPanel = new JPanel();
southPanel.add(XButton);
southPanel.add(OButton);
southPanel.add(CButton);
southPanel.add(C1Button);
setStatus("wlc,to start chose X or O or let computer decide");
setButtonsEnabled(false);
add(northPanel,"North");
add(centerPanel,"Center");
add(southPanel,"South");
setSize(600,600);
setLocationRelativeTo(null);
}
public static void main(String []args) {
new XOGAMEMAIN().setVisible(true);
}
private void computerTurn1() { ////////// this method for computer ( when the human chose the computer buttons to start first ) with X or O
int []pos = game.nextMove(computer);
if(pos!=null) {
int i = pos[0];
int j = pos[1];
buttons[i][j].setText(chars[computer]);
game.setBoardValue(i,j,computer);
setStatus("computer did its move ");
}
checkState();
}
private void computerTurn() { // this method for computer movment( when the human chose (X,O)buttons to start ) human method==>(using click method) and after that(computer turn==> this method will run
int []pos = game.nextMove(computer);
if(pos!=null) {
int i = pos[0];
int j = pos[1];
buttons[i][j].setText(chars[computer]);
game.setBoardValue(i,j,computer);
setStatus("computer did its move , now your turn ");
}
checkState();
}
private void gameOver(String s) {
setStatus(s);
setButtonsEnabled(false);
isPlay = false;
}
private void checkState() {
if(game.isWin(human)) {
gameOver(" You've Won!");
}
if(game.isWin(computer)) {
gameOver("Sorry, You Lose!");
}
if(game.nextMove(human)==null && game.nextMove(computer)==null) {
gameOver(" Draw ");
}
}
private void click(int i,int j) { //// this method is for human , when he click any button
if(game.getBoardValue(i,j)==XOGAMEAI.EMPTY) {
buttons[i][j].setText(chars[human]);
game.setBoardValue(i,j,human);
checkState();
computerTurn();}
}
public void actionPerformed(ActionEvent event) { //// this is action event that is senseing any click from the human(every button click ==> go for a method==> this methods are declared before )
if(event.getSource()==C1Button) { /// event.getsourse mean ==> the click that human make is on C1 button ?
play4(); /// if yes go to method play4() ==> thats mean the computer will start first with O char
}
if(event.getSource()==CButton) { /// for computer to start first with X
play3();
}
if(event.getSource()==OButton) { ////////// human click to start first with O==> start play1 method
play1();}
else {
for(int i=0;i<3;i++) //// if this is not the first click ==> thats mean this will check in turn 2 for human for example , put not the first 1
for(int j=0;j<3;j++) ////it will go for method click() directly for any of the 9 buttons choices
if(event.getSource()==buttons[i][j]) ///
click(i,j); }
////
if(event.getSource()==XButton) { // the same here but the human has chose Xbutton to start first
play();
}else {
for(int i=0;i<3;i++)
for(int j=0;j<3;j++)
if(event.getSource()==buttons[i][j])
click(i,j);
}
}
private void play4() { //// this is play4() method , its happened when Computer supposed to start first with O
game = new XOGAMEAI();
human = XOGAMEAI.ONE; // human is int number=0 , now the is Matrix defined which include "","x","O" , human=o ==> char "", human=ONE ==>char X , human=TWO ==>char O
computer = XOGAMEAI.TWO; // ///
setButtonsEnabled(true); ///
isPlay = true;
computerTurn1();
///
}
private void play3() { //// for Computer to start first with X
game = new XOGAMEAI();
human = XOGAMEAI.TWO; //
computer = XOGAMEAI.ONE; // ///
setButtonsEnabled(true); ///
isPlay = true;
computerTurn1();
///
}
private void play1() { //// for O
game = new XOGAMEAI();
human = XOGAMEAI.TWO; //
computer = XOGAMEAI.ONE; //
setStatus("Your Turn"); ///
setButtonsEnabled(true); ///
isPlay = true; ///
} ////
private void play() { ////// for X
game = new XOGAMEAI();
human = XOGAMEAI.ONE;
computer = XOGAMEAI.TWO;
setStatus("Your Turn");
setButtonsEnabled(true);
isPlay = true;
}
public static class XOGAMEAI {
/* the board */
private int board[][];
/* empty */
public static final int EMPTY = 0;
/* player one */
public static final int ONE = 1;
/* player two */
public static final int TWO = 2;
public XOGAMEAI() {
board = new int[3][3];
}
/* get the board value for position (i,j) */
public int getBoardValue(int i,int j) {
if(i < 0 || i >= 3) return EMPTY;
if(j < 0 || j >= 3) return EMPTY;
return board[i][j];
}
/* set the board value for position (i,j) */
public void setBoardValue(int i,int j,int token) {////////////////\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
if(i < 0 || i >= 3) return;
if(j < 0 || j >= 3) return;
board[i][j] = token;
}
/* calculate the winning move for current token */
public int []nextWinningMove(int token) {
for(int i=0;i<3;i++)
for(int j=0;j<3;j++)
if(getBoardValue(i, j)==EMPTY) {
board[i][j] = token;
boolean win = isWin(token);
board[i][j] = EMPTY;
if(win) return new int[]{i,j};
}
return null;
}
public int inverse(int token) {
return token==ONE ? TWO : ONE;
}
/* calculate the best move for current token */
public int []nextMove(int token) {
/* lucky position in the center of board*/
if(getBoardValue(1, 1)==EMPTY) return new int[]{1,1};
/* if we can move on the next turn */
int winMove[] = nextWinningMove(token);
if(winMove!=null) return winMove;
/* choose the move that prevent enemy to win */
for(int i=0;i<3;i++)
for(int j=0;j<3;j++)
if(getBoardValue(i, j)==EMPTY)
{
board[i][j] = token;
boolean ok = nextWinningMove(inverse(token)) == null;
board[i][j] = EMPTY;
if(ok) return new int[]{i,j};
}
/* choose available move */
for(int i=0;i<3;i++)
for(int j=0;j<3;j++)
if(getBoardValue(i, j)==EMPTY)
return new int[]{i,j};
/* no move is available */
return null;
}
/* determine if current token is win or not win */
public boolean isWin(int token) {
final int DI[]={-1,0,1,1};
final int DJ[]={1,1,1,0};
for(int i=0;i<3;i++)
for(int j=0;j<3;j++) {
// we skip if the token in position(i,j) not equal current token */
if(getBoardValue(i, j)!=token){
continue;
}
for(int k=0;k<4;k++) {
int ctr = 0;
while(getBoardValue(i+DI[k]*ctr, j+DJ[k]*ctr)==token) ctr++;
if(ctr==3) return true;
}
}
return false;
}
}
}
Inside the click(int i, int j) method you check the condition if(game.getBoardValue(i,j)==XOGAMEAI.EMPTY) - doesn't that do what you what you want?
OK, I've found the bug, it was in the ActionPerformed method. The problem was, you wrote
if(xbutton pressed){...}
else{click()}
if(ybutton pressed){...}
else{click()}
And both else statements were executed. Here's the fixed code:
public void actionPerformed(ActionEvent event) { //// this is action event
//// that is senseing
//// any click from the
//// human(every button
//// click ==> go for a
//// method==> this
//// methods are
//// declared before )
if (event.getSource() == C1Button) { /// event.getsourse mean ==> the
/// click that human make is on
/// C1 button ?
play4(); /// if yes go to method play4() ==> thats mean the computer
/// will start first with O char
} else if (event.getSource() == CButton) { /// for computer to start
/// first with
/// X
play3();
}
else if (event.getSource() == OButton) { ////////// human click to start
////////// first with O==> start
////////// play1 method
play1();
} else if (event.getSource() == XButton) { // the same here but the
// human has
// chose Xbutton to start first
play();
} else {
for (int i = 0; i < 3; i++) //// if this is not the first click ==>
//// thats mean this will check in turn
//// 2 for human for example , put not
//// the first 1
for (int j = 0; j < 3; j++) //// it will go for method click()
//// directly for any of the 9
//// buttons choices
if (event.getSource() == buttons[i][j]) ///
click(i, j);
}
}
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);
}
}
I need help tweaking my code. I need to write a program that outputs the count of individual ascii characters in a txt file that the user uploads, but I'm having a lot of problems trying to get the array that I count into the GUI portion of the program that "draws" the data on the screen.
I have the output looking how I want, but I can't figure out how to get the character count up there
I want to put the number of times a character/punction/number is used in a file that the user uploads on a graphic display. For instance, 33 or ! there are 3 instances. Or 65 A there are 4354 instances in the file. However I'm having a large problem with getting the counter to count the characters in the word correctly, and even more trouble getting the stored array of numbers of characters to the GUI (g.draw) section of the program.
Instead of a number, I just get a blank output column.
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import java.io.FileReader; // both needed
import java.io.BufferedReader;
import java.io.IOException;
public class textreader extends Frame implements ActionListener
{
String dataFilePath = null;
String dataFileName = null;
int[] counter = new int[256];
String command = "";
public static void main(String[] args)
{
Frame frame = new textreader();
frame.setResizable(true);
frame.setSize(1000,850);
frame.setVisible(true);
}
public textreader()
{
setTitle("Text File Processing");
// Menu Creation
MenuBar mn = new MenuBar();
setMenuBar(mn);
// Create "File" and add it
Menu fileMenu = new Menu("File");
mn.add(fileMenu);
// Create Menu Items, Add action Listener, Add to "File" Menu Group
// Open file
MenuItem miOpen = new MenuItem("Open");
miOpen.addActionListener(this);
fileMenu.add(miOpen);
// Process file
MenuItem miProcess = new MenuItem("Process");
miProcess.addActionListener(this);
fileMenu.add(miProcess);
// Exit program
MenuItem miExit = new MenuItem("Exit");
miExit.addActionListener(this);
fileMenu.add(miExit);
// To Terminate
WindowListener d = new WindowAdapter()
{
public void windowClosing(WindowEvent ev)
{
System.exit(0);
}
public void windowActivated(WindowEvent ev)
{
repaint();
}
public void windowStateChanged(WindowEvent ev)
{
repaint();
}
};
ComponentListener k = new ComponentAdapter()
{
public void componentResized(ComponentEvent e)
{
repaint();
}
};
// listener registry
this.addWindowListener(d);
this.addComponentListener(k);
}
public void actionPerformed (ActionEvent ev)
{
// which command was issued?
command = ev.getActionCommand();
// act
if("Open".equals(command))
{
dataFilePath = null;
dataFileName = null;
JFileChooser chooser = new JFileChooser();
chooser.setDialogType(JFileChooser.OPEN_DIALOG );
chooser.setDialogTitle("Open Data File");
int returnVal = chooser.showOpenDialog(null);
if( returnVal == JFileChooser.APPROVE_OPTION)
{
dataFilePath = chooser.getSelectedFile().getPath();
dataFileName = chooser.getSelectedFile().getName();
}
repaint();
}
else
if("Process".equals(command))
{
try
{
// Initialize
int[] aCount = new int[256];
// "Instantiate" streams
BufferedReader inputStream = new BufferedReader(new FileReader(dataFilePath));
// read the file line by line and count the characters read
String line = null;
char c = 0;
int lineLength = 0;
int charValue = 0;
while ((line = inputStream.readLine()) != null)
{
// ********* process line
for (int i = 0; i < line.length(); i++)
{
char ch = line.charAt(i);
if (ch >= 0 && ch <= 255)
{
counter[(int)ch]++;
}
else
{ // silently ignore non-ASCII characters
}
// count newline at the end
counter['\n']++;
}
}
}
catch(IOException ioe)
{
System.out.print("You want to run that by me again?");
}
repaint();
}
else
if("Exit".equals(command))
{
System.exit(0);
}
}
//********************************************************
//called by repaint() to redraw the screen
//********************************************************
public void paint(Graphics g)
{
if("Open".equals(command))
{
// Acknowledge that file was opened
if (dataFileName != null)
{
g.drawString("File -- "+dataFileName+" -- was successfully opened", 400, 400);
}
else
{
g.drawString("NO File is Open", 400, 400);
}
return;
}
else
if("Process".equals(command))
{
for(int i = 0; i < 256; i++)
{
int x = 100;
int y = 100;
g.drawString("Int", x, y);
g.drawString("Char", x+50, y);
g.drawString("Count", x+100, y);
g.drawLine(100, y+15, x+120, y+15);
y = y + 30;
int line = 0;
for(int j = 0; j < 256; j++)
{
line++;
g.drawString(Integer.toString(j), x, y);
g.drawString(Character.toString((char)j), x + 50, y);
// Converts the # to a char, then to a String
// This part of the code adds a new column when the flag reaches 43
if(line == 45)
{
x = x + 150;
y = 100;
g.drawString("Int", x, y);
g.drawString("Char", x+50, y);
g.drawString("Count", x+100, y);
g.drawLine(100, y+15, x+120, y+15);
y = y + 15;
line = 0;
}
y = y+15;
}
}
return;
}
}
}
just add this to your code:
g.drawString(Integer.toString(counter[j]), x + 120, y);
right here (int the paint method):
g.drawString(Integer.toString(j), x, y);
g.drawString(Character.toString((char)j), x + 50, y);
g.drawString(Integer.toString(counter[j]), x + 120, y);
Trying to get the final part of this game to work. Its a hangman game, I just need it to display correct guesses where they are in the word.
This is the snippet of code of when a correct guess is given
else
{
int alreadyGuessed = guesses.indexOf(guess);
if (alreadyGuessed == -1)
{
guesses = guesses + guess + "";
jlbWord.setText("Word: " + charWord[currentGuess]);
}
else{}
}
Right now it simply shows each letter. I can also set it, so it shows each one as they are typed in but its not in the right order, which makes it much more difficult for the user to guess what the word is.
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.util.*;
import java.awt.Dimension;
public class RightPanel extends JPanel implements KeyListener
{
JLabel jlbMissed, jlbWord, jlbTimer;
Color btnColor;
JComboBox jcbDifficulty;
JButton jbtStart, jbtQuit;
String[] difficulties = {"Easy", "Medium", "Hard"};
String[] words = {"First", "Next", "Hello", "World"};
char guess;
String word, guesses = "";
char[] charWord;
public static int incorrectGuesses = 0;
boolean clockIsRunning = false;
boolean gameInPlay = false;
int sec = 0;
int min = 0;
public RightPanel()
{
this.setLayout(new GridBagLayout());
GridBagConstraints c = new GridBagConstraints();
Random ran = new Random(); //
int rand = ran.nextInt(4); // Generates random number then selects word from words array
word = words[rand]; //
charWord = word.toCharArray();
ActionHandler actionHandler = new ActionHandler();
jlbMissed = new JLabel("Missed: ");
jlbWord = new JLabel("Word: ");
jlbTimer = new JLabel("Time: " + "0:00");
jbtStart = new JButton("Start");
jbtQuit = new JButton("Quit");
jcbDifficulty = new JComboBox();
jbtStart.addActionListener(actionHandler);
jbtQuit.addActionListener(actionHandler);
jcbDifficulty.addKeyListener(this);
jbtStart.addKeyListener(this);
for (int i = 0; i < 3; i++)
{
jcbDifficulty.addItem(difficulties[i]); // Creates Difficutly ComboBox
}
this.add(jcbDifficulty, getConstraints(0,0,1,1, GridBagConstraints.WEST));
this.add(jlbMissed, getConstraints(0,1,1,1, GridBagConstraints.WEST));
this.add(jlbWord, getConstraints(0,2,1,1, GridBagConstraints.WEST));
this.add(jlbTimer, getConstraints(0,4,1,1, GridBagConstraints.WEST));
this.add(jbtStart, getConstraints(0,6,1,1, GridBagConstraints.WEST));
this.add(jbtQuit, getConstraints(0,7,1,1, GridBagConstraints.WEST));
}
public void keyPressed(KeyEvent e){}
public void keyReleased(KeyEvent e){}
public void keyTyped(KeyEvent e)
{
guess = e.getKeyChar();
if (gameInPlay == false)
{
JOptionPane.showMessageDialog(this, "You have not started the game yet!", "Game has not Started", JOptionPane.ERROR_MESSAGE);
System.out.println("Game Not in Play");
}
else
{
if (Character.isLetter(guess))
{
if (incorrectGuesses > 11)
{
clockIsRunning = false;
gameInPlay = false;
JOptionPane.showMessageDialog(this, "You Killed Him! \nThe word was " + word, "He Ceases to Exist", JOptionPane.ERROR_MESSAGE);
jbtStart.setText("Retry?");
jbtStart.setBackground(Color.RED);
}
else
{
int currentGuess = word.indexOf(guess);
if (currentGuess == -1)
{
int alreadyGuessed = guesses.indexOf(guess);
if (alreadyGuessed == -1)
{
guesses = guesses + guess + "";
System.out.println(alreadyGuessed);
System.out.println(guesses);
String temp = jlbMissed.getText();
jlbMissed.setText(temp + guess + ", ");
incorrectGuesses++;
leftPanel.hangmanPic.setIcon(leftPanel.image[RightPanel.incorrectGuesses]);
}
else {}
}
else
{
int alreadyGuessed = guesses.indexOf(guess);
if (alreadyGuessed == -1)
{
guesses = guesses + guess + "";
jlbWord.setText("Word: " + charWord[currentGuess]);
}
else{}
}
}
}
else
JOptionPane.showMessageDialog(this, "That is not a valid guess!\n Please enter a character from A-Z", "Invalid Guess", JOptionPane.ERROR_MESSAGE);
}
}
private GridBagConstraints getConstraints(int gridx, int gridy, int gridwidth, int gridheight, int anchor)
{
GridBagConstraints c = new GridBagConstraints();
c.insets = new Insets(5,5,5,5);
c.ipadx = 0;
c.ipady = 0;
c.gridx = gridx;
c.gridy = gridy;
c.gridwidth = gridwidth;
c.gridheight = gridheight;
c.anchor = anchor;
return c;
}
class ActionHandler implements ActionListener
{
public void actionPerformed(ActionEvent e)
{
Object source = e.getSource();
if (source == jbtStart)
{
if (clockIsRunning == true){}
else
{
if (jbtStart.getText() == "Start")
{
btnColor = jbtStart.getBackground();
clockIsRunning = true;
MyTimer timer = new MyTimer();
timer.start();
gameInPlay = true;
}
else if (jbtStart.getText() == "Retry?")
{
jbtStart.setText("Start");
jbtStart.setBackground(btnColor);
jlbTimer.setText("Time: " + "0:00");
sec = 0;
min = 0;
MyTimer timer = new MyTimer();
timer.start();
clockIsRunning = true;
gameInPlay = true;
incorrectGuesses = 0;
guesses = "";
jlbMissed.setText("Missed: ");
jlbWord.setText("Word: ");
leftPanel.hangmanPic.setIcon(leftPanel.image[RightPanel.incorrectGuesses]);
Random ran = new Random();
int rand = ran.nextInt(4);
word = words[rand];
}
}
}
else if (source == jbtQuit)
{
System.exit(0);
}
}
}
class MyTimer extends Thread
{
public void run()
{
while(true)
{
if(!clockIsRunning)
break;
try
{
Thread.sleep(1000);
}
catch (InterruptedException ecp)
{
}
if (sec == 59)
{
min++;
sec = 0;
}
else
sec++;
if(sec < 10)
jlbTimer.setText("Time:" + min+":0"+sec);
else
jlbTimer.setText("Time:" + min+":"+sec);
}
}
}
}
Yikes.
You should refactor your code and keep the guesses in a TreeSet<Character> data structure. It assures, that each character is stored only once and that an iterator returns all stored chars in ascending order.
Snippet:
Set<Character> guesses = new HashSet<Character>();
// add a guess
guesses.add('e');
guesses.add('r');
guesses.add('a');
guesses.add('e'); // will not be added, already in the set
// test
if (guesses.contains('e')) { ... }
// test if a word is "guessed"
boolean foundIt = true;
for (char c:word.toCharArray()) {
if (!guesses.contains(c)) {
foundIt = false;
break;
}
}
// foundIt is true if all chars of word have been guessed
// print
for (char c:guesses)
System.out.print(c); // prints: aer