Configs.java
package main; /** * @author Daniel * * A load of configs for the application. */ public class Configs { public static final String APPLICATION_NAME = "Sorting Algorithm Animation"; public static final int APPLICATION_WIDTH = 1280; public static final int APPLICATION_HEIGHT = 720; public static final int DISPLAY_PANEL_WIDTH = Configs.APPLICATION_WIDTH * 4 / 5; public static final int DISPLAY_PANEL_HEIGHT = Configs.APPLICATION_HEIGHT; public static final int BUTTONS_PANEL_WIDTH = Configs.APPLICATION_WIDTH / 5; public static final int BUTTONS_PANEL_HEIGHT = Configs.APPLICATION_HEIGHT; public static final int INITIAL_LIST_STARTING_VALUE = 1024; public static final String[] ALL_SORTS_COMBO_BOX_VALUES = {"Bubble Sort", "Quick Sort", "Selection Sort", "Insertion Sort", "Merge Sort"}; public static final int MAXIMUM_DELAY_VALUE = 10000; public static final int MINIMUM_DELAY_VALUE = 0; public static final int TICK_SPACING = 3333; public static final int INITIAL_DELAY_VALUE = MAXIMUM_DELAY_VALUE / 2; }
SortingAlgorithmAnimationApp.java
package main; import javax.swing.SwingUtilities; import gui.AppGUI; /** * @author Daniel * * The driver class. */ public class SortingAlgorithmAnimationApp { public static void main(String[] args) { SwingUtilities.invokeLater(AppGUI::new); } }
AppGUI,java
package gui; import java.awt.FlowLayout; import javax.swing.JFrame; import gui_components.GUIComponents; import main.Configs; import storage.NumbersList; /** * @author Daniel * * Puts the GUI together. */ public class AppGUI { public AppGUI() { NumbersList.generateList(Configs.INITIAL_LIST_STARTING_VALUE); initGUI(); } private void initGUI() { JFrame window = new JFrame(); window.getContentPane().setLayout(new FlowLayout()); window.getContentPane().add(GUIComponents.buttonsPanel); window.getContentPane().add(GUIComponents.displayPanel); window.setTitle(Configs.APPLICATION_NAME); window.setResizable(false); window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); window.pack(); window.setLocationRelativeTo(null); window.setVisible(true); } }
GUIComponents.java
package gui_components; import java.awt.Color; import java.awt.Dimension; import java.awt.event.ActionEvent; import javax.swing.JButton; import javax.swing.JComboBox; import javax.swing.JLabel; import javax.swing.JOptionPane; import javax.swing.JPanel; import javax.swing.JSlider; import javax.swing.event.ChangeEvent; import drawing.PaintSurface; import main.Configs; import sorting_algorithms.BubbleSort; import sorting_algorithms.InsertionSort; import sorting_algorithms.MergeSort; import sorting_algorithms.QuickSort; import sorting_algorithms.SelectionSort; import sorting_algorithms.SortingAlgorithm; import storage.NumbersList; /** * @author Daniel * * Creates and holds all the GUI components. */ public class GUIComponents { // don't let anyone instantiate this class. private GUIComponents() {} public static JPanel buttonsPanel, displayPanel; private static JButton newListButton; public static JSlider delaySlider; private static JButton randomizeListButton; private static JComboBox<String> allSortsComboBox; private static JButton doSortButton; private static SortingAlgorithm algorithm; static { initButtonsPanel(); displayPanel = new PaintSurface(); } private static void initButtonsPanel() { buttonsPanel = new JPanel(); buttonsPanel.setPreferredSize(new Dimension(Configs.BUTTONS_PANEL_WIDTH, Configs.BUTTONS_PANEL_HEIGHT)); buttonsPanel.setBackground(Color.LIGHT_GRAY); initNewListButton(); initDelaySlider(); initRandomizeListButton(); initAllSortsComboBox(); initDoSortButton(); buttonsPanel.add(new JLabel("Sorting Delay (ms)")); buttonsPanel.add(delaySlider); buttonsPanel.add(newListButton); buttonsPanel.add(randomizeListButton); buttonsPanel.add(allSortsComboBox); buttonsPanel.add(doSortButton); } private static void initNewListButton() { newListButton = new JButton("New List"); newListButton.addActionListener((ActionEvent event) -> { int amount = NumbersList.getList().length; try { String temp = JOptionPane.showInputDialog(null, "How many numbers?", "Enter Information", JOptionPane.INFORMATION_MESSAGE); if(temp != null && temp.length() > 0) { amount = Integer.parseInt(temp); } else return; } catch(java.lang.NumberFormatException exception) { JOptionPane.showMessageDialog(null, "Something went wrong!", "Error", JOptionPane.ERROR_MESSAGE); return; } if(amount < 0 || amount > 1024) { JOptionPane.showMessageDialog(null, "Invalid Amount! 0 - 1024 only.", "Error", JOptionPane.ERROR_MESSAGE); return; } NumbersList.generateList(amount); GUIComponents.displayPanel.repaint(); }); } private static void initDelaySlider() { delaySlider = new JSlider(JSlider.HORIZONTAL, Configs.MINIMUM_DELAY_VALUE, Configs.MAXIMUM_DELAY_VALUE, Configs.INITIAL_DELAY_VALUE); delaySlider.setMajorTickSpacing(Configs.TICK_SPACING); delaySlider.setMinorTickSpacing(10); delaySlider.setPaintLabels(true); delaySlider.setSnapToTicks(true); delaySlider.setBackground(Color.LIGHT_GRAY); delaySlider.addChangeListener((ChangeEvent event) -> { if(algorithm != null) algorithm.changeDelay(delaySlider.getValue() * 1000); }); } private static void initRandomizeListButton() { randomizeListButton = new JButton("Randomize List"); randomizeListButton.addActionListener((ActionEvent event) -> { NumbersList.randomizeList(); GUIComponents.displayPanel.repaint(); }); } private static void initAllSortsComboBox() { allSortsComboBox = new JComboBox<String>(Configs.ALL_SORTS_COMBO_BOX_VALUES); } private static void initDoSortButton() { doSortButton = new JButton("Do Sort"); doSortButton.addActionListener((ActionEvent event) -> { randomizeListButton.setEnabled(false); newListButton.setEnabled(false); doSortButton.setEnabled(false); allSortsComboBox.setEnabled(false); switch((String) allSortsComboBox.getSelectedItem()) { case "Bubble Sort": algorithm = new BubbleSort(); break; case "Quick Sort": algorithm = new QuickSort(); break; case "Selection Sort": algorithm = new SelectionSort(); break; case "Insertion Sort": algorithm = new InsertionSort(); break; case "Merge Sort": algorithm = new MergeSort(); break; } new Thread(new Runnable() { @Override public void run() { algorithm.doSort(NumbersList.getList()); randomizeListButton.setEnabled(true); newListButton.setEnabled(true); doSortButton.setEnabled(true); allSortsComboBox.setEnabled(true); }}).start(); displayPanel.repaint(); }); } }
NumbersList.java
package storage; import main.Configs; /** * @author Daniel * * Holds the list and methods concerning the list. */ public class NumbersList { private static int[] numbers; public static void generateList(int amount) { numbers = new int[amount]; double spacing = (double) Configs.APPLICATION_HEIGHT / amount, height = spacing; for(int i = 0; i < amount; i++) { numbers[i] = (int) (height); height += spacing; } } public static void randomizeList() { for(int i = 0; i < NumbersList.numbers.length; i++) { int temp = NumbersList.numbers[i]; int randomPlace = (int) (Math.random() * NumbersList.numbers.length); NumbersList.numbers[i] = NumbersList.numbers[randomPlace]; NumbersList.numbers[randomPlace] = temp; } } public static int[] getList() { return NumbersList.numbers; } }
PaintSurface.java
package drawing; import java.awt.Color; import java.awt.Dimension; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.RenderingHints; import javax.swing.JPanel; import main.Configs; import storage.NumbersList; /** * @author Daniel * * The display panel for the animation. */ public class PaintSurface extends JPanel { private static final long serialVersionUID = 1L; public static int currentBarIndex = 0; public PaintSurface() { this.setPreferredSize(new Dimension(Configs.DISPLAY_PANEL_WIDTH, Configs.DISPLAY_PANEL_HEIGHT)); this.setBackground(Color.PINK); } @Override protected void paintComponent(Graphics g) { Graphics2D graphics = (Graphics2D) g; graphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); super.paintComponent(graphics); int[] listNumbers = NumbersList.getList(); double x = 0, width = (double) Configs.DISPLAY_PANEL_WIDTH / listNumbers.length; for(int i = 0; i < listNumbers.length; i++) { if(currentBarIndex == i) graphics.setPaint(Color.RED); else graphics.setPaint(Color.BLACK); graphics.fillRect((int) x, Configs.APPLICATION_HEIGHT - listNumbers[i], (int) width + 1, listNumbers[i]); x += width; } graphics.dispose(); g.dispose(); } }
BubbleSort.java
package sorting_algorithms; import gui_components.GUIComponents; /** * @author Daniel * * Implementation of the bubble sort. */ public class BubbleSort implements SortingAlgorithm { private int delay = GUIComponents.delaySlider.getValue() * 1000; @Override public String getName() { return "Bubble Sort"; } @Override public void doSort(int[] nums) { int n = nums.length; for (int i = 0; i < n - 1; i++) for (int j = 0; j < n - i - 1; j++) if (nums[j] > nums[j + 1]) { int temp = nums[j]; nums[j] = nums[j + 1]; nums[j + 1] = temp; SortingAlgorithm.setCurrentBar(j+1); SortingAlgorithm.sleepFor(delay); } SortingAlgorithm.setCurrentBar(0); } @Override public void changeDelay(int delay) { this.delay = delay; } }
QuickSort.java
package sorting_algorithms; import gui_components.GUIComponents; public class QuickSort implements SortingAlgorithm { private int delay = GUIComponents.delaySlider.getValue() * 1000; @Override public String getName() { return "Quick Sort"; } @Override public void doSort(int[] nums) { sort(nums, 0, nums.length - 1); } private int partition(int nums[], int low, int high) { int pivot = nums[high]; int i = (low - 1); for (int j = low; j < high; j++) { if (nums[j] < pivot) { i++; int temp = nums[i]; nums[i] = nums[j]; nums[j] = temp; SortingAlgorithm.setCurrentBar(j); SortingAlgorithm.sleepFor(delay); } } int temp = nums[i + 1]; nums[i + 1] = nums[high]; nums[high] = temp; return i + 1; } private void sort(int nums[], int low, int high) { if (low < high) { int pi = partition(nums, low, high); sort(nums, low, pi - 1); sort(nums, pi + 1, high); } } @Override public void changeDelay(int delay) { this.delay = delay; } }
SelectionSort.java
package sorting_algorithms; import gui_components.GUIComponents; /** * @author Daniel * * Implementation of the selection sort. */ public class SelectionSort implements SortingAlgorithm { private int delay = GUIComponents.delaySlider.getValue() * 1000; @Override public String getName() { return "Selection Sort"; } @Override public void doSort(int[] nums) { int n = nums.length; for (int i = 0; i < n - 1; i++) { int minIndex = i; for (int j = i + 1; j < n; j++) if (nums[j] < nums[minIndex]) { minIndex = j; SortingAlgorithm.setCurrentBar(i); SortingAlgorithm.setCurrentBar(j); SortingAlgorithm.sleepFor(delay); } int temp = nums[minIndex]; nums[minIndex] = nums[i]; nums[i] = temp; } } @Override public void changeDelay(int delay) { this.delay = delay; } }
InsertionSort.java
package sorting_algorithms; import gui_components.GUIComponents; /** * @author Daniel * * Implementation of the insertion sort. */ public class InsertionSort implements SortingAlgorithm { private int delay = GUIComponents.delaySlider.getValue() * 1000; @Override public String getName() { return "Insertion Sort"; } @Override public void doSort(int[] nums) { int n = nums.length; for (int i = 1; i < n; ++i) { int key = nums[i]; int j = i - 1; while (j >= 0 && nums[j] > key) { nums[j + 1] = nums[j]; j--; } nums[j + 1] = key; SortingAlgorithm.setCurrentBar(j); SortingAlgorithm.sleepFor(delay); } } @Override public void changeDelay(int delay) { this.delay = delay; } }
MergeSort.java
package sorting_algorithms; import gui_components.GUIComponents; public class MergeSort implements SortingAlgorithm { private int delay = GUIComponents.delaySlider.getValue() * 1000; @Override public String getName() { return "Merge Sort"; } @Override public void doSort(int[] nums) { sort(nums, 0, nums.length - 1); } private void merge(int nums[], int l, int m, int r) { int n1 = m - l + 1; int n2 = r - m; int L[] = new int[n1]; int R[] = new int[n2]; for(int i = 0; i < n1; ++i) L[i] = nums[l + i]; for(int j = 0; j < n2; ++j) R[j] = nums[m + 1 + j]; int i = 0, j = 0; int k = l; while (i < n1 && j < n2) { if (L[i] <= R[j]) { nums[k] = L[i]; i++; SortingAlgorithm.setCurrentBar(j); SortingAlgorithm.sleepFor(delay); } else { nums[k] = R[j]; j++; SortingAlgorithm.setCurrentBar(j); SortingAlgorithm.sleepFor(delay); } k++; } while (i < n1) { nums[k] = L[i]; i++; k++; SortingAlgorithm.setCurrentBar(j); SortingAlgorithm.sleepFor(delay); } while (j < n2) { nums[k] = R[j]; j++; k++; SortingAlgorithm.setCurrentBar(j); SortingAlgorithm.sleepFor(delay); } } private void sort(int nums[], int l, int r) { if (l < r) { int m = (l + r) / 2; sort(nums, l, m); sort(nums, m + 1, r); merge(nums, l, m, r); } } @Override public void changeDelay(int delay) { this.delay = delay; } }
SortingAlgorithm.java
package sorting_algorithms; import drawing.PaintSurface; import gui_components.GUIComponents; /** * @author Daniel * * Template for the sorting algorithms. */ public abstract interface SortingAlgorithm { public abstract String getName(); public abstract void doSort(int[] nums); public abstract void changeDelay(int delay); public static void setCurrentBar(int currentBarIndex) { PaintSurface.currentBarIndex = currentBarIndex; } public static void sleepFor(int delay) { long timeElapsed; final long startTime = System.nanoTime(); do { timeElapsed = System.nanoTime() - startTime; } while(timeElapsed < delay); GUIComponents.displayPanel.repaint(); } }
Any helpful recommendations, comments, or suggestions are great. I'm only in high school, so any constructive criticism is nice! Thanks!
interface SortingAlgorithm
are your own design, what was specified beforehand?\$\endgroup\$