0

I have been learning about arrays and an interesting question popped up in my head.

I was wondering that with the current Java version, is there a way for me to print a character string n and make it appear for a brief moment at every index of an array consisting of only "", and then towards the end of the array, it can stop when it reaches the end index of the array.

For example if here is the given array and string n = "2" :

[2,"","","",""]

the code will continously update like

["2","","","",""]
["","2","","",""]
["","","2","",""]
["","","","2",""]
["","","","","2"]

and the end result would be

["","","","","2"]

I would like to see the whole movement of "2" being played out without printing any excess arrays ( no more than one array should be in the output).

Is this possible? If yes, can you please suggest what should I look over to learn how to do this?

Stephen C
  • 698,415
  • 94
  • 811
  • 1,216
Droid
  • 520
  • 1
  • 7
  • In java you can not have arrays of different datatypes (in this case int and String). You could however have the 2 be in a string so ["2","","","",""] or [String.valueOf(n), "","","",""]. If I then I understood your question correctly, to make the "2" move across you just need to swap values. So index 0 is swapped with index 1, then 1 with 2 etc, until you are at the end. – George R Nov 13 '22 at 08:27
  • I meant "string n". Sorry for the confusion. Also, would your approach display the movement of the string "2" though. I would like to know if that is possible in Java. – Droid Nov 13 '22 at 08:41
  • Yes it is possible to do simple animations, but it depends on the capabilities of the terminal / console you are writing the output to. Leads: https://stackoverflow.com/questions/439799 and google for "ansi escape codes" . – Stephen C Nov 13 '22 at 09:00
  • For simple one-line animations you may be able to use a combination of "backspace" and "carriage return" characters to overwrite the current line. (It depends on the console's behavior.) – Stephen C Nov 13 '22 at 09:04

3 Answers3

0

You can do this with Java but you won't be able to do it reliably within all consoles or terminals. You can however do it reliably if you utilize a GUI mechanism like a JOptionPane or JDialog and display that during console operation, for example:

enter image description here

The above example is a JDialog. Below is the code (read comments within):

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.geom.Rectangle2D;
import java.util.Arrays;
import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.Timer;


public class AnimatedMoveArrayElementDemo {

    /* Default. The length of the Array to animate.
       Can be changed via command-line (/L:n) argument.   */
    private int lengthOfArray = 8;
    
    /* Default. The Array value to move from beginning to end.
       Can be changed via command-line (/N:n) argument.   */
    private int arrayValueToMove = 2;
    
    /* In Milliseconds (1000 = 1 Second).
       Can be changed via command-line (/S:n) argument.   */
    private int animationSpeed = 1000;
    
    /* Default. The dialog display font size.
       Can be changed via command-line (/F:n) argument.   */
   private int displayFontSize = 24;
    
    private String[] stringArray = {}; 
    int arrayIndex = 0;

    Timer animationTimer;
    JButton startButton;
    JLabel arrayLabel;

    
    public static void main(String[] args) {
        // App started this way to avoid the need for statics
        new AnimatedMoveArrayElementDemo().startApp(args);
    }

    private void startApp(String[] args) {
        if (args.length > 0) {
            readCommandLineArguments(args);
        }
        
        fillArray();
        createAndShowDialog();
    }

    private void createAndShowDialog() {
        JDialog dialog = new JDialog();
        dialog.setTitle("Moving Array Element To The End Position");
        dialog.setBackground(Color.white);
        dialog.getContentPane().setBackground(Color.white);
        
        dialog.setAlwaysOnTop(true);
        dialog.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
        dialog.setModal(true);

        arrayLabel = new JLabel();
        resetDisplayLabel();
        arrayLabel.setOpaque(false);
        arrayLabel.setHorizontalAlignment(JLabel.CENTER);
        arrayLabel.setVerticalAlignment(JLabel.CENTER);
        arrayLabel.setFont(new Font(arrayLabel.getFont().getFamily(), 
                                    arrayLabel.getFont().getStyle(), displayFontSize));
        dialog.add(arrayLabel, BorderLayout.NORTH);

        int calculatedWidth = getStringPixelWidth(arrayLabel.getFont(), 
                                      arrayLabel.getText().replaceAll("<.+?>", "")) + 50;
        int calculatedHeight = getStringPixelHeight(arrayLabel.getFont(), 
                                      arrayLabel.getText().replaceAll("<.+?>", "")) + 100;
        dialog.setPreferredSize(new Dimension(calculatedWidth, calculatedHeight));
        
        JPanel buttonPanel = new JPanel();
        buttonPanel.setOpaque(false);
        startButton = new JButton("Start Animation");
        startButton.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                if (e.getActionCommand().equals("Start Animation"))  {
                    if (arrayIndex > stringArray.length - 1) {
                        resetDisplayLabel();
                        arrayIndex = 0;
                    }
                    startButton.setActionCommand("Stop Animation");
                    // Using a Swing Timer...for animation
                    ActionListener performTask = new ActionListener() {
                        @Override
                        public void actionPerformed(ActionEvent evt) {
                            arrayIndex++;
                            if (arrayIndex > stringArray.length - 1) {
                                animationTimer.stop();
                                startButton.setText("Restart Animation");
                                startButton.setActionCommand("Start Animation");
                                return;
                            }
                            stringArray[arrayIndex - 1] = "\"\"";
                            stringArray[arrayIndex] = String.valueOf(arrayValueToMove);
                            String arrayString = "<html>" + Arrays.toString(stringArray) + "</html>";
                            arrayString = arrayString.replace(String.valueOf(arrayValueToMove),
                                    "\"<font color=red>" + String.valueOf(arrayValueToMove)
                                    + "</font>\"");
                            arrayLabel.setText(arrayString);
                        }
                    };
                    animationTimer = new Timer(animationSpeed, performTask);
                    animationTimer.start();
                    startButton.setText("Stop Animation");
                }
                else {
                    animationTimer.stop();
                    startButton.setText("Start Animation");
                    startButton.setActionCommand("Start Animation");
                }
            }

        });
        buttonPanel.add(startButton);
        dialog.add(buttonPanel, BorderLayout.SOUTH);

        dialog.pack();
        dialog.setLocationRelativeTo(null);
        
        java.awt.EventQueue.invokeLater(() -> {
            dialog.setVisible(true);
        });
        
    }
    
    private void fillArray() {
        stringArray = new String[lengthOfArray];
        for (int i = 0; i < stringArray.length; i++) {
            if (i == 0) {
                stringArray[i] = "\"" + arrayValueToMove + "\"";
            }
            else {
                stringArray[i] = "\"\"";
            }
        }
    }
    
    private void resetDisplayLabel() {
        fillArray();
        String arrayString = "<html>" + Arrays.toString(stringArray) + "</html>";
        arrayString = arrayString.replace(String.valueOf(arrayValueToMove),
                "<font color=red>" + String.valueOf(arrayValueToMove)
                + "</font>");
        
        arrayLabel.setText(arrayString);
    }

    /**
     * This application can currently accept four specific integer command-line 
     * arguments prefixed with a specific Command related to that argument.
     * 
     * @param args (Command-Line varArgs [optional])<pre>
     * 
     *   Length Of Array:     The length (# of elements) of the String[] Array 
     *                        to animate. The longer the array the smaller the
     *    Command: /L         font size you <u>may</u> want to use so to fit the array
     *                        into the display window. The display window will 
     *                        automatically size itself to try and accommodate 
     *                        the array length. The default is 8.
     *                      
     *                        Examples of acceptable command-line commands for 
     *                        this argument are: /L{value}, /L:{value}, etc.
     *                        Basically, The command can be anything as long as 
     *                        it starts with /L (or /l) and contains no spaces
     *                        or digit(s). Digits are reserved for the actual 
     *                        argument value passed along with the command, for
     *                        example: /L:8 (/L: 8 is not acceptable) or you 
     *                        could use: /Length=8. Anything can be between the
     *                        /L and the integer argument value. Either will tell 
     *                        the application the the length of the Array to 
     *                        display will contain 8 elements. No whitespaces 
     *                        are permitted within a Command-Line Command.
     *                     
     *   Array Value To Move: This would be the integer value that is placed 
     *                        within the first element of the String Array at
     *       Command: /N      index 0. The default value is: <b>2</b> however
     *                        you can change this value to whatever you like.
     * 
     *                        Examples of acceptable command-line commands for 
     *                        this argument are: /N{value}, /N:{value}, etc.
     *                        Basically, The command can be anything as long as 
     *                        it starts with /N (or /n) and contains no spaces
     *                        or digit(s). Digits are reserved for the actual 
     *                        argument value passed along with the command, for
     *                        example: /N:8 (/N: 8 is not acceptable) or you 
     *                        could use: /Number=8. Anything can be between the
     *                        /N and the integer argument value. Either will tell 
     *                        the application the the number within the Array to 
     *                        display will be the number 8. No whitespaces are
     *                        permitted within a Command-Line Command.
     *  
     *   Animation Speed:     Default is a value of 1000 milliseconds which is
     *                        basically equivalent to 1 second. You can set the 
     *     Command: /S        animation speed to whatever you like but do keep
     *                        in mind that you could set a speed that will be so
     *                        fast that you can't tell there is any animation.
     * 
     *                        The value passed with this command would be an 
     *                        integer value representing Milliseconds.
     * 
     *                        Examples of acceptable command-line commands for 
     *                        this argument are: /S{value}, /S:{value}, etc.
     *                        Basically, The command can be anything as long as 
     *                        it starts with /S (or /s) and contains no spaces
     *                        or digit(s). Digits are reserved for the actual 
     *                        argument value passed along with the command, for
     *                        example: /S:800 (/S: 800 is not acceptable) or you 
     *                        could use: /Speed=800. Anything can be between the
     *                        /S and the integer argument value. Either will tell 
     *                        the application that the animation speed for the 
     *                        Array display will be 800ms. No whitespaces are
     *                        permitted within a Command-Line Command.
     * 
     *   Display Font Size:   Default is a font size of 24 but any font size can
     *                        be used to display the Animation and the display 
     *      Command: /F       window will automatically size accordingly.
     * 
     *                        Examples of acceptable command-line commands for 
     *                        this argument are: /F{value}, /F:{value}, etc.
     *                        Basically, The command can be anything as long as 
     *                        it starts with /F (or /f) and contains no spaces
     *                        or digit(s). Digits are reserved for the actual 
     *                        argument value passed along with the command, for
     *                        example: /F:36 (/F: 36 is not acceptable) or you 
     *                        could use: /Font=36. Anything can be between the
     *                        /F and the integer argument value. Either will tell 
     *                        the application that the animation Font size for the 
     *                        Array display will be 36pt. No whitespaces are allowed
     *                        within a Command-Line Command.</pre>
     */
    private void readCommandLineArguments(String[] args) {
        String command = "";
        int value;
        for (String arg : args) {
            // Split Alpha and Numeric.
            String[] argParts = arg.split("(?<=\\D)(?=\\d)|(?<=\\d)(?=\\D)");
            command = argParts[0].substring(0, 2);
            value = 0;
            if (argParts.length == 2) { 
                value = Integer.parseInt(argParts[1]);
            }
            switch (command.toUpperCase()) {
                case "/L":
                    this.lengthOfArray = value;
                    break;
                case "/N":
                    this.arrayValueToMove = value;
                    break;
                case "/S":
                    this.animationSpeed = value;
                    break;
                case "/F":
                    this.displayFontSize = value;
                    break;
                default:
                    System.err.println("Unknown Command-Line Argument!");
            }
        } 
    }
    
    /**
     * Returns the pixel width of the supplied String.<br>
     * 
     * @param font (Font) The String Font to base calculations from.<br>
     * 
     * @param characterString (String) The string to get the pixel width for.<br>
     * 
     * @return (int) The pixel width of the supplied String.
     */
    public int getStringPixelWidth(Font font, String characterString) {
        FontMetrics metrics = new FontMetrics(font) {
            private static final long serialVersionUID = 1L;
        };
        Rectangle2D bounds = metrics.getStringBounds(characterString, null);
        return (int) bounds.getWidth();
    }
    
    /**
     * Returns the pixel height of the supplied String.<br>
     * 
     * @param font (Font) The String Font to base calculations from.<br>
     * 
     * @param characterString (String) The string to get the pixel height for.<br>
     * 
     * @return (int) The pixel height of the supplied String.
     */
    public int getStringPixelHeight(Font font, String characterString) {
        FontMetrics metrics = new FontMetrics(font) {
            private static final long serialVersionUID = 1L;
        };
        Rectangle2D bounds = metrics.getStringBounds(characterString, null);
        return (int) bounds.getHeight();
    }
}
DevilsHnd - 退職した
  • 8,739
  • 2
  • 19
  • 22
-1
import java.io.*;
import java.util.Arrays;

public class MyClass {
    public static void main(String args[]) {
        String n = "2";
        String array[] = new String[10];
        Arrays.fill(array, "");
        array[0] = n;
        int i = 0;
        System.out.println(Arrays.toString(array));
        while(i < array.length-1){
            // swap 
            String temp = array[i+1];
            array[i+1] = array[i];
            array[i] = temp;
            System.out.println(Arrays.toString(array));
            i++;
        }
    }
}
George R
  • 484
  • 6
  • 19
  • Thank you for ur response. I was however wondering that would it be possible to show the movement in one single array only. Like maybe let 2 appear at index 0 for a second and then move 2 to index 1, showing it for a second and so on, sort of like an animation... I'm not sure if this is possible in Java or not, which is why I asked. – Droid Nov 13 '22 at 08:52
  • To animate that you would need to do it within a dialog or window of some kind other than the console window. – DevilsHnd - 退職した Nov 13 '22 at 10:19
-1

You could try something like the following:

public static void main(String[] args) throws InterruptedException {
    annimate("2");
}

private static void annimate(String uniqueElement) throws InterruptedException {
    String[] array = new String[]{"2", "", "", "", ""};
    int uniqueElemIndex = 0;

    while (uniqueElemIndex < array.length) {
        System.out.println(Arrays.toString(array));
        for (int i = 0; i < array.length; i++) {
            if (array[i].equals(uniqueElement)) {
                uniqueElemIndex = i;
                break;
            }
        }
        if (uniqueElemIndex + 1 < array.length) {
            String elem = array[uniqueElemIndex];
            array[uniqueElemIndex + 1] = elem;
            array[uniqueElemIndex] = "";
        }
        uniqueElemIndex++;
        Thread.sleep(500);
    }
}

This outputs the following:

[2, , , , ]
[, 2, , , ]
[, , 2, , ]
[, , , 2, ]
[, , , , 2]
mrkachariker
  • 411
  • 4
  • 9