Run-time error for GUI calculator in Java - java

I'm creating a GUI calculator, using FlowLayout, GridLayout and BorderLayout. I have the following code.
import java.awt.*;
import javax.swing.*;
//Imports visual components for program
import java.awt.event.*;
//Imports functions for providing performing action on object
public class Calc extends JFrame implements ActionListener {
JPanel[] row = new JPanel[5];
//5 panels are created for 5 rows of buttons
JButton[] button = new JButton[19];
String[] buttonString = {"1","2","3","+","4","5","6","-",
"7","8","9","*",".","/","C","rt","%",
"=", "0"};
double[] temporary = {0,0};
//Two memory locations for current number and upcoming number for signs such as *,/,%,+,-
boolean[] sign = new boolean[5];
//5 values for +,-,*,/,% are stored in array because they expect another number upon invocation
JTextArea display = new JTextArea(1,10);
//Creates display with location specified
Calc(){
//Constructor begins here
setResizable(false);
//Sets calculator size to be fixed at 380x250
//5x5 is created and selected for the calculator
for(int a = 0; a < 5; a++)
sign[a] = false;
//Initialises the state of the signs for +,-,*,/,%
JPanel displaypanel = new JPanel();
JPanel first = new JPanel();
JPanel last = new JPanel();
//Create three panels for buttons to be placed in
displaypanel.setLayout(new FlowLayout());
displaypanel.add(display);
//Display is added
first.setLayout(new GridLayout(3,5));
for(int a = 0; a<15; a++)
first.add(button[a]);
//"first" panel is added
last.setLayout(new GridLayout(1,4));
last.add(button[15]);
last.add(button[16]);
last.add(button[17]);
last.add(button[18]);
JFrame window = new JFrame("Task twelve");
window.setLayout(new BorderLayout());
window.add(displaypanel, BorderLayout.PAGE_START);
window.add(first, BorderLayout.CENTER);
window.add(last, BorderLayout.PAGE_END);
window.setVisible(true);
window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
window.setSize(400, 400);
for(int a = 0; a < 19; a++){
button[a] = new JButton();
button[a].setText(buttonString[a]);
button[a].addActionListener(this);
//Assigns all the numbers and signs for the buttons
}
for(int a = 0; a < 5; a++)
row[a] = new JPanel();
//Initialises JPanel for rows so they can be used
//Assigns size for all buttons and display
display.setEditable(false);
}
public void clear(){
try{
display.setText("");
//Sets the display to be blank
for(int a = 0; a < 5; a++)
sign[a] = false;
//Sets state of all signs to be false
temporary[0] = 0;
temporary[1] = 0;
//Sets temporary values to be 0 as well
} catch(NullPointerException e){
}
}
public void root(){
try{
double temp = Math.sqrt(Double.parseDouble(display.getText()));
//Creates variable that converts the value in display to a double and Sqroots the value
display.setText(Double.toString(temp));
//Converts value in temp to string and copies it to display
} catch(NullPointerException e){
}
}
public void getResult() {
double result = 0;
temporary[1] = Double.parseDouble(display.getText());
String temp0 = Double.toString(temporary[0]);
String temp1 = Double.toString(temporary[1]);
try {
if(temp0.contains("-")) {
String[] temp2 = temp0.split("-", 2);
temporary[0] = (Double.parseDouble(temp2[1]) * -1);
}
if(temp1.contains("-")) {
String[] temp3 = temp1.split("-", 2);
temporary[1] = (Double.parseDouble(temp3[1]) * -1);
}
} catch(ArrayIndexOutOfBoundsException e) {
}
try {
if(sign[0] == true)
//Addition sign
result = temporary[0] + temporary[1];
else if(sign[1] == true)
//Subtraction sign
result = temporary[0] - temporary[1];
else if(sign[2] == true)
//Multiplication sign
result = temporary[0] * temporary[1];
else if(sign[3] == true)
//Division sign
result = temporary[0] / temporary[1];
else if(sign[4] == true)
//Modulus sign
result = temporary[0] % temporary[1];
display.setText(Double.toString(result));
for(int a = 0; a < 5; a++)
sign[a] = false;
//Sets state of all signs to be false after one of them has been invoked
} catch(NumberFormatException e) {
}
}
public void actionPerformed(ActionEvent ae){
if(ae.getSource() == button[0])
display.append("1");
//When "1" is pressed, "1" is inserted to the display
if(ae.getSource() == button[1])
display.append("2");
if(ae.getSource() == button[2])
display.append("3");
if(ae.getSource() == button[3]){
//Addition sign is selected
temporary[0] = Double.parseDouble(display.getText());
sign[0] = true;
display.setText("");
}
if(ae.getSource() == button[4])
display.append("4");
if(ae.getSource() == button[5])
display.append("5");
if(ae.getSource() == button[6])
display.append("6");
if(ae.getSource() == button[7]){
//Subtraction sign is selected
temporary[0] = Double.parseDouble(display.getText());
sign[1] = true;
display.setText("");
}
if(ae.getSource() == button[8])
display.append("7");
if(ae.getSource() == button[9])
display.append("8");
if(ae.getSource() == button[10])
display.append("9");
if(ae.getSource() == button[11]){
//Multiplication sign is selected
temporary[0] = Double.parseDouble(display.getText());
sign[2] = true;
display.setText("");
}
if(ae.getSource() == button[12])
display.append(".");
if(ae.getSource() == button[13]){
//Division sign is selected
temporary[0] = Double.parseDouble(display.getText());
sign[3] = true;
display.setText("");
}
if(ae.getSource() == button[14])
clear();
if(ae.getSource() == button[15])
root();
if(ae.getSource() == button[16]){
//Modulus sign is selected
temporary[0] = Double.parseDouble(display.getText());
sign[4] = true;
display.setText("");
}
if(ae.getSource() == button[17])
getResult();
if(ae.getSource() == button[18])
display.append("0");
}
public static void main(String[] args){
Calc c = new Calc();
}
}
Compiling this doesn't result in any errors. However, running the class does.
Exception in thread"main" java.lang.NullPointerException
at java.awt.Container.addlmpl(Unknown Source)
at java.awt.Container.add(Unknown Source)
at Calc.<init>(Calc.java:43)
at Calc.main(Calc.java:198)
I don't understand these errors so I do not know how to fix this. Can anyone help?

You are creating 15 buttons in the loop button[a] = new JButton(buttonString[a]); but then you are asking for button[15, 16, ...] (the 16nth, 17nth... button you have not created) and are null.

Related

Why wont my JOptionPane error message pop up?

I made a GUI program where it counts certain elements of whatever is entered in the main text field. If the text field is empty, a message should pop up saying that the user should enter text in the text field. I made an if statement if tfMain == null, a JOptionPane message should pop-up, but for some reason it won't. Any tips on why it doesn't pop up?
here is my code:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import java.lang.*;
public class LabExcer9 extends WindowAdapter implements ActionListener
{
//Container
private Frame f;
private Panel p1,p2,p3;
//Component
private Button bReadAndComp, bClear;
private TextField tfMain,tf1,tf2,tf3,tf4,tf5,tf6;
private Label l1,l2,l3,l4,l5,l6;
public LabExcer9()
{
f = new Frame("Character Counter of Miguel Martin");
p1 = new Panel();
p2 = new Panel();
p3 = new Panel();
bReadAndComp = new Button("Read and Compute");
bClear = new Button("Clear ALL Values");
tfMain = new TextField(null);
tf1 = new TextField("0");
tf2 = new TextField("0");
tf3 = new TextField("0");
tf4 = new TextField("0");
tf5 = new TextField("0");
tf6 = new TextField("0");
l1 = new Label("Number of Words ");
l2 = new Label("Number of Characters ");
l3 = new Label("Number of Vowels ");
l4 = new Label("Number of Consonants ");
l5 = new Label("Number of Digits ");
l6 = new Label("Number of Symbols and Spaces ");
}
public void assembleGUI()
{
p1.setLayout(new GridLayout(1,1));
p1.setPreferredSize(new Dimension(200, 200));
p1.add(tfMain);
p2.setLayout(new GridLayout(6,2));
p2.add(l1);
p2.add(tf1);
p2.add(l2);
p2.add(tf2);
p2.add(l3);
p2.add(tf3);
p2.add(l4);
p2.add(tf4);
p2.add(l5);
p2.add(tf5);
p2.add(l6);
p2.add(tf6);
p3.setLayout(new GridLayout(1,2));
p3.add(bReadAndComp);
p3.add(bClear);
f.add(p1,BorderLayout.NORTH);
f.add(p2,BorderLayout.CENTER);
f.add(p3,BorderLayout.SOUTH);
f.pack();
f.addWindowListener(this);
f.setVisible(true);
//registers
bReadAndComp.addActionListener(this);
bClear.addActionListener(this);
}
public void windowClosing(WindowEvent we)
{
System.exit(0);
}
public void actionPerformed(ActionEvent ae)
{
Object source = ae.getSource();
//gets main text
String textString = tfMain.getText();
//puts words into array
int vowels = 0, consonants = 0, digits = 0, symbolsAndSpaces = 0;
int characters = textString.length();
if(tfMain.getText() == "" || tfMain.getText() == null )
{
if(source == bReadAndComp)
JOptionPane.showMessageDialog(null, "Please Enter Text!");
}
else if(tfMain.getText() != null && tfMain.getText() != "")
{
if(source == bReadAndComp)
{
for(int i = 0;i<textString.length();i++)
{
if(Character.isDigit(textString.charAt(i)))
digits++;
if(Character.isLetterOrDigit(textString.charAt(i)) == false)
symbolsAndSpaces++;
if(isVowel(textString.charAt(i)) == true)
vowels++;
else if(Character.isDigit(textString.charAt(i)) == false && isVowel(textString.charAt(i)) == false && textString.charAt(i) != ' ' && Character.isLetter(textString.charAt(i)) == true)
consonants++;
}
tf1.setText(""+textString.split(" ").length);
tf2.setText(""+characters);
tf3.setText(""+vowels);
tf4.setText(""+consonants);
tf5.setText(""+digits);
tf6.setText(""+symbolsAndSpaces);
//System.out.println(textStringArray[0]+"wat");
//JOptionPane.showMessageDialog(null, "Please Enter Text!");
}
else if (source == bClear)
{
tf1.setText("0");
tf2.setText("0");
tf3.setText("0");
tf4.setText("0");
tf5.setText("0");
tf6.setText("0");
tfMain.setText(null);
}
}
}
public boolean isVowel(char c)
{
if (c == 'a' || c == 'A' ||c== 'e' ||c == 'E' ||c == 'i' ||c == 'I' ||c == 'o' ||c == 'O' ||c == 'u' ||c == 'U')
return true;
else
return false;
}
public static void main(String args [])
{
LabExcer9 GUI = new LabExcer9();
GUI.assembleGUI();
}
}
To compare string please use equals or equalsIgnoreCase.
Replace your
if(tfMain.getText() == "" || tfMain.getText() == null )
statement with the following:
if("".equals(tfMain.getText())){
}

Creating a calculator using JFrame

I am a beginner at using Java. I am trying to create a calculator using JFrame through Net beans IDE. When I run the program the build is successful but the GUI display of the calculator is blank. I made sure I put the set visible code but it is still displaying a blank calculator. What could be the problem?
Here is a copy of the code:
public static void main(String[] args)
{
EventQueue.invokeLater(new Runnable()
{
#Override
public void run()
{
new Calculator();
}
});
//TODO code application logic here
}
JPanel[] row = new JPanel[5];
JButton[] button = new JButton[19];
String[] buttonString = {"7", "8", "9", "+",
"4", "5", "6", "-",
"1", "2", "3", "*",
".", "/", "C","Sqrt",
"+/-", "=", "0"};
int[] dimW = {300,45,100,90};
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]);
boolean[] function = new boolean[4];
double[] temporary = {0, 0};
JTextArea display = new JTextArea(1,20);
Font font = new Font("Times new Roman", Font.BOLD, 12);
Calculator(){
super("Calculator");
setDesign();
setSize(400, 400);
setResizable(false);
setDefaultCloseOperation(EXIT_ON_CLOSE);
GridLayout grid = new GridLayout (5,5);
setLayout(grid);
setVisible(true);
for(int i = 0; i < 19; i++)
function[i] = false;
FlowLayout f1 = new FlowLayout(FlowLayout.CENTER);
FlowLayout f2 = new FlowLayout(FlowLayout.CENTER,1,1);
for(int i = 0; i < 5; i++)
row[i] = new JPanel();
row[0].setLayout(f1);
for(int i = 1; i < 5; i++)
row[i].setLayout(f2);
for(int i = 0; i < 19; 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.setComponentOrientation(ComponentOrientation.RIGHT_TO_LEFT);
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);
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]);
}
public void clear() {
try {
display.setText("");
for (int i = 0; i < 4; i++)
function[i] = false;
for(int i = 0; i < 2; i++)
temporary[i] = 0;
} catch(NullPointerException e) {
}
}
public void getSqrt() {
try {
double value = Math.sqrt(Double.parseDouble(display.getText()));
display.setText(Double.toString(value));
}
catch(NumberFormatException e) {
}
}
public void getPosNeg() {
try {
double value = Double.parseDouble(display.getText());
if(value !=0) {
value = value * (-1);
display.setText(Double.toString(value));
}
else {
}
} catch(NumberFormatException e) {
}
}
public void getResult() {
double result = 0;
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 {
if(function[2] == true)
result = temporary[0] * temporary[1];
else if(function[3] == true)
result = temporary[0] / temporary[1];
else if(function[0] == true)
result = temporary[0] + temporary[1];
else if(function[1] == true)
result = temporary[0] - temporary[1];
display.setText(Double.toString(result));
for(int i = 0; i < 4; i++)
function[i] = false;
}
catch(NumberFormatException e) {
}
}
public final void setDesign(){
try {
UIManager.setLookAndFeel(
"com.sun.java.swing.plaf.nimbus.NimbusLookAndFeel");
} catch(Exception e) {
}
}
public void actionPerformed(ActionEvent ae) {
if(ae.getSource() == button[0])
display.append("7");
if(ae.getSource() == button[1])
display.append("8");
if(ae.getSource() == button[2])
display.append("9");
if(ae.getSource() == button[3]) {
temporary[0] = Double.parseDouble(display.getText());
function[0] = true;
display.setText("");
}
if(ae.getSource() == button[4])
display.append("4");
if(ae.getSource() == button[5]);
display.append("5");
if(ae.getSource() == button[6])
display.append("6");
if(ae.getSource() == button[7]) {
temporary[0] = Double.parseDouble(display.getText());
function[1] = true;
display.setText("");
}
if(ae.getSource() == button[8])
display.append("1");
if(ae.getSource() == button[9]);
display.append("2");
if(ae.getSource() == button[10]);
display.append("3");
if(ae.getSource() == button[11]) {
temporary[0] = Double.parseDouble(display.getText());
function[2] = true;
display.setText("");
}
if(ae.getSource() == button[12])
display.append(".");
if(ae.getSource() == button[13]) {
temporary[0] = Double.parseDouble(display.getText());
function[3] = true;
display.setText("");
}
if(ae.getSource() == button[14])
clear();
if(ae.getSource() == button[15])
getSqrt();
if(ae.getSource() == button[16])
getPosNeg();
if(ae.getSource() == button[17])
getResult();
if(ae.getSource() == button[18])
display.append("0");
}

Java Calculator ActionListener. How to change the message "Infinity" when dividing by zero?

I am a student at Uni and having an assignment for Programming. We have to make a Calculator using java and one of the points is to type a message "Not a number" when the user divides by zero. Normally, it shows "Infinity", so the task is to change that message, however I didn't go so far to understand how to do it. If anyone has an idea or can help me rewrite it, please comment here. Thank you!
public void getResult() {
double result = 0;
temporary[1] = Double.parseDouble(display.getText());
String temp0 = Double.toString(temporary[0]);
String temp1 = Double.toString(temporary[1]);
try {
if(function[2] == true)
result = temporary[0] * temporary[1];
else if(function[3] == true)
result = temporary[0] / temporary[1];
else if(function[0] == true)
result = temporary[0] + temporary [1];
else if(function[1] == true)
result = temporary[0] - temporary[1];
display.setText(Double.toString(result));
for(int i=0; i<4; i++)
function[i] = false;
} catch(NumberFormatException e) {}
}
public void actionPerformed(ActionEvent ae) {
if(ae.getSource() == button[0])
display.append("1");
if(ae.getSource() == button[1])
display.append("2");
if(ae.getSource() == button[2])
display.append("3");
if(ae.getSource() == button[3]) {
temporary[0] = Double.parseDouble(display.getText());
function[0] = true;
display.setText("");
}
if(ae.getSource() == button[4])
display.append("4");
if(ae.getSource() == button[5])
display.append("5");
if(ae.getSource() == button[6])
display.append("6");
if(ae.getSource() == button[7]) {
temporary[0] = Double.parseDouble(display.getText());
function[1] = true;
display.setText("");
}
if(ae.getSource() == button[8])
display.append("7");
if(ae.getSource() == button[9])
display.append("8");
if(ae.getSource() == button[10])
display.append("9");
if(ae.getSource() == button[11]) {
temporary[0] = Double.parseDouble(display.getText());
function[2] = true;
display.setText("");
}
if(ae.getSource() == button[12])
display.append("0");
if(ae.getSource() == button[13])
display.append(".");
if(ae.getSource() == button[14])
clear();
if(ae.getSource() == button[15]){
temporary[0] = Double.parseDouble(display.getText());
function[3] = true;
display.setText("");
}
if(ae.getSource() == button[16])
getResult();
}
public static void main(String[] arguments) {
Calculator c = new Calculator();
}
}
As you know divide by zero is infinity. In java there is no error if you divide by zero for primitive wrapper classes. For example
public static void main(String[] args) {
Double a = 1.0;
Double b = 0.0;
Double c = a/b;
c.isInfinite();
System.out.println(c.toString());
}
prints:
Infinity
SO, just change result form double to Double and:
public void getResult() {
Double result = 0;
temporary[1] = Double.parseDouble(display.getText());
String temp0 = Double.toString(temporary[0]);
String temp1 = Double.toString(temporary[1]);
try {
if (function[2] == true)
result = temporary[0] * temporary[1];
else if (function[3] == true)
result = temporary[0] / temporary[1];
else if (function[0] == true)
result = temporary[0] + temporary[1];
else if (function[1] == true)
result = temporary[0] - temporary[1];
if(c.isInfinite() || c.isNaN()) {
display.setText("Not a number");
} else {
display.setText(result.toString());
}
for (int i = 0; i < 4; i++)
function[i] = false;
} catch (NumberFormatException e) {
display.setText(e.getMessage());
}
}

Tic Tac Toe game in Java

Ok guys...I'm stumped again.
I managed to get the game working. However, now I'm down to the point of trying to code the win conditions. I'm thinking of using a boolean array for each of the buttons, but can't figure out how to cross reference the buttons[] to the gameSquares[] to set the elements of gameSquares[] to true/false flags.
Any pointers? (Code is copied below).
** A few other interesting bugs I feel worth mentioning:
1) Start and Reset don't seem to work correctly
2) When the computer tries multiple attempts in invalid squares, the squares seem to jump or dance around. It's really weird.
package tictactoegame;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Random;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
class TicTacToeBoard extends JFrame implements ActionListener
{
JButton[] buttons = new JButton[10];
boolean player1 = false, player2 = false;
boolean[] gameSquares = {false, false, false,
false, false, false,
false, false, false};
boolean startPlayer = false;
int turnCount = 0;
public TicTacToeBoard()
{
JFrame gameWindow = new JFrame();
gameWindow.setDefaultCloseOperation(EXIT_ON_CLOSE);
gameWindow.setSize(300,400);
gameWindow.setVisible(true);
JPanel gamePanel = new JPanel();
gamePanel.setSize(300,400);
GridLayout grid = new GridLayout(4,3);
gamePanel.setLayout(grid);
for(int i = 0; i < 9; i++)
{
buttons[i] = new JButton("");
buttons[i].addActionListener(this);
gamePanel.add(buttons[i]);
}
JButton startButton = new JButton("Start");
startButton.addActionListener(this);
JButton resetButton = new JButton("Reset");
resetButton.addActionListener(this);
JButton helpButton = new JButton("Help");
helpButton.addActionListener(this);
gamePanel.add(startButton);
gamePanel.add(helpButton);
gamePanel.add(resetButton);
gameWindow.add(gamePanel);
gameWindow.pack();
while (turnCount < 9)
{
gamePlay();
}
}
public void gamePlay()
{
while(!startPlayer)
{
int random = randomGenerator();
if (random%2 == 0)
{
player1 = true;
JOptionPane.showMessageDialog(null, "Player is first.");
startPlayer = true;
}
else if (random%2 == 1)
{
player2 = true;
JOptionPane.showMessageDialog(null, "Computer is first.");
startPlayer = true;
}
}
if (player2)
{
int index;
Random randomGenerator = new Random();
index = randomGenerator.nextInt(9);
buttons[index].doClick();
player2 = false;
player1 = true;
}
}
public int randomGenerator()
{
int randomNum;
Random randomGenerator = new Random();
randomNum = randomGenerator.nextInt(100);
return randomNum;
}
#Override
public void actionPerformed(ActionEvent e)
{
Object source = e.getSource();
if(source instanceof JButton)
{
JButton button = (JButton) source;
if (button.getText() == "Start")
{
startPlayer = false;
player1 = false;
player2 = false;
gamePlay();
}
else if (button.getText() == "Reset")
{
for(int i = 0; i < 9; i++)
{
buttons[i].setText("");
}
startPlayer = false;
player1 = false;
player2 = false;
gamePlay();
}
else if (button.getText() == "Help")
{
JOptionPane.showMessageDialog(null, "Help:\n\n" +
"How to play-\n" +
"Select an empty square. The square will be filled with"
+ "with your symbole, either X or O.\n" +
"The game is won when either player gets three X's or"
+ "O's in a row horizontally,\n vertically, or diagonally.");
}
if (button.getText() == "" && player1)
{
button.setText("X");
turnCount += 1;
player1 = false;
player2 = true;
}
else if (button.getText() == "" && player2)
{
button.setText("O");
turnCount+=1;
player2 = false;
player1 = true;
}
else if (button.getText() == "X" || button.getText() == "O")
{
if(player2 == true)
{
gamePlay();
}
else
{
JOptionPane.showMessageDialog(null, "Invalid choice. Select"
+ " another square.");
}
}
}
}
}
Check this TicTacToe Full code using the Applets...:
import java.applet.Applet;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
/*
<applet code="TicTacToe.class" width="300" height="300">
</applet>
*/
public class TicTacToe extends Applet implements ActionListener {
Button[] btnarray = new Button[9];
private final static String PLAYER1 = "PLAYER1";
private final static String PLAYER2 = "PLAYER2";
private static String CURRENT_PLAYER = null;
Label lbl = new Label();
public void init() {
CURRENT_PLAYER = PLAYER1;
lbl.setText(CURRENT_PLAYER + " Turn!");
setLayout(new BorderLayout());
Panel p = new Panel();
GridLayout gl = new GridLayout(3, 3);
p.setLayout(gl);
setBackground(Color.BLACK);
setForeground(Color.WHITE);
setSize(300, 300);
Font myFont = new Font("TimesRoman", Font.BOLD, 80);
for (int i = 0; i < 9; i++) {
btnarray[i] = new Button(null);
btnarray[i].setActionCommand("" + i);
btnarray[i].addActionListener(this);
btnarray[i].setFont(myFont);
btnarray[i].setBackground(Color.white);
p.add(btnarray[i]);
}
add(BorderLayout.CENTER, p);
add(BorderLayout.NORTH, lbl);
add(BorderLayout.SOUTH, new Label("Player 1 => X , Player 2 => 0"));
}
#Override
public void actionPerformed(ActionEvent e) {
// TODO Auto-generated method stub
int index = Integer.parseInt(e.getActionCommand());
btnarray[index].disable();
if (CURRENT_PLAYER == PLAYER1) {
btnarray[index].setLabel("X");
CURRENT_PLAYER = PLAYER2;
} else {
btnarray[index].setLabel("0");
CURRENT_PLAYER = PLAYER1;
}
lbl.setText(CURRENT_PLAYER + " Turn!");
check();
}
void check() {
String[] pattern = new String[8];
pattern[0] = btnarray[0].getLabel() + btnarray[1].getLabel()
+ btnarray[2].getLabel();
pattern[1] = btnarray[3].getLabel() + btnarray[4].getLabel()
+ btnarray[5].getLabel();
pattern[2] = btnarray[6].getLabel() + btnarray[7].getLabel()
+ btnarray[8].getLabel();
pattern[3] = btnarray[0].getLabel() + btnarray[3].getLabel()
+ btnarray[6].getLabel();
pattern[4] = btnarray[1].getLabel() + btnarray[4].getLabel()
+ btnarray[7].getLabel();
pattern[5] = btnarray[2].getLabel() + btnarray[5].getLabel()
+ btnarray[8].getLabel();
pattern[6] = btnarray[0].getLabel() + btnarray[4].getLabel()
+ btnarray[8].getLabel();
pattern[7] = btnarray[2].getLabel() + btnarray[4].getLabel()
+ btnarray[6].getLabel();
int j = 0;
while (j < 8) {
char[] array = pattern[j].toCharArray();
if (array[0] == 'X' && array[1] == 'X' && array[2] == 'X') {
lbl.setText(PLAYER1 + " Wins!");
} else if (array[0] == '0' && array[1] == '0' && array[2] == '0') {
lbl.setText(PLAYER2 + " Wins!");
}
j++;
}
}
}

Knight's Tour recursive algorithm

Okay everybody, I know the knight's tour problem is popular for all cs students and I am having trouble getting mine to work. I use this recursive algorithm to progress through the moves, however, once I get to around move 50 I have to backtrack since no moves are available and I end up never completing the tour. I pass a ChessNode (holds things like if node has been visited, move it was visited, etc...), next row, next column, and previous node's move count.
private int moveRecur(ChessNode current, int row, int column, int moveV){
current.moveVisited = moveV+1;
if(current.moveVisited > 63){
return 0;
}
if(current.position==13 && aboard[row-1][column+2].visited != 1){
current.visited = 1;
moveRecur(aboard[row-1][column+2], row-1, column+2, current.moveVisited);
}
else if(current.position==22 && aboard[row-2][column+1].visited != 1){
current.visited = 1;
moveRecur(aboard[row-2][column+1], row-2, column+1, current.moveVisited);
}
else if(current.position == 50 && aboard[row+1][column-2].visited != 1){
current.visited = 1;
moveRecur(aboard[row+1][column-2], row+1, column-2, current.moveVisited);
}
else if(current.position == 41 && aboard[row+2][column-1].visited != 1){
current.visited =1;
moveRecur(aboard[row+2][column-1], row+2, column-1, current.moveVisited);
}
else if(current.position == 46 && aboard[row+2][column+1].visited != 1){
current.visited = 1;
moveRecur(aboard[row+2][column+1], row+2, column+1, current.moveVisited);
}
else if(current.position == 53 && aboard[row+1][column+2].visited != 1){
current.visited = 1;
moveRecur(aboard[row+1][column+2], row+1, column+2, current.moveVisited);
}
else if(current.position == 10 && aboard[row-1][column-2].visited != 1){
current.visited = 1;
moveRecur(aboard[row-1][column-2], row-1, column-2, current.moveVisited);
}
else if (current.position == 17 && aboard[row-2][column-1].visited != 1){
current.visited =1;
moveRecur(aboard[row-2][column-1], row-2, column-2, current.moveVisited);
}
if(row+1>=0 && row+1<8 && column+2>=0 && column+2<8){
if(aboard[row+1][column+2].visited != 1){
current.visited = 1;
moveRecur(aboard[row+1][column+2], row+1, column+2, current.moveVisited);
}
}
if(row+2>=0 && row+2<8 && column+1>=0 && column+1<8){
if(aboard[row+2][column+1].visited != 1){
current.visited = 1;
moveRecur(aboard[row+2][column+1], row+2, column+1, current.moveVisited);
}
}
if(row-1>=0 && row-1<8 && column-2>=0 && column-2<8){
if(aboard[row-1][column-2].visited != 1){
current.visited = 1;
moveRecur(aboard[row-1][column-2], row-1, column-2, current.moveVisited);
}
}
if(row-2>=0 && row-2<8 && column-1>=0 && column-1<8){
if(aboard[row-2][column-1].visited != 1){
current.visited = 1;
moveRecur(aboard[row-2][column-1], row-2, column-1, current.moveVisited);
}
}
if(row+1>=0 && row+1<8 && column-2>=0 && column-2<8){
if(aboard[row+1][column-2].visited != 1){
current.visited = 1;
moveRecur(aboard[row+1][column-2], row+1, column-2, current.moveVisited);
}
}
if(row+2>=0 && row+2<8 && column-1>=0 && column-1<8){
if(aboard[row+2][column-1].visited != 1){
current.visited = 1;
moveRecur(aboard[row+2][column-1], row+2, column-1, current.moveVisited);
}
}
if(row-1>=0 && row-1<8 && column+2>=0 && column+2<8){
if(aboard[row-1][column+2].visited != 1){
current.visited = 1;
moveRecur(aboard[row-1][column+2], row-1, column+2, current.moveVisited);
}
}
if(row-2>=0 && row-2<8 && column+1>=0 && column+1<8){
if(aboard[row-2][column+1].visited != 1){
current.visited = 1;
moveRecur(aboard[row-2][column+1], row-2, column+1, current.moveVisited);
}
}
//System.out.println(current.position + " "+current.moveVisited);
current.visited = 0;
return 0;
}
So, initially I check for the spots that can move to the corner board positions, and then I just make recursive calls based on available moves. So I guess my main question is am I doing something wrong? or is there another condition I can used to make the tour a little more intuitive?
Thanks in advance!
This is the Knight's tour code in java and has a brilliant layout. I did this using backtracking using recursion. This was my class assignment. Do contact me if you have any problem understanding or running this code.
package knights.tour;
import java.awt.*;
import java.awt.event.*;
import java.util.logging.*;
import javax.swing.*;
public class KnightsTour extends JFrame implements ActionListener{
//All the static variables used between action listeners and functions.
public static String path;
public static int btnPressed = 0;
public static int rowSelected;
public static String[] pathArray;
public static int[][] coordinatesArray;
public static int columnSelected;
public static int flag =0;
public static int increment = 0;
public static JPanel panel1 = new JPanel();
public static JPanel panel3 ;
public static JButton btnStart = new JButton("Start Animation");
public static JButton btnClear = new JButton("Clear");
public static JTextArea lblPath = new JTextArea();
public static JLabel lblStartRow = new JLabel();
public static JLabel lblStartColumn = new JLabel();
public static JButton[][] button;
public static int variableForIncrement=0;
static int row ;
static int column ;
static int[][] array = new int[row][column];
public static int count = 1;
KnightsTour(){
//Setting layout of the frame in the constructor and adding buttons to the panel and the frame.
getContentPane().setLayout(new GridLayout(2,1));
lblPath.setLineWrap(true);
lblPath.setColumns(10);
lblPath.setSize(700, 100);
lblPath.setEditable(false);
panel1.add(btnStart);
panel1.add(btnClear);
panel1.add(lblStartRow);
panel1.add(lblStartColumn);
panel1.add(lblPath);
panel3 = new JPanel(new GridLayout(row,column));
// Initializing Array of buttons for the user to click on the chess board.
button= new JButton[row][column];
array = new int[row][column];
coordinatesArray = new int[row*column][2]; // This array stores the coordinates as the Knight
for(int i=0;i<row;i++){
for(int j=0;j<column;j++){
button[i][j] = new JButton();
}
}
//Setting background of the buttons to black and white for chessboard layout.
for(int i=0;i<row;i++){
for(int j=0;j<column;j++){
if(i%2 ==j%2){
button[i][j].setBackground(Color.BLACK);
button[i][j].setForeground(Color.WHITE);
}
else{
button[i][j].setBackground(Color.WHITE);
}
panel3.add(button[i][j]);
button[i][j].addActionListener(this);
}
}
btnClear.addActionListener(this);
btnStart.addActionListener(this);
add(panel3);
add(panel1);
setDefaultCloseOperation(EXIT_ON_CLOSE);
}
public static void main(String[] args) {
// TODO code application logic here
String input =JOptionPane.showInputDialog("Enter the rows and columns in the format (row,column)");
String[] ar = input.split(",");
row = Integer.parseInt(ar[0]); // Finding out row and column from the user input.
column = Integer.parseInt(ar[1]);
pathArray = new String[row*column]; // This array is kept to store the path of the knight.
JFrame frame = new KnightsTour();
frame.setVisible(true);
frame.setSize(700,700);
}
//All the computation takes place in this function. It checks the neighbour and recursively calls itself.
public static void neighbourRecursion(int a,int b){
pathArray[increment] = Integer.toString(a) + "," + Integer.toString(b); // Storing the path of the Knight
increment++;
array[a][b] = count; //Stroing value of count.
button[a][b].setText(String.valueOf(count));
coordinatesArray[variableForIncrement][0] = button[a][b].getX(); //Finding coordinates of buttons to show animation
coordinatesArray[variableForIncrement][1] = button[a][b].getY();
count++;
variableForIncrement++;
//Checking for valid neighbours and calling itself recursively.
if(a <= row-3 && b<=column-2){
if(alreadyVisited(a+2,b+1)){
neighbourRecursion(a+2,b+1);
}
}
if(a<=row-3 && b>=1){
if(alreadyVisited(a+2,b-1)){
neighbourRecursion(a+2,b-1);
}
}
if(a>=2 && b<=column-2){
if(alreadyVisited(a-2,b+1)){
neighbourRecursion(a-2,b+1);
}
}
if(a>=2 && b>=1){
if(alreadyVisited(a-2,b-1)){
neighbourRecursion(a-2,b-1);
}
}
if(a<=row-2 && b>=2){
if(alreadyVisited(a+1,b-2)){
neighbourRecursion(a+1,b-2);
}
}
if(a<=row-2 && b<=column-3){
if(alreadyVisited(a+1,b+2)){
neighbourRecursion(a+1,b+2);
}
}
if(a>=1 && b>=2){
if(alreadyVisited(a-1,b-2)){
neighbourRecursion(a-1,b-2);
}
}
if(a>=1 && b <=column-3){
if(alreadyVisited(a-1,b+2)){
neighbourRecursion(a-1,b+2);
}
}
//Breaking condition of the function.
if(count == (row*column)+1){
}
// Backtracking condition if there is no neighbour.
else{
button[a][b].setText("");
array[a][b]=0;
count--;
variableForIncrement--;
if(increment >0){
increment--;
}
return ;
}
}
//This function checks if the neighbour is already visited.
public static boolean alreadyVisited(int a,int b){
if(array[a][b] != 0){
return false;
}
else{
return true;
}
}
#Override
public void actionPerformed(ActionEvent e) {
//when clear is pressed all arrays and global variables are set to initial conditon.
if(e.getSource() == btnClear){
for(int i =0;i<row;i++){
for(int j=0;j<column;j++){
array[i][j] = 0;
button[i][j].setText("");
count = 1;
lblPath.setText("");
lblStartRow.setText("");
lblStartColumn.setText("");
flag =0;
variableForIncrement=0;
increment =0;
path =" ";
}
}
}
//If start animation button is pressed animation is started.
else if(e.getSource() == btnStart){
animate();
}
// When the button is pressed.
else{
for(int i=0;i<row;i++){
for(int j=0;j<column;j++){
if(e.getSource() == button[i][j]){
if(flag == 1){
lblPath.setText(" Please press clear before clicking again"); // Button pressed twice without reset.
}
else{
rowSelected = i;
columnSelected =j;
// If odd * odd board and selected postion is odd then No path is possible.
if(row%2 ==1 && column%2 == 1 && rowSelected%2 ==0 && columnSelected%2 == 1 || row%2 ==1 && column%2 == 1 && rowSelected%2 ==1 && columnSelected%2 == 0){
lblPath.setText(" Path not possible from this point");
}
else{
int count;
lblStartRow.setText("Starting Row : "+String.valueOf(rowSelected + 1));
lblStartColumn.setText("Starting Column : "+String.valueOf(columnSelected + 1));
count = 1;
flag = 1;
startTour(); //Start tour function called.
for(int q=0;q<row;q++){
for(int w=0;w<column;w++){
if(array[i][j] == 0){
count++;
}
}
}
if(count > 2){
lblPath.setText(" No Path found");
}
//Printing path of the knight here.
else{
for(int k=0;k<pathArray.length;k++){
path = path+"->"+ pathArray[k];
}
lblPath.setText(" Path : \n"+ path.substring(5));
}
btnPressed = 1;
break;
}
}
}
}
}
} }
//Function for the animation.
void animate(){
if(btnPressed == 1){
btnPressed =0;
Graphics g = getGraphics();
for(int i=0;i<(row*column)-1;i++){
try {
Thread.sleep(600); // this function slows down drawing of lines.
} catch (InterruptedException ex) {
}
g.setColor(Color.RED); // setting colour or line to red.
g.drawLine((coordinatesArray[i][0]+65),(coordinatesArray[i][1]+50),(coordinatesArray[i+1] [0]+65),(coordinatesArray[i+1][1]+50));
}
}
else{
lblPath.setText(" Please clear, select a button to see the animation again"); //Animate button pressed twice without clear.
}
}
//This function calls the neighbour function with the selected row and column by the user.
static void startTour(){
neighbourRecursion(rowSelected,columnSelected);
for(int i=0;i<row;i++){
for(int j=0;j<column;j++){
System.out.print(array[i][j]+" ");
}
System.out.println();
}
}
}
I have an implementation of this program in C#. You can find it here:
http://github.com/danieltian/KnightBoard
It will only find the first solution though. I'm not saying to copy it, but you can take a look at it and see if it helps.

Categories

Resources