├── .gitignore ├── .vscode ├── settings.json └── tasks.json ├── README.md ├── build.gradle ├── settings.gradle └── src └── main ├── java └── sortvisualiser │ ├── MainApp.java │ ├── MidiSoundPlayer.java │ ├── SortArray.java │ ├── Util │ └── Util.java │ ├── algorithms │ ├── BubbleSort.java │ ├── CountingSort.java │ ├── CycleSort.java │ ├── GnomeSort.java │ ├── HeapSort.java │ ├── ISortAlgorithm.java │ ├── InsertionSort.java │ ├── IterativeMergeSort.java │ ├── MergeSort.java │ ├── PancakeSort.java │ ├── QuickSort.java │ ├── RadixSort.java │ ├── SelectionSort.java │ └── StoogeSort.java │ └── screens │ ├── MainMenuScreen.java │ ├── Screen.java │ └── SortingVisualiserScreen.java └── resources └── logo.png /.gitignore: -------------------------------------------------------------------------------- 1 | nbproject/private/ 2 | build/ 3 | nbbuild/ 4 | dist/ 5 | nbdist/ 6 | .nb-gradle/ 7 | .gradle 8 | .vscode/ 9 | gradle-app.setting 10 | !gradle-wrapper.jar 11 | .gradletasknamecache 12 | 13 | bin/ 14 | .settings 15 | .classpath 16 | .project 17 | 18 | .idea/ 19 | out/ -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "java.configuration.updateBuildConfiguration": "disabled" 3 | } -------------------------------------------------------------------------------- /.vscode/tasks.json: -------------------------------------------------------------------------------- 1 | { 2 | // See https://go.microsoft.com/fwlink/?LinkId=733558 3 | // for the documentation about the tasks.json format 4 | "version": "2.0.0", 5 | "tasks": [ 6 | { 7 | "label": "build sorter", 8 | "type": "shell", 9 | "command": "gradle run", 10 | "args": [], 11 | "group": { 12 | "kind": "build", 13 | "isDefault": true 14 | } 15 | } 16 | ] 17 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Sort Algorithm Visualiser 2 | 3 | A simple program to visualise sort algorithms written in java, using Swing for graphics 4 | 5 | ### Build and Run 6 | 7 | ``` 8 | git clone https://github.com/Hopson97/Sort-Algorithm-Visualiser.git 9 | cd Sort-Algorithm-Visualiser 10 | gradle run 11 | ``` 12 | 13 | ### Features 14 | 15 | For now, this just shows a bunch of sorting algorithms, one after the other: 16 | 17 | * Bubble Sort 18 | * Gnome Sort 19 | * Insertion Sort 20 | * Merge Sort 21 | * Quick Sort 22 | * Selection Sort 23 | 24 | ![screenshot](https://i.imgur.com/TMXTcBr.png) 25 | 26 | ### Javadoc 27 | 28 | ``` 29 | git clone https://github.com/Hopson97/Sort-Algorithm-Visualiser.git 30 | cd Sort-Algorithm-Visualiser 31 | gradle javadoc 32 | ``` 33 | Then open **build/docs/javadoc/index.html** file. 34 | 35 | ### Special Thanks 36 | 37 | [sackerm](https://github.com/sackerm) - Improved the rendering code to allow for varying sized windows and other improvements. Also fixed several bugs, such as a white bar appearing at the top of the window when swtiching screens. 38 | 39 | [Wabri/ Gabriele Puliti](https://github.com/Wabri) - Added JavaDocs to lots of places in the code. -------------------------------------------------------------------------------- /build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'java' 2 | apply plugin: 'application' 3 | 4 | sourceCompatibility = '1.8' 5 | [compileJava, compileTestJava]*.options*.encoding = 'UTF-8' 6 | 7 | if (!hasProperty('mainClass')) { 8 | ext.mainClass = 'sortvisualiser.MainApp' 9 | mainClassName = ext.mainClass 10 | } 11 | 12 | repositories { 13 | mavenCentral() 14 | } 15 | 16 | dependencies { 17 | testCompile group: 'junit', name: 'junit', version: '4.10' 18 | } 19 | -------------------------------------------------------------------------------- /settings.gradle: -------------------------------------------------------------------------------- 1 | rootProject.name = 'sortvisualiser' 2 | -------------------------------------------------------------------------------- /src/main/java/sortvisualiser/MainApp.java: -------------------------------------------------------------------------------- 1 | package sortvisualiser; 2 | 3 | import sortvisualiser.screens.MainMenuScreen; 4 | import sortvisualiser.screens.Screen; 5 | import java.util.ArrayList; 6 | import javax.swing.JFrame; 7 | import javax.swing.SwingUtilities; 8 | 9 | /** 10 | * The main application point for controlling the program 11 | * @author Matthew Hopson 12 | */ 13 | public class MainApp { 14 | private final JFrame window; 15 | 16 | public static final int WIN_WIDTH = 1280; 17 | public static final int WIN_HEIGHT = 720; 18 | 19 | private final ArrayList screens; 20 | 21 | public MainApp() { 22 | screens = new ArrayList<>(); 23 | window = new JFrame ("Sort visualiser"); 24 | window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 25 | window.setVisible(true); 26 | } 27 | 28 | public Screen getCurrentScreen() { 29 | return screens.get(screens.size() - 1); 30 | } 31 | 32 | public void pushScreen(Screen screen) { 33 | if (!screens.isEmpty()) { 34 | window.remove(getCurrentScreen()); 35 | } 36 | screens.add(screen); 37 | window.setContentPane(screen); 38 | window.validate(); 39 | screen.onOpen(); 40 | } 41 | 42 | public void popScreen() { 43 | if (!screens.isEmpty()) { 44 | Screen prev = getCurrentScreen(); 45 | screens.remove(prev); 46 | window.remove(prev); 47 | if (!screens.isEmpty()) { 48 | Screen current = getCurrentScreen(); 49 | window.setContentPane(current); 50 | window.validate(); 51 | current.onOpen(); 52 | } 53 | else { 54 | window.dispose(); 55 | } 56 | } 57 | } 58 | 59 | public void start() { 60 | pushScreen(new MainMenuScreen(this)); 61 | window.pack(); 62 | } 63 | 64 | public static void main(String... args) { 65 | System.setProperty("sun.java2d.opengl", "true"); 66 | SwingUtilities.invokeLater(() -> { 67 | new MainApp().start(); 68 | }); 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /src/main/java/sortvisualiser/MidiSoundPlayer.java: -------------------------------------------------------------------------------- 1 | package sortvisualiser; 2 | 3 | import java.util.ArrayList; 4 | import javax.sound.midi.Instrument; 5 | import javax.sound.midi.MidiChannel; 6 | import javax.sound.midi.MidiSystem; 7 | import javax.sound.midi.MidiUnavailableException; 8 | import javax.sound.midi.Synthesizer; 9 | 10 | /** 11 | * 12 | * @author Matthew Hopson 13 | */ 14 | public class MidiSoundPlayer { 15 | private final ArrayList keys; 16 | private Synthesizer synth; 17 | private final MidiChannel channel; 18 | 19 | private final int inputValueMaximum; 20 | private static int CACHED_INDEX = -1; 21 | 22 | public MidiSoundPlayer(int maxValue) { 23 | try { 24 | synth = MidiSystem.getSynthesizer(); 25 | synth.open(); 26 | } catch (MidiUnavailableException ex) { 27 | ex.printStackTrace(); 28 | } 29 | inputValueMaximum = maxValue; 30 | 31 | 32 | //Set up midi channel 33 | channel = synth.getChannels()[0]; 34 | 35 | //Electric grand piano sounds the best, so it tries to find that. 36 | //Sometimes it is not supported, so it defaults to 143 37 | Instrument[] instruments = synth.getDefaultSoundbank().getInstruments(); 38 | if (CACHED_INDEX == - 1) { 39 | boolean found = false; 40 | int index; 41 | for(index = 0; index < instruments.length; index++) { 42 | Instrument i = instruments[index]; 43 | if (i.getName().equals("Electric Grand Piano")) { 44 | found = true; 45 | break; 46 | } 47 | } 48 | if (!found) { 49 | index = 2; 50 | } 51 | CACHED_INDEX = index; 52 | } 53 | 54 | channel.programChange(instruments[CACHED_INDEX].getPatch().getProgram()); 55 | 56 | //Set up keys 57 | keys = new ArrayList<>(); 58 | //24 is the start of the somewhat audible major keys 59 | //108 is the last decent 60 | for (int i = 24; i < 108; i += 12) { 61 | keys.add(i); 62 | keys.add(i + 2); 63 | keys.add(i + 4); 64 | keys.add(i + 5); 65 | keys.add(i + 7); 66 | keys.add(i + 9); 67 | keys.add(i + 11); 68 | } 69 | } 70 | 71 | private int convertToMajor(int v) { 72 | float n = ((float)v / (float)inputValueMaximum); 73 | int index = (int)(n * (float)keys.size()); 74 | index = Math.max(1, Math.min(107, index)); 75 | return keys.get(index); 76 | } 77 | 78 | public void makeSound(int value) { 79 | int note = convertToMajor(value); 80 | channel.noteOn(note, 25); 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /src/main/java/sortvisualiser/SortArray.java: -------------------------------------------------------------------------------- 1 | package sortvisualiser; 2 | 3 | import java.awt.AlphaComposite; 4 | import java.awt.BorderLayout; 5 | import java.awt.Color; 6 | import java.awt.Dimension; 7 | import java.awt.Font; 8 | import java.awt.Graphics; 9 | import java.awt.Graphics2D; 10 | import java.awt.RenderingHints; 11 | import java.awt.image.BufferedImage; 12 | import java.util.Arrays; 13 | import java.util.HashMap; 14 | import java.util.Map; 15 | import java.util.Random; 16 | 17 | import javax.swing.BoxLayout; 18 | import javax.swing.JPanel; 19 | import javax.swing.JSpinner; 20 | import javax.swing.SpinnerNumberModel; 21 | 22 | import sortvisualiser.algorithms.ISortAlgorithm; 23 | 24 | /** 25 | * The array that can be sorted 26 | * 27 | * @author mhops 28 | */ 29 | public class SortArray extends JPanel { 30 | public static final int DEFAULT_WIN_WIDTH = 1280; 31 | public static final int DEFAULT_WIN_HEIGHT = 720; 32 | private static final int DEFAULT_BAR_WIDTH = 5; 33 | /** 34 | * This is the percent of the panel the bars will consume. 35 | * Based on the original 256 bars each being 2x their height 36 | * and 720px window height, or 512/720 37 | */ 38 | private static final double BAR_HEIGHT_PERCENT = 512.0/720.0; 39 | private static final int NUM_BARS = DEFAULT_WIN_WIDTH / DEFAULT_BAR_WIDTH; 40 | 41 | private final int[] array; 42 | private final int[] barColours; 43 | private int spinnerValue = 0; 44 | private String algorithmName = ""; 45 | private ISortAlgorithm algorithm; 46 | private long algorithmDelay = 0; 47 | 48 | private MidiSoundPlayer player; 49 | private JSpinner spinner; 50 | private boolean playSounds; 51 | 52 | private int arrayChanges = 0; // Number of changes to the array the current algorithm has taken so far 53 | 54 | public SortArray(boolean playSounds) { 55 | setBackground(Color.DARK_GRAY); 56 | array = new int[NUM_BARS]; 57 | barColours = new int[NUM_BARS]; 58 | for (int i = 0; i < NUM_BARS; i++) { 59 | array[i] = i; 60 | barColours[i] = 0; 61 | } 62 | player = new MidiSoundPlayer(NUM_BARS); 63 | this.playSounds = playSounds; 64 | spinner = new JSpinner(new SpinnerNumberModel(1, 1, 1000, 1)); 65 | spinner.addChangeListener((event) -> { 66 | algorithmDelay = (Integer) spinner.getValue(); 67 | algorithm.setDelay(algorithmDelay); 68 | }); 69 | add(spinner,BorderLayout.LINE_START); 70 | } 71 | 72 | public int arraySize() { 73 | return array.length; 74 | } 75 | 76 | public int getValue(int index) { 77 | return array[index]; 78 | } 79 | 80 | /** 81 | * Gets the max value of the array or Integer.MIN_VALUE if there isn't one. 82 | * @return the max value or Integer.MIN_VALUE. 83 | */ 84 | public int getMaxValue() { 85 | return Arrays.stream(array).max().orElse(Integer.MIN_VALUE); 86 | } 87 | 88 | private void finaliseUpdate(int value, long millisecondDelay, boolean isStep) { 89 | repaint(); 90 | try { 91 | Thread.sleep(millisecondDelay); 92 | } catch (InterruptedException ex) { 93 | Thread.currentThread().interrupt(); 94 | } 95 | if (playSounds) { 96 | player.makeSound(value); 97 | } 98 | if (isStep) 99 | arrayChanges++; 100 | } 101 | 102 | public void swap(int firstIndex, int secondIndex, long millisecondDelay, boolean isStep) { 103 | int temp = array[firstIndex]; 104 | array[firstIndex] = array[secondIndex]; 105 | array[secondIndex] = temp; 106 | 107 | barColours[firstIndex] = 100; 108 | barColours[secondIndex] = 100; 109 | 110 | finaliseUpdate((array[firstIndex] + array[secondIndex]) / 2, millisecondDelay, isStep); 111 | } 112 | 113 | public void updateSingle(int index, int value, long millisecondDelay, boolean isStep) { 114 | array[index] = value; 115 | barColours[index] = 100; 116 | 117 | 118 | finaliseUpdate(value, millisecondDelay, isStep); 119 | repaint(); 120 | } 121 | 122 | public void shuffle() { 123 | arrayChanges = 0; 124 | Random rng = new Random(); 125 | for (int i = 0; i < arraySize(); i++) { 126 | int swapWithIndex = rng.nextInt(arraySize() - 1); 127 | swap(i, swapWithIndex, 5, false); 128 | } 129 | arrayChanges = 0; 130 | } 131 | 132 | public void highlightArray() { 133 | for (int i = 0; i < arraySize(); i++) { 134 | updateSingle(i, getValue(i), 5, false); 135 | } 136 | } 137 | 138 | /** 139 | * Gets the canvas size 140 | * 141 | * @return size 142 | */ 143 | @Override 144 | public Dimension getPreferredSize() { 145 | return new Dimension(DEFAULT_WIN_WIDTH, DEFAULT_WIN_HEIGHT); 146 | } 147 | 148 | public void resetColours() { 149 | for (int i = 0; i < NUM_BARS; i++) { 150 | barColours[i] = 0; 151 | } 152 | repaint(); 153 | } 154 | 155 | /** 156 | * Draws the array 157 | * 158 | * @param g The graphics device for drawing 159 | */ 160 | @Override 161 | public void paintComponent(Graphics g) { 162 | super.paintComponent(g); 163 | Graphics2D panelGraphics = (Graphics2D) g.create(); 164 | 165 | try 166 | { 167 | Map renderingHints = new HashMap<>(); 168 | renderingHints.put(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); 169 | panelGraphics.addRenderingHints(renderingHints); 170 | panelGraphics.setColor(Color.WHITE); 171 | panelGraphics.setFont(new Font("Monospaced", Font.BOLD, 20)); 172 | panelGraphics.drawString(" Current algorithm: " + algorithmName, 10, 30); 173 | panelGraphics.drawString("Current step delay: " + algorithmDelay + "ms", 10, 55); 174 | panelGraphics.drawString(" Array Changes: " + arrayChanges, 10, 80); 175 | 176 | drawBars(panelGraphics); 177 | } finally { 178 | panelGraphics.dispose(); 179 | } 180 | } 181 | 182 | private void drawBars(Graphics2D panelGraphics) 183 | { 184 | int barWidth = getWidth() / NUM_BARS; 185 | int bufferedImageWidth = barWidth * NUM_BARS; 186 | int bufferedImageHeight = getHeight(); 187 | 188 | if(bufferedImageHeight > 0 && bufferedImageWidth > 0) { 189 | if(bufferedImageWidth < 256) { 190 | bufferedImageWidth = 256; 191 | } 192 | 193 | double maxValue = getMaxValue(); 194 | 195 | BufferedImage bufferedImage = new BufferedImage(bufferedImageWidth, bufferedImageHeight, BufferedImage.TYPE_INT_ARGB); 196 | makeBufferedImageTransparent(bufferedImage); 197 | Graphics2D bufferedGraphics = null; 198 | try 199 | { 200 | bufferedGraphics = bufferedImage.createGraphics(); 201 | 202 | for (int x = 0; x < NUM_BARS; x++) { 203 | double currentValue = getValue(x); 204 | double percentOfMax = currentValue / maxValue; 205 | double heightPercentOfPanel = percentOfMax * BAR_HEIGHT_PERCENT; 206 | int height = (int) (heightPercentOfPanel * (double) getHeight()); 207 | int xBegin = x + (barWidth - 1) * x; 208 | int yBegin = getHeight() - height; 209 | 210 | int val = barColours[x] * 2; 211 | if (val > 190) { 212 | bufferedGraphics.setColor(new Color(255 - val, 255, 255 - val)); 213 | } 214 | else { 215 | bufferedGraphics.setColor(new Color(255, 255 - val, 255 - val)); 216 | } 217 | bufferedGraphics.fillRect(xBegin, yBegin, barWidth, height); 218 | if (barColours[x] > 0) { 219 | barColours[x] -= 5; 220 | } 221 | } 222 | } 223 | finally 224 | { 225 | if(bufferedGraphics != null) 226 | { 227 | bufferedGraphics.dispose(); 228 | } 229 | } 230 | 231 | panelGraphics.drawImage(bufferedImage, 0, 0, getWidth(), getHeight(), 0, 0, bufferedImage.getWidth(), bufferedImage.getHeight(), null); 232 | } 233 | } 234 | 235 | private void makeBufferedImageTransparent(BufferedImage image) 236 | { 237 | Graphics2D bufferedGraphics = null; 238 | try 239 | { 240 | bufferedGraphics = image.createGraphics(); 241 | 242 | bufferedGraphics.setComposite(AlphaComposite.getInstance(AlphaComposite.CLEAR)); 243 | bufferedGraphics.fillRect(0, 0, image.getWidth(), image.getHeight()); 244 | bufferedGraphics.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER)); 245 | } 246 | finally 247 | { 248 | if(bufferedGraphics != null) 249 | { 250 | bufferedGraphics.dispose(); 251 | } 252 | } 253 | } 254 | 255 | @Override 256 | public void setName(String algorithmName) { 257 | this.algorithmName = algorithmName; 258 | } 259 | 260 | public void setAlgorithm(ISortAlgorithm algorithm) { 261 | this.algorithm = algorithm; 262 | algorithmDelay = algorithm.getDelay(); 263 | spinner.setValue((int) algorithm.getDelay()); 264 | } 265 | public long getAlgorithmDelay(){ 266 | return algorithmDelay; 267 | } 268 | } 269 | -------------------------------------------------------------------------------- /src/main/java/sortvisualiser/Util/Util.java: -------------------------------------------------------------------------------- 1 | package sortvisualiser.Util; 2 | 3 | import sortvisualiser.SortArray; 4 | 5 | public class Util { 6 | public static int findMaxValueIndex(SortArray array, int upToIndex) { 7 | int maxIndex = 0; 8 | for (int i = 0; i < upToIndex; i++) { 9 | if (array.getValue(i) > array.getValue(maxIndex)) { 10 | maxIndex = i; 11 | } 12 | } 13 | return maxIndex; 14 | } 15 | } -------------------------------------------------------------------------------- /src/main/java/sortvisualiser/algorithms/BubbleSort.java: -------------------------------------------------------------------------------- 1 | package sortvisualiser.algorithms; 2 | 3 | import sortvisualiser.SortArray; 4 | 5 | /** 6 | * Bubble sort implementation 7 | * 8 | * @author mhops 9 | */ 10 | public class BubbleSort implements ISortAlgorithm { 11 | 12 | private long stepDelay = 2; 13 | /** 14 | * This method implements the bubble sort algorithm, see 15 | * Bubble_sort to understand more. 16 | * Takes a SortArray object called array and sorts his elements according to the mathematical theory 17 | * of the order "less than", see Order_theory to 18 | * understand more. 19 | * 20 | * @param array the array to be sorted 21 | * @see SortArray 22 | */ 23 | @Override 24 | public void runSort(SortArray array) { 25 | int len = array.arraySize(); 26 | for (int i = 0; i < len - 1; i++) { 27 | for (int j = 0; j < len - i - 1; j++) { 28 | if (array.getValue(j) > array.getValue(j + 1)) { 29 | array.swap(j, j + 1, getDelay(), true); 30 | } 31 | } 32 | } 33 | } 34 | 35 | @Override 36 | public String getName() { 37 | return "Bubble Sort"; 38 | } 39 | 40 | @Override 41 | public long getDelay() { 42 | return stepDelay; 43 | } 44 | 45 | @Override 46 | public void setDelay(long delay) { 47 | this.stepDelay = delay; 48 | } 49 | } -------------------------------------------------------------------------------- /src/main/java/sortvisualiser/algorithms/CountingSort.java: -------------------------------------------------------------------------------- 1 | package sortvisualiser.algorithms; 2 | import sortvisualiser.SortArray; 3 | 4 | /** 5 | * Counting Sort implementation 6 | * 7 | * @author Randy Bushman 8 | */ 9 | public class CountingSort implements ISortAlgorithm 10 | { 11 | private long stepDelay = 5; 12 | 13 | @Override 14 | public String getName() 15 | { 16 | return "Counting Sort"; 17 | } 18 | 19 | @Override 20 | public long getDelay() 21 | { 22 | return stepDelay; 23 | } 24 | 25 | @Override 26 | public void setDelay(long delay) 27 | { 28 | stepDelay = delay; 29 | } 30 | 31 | @Override 32 | 33 | /** 34 | * This is an implementation of a stable version of Counting Sort. 35 | * It counts every instance of every number and adds them back in order. 36 | * 37 | * @param array the array to be sorted 38 | */ 39 | public void runSort(SortArray array) 40 | { 41 | int[] result = new int[array.arraySize()]; 42 | int[] count = new int[array.getMaxValue()+1]; 43 | for(int i = 0; i < result.length; ++i) 44 | { 45 | array.updateSingle(i, result[i] = array.getValue(i), getDelay(), false); 46 | ++count[array.getValue(i)]; 47 | } 48 | for(int i = 1; i < count.length; ++i) 49 | count[i] += count[i-1]; 50 | for(int i = result.length-1; i > -1; --i) 51 | array.updateSingle(--count[result[i]], result[i], getDelay(), true); 52 | } 53 | 54 | } 55 | -------------------------------------------------------------------------------- /src/main/java/sortvisualiser/algorithms/CycleSort.java: -------------------------------------------------------------------------------- 1 | package sortvisualiser.algorithms; 2 | 3 | import sortvisualiser.SortArray; 4 | 5 | 6 | public class CycleSort implements ISortAlgorithm { 7 | 8 | private long stepDelay = 125; 9 | private class CycleResult { 10 | public int position; 11 | public boolean cont; 12 | 13 | public CycleResult(int retValue, boolean shouldContinue) { 14 | position = retValue; 15 | cont = shouldContinue; 16 | 17 | } 18 | } 19 | 20 | private CycleResult doCycle(int begin, int position, int value, SortArray array, boolean canFinishEarly) { 21 | position = begin; 22 | for (int i = begin + 1; i < array.arraySize(); i++) { 23 | if (array.getValue(i) < value) { 24 | position++; 25 | } 26 | } 27 | if ((position == begin) && canFinishEarly) return new CycleResult(0, true); 28 | 29 | while (value == array.getValue(position)) { 30 | position++; 31 | } 32 | return new CycleResult(position, false); 33 | } 34 | 35 | @Override 36 | public void runSort(SortArray array) { 37 | int n = array.arraySize(); 38 | for (int begin = 0; begin <= n - 2; begin++) { 39 | int value = array.getValue(begin); 40 | int position = begin; 41 | CycleResult result = doCycle(begin, position, value, array, true); 42 | if (result.cont) continue; 43 | position = result.position; 44 | if (position != begin) { 45 | int t = value; 46 | value = array.getValue(position); 47 | array.updateSingle(position, t, getDelay(), true); 48 | } 49 | while (position != begin) { 50 | position = doCycle(begin, position, value, array, false).position; 51 | if (value != array.getValue(position)) { 52 | int t = value; 53 | value = array.getValue(position); 54 | array.updateSingle(position, t, getDelay(), true); 55 | } 56 | } 57 | } 58 | } 59 | 60 | @Override 61 | public String getName() { 62 | return "Cycle sort"; 63 | } 64 | 65 | @Override 66 | public long getDelay() { 67 | return stepDelay; 68 | } 69 | 70 | @Override 71 | public void setDelay(long delay) { 72 | this.stepDelay = delay; 73 | } 74 | } -------------------------------------------------------------------------------- /src/main/java/sortvisualiser/algorithms/GnomeSort.java: -------------------------------------------------------------------------------- 1 | package sortvisualiser.algorithms; 2 | 3 | import sortvisualiser.SortArray; 4 | 5 | /** 6 | * Gnome sort implementation 7 | * 8 | * @author Matthew Hopson 9 | */ 10 | public class GnomeSort implements ISortAlgorithm { 11 | 12 | private long stepDelay = 2; 13 | /** 14 | * This method implements the gnome sort algorithm, see 15 | * Gnome_sort to understand more. 16 | * Takes a SortArray object called array and sorts his elements according to the mathematical theory 17 | * of the order "less than", see Order_theory to 18 | * understand more. 19 | * 20 | * @param array the array to be sorted 21 | * @see SortArray 22 | */ 23 | @Override 24 | public void runSort(SortArray array) { 25 | int index = 0; 26 | while (index < array.arraySize()) { 27 | if (index == 0) { 28 | index++; 29 | } 30 | if (array.getValue(index) >= array.getValue(index - 1)) { 31 | index++; 32 | } else { 33 | array.swap(index, index - 1, getDelay(), true); 34 | index--; 35 | } 36 | } 37 | } 38 | 39 | @Override 40 | public String getName() { 41 | return "Gnome sort"; 42 | } 43 | 44 | @Override 45 | public long getDelay() { 46 | return stepDelay; 47 | } 48 | 49 | @Override 50 | public void setDelay(long delay) { 51 | this.stepDelay = delay; 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /src/main/java/sortvisualiser/algorithms/HeapSort.java: -------------------------------------------------------------------------------- 1 | package sortvisualiser.algorithms; 2 | 3 | import sortvisualiser.SortArray; 4 | 5 | 6 | public class HeapSort implements ISortAlgorithm { 7 | 8 | private long stepDelay = 20; 9 | 10 | private boolean isChildLargerThanRoot(int child, int largest, int n, SortArray array) { 11 | return child < n && array.getValue(child) > array.getValue(largest); 12 | } 13 | 14 | private void toBinaryTreeArray(SortArray array, int n, int rootIndex) { 15 | int largest = rootIndex; 16 | int leftChild = 2 * rootIndex + 1; 17 | int rightChild = 2 * rootIndex + 2; 18 | 19 | if (isChildLargerThanRoot(leftChild, largest, n, array)) { 20 | largest = leftChild; 21 | } 22 | if (isChildLargerThanRoot(rightChild, largest, n, array)) { 23 | largest = rightChild; 24 | } 25 | if (largest != rootIndex) { 26 | array.swap(rootIndex, largest, getDelay(), true); 27 | toBinaryTreeArray(array, n, largest); 28 | } 29 | } 30 | 31 | 32 | @Override 33 | public void runSort(SortArray array) { 34 | int n = array.arraySize(); 35 | for (int i = n / 2 - 1; i >= 0; i--) { 36 | toBinaryTreeArray(array, n, i); 37 | } 38 | for (int i = n - 1; i >= 0; i--) { 39 | array.swap(0, i, getDelay(), true); 40 | toBinaryTreeArray(array, i, 0); 41 | } 42 | } 43 | 44 | @Override 45 | public String getName() { 46 | return "Heap sort"; 47 | } 48 | 49 | @Override 50 | public long getDelay() { 51 | return stepDelay; 52 | } 53 | 54 | @Override 55 | public void setDelay(long delay) { 56 | this.stepDelay = delay; 57 | } 58 | } -------------------------------------------------------------------------------- /src/main/java/sortvisualiser/algorithms/ISortAlgorithm.java: -------------------------------------------------------------------------------- 1 | package sortvisualiser.algorithms; 2 | 3 | import sortvisualiser.SortArray; 4 | 5 | /** 6 | * Base interface for the sort algorithms 7 | * 8 | * @author Matt Hopson 9 | */ 10 | public interface ISortAlgorithm { 11 | public String getName(); 12 | 13 | public long getDelay(); 14 | 15 | public void setDelay(long delay); 16 | 17 | public void runSort(SortArray array); 18 | } 19 | -------------------------------------------------------------------------------- /src/main/java/sortvisualiser/algorithms/InsertionSort.java: -------------------------------------------------------------------------------- 1 | package sortvisualiser.algorithms; 2 | 3 | import sortvisualiser.SortArray; 4 | 5 | /** 6 | * Insertion sort implementation 7 | * 8 | * @author Matthew Hopson 9 | */ 10 | public class InsertionSort implements ISortAlgorithm { 11 | 12 | private long stepDelay = 1; 13 | /** 14 | * This method implements the insertion sort algorithm, see 15 | * Insertion_sort to understand more. 16 | * Takes a SortArray object called array and sorts his elements according to the mathematical theory 17 | * of the order "less than", see Order_theory to 18 | * understand more. 19 | * 20 | * @param array the array to be sorted 21 | * @see SortArray 22 | */ 23 | @Override 24 | public void runSort(SortArray array) { 25 | for (int i = 0; i < array.arraySize(); i++) { 26 | int key = array.getValue(i); 27 | int j = i - 1; 28 | while (j >= 0 && array.getValue(j) > key) { 29 | array.updateSingle(j + 1, array.getValue(j), 5, true); 30 | j--; 31 | } 32 | array.updateSingle(j + 1, key, getDelay(), true); 33 | } 34 | } 35 | 36 | @Override 37 | public String getName() { 38 | return "Insertion Sort"; 39 | } 40 | 41 | @Override 42 | public long getDelay() { 43 | return stepDelay; 44 | } 45 | 46 | @Override 47 | public void setDelay(long delay) { 48 | this.stepDelay = delay; 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /src/main/java/sortvisualiser/algorithms/IterativeMergeSort.java: -------------------------------------------------------------------------------- 1 | package sortvisualiser.algorithms; 2 | import sortvisualiser.SortArray; 3 | 4 | /** 5 | * Iterative Merge sort implementation 6 | * 7 | * @author Randy Bushman 8 | */ 9 | public class IterativeMergeSort implements ISortAlgorithm 10 | { 11 | private long stepDelay = 5; 12 | 13 | /** 14 | * This is an implementation of Merge Sort using Iteration instead of Recursion. 15 | * It works by splitting the array into small subsequences. These subsequences are 16 | * then merged into larger sorted arrays. In the end, there will be one big sorted array. 17 | * @param array the array to be sorted 18 | * @see SortArray 19 | */ 20 | @Override 21 | public void runSort(SortArray array) 22 | { 23 | for(int exp = 1; exp < array.arraySize(); exp <<= 1) 24 | for(int k = 0, j = exp+exp, s = array.arraySize()-exp; kMerge_sort to understand more. 77 | * The method takes a SortArray object called array and sorts his elements according to the mathematical theory 78 | * of the order "less than", see Order_theory to 79 | * understand more. 80 | * Recursion was adopted for simplicity 81 | * 82 | * @param array the array to be sorted 83 | * @param left the left index of the array 84 | * @param right the right index of the array 85 | * @see SortArray 86 | */ 87 | private void mergeSort(SortArray array, int left, int right) { 88 | if (left < right) { 89 | int middleIndex = (left + right) / 2; 90 | 91 | mergeSort(array, left, middleIndex); 92 | mergeSort(array, middleIndex + 1, right); 93 | merge(array, left, middleIndex, right); 94 | } 95 | } 96 | 97 | /** 98 | * This is the method that call the first instance of mergeSort. 99 | * Merge sort is a "divide and conquer" algorithm, it works by splitting the array into tiny sections 100 | * sorting them indivually, and then finally merges it back together, see 101 | * Merge_sort to understand more. 102 | * The method takes a SortArray object called array and sorts his elements according to the mathematical theory 103 | * of the order "less than", see Order_theory to 104 | * understand more. 105 | * 106 | * @param array the array to be sorted 107 | * @see SortArray 108 | */ 109 | @Override 110 | public void runSort(SortArray array) { 111 | int left = 0; 112 | int right = array.arraySize() - 1; 113 | mergeSort(array, left, right); 114 | } 115 | 116 | @Override 117 | public String getName() { 118 | return "Merge Sort"; 119 | } 120 | 121 | @Override 122 | public long getDelay() { 123 | return stepDelay; 124 | } 125 | 126 | @Override 127 | public void setDelay(long delay) { 128 | this.stepDelay = delay; 129 | } 130 | } 131 | -------------------------------------------------------------------------------- /src/main/java/sortvisualiser/algorithms/PancakeSort.java: -------------------------------------------------------------------------------- 1 | package sortvisualiser.algorithms; 2 | 3 | import sortvisualiser.SortArray; 4 | import sortvisualiser.Util.Util; 5 | 6 | public class PancakeSort implements ISortAlgorithm { 7 | private long stepDelay = 1 8 | ; 9 | private void flip(SortArray array, int i) { 10 | for (int j = 0; j < i; j++, i--) { 11 | array.swap(i, j, getDelay(), true); 12 | } 13 | } 14 | 15 | @Override 16 | public void runSort(SortArray array) { 17 | for (int i = array.arraySize(); i > 1; i--) { 18 | int maxValueIndex = Util.findMaxValueIndex(array, i); 19 | if (maxValueIndex != i - 1) { 20 | flip(array, maxValueIndex); 21 | flip(array, i - 1); 22 | } 23 | } 24 | } 25 | 26 | @Override 27 | public String getName() { 28 | return "Pancake sort"; 29 | } 30 | 31 | @Override 32 | public long getDelay() { 33 | return stepDelay; 34 | } 35 | 36 | @Override 37 | public void setDelay(long delay) { 38 | this.stepDelay = delay; 39 | } 40 | } -------------------------------------------------------------------------------- /src/main/java/sortvisualiser/algorithms/QuickSort.java: -------------------------------------------------------------------------------- 1 | package sortvisualiser.algorithms; 2 | 3 | import sortvisualiser.SortArray; 4 | 5 | /** 6 | * Quick sort implementation 7 | * 8 | * @author mhops 9 | */ 10 | public class QuickSort implements ISortAlgorithm { 11 | 12 | private long stepDelay = 30; 13 | /** 14 | * This is where the magic of quick sort append. 15 | * 16 | * @param array this is the array to cut and merge 17 | * @param lowIndex the most left index of the array 18 | * @param highIndex the most right index of the array 19 | * @see SortArray 20 | */ 21 | private int findPivotPoint(SortArray array, int lowIndex, int highIndex) { 22 | int pivotValue = array.getValue(highIndex); 23 | int i = lowIndex - 1; 24 | for (int j = lowIndex; j <= highIndex - 1; j++) { 25 | if (array.getValue(j) <= pivotValue) { 26 | i++; 27 | array.swap(i, j, getDelay(), true); 28 | } 29 | } 30 | array.swap(i + 1, highIndex, getDelay(), true); 31 | return i + 1; 32 | } 33 | 34 | /** 35 | * This is the core of the algorithm quick sort. 36 | * 37 | * @param array this is the array to cut and merge 38 | * @param lowIndex the most left index of the array 39 | * @param highIndex the most right index of the array 40 | * @see SortArray 41 | */ 42 | private void quickSort(SortArray array, int lowIndex, int highIndex) { 43 | if (lowIndex < highIndex) { 44 | int pivotPoint = findPivotPoint(array, lowIndex, highIndex); 45 | quickSort(array, lowIndex, pivotPoint - 1); 46 | quickSort(array, pivotPoint + 1, highIndex); 47 | } 48 | } 49 | 50 | /** 51 | * This is the method that call the first instance of quickSort, see 52 | * Quicksort to understand more. 53 | * The method takes a SortArray object called array and sorts his elements according to the mathematical theory 54 | * of the order "less than", see Order_theory to 55 | * understand more. 56 | * 57 | * @param array the array to be sorted 58 | * @see SortArray 59 | */ 60 | @Override 61 | public void runSort(SortArray array) { 62 | quickSort(array, 0, array.arraySize() - 1); 63 | } 64 | 65 | @Override 66 | public String getName() { 67 | return "Quick Sort"; 68 | } 69 | 70 | @Override 71 | public long getDelay() { 72 | return stepDelay; 73 | } 74 | 75 | @Override 76 | public void setDelay(long delay) { 77 | this.stepDelay = delay; 78 | } 79 | 80 | } 81 | -------------------------------------------------------------------------------- /src/main/java/sortvisualiser/algorithms/RadixSort.java: -------------------------------------------------------------------------------- 1 | package sortvisualiser.algorithms; 2 | import java.util.Arrays; 3 | import sortvisualiser.SortArray; 4 | 5 | /** 6 | * Radix sort implementation 7 | * 8 | * @author Randy Bushman 9 | */ 10 | public class RadixSort implements ISortAlgorithm { 11 | 12 | private long stepDelay = 5; 13 | private int radix; 14 | private int[] countingArr; 15 | 16 | /** 17 | * @param radix The number system that you wish to work in. Must be greater than zero. 18 | */ 19 | public RadixSort(int radix) 20 | { 21 | this.radix = radix; 22 | countingArr = new int[radix]; 23 | } 24 | 25 | /** 26 | * Sets Radix to 10 by default. 27 | */ 28 | public RadixSort() 29 | { 30 | this(10); 31 | } 32 | 33 | /** 34 | * This is the method that call the first instance of Radix Sort. 35 | * Radix Sort is a non comparison based algorithm that uses counting sort as a subroutine. 36 | * It works by sorting by the least significant digit from smallest to largest. It then 37 | * sorts the next least significant digit and so on. We are not limited to the decimal number 38 | * system however. We can sort in Hex, Binary, etc; hence the name Radix Sort. 39 | * 40 | * @param array the array to be sorted 41 | * @see SortArray 42 | */ 43 | @Override 44 | public void runSort(SortArray array) 45 | { 46 | int largest = array.getMaxValue(); 47 | int[] result = new int[array.arraySize()]; 48 | 49 | for(int exp = 1; largest/exp > 0; exp *= radix) //in real life if Radix was 2, then we would bit shift. 50 | { 51 | countingArr = countingSort(array, exp); 52 | 53 | for(int i = 0; i < result.length; ++i) 54 | array.updateSingle(i, result[i] = array.getValue(i), getDelay(), false); 55 | 56 | for(int i = 1; i < radix; ++i) 57 | countingArr[i] += countingArr[i-1]; 58 | 59 | for(int i = array.arraySize() - 1; i > -1 ; --i) 60 | array.updateSingle(--countingArr[(result[i]/exp)%radix], result[i], getDelay(), true); 61 | } 62 | } 63 | 64 | /** 65 | * Performs a Counting Sort subroutine 66 | * @param arr The array being sorted 67 | * @param exp The current exponent 68 | * @return A counting array that gives new indices to all values 69 | */ 70 | private int[] countingSort(SortArray arr, int exp) 71 | { 72 | Arrays.fill(countingArr, 0); 73 | for(int i = 0; i < arr.arraySize(); ++i) 74 | countingArr[(arr.getValue(i)/exp)%radix]++; 75 | return countingArr; 76 | } 77 | 78 | @Override 79 | public String getName() { 80 | return "Radix Sort (Base " + radix + ")"; 81 | } 82 | 83 | @Override 84 | public long getDelay() { 85 | return stepDelay; 86 | } 87 | 88 | @Override 89 | public void setDelay(long delay) { 90 | this.stepDelay = delay; 91 | } 92 | } 93 | -------------------------------------------------------------------------------- /src/main/java/sortvisualiser/algorithms/SelectionSort.java: -------------------------------------------------------------------------------- 1 | package sortvisualiser.algorithms; 2 | 3 | import sortvisualiser.SortArray; 4 | 5 | /** 6 | * Selection sort implementation 7 | * 8 | * @author Matt Hopson 9 | */ 10 | public class SelectionSort implements ISortAlgorithm { 11 | 12 | private long stepDelay = 120; 13 | /** 14 | * This method implements the Selection sort algorithm, see 15 | * Selection_sort to understand more. 16 | * Takes a SortArray object called array and sorts his elements according to the mathematical theory 17 | * of the order "less than", see Order_theory to 18 | * understand more. 19 | * 20 | * @param array the array to be sorted 21 | * @see SortArray 22 | */ 23 | @Override 24 | public void runSort(SortArray array) { 25 | int len = array.arraySize(); 26 | for (int i = 0; i < len - 1; i++) { 27 | int minIndex = i; 28 | for (int j = i + 1; j < len; j++) { 29 | if (array.getValue(j) < array.getValue(minIndex)) { 30 | minIndex = j; 31 | } 32 | } 33 | array.swap(i, minIndex, getDelay(), true); 34 | } 35 | } 36 | 37 | @Override 38 | public String getName() { 39 | return "Selection Sort"; 40 | } 41 | 42 | @Override 43 | public long getDelay() { 44 | return stepDelay; 45 | } 46 | 47 | @Override 48 | public void setDelay(long delay) { 49 | this.stepDelay = delay; 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /src/main/java/sortvisualiser/algorithms/StoogeSort.java: -------------------------------------------------------------------------------- 1 | package sortvisualiser.algorithms; 2 | 3 | import sortvisualiser.SortArray; 4 | 5 | 6 | public class StoogeSort implements ISortAlgorithm { 7 | 8 | private long stepDelay = 5; 9 | public void stoogeSort(SortArray array, int lowIndex, int highIndex) { 10 | if (lowIndex >= highIndex) { 11 | return; 12 | } 13 | if (array.getValue(lowIndex) > array.getValue(highIndex)) { 14 | array.swap(lowIndex, highIndex, getDelay(), true); 15 | } 16 | 17 | if (highIndex - lowIndex + 1 > 2) { 18 | int t = (highIndex - lowIndex + 1) / 3; 19 | stoogeSort(array, lowIndex, highIndex - t); 20 | stoogeSort(array, lowIndex + t, highIndex); 21 | stoogeSort(array, lowIndex, highIndex - t); 22 | } 23 | } 24 | 25 | @Override 26 | public void runSort(SortArray array) { 27 | stoogeSort(array, 0, array.arraySize() - 1); 28 | } 29 | 30 | @Override 31 | public String getName() { 32 | return "Stooge sort"; 33 | } 34 | 35 | @Override 36 | public long getDelay() { 37 | return stepDelay; 38 | } 39 | 40 | @Override 41 | public void setDelay(long delay) { 42 | this.stepDelay = delay; 43 | } 44 | } -------------------------------------------------------------------------------- /src/main/java/sortvisualiser/screens/MainMenuScreen.java: -------------------------------------------------------------------------------- 1 | package sortvisualiser.screens; 2 | 3 | import java.awt.CheckboxGroup; 4 | import java.awt.Color; 5 | import java.awt.Component; 6 | import java.awt.Dimension; 7 | import java.awt.event.ActionEvent; 8 | import java.awt.image.BufferedImage; 9 | import java.io.File; 10 | import java.io.IOException; 11 | import java.util.ArrayList; 12 | 13 | import javax.imageio.ImageIO; 14 | import javax.swing.Box; 15 | import javax.swing.BoxLayout; 16 | import javax.swing.ImageIcon; 17 | import javax.swing.JButton; 18 | import javax.swing.JCheckBox; 19 | import javax.swing.JLabel; 20 | import javax.swing.JPanel; 21 | 22 | import sortvisualiser.MainApp; 23 | import sortvisualiser.algorithms.*; 24 | 25 | 26 | /** 27 | * 28 | * @author Matthew Hopson 29 | */ 30 | public final class MainMenuScreen extends Screen { 31 | private static final Color BACKGROUND_COLOUR = Color.DARK_GRAY; 32 | private final ArrayList checkBoxes; 33 | 34 | public MainMenuScreen(MainApp app) { 35 | super(app); 36 | checkBoxes = new ArrayList<>(); 37 | setUpGUI(); 38 | } 39 | 40 | private void addCheckBox(ISortAlgorithm algorithm, JPanel panel) { 41 | JCheckBox box = new JCheckBox("", true); 42 | box.setAlignmentX(Component.LEFT_ALIGNMENT); 43 | box.setBackground(BACKGROUND_COLOUR); 44 | box.setForeground(Color.WHITE); 45 | checkBoxes.add(new AlgorithmCheckBox(algorithm, box)); 46 | panel.add(box); 47 | } 48 | 49 | private void initContainer(JPanel p) { 50 | p.setLayout(new BoxLayout(p, BoxLayout.PAGE_AXIS)); 51 | p.setBackground(BACKGROUND_COLOUR); 52 | //p.setBorder(BorderFactory.createLineBorder(Color.WHITE)); 53 | } 54 | 55 | public void setUpGUI() { 56 | JPanel sortAlgorithmContainer = new JPanel(); 57 | JPanel optionsContainer = new JPanel(); 58 | JPanel outerContainer = new JPanel(); 59 | initContainer(this); 60 | initContainer(optionsContainer); 61 | initContainer(sortAlgorithmContainer); 62 | 63 | outerContainer.setBackground(BACKGROUND_COLOUR); 64 | outerContainer.setLayout(new BoxLayout(outerContainer, BoxLayout.LINE_AXIS)); 65 | 66 | try { 67 | ClassLoader loader = getClass().getClassLoader(); 68 | BufferedImage image = ImageIO.read(new File(loader.getResource("logo.png").getFile())); 69 | JLabel label = new JLabel(new ImageIcon(image)); 70 | label.setAlignmentX(Component.CENTER_ALIGNMENT); 71 | add(label); 72 | } catch (IOException e) { 73 | System.out.println("Unable to load logo"); 74 | } 75 | 76 | sortAlgorithmContainer.setAlignmentX(Component.CENTER_ALIGNMENT); 77 | addCheckBox(new BubbleSort(), sortAlgorithmContainer); 78 | addCheckBox(new SelectionSort(), sortAlgorithmContainer); 79 | addCheckBox(new CycleSort(), sortAlgorithmContainer); 80 | addCheckBox(new StoogeSort(), sortAlgorithmContainer); 81 | addCheckBox(new QuickSort(), sortAlgorithmContainer); 82 | addCheckBox(new PancakeSort(), sortAlgorithmContainer); 83 | addCheckBox(new MergeSort(), sortAlgorithmContainer); 84 | addCheckBox(new InsertionSort(), sortAlgorithmContainer); 85 | addCheckBox(new HeapSort(), sortAlgorithmContainer); 86 | addCheckBox(new GnomeSort(), sortAlgorithmContainer); 87 | addCheckBox(new CountingSort(), sortAlgorithmContainer); 88 | addCheckBox(new RadixSort(), sortAlgorithmContainer); 89 | addCheckBox(new IterativeMergeSort(), sortAlgorithmContainer); 90 | 91 | JCheckBox soundCheckBox = new JCheckBox("Play Sounds"); 92 | soundCheckBox.setAlignmentX(Component.LEFT_ALIGNMENT); 93 | soundCheckBox.setBackground(BACKGROUND_COLOUR); 94 | soundCheckBox.setForeground(Color.WHITE); 95 | 96 | optionsContainer.add(soundCheckBox); 97 | 98 | JButton startButton = new JButton("Begin Visual Sorter"); 99 | startButton.addActionListener((ActionEvent e) -> { 100 | ArrayList algorithms = new ArrayList<>(); 101 | for (AlgorithmCheckBox cb : checkBoxes) { 102 | if (cb.isSelected()) { 103 | algorithms.add(cb.getAlgorithm()); 104 | } 105 | } 106 | app.pushScreen( 107 | new SortingVisualiserScreen( 108 | algorithms, 109 | soundCheckBox.isSelected(), 110 | app 111 | )); 112 | }); 113 | startButton.setAlignmentX(Component.CENTER_ALIGNMENT); 114 | 115 | outerContainer.add(optionsContainer); 116 | outerContainer.add(Box.createRigidArea(new Dimension(5,0))); 117 | outerContainer.add(sortAlgorithmContainer); 118 | 119 | int gap = 15; 120 | add(Box.createRigidArea(new Dimension(0, gap))); 121 | add(outerContainer); 122 | add(Box.createRigidArea(new Dimension(0, gap))); 123 | add(startButton); 124 | } 125 | 126 | @Override 127 | public void onOpen() { 128 | checkBoxes.forEach((box) -> { 129 | box.unselect(); 130 | 131 | }); 132 | 133 | } 134 | 135 | private class AlgorithmCheckBox { 136 | private final ISortAlgorithm algorithm; 137 | private final JCheckBox box; 138 | 139 | public AlgorithmCheckBox(ISortAlgorithm algorithm, JCheckBox box) { 140 | this.algorithm = algorithm; 141 | this.box = box; 142 | this.box.setText(algorithm.getName()); 143 | } 144 | 145 | public void unselect() { 146 | box.setSelected(false); 147 | } 148 | 149 | 150 | public boolean isSelected() { 151 | return box.isSelected(); 152 | } 153 | 154 | public ISortAlgorithm getAlgorithm() { 155 | return algorithm; 156 | } 157 | } 158 | 159 | } 160 | -------------------------------------------------------------------------------- /src/main/java/sortvisualiser/screens/Screen.java: -------------------------------------------------------------------------------- 1 | package sortvisualiser.screens; 2 | 3 | import static sortvisualiser.MainApp.WIN_HEIGHT; 4 | import static sortvisualiser.MainApp.WIN_WIDTH; 5 | 6 | import java.awt.Dimension; 7 | 8 | import javax.swing.JPanel; 9 | 10 | import sortvisualiser.MainApp; 11 | 12 | /** 13 | * 14 | * @author mhops 15 | */ 16 | public abstract class Screen extends JPanel { 17 | protected MainApp app; 18 | 19 | public Screen(MainApp app) { 20 | this.app = app; 21 | } 22 | 23 | @Override 24 | public Dimension getPreferredSize() { 25 | return new Dimension(WIN_WIDTH, WIN_HEIGHT); 26 | } 27 | 28 | public abstract void onOpen(); 29 | } 30 | -------------------------------------------------------------------------------- /src/main/java/sortvisualiser/screens/SortingVisualiserScreen.java: -------------------------------------------------------------------------------- 1 | package sortvisualiser.screens; 2 | 3 | import java.awt.BorderLayout; 4 | import java.util.ArrayList; 5 | 6 | import javax.swing.JSpinner; 7 | import javax.swing.SpinnerNumberModel; 8 | import javax.swing.SwingWorker; 9 | import sortvisualiser.MainApp; 10 | import sortvisualiser.SortArray; 11 | import sortvisualiser.algorithms.ISortAlgorithm; 12 | 13 | /** 14 | * The main class for the sort visualiser GUI 15 | * 16 | * @author Matt Hopson 17 | */ 18 | public final class SortingVisualiserScreen extends Screen { 19 | private final SortArray sortArray; 20 | private final ArrayList sortQueue; 21 | 22 | /** 23 | * Creates the GUI 24 | * @param algorithms List of algorithms to run for visualisation 25 | * @param playSounds Whether or not you want the algorithm to play sounds 26 | * @param app The main application 27 | */ 28 | public SortingVisualiserScreen(ArrayList algorithms, boolean playSounds, MainApp app) { 29 | super(app); 30 | setLayout(new BorderLayout()); 31 | sortArray = new SortArray(playSounds); 32 | add(sortArray, BorderLayout.CENTER); 33 | sortQueue = algorithms; 34 | } 35 | 36 | private void longSleep() { 37 | try { 38 | Thread.sleep(1000); 39 | } catch (InterruptedException ex) { 40 | ex.printStackTrace(); 41 | } 42 | } 43 | 44 | private void shuffleAndWait() { 45 | sortArray.shuffle(); 46 | sortArray.resetColours(); 47 | longSleep(); 48 | } 49 | 50 | public void onOpen() { 51 | //This would block the EventDispatchThread, and so 52 | //it must run on a worker thread 53 | SwingWorker swingWorker = new SwingWorker() { 54 | @Override 55 | protected Void doInBackground() throws Exception { 56 | try { 57 | Thread.sleep(250); 58 | } catch (InterruptedException ex) { 59 | ex.printStackTrace(); 60 | } 61 | for (ISortAlgorithm algorithm : sortQueue) { 62 | shuffleAndWait(); 63 | 64 | sortArray.setName(algorithm.getName()); 65 | sortArray.setAlgorithm(algorithm); 66 | 67 | algorithm.runSort(sortArray); 68 | sortArray.resetColours(); 69 | sortArray.highlightArray(); 70 | sortArray.resetColours(); 71 | longSleep(); 72 | } 73 | return null; 74 | } 75 | 76 | @Override 77 | public void done() { 78 | app.popScreen(); 79 | } 80 | }; 81 | 82 | swingWorker.execute(); 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /src/main/resources/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Hopson97/Sort-Algorithm-Visualiser/4940d5d70578c9878b9cf6d54aea999506223932/src/main/resources/logo.png --------------------------------------------------------------------------------