Showing posts with label gui. Show all posts
Showing posts with label gui. Show all posts

Monday, August 25, 2014

Tic Tac Toe AI [ Minimax Algorithm ] with GUI using JavaFX [Tic Tac Toe][Artificial Intelligence][Minimax][Java][JavaFX]

I made this GUI for the TicTacToe AI: http://coderbots.blogspot.in/2014/08/minimax-algorithm-tic-tac-toe-ai-in.html. The GUI is written in JavaFX. You might wanna give it a shot and see if you can defeat the AI (not possible though).

Lamba Expressions (Java 8): http://coderbots.blogspot.in/2014/08/using-lambdas-java-8-java-8lambda.html

[Make sure you have JDK 8.0 Installed] If not, here's a link: http://www.oracle.com/technetwork/java/javase/downloads/jre8-downloads-2133155.html

Here's a link to a click and run JAR : http://www.mediafire.com/download/yktyrg2w8754yah/TicTacToe_v2.jar
[CSS and Image files included in the JAR. Just open it up with WinRAR, if you feel like seeing the CSS]

Screenshots:


Source [GUI]:

import java.util.Random;
import javafx.application.Application;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.layout.GridPane;
import javafx.stage.Stage;

/**
 *
 * @author Jatin Thakur
 */
class Turn {

    enum NextMove {

        O, X, E
    }
    NextMove next;
}

public class TicTacToeAIGUI extends Application {

    Board board = new Board();
    Turn boardTurn = new Turn();
    GridPane grid;
    Label cell1, cell2, cell3,
            cell4, cell5, cell6,
            cell7, cell8, cell9;
    Label[] cells;

    @Override
    public void start(Stage primaryStage) {

        Stage stage = new Stage();
        GridPane g = new GridPane();
        g.setId("firstDialog");
        g.setPadding(new Insets(20, 20, 20, 20));
        g.setVgap(20);
        g.setHgap(20);

        //First Dialog Labels and Buttons
        Label label = new Label("Who will play first?");
        Button IWillPlay = new Button("Lemme play first!");
        Button YouPlay = new Button("You're a legend! you play first!");
        g.add(label, 0, 0, 2, 1);
        g.add(IWillPlay, 0, 1, 1, 1);
        g.add(YouPlay, 1, 1, 1, 1);

        //Scene for the firstDialog
        Scene sc = new Scene(g, 450, 200);
        g.setAlignment(Pos.CENTER);
        sc.getStylesheets().addAll(this.getClass().getResource("firstDialog.css").toExternalForm());
        stage.setTitle("Choose turn");
        stage.setScene(sc);
        stage.setOnCloseRequest(e -> {
            System.exit(0);
        });

        //Board scene
        GridPane grid = new GridPane();
        cell1 = new Label();
        cell2 = new Label();
        cell3 = new Label();
        cell4 = new Label();
        cell5 = new Label();
        cell6 = new Label();
        cell7 = new Label();
        cell8 = new Label();
        cell9 = new Label();

        cells = new Label[]{cell1, cell2, cell3,
            cell4, cell5, cell6,
            cell7, cell8, cell9};

        for (Label cell : cells) {
            cell.setMinSize(128, 128);
            boolean isUsed = false;
            cell.setUserData(isUsed);
        }

        grid.addRow(0, cell1, cell2, cell3);
        grid.addRow(1, cell4, cell5, cell6);
        grid.addRow(2, cell7, cell8, cell9);

        grid.setAlignment(Pos.CENTER);
        grid.setMaxSize(800, 800);
        grid.setGridLinesVisible(true);
        grid.setId("board");

        boardTurn.next = Turn.NextMove.O;
        Image OPic = new Image(getClass().getResourceAsStream("O.png"));
        Image XPic = new Image(getClass().getResourceAsStream("X.png"));

        for (Label cell : cells) {

            cell.setOnMouseClicked(event -> {
                if (((boolean) cell.getUserData()) == false) {
                    cell.setGraphic(new ImageView(XPic));

                    int index = -1;
                    for (int i = 0; i < cells.length; ++i) {
                        if (cell == cells[i]) {
                            index = i;
                        }
                    }

                    board.placeAMove(new Point(index / 3, index % 3), 2);
                    board.displayBoard();
                    System.out.println("Placed a move at: (" + index / 3 + ", " + index % 3 + ")");
                    boolean mark = true;
                    int next = board.returnNextMove();

                    if (next != -1) {   //If the game isn't finished yet!   
                        int indexCell = next;

                        cells[indexCell].setGraphic(new ImageView(OPic));
                        cells[indexCell].setUserData(mark); //Used!
                        System.out.println("Computer has evaluated the next move! " + indexCell);
                        board.placeAMove(new Point(indexCell / 3, indexCell % 3), 1);
                        cell.setUserData(mark);
                    }

                    if (board.isGameOver()) {
                        Stage stage2 = new Stage();
                        GridPane g2 = new GridPane();
                        g2.setPadding(new Insets(20, 20, 20, 20));
                        g2.setVgap(20);
                        g2.setHgap(20);
                        Label label2 = new Label();
                        if (board.hasXWon()) {
                            label2.setText("You better learn to play first, kid!");
                            stage2.setTitle("You lost!");
                        } else {
                            label2.setText("You can't beat me, Stop trying!");
                            stage2.setTitle("It's a draw!");
                        }
                        g2.add(label2, 0, 0, 2, 1);
                        Button onceMore = new Button("Lemme play again!");
                        Button quit = new Button("I'm tired. I quit!");
                        g2.add(onceMore, 1, 1, 1, 1);
                        g2.add(quit, 2, 1, 1, 1);
                        onceMore.setOnMouseClicked(q -> {
                            primaryStage.close();
                            stage2.close();
                            board.resetBoard();
                            start(new Stage());
                        });

                        quit.setOnMouseClicked(q -> {
                            System.exit(0);
                        });
                        Scene scene = new Scene(g2);
                        scene.getStylesheets().addAll(this.getClass().getResource("result.css").toExternalForm());
                        stage2.setScene(scene);
                        stage2.setOnCloseRequest(q -> {
                            primaryStage.close();
                        });
                        stage2.show();
                    }
                }
            });
        };

        Scene scene = new Scene(grid);
        primaryStage.setTitle("Tic Tac Toe");
        primaryStage.setScene(scene);

        scene.getStylesheets().addAll(this.getClass().getResource("board.css").toExternalForm());

        //FirstWindow Action Listeners
        IWillPlay.setOnMouseClicked((event) -> {
            boardTurn.next = Turn.NextMove.X;
            stage.close();
        });

        YouPlay.setOnMouseClicked((event) -> {
            int index = new Random().nextInt(9);
            cells[index].setGraphic(new ImageView(OPic));
            cells[index].setUserData(new Boolean(true));
            board.placeAMove(new Point(index / 3, index % 3), 1);
            boardTurn.next = Turn.NextMove.X;
            stage.close();
        });
        stage.showAndWait();  //Tag1 
        /*
         The placement position of this line (tag1) is important.
         If you place this line above the listeners, the listeners 
         aren't gonna work
         */
        primaryStage.show();
    }

    public static void main(String[] args) {
        launch(args);
    }

}


Source [Logic][Board class]:

import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import java.util.Scanner;

class Point {

    int x, y;

    public Point(int x, int y) {
        this.x = x;
        this.y = y;
    }

    @Override
    public String toString() {
        return "[" + x + ", " + y + "]";
    }
}

class PointAndScore {

    int score;
    Point point;

    PointAndScore(int score, Point point) {
        this.score = score;
        this.point = point;
    }
}

class Board {
 
    List<Point> availablePoints;
    Scanner scan = new Scanner(System.in);
    int[][] board = new int[3][3];

    public Board() {
    }

    public boolean isGameOver() {
        //Game is over is someone has won, or board is full (draw)
        return (hasXWon() || hasOWon() || getAvailableStates().isEmpty());
    }

    public boolean hasXWon() {
        if ((board[0][0] == board[1][1] && board[0][0] == board[2][2] && board[0][0] == 1) || (board[0][2] == board[1][1] && board[0][2] == board[2][0] && board[0][2] == 1)) {
            //System.out.println("X Diagonal Win");
            return true;
        }
        for (int i = 0; i < 3; ++i) {
            if (((board[i][0] == board[i][1] && board[i][0] == board[i][2] && board[i][0] == 1)
                    || (board[0][i] == board[1][i] && board[0][i] == board[2][i] && board[0][i] == 1))) {
                // System.out.println("X Row or Column win");
                return true;
            }
        }
        return false;
    }

    public boolean hasOWon() {
        if ((board[0][0] == board[1][1] && board[0][0] == board[2][2] && board[0][0] == 2) || (board[0][2] == board[1][1] && board[0][2] == board[2][0] && board[0][2] == 2)) {
            // System.out.println("O Diagonal Win");
            return true;
        }
        for (int i = 0; i < 3; ++i) {
            if ((board[i][0] == board[i][1] && board[i][0] == board[i][2] && board[i][0] == 2)
                    || (board[0][i] == board[1][i] && board[0][i] == board[2][i] && board[0][i] == 2)) {
                //  System.out.println("O Row or Column win");
                return true;
            }
        }

        return false;
    }

    public List<Point> getAvailableStates() {
        availablePoints = new ArrayList<>();
        for (int i = 0; i < 3; ++i) {
            for (int j = 0; j < 3; ++j) {
                if (board[i][j] == 0) {
                    availablePoints.add(new Point(i, j));
                }
            }
        }
        return availablePoints;
    }

    public void placeAMove(Point point, int player) {
        board[point.x][point.y] = player;   //player = 1 for X, 2 for O
    } 
    
    void takeHumanInput() {
        System.out.println("Your move: ");
        int x = scan.nextInt();
        int y = scan.nextInt();
        Point point = new Point(x, y);
        placeAMove(point, 2); 
    }

    public void displayBoard() {
        System.out.println();

        for (int i = 0; i < 3; ++i) {
            for (int j = 0; j < 3; ++j) {
                System.out.print(board[i][j] + " ");
            }
            System.out.println();

        }
    } 
    
    Point computersMove; 
    
    public int minimax(int depth, int turn) {  
        if (hasXWon()) return +1; 
        if (hasOWon()) return -1;

        List<Point> pointsAvailable = getAvailableStates();
        if (pointsAvailable.isEmpty()) return 0; 
 
        int min = Integer.MAX_VALUE, max = Integer.MIN_VALUE;
         
        for (int i = 0; i < pointsAvailable.size(); ++i) {  
            Point point = pointsAvailable.get(i);   
            if (turn == 1) { 
                placeAMove(point, 1); 
                int currentScore = minimax(depth + 1, 2);
                max = Math.max(currentScore, max);
                
                if(depth == 0)System.out.println("Score for position "+(i+1)+" = "+currentScore);
                if(currentScore >= 0){ if(depth == 0) computersMove = point;} 
                if(currentScore == 1){board[point.x][point.y] = 0; break;} 
                if(i == pointsAvailable.size()-1 && max < 0){if(depth == 0)computersMove = point;}
            } else if (turn == 2) {
                placeAMove(point, 2); 
                int currentScore = minimax(depth + 1, 1);
                min = Math.min(currentScore, min); 
                if(min == -1){board[point.x][point.y] = 0; break;}
            }
            board[point.x][point.y] = 0; //Reset this point
        } 
        return turn == 1?max:min;
    }  
    
    //Functions for GUI
    public int returnNextMove() {
        if (isGameOver()) return -1;
        minimax(0, 1); 
        return computersMove.x * 3 + computersMove.y;
    }

    public void resetBoard(){
        for(int i = 0;i<3;++i)
            for(int j=0;j<3;++j)
                board[i][j] = 0;
    }
}

Thursday, August 14, 2014

JSlider Color Painter GUI Java [Swing]

This application has two JSlider s which paint a JPanel as their values change. The JSliders represent the coordinates of the JPanel to paint. A clear button clears the Panel.


Code:

import java.awt.*;
import java.awt.event.*;
import java.util.ArrayList;
import javax.swing.*;
import javax.swing.event.*;

class Point {

    int x;
    int y;

    Point(int x, int y) {
        this.x = x;
        this.y = y;
    }
}

class Display extends JPanel {

    ArrayList<Point> points = new ArrayList<>();
    Point previous, newPoint;
    Color color = Color.RED;

    public void paintComponent(Graphics g) {
        super.paintComponent(g);
        Graphics2D gg = (Graphics2D) g;

        gg.setColor(color);

        previous = null;

        for (Point p : points) {
            if (previous == null) {
                previous = p;
                continue;
            }
            gg.drawLine(previous.x, previous.y, p.x, p.y);
            previous = p;
        }
    }
}

public class SketchBox2 extends JFrame {

    JButton clear = new JButton("Clear Points [0]");
    private Display screen = new Display();
    private JSlider xAxis = new JSlider(0, 0, 0);
    private JSlider yAxis = new JSlider(JSlider.VERTICAL, 0, 0, 0);

    SketchBox2() {
        yAxis.setInverted(true);
        xAxis.addChangeListener(cl);
        yAxis.addChangeListener(cl);
        xAxis.setValue(0);
        yAxis.setValue(0);

        setTitle("Painter");

        add(BorderLayout.CENTER, screen);
        add(BorderLayout.NORTH, clear);
        add(BorderLayout.WEST, yAxis);
        add(BorderLayout.SOUTH, xAxis);

        screen.addComponentListener(new ComponentAdapter() {
            public void componentResized(ComponentEvent e) {
                yAxis.setMaximum(screen.getHeight());
                xAxis.setMaximum(screen.getWidth());
            }
        });

        setSize(500, 500);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setVisible(true);

        clear.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {
                screen.points.clear();
                screen.repaint();
                clear.setText(
                        "[Erase] points.size() = "
                        + screen.points.size());
            }
        });

        clear.doClick();
    }

    ChangeListener cl = new ChangeListener() {

        @Override
        public void stateChanged(ChangeEvent e) {
            screen.newPoint = new Point(xAxis.getValue(), yAxis.getValue());
            screen.points.add(screen.newPoint);

            clear.setText(
                    "[Erase] points.size() = "
                    + screen.points.size());
            screen.repaint();
        }
    };

    public static void main(String[] args) {
        new SketchBox2();
    }
}

[Concept : Thinking In Java 4th Edition GUI Ex24]


Wednesday, August 13, 2014

ColorMixer GUI Application Swing [Java]

The application has three JSliders that represent the color values (Red, Green, Blue). As soon as the
value is changed by any of the slider, the new mixed color gets displayed on a panel. A status bar shows
the current mixing of color values.


Code:

import java.awt.*; 
import javax.swing.*;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener; 

class ColorMixer extends JFrame {

    class DrawPanel extends JPanel {

        public void paintComponent(Graphics g) {
            super.paintComponent(g);
            setBackground(new Color(redValue, greenValue, blueValue));
            repaint();
        }
    }

    JSlider red, green, blue;
    JPanel sliderPanel;
    DrawPanel display;
    JTextField status;
    int redValue = 0, greenValue = 0, blueValue = 0;

    {
        red = new JSlider(0, 255, 0);
        green = new JSlider(0, 255, 0);
        blue = new JSlider(0, 255, 0);

        sliderPanel = new JPanel();
        display = new DrawPanel();

        status = new JTextField();
        status.setEditable(false);
        status.setText("Red : " + redValue + " Green : " + greenValue + " Blue : " + blueValue);
    }

    ColorMixer() {
        setLayout(new GridLayout(2, 1));
        add(display);
        add(sliderPanel);

        sliderPanel.add(status);
        sliderPanel.add(red);
        sliderPanel.add(green);
        sliderPanel.add(blue);

        sliderPanel.setLayout(new GridLayout(4, 1));

        SliderListener changeListener = new SliderListener();
        red.addChangeListener(changeListener);
        green.addChangeListener(changeListener);
        blue.addChangeListener(changeListener);

        
        setTitle("Color Mixer");
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setSize(500, 500);
        setVisible(true);
    }

    class SliderListener implements ChangeListener {

        @Override
        public void stateChanged(ChangeEvent e) {
     
            if (e.getSource() == red) {
                redValue = ((JSlider) e.getSource()).getValue();
            } else if (e.getSource() == green) {
                greenValue = ((JSlider) e.getSource()).getValue();
            } else if (e.getSource() == blue) {
                blueValue = ((JSlider) e.getSource()).getValue();
            }
            status.setText("Red : " + redValue + " Green : " + greenValue + " Blue : " + blueValue);
            display.repaint();
        }
    }
}

public class ColorMixerRunner {

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                try {
                    for (UIManager.LookAndFeelInfo info : UIManager.getInstalledLookAndFeels()) {
                        System.out.println(info.getClassName());
                        if ("Nimbus".equals(info.getName())) {
                            UIManager.setLookAndFeel(info.getClassName());
                            break;
                        }
                    }
                } catch (Exception e) {
                    // If Nimbus is not available, you can set the GUI to another look and feel.
                }
            }
        });
        ColorMixer cm = new ColorMixer();
    }
}

Sunday, August 10, 2014

GUI based Regex Matcher [Swing][Java]

This program takes an input string from the user as well as the regular expression to match on the string.
If a match is found it displays the result else displays "Regex pattern incorrect. Try again!" if the regex pattern is incorrect.


Source:

import java.awt.GridLayout;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.swing.*;

public class Application extends JFrame {

    JTextArea area1, area2, area3;
    JLabel label1 = new JLabel("Result: "),
            labelTopLeft = new JLabel("Input String"),
            labelTopRight = new JLabel("Regex: ");
    JPanel panel1;
    JScrollPane scroller1, scroller2, scroller3;

    {
        area1 = new JTextArea();
        area2 = new JTextArea();
        area3 = new JTextArea();
        panel1 = new JPanel();
        scroller1 = new JScrollPane(area1);
        scroller2 = new JScrollPane(area2);
        scroller3 = new JScrollPane(area3);
    }

    Ex6() {
        panel1.setLayout(new GridLayout(2, 2));
        panel1.add(labelTopLeft);
        panel1.add(labelTopRight);
        panel1.add(scroller1);
        panel1.add(scroller2);
        add(panel1);

        setLayout(new GridLayout(3, 1));
        add(label1);
        add(scroller3);
        area3.setEditable(false);

        area2.addKeyListener(new FieldListener());

        this.setSize(700, 400);
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        this.setVisible(true);
    }

    class FieldListener extends KeyAdapter {

        public void keyTyped(KeyEvent e) {
            if (e.getKeyChar() == '\n') {
                String userString = area1.getText();
                String userRegex = ((JTextArea) e.getSource()).getText();
                userRegex = userRegex.substring(0, userRegex.length() - 1);
                Pattern p;
                try {
                    p = Pattern.compile(userRegex);
                } catch (Exception ex) {
                    area3.setText("Regex pattern incorrect. Try again!");
                    return;
                }
                Matcher m = p.matcher(userString);
                area3.setText("");
                while (m.find()) {
                    area3.append(m.group() + "\n");
                }
            }
        }
    }

    public static void main(String[] args) {
        Application app = new Application();
    }
}