Classic Hundred Doors Simulation I am doing the 100 Doors problem as an exercise to practice user input and loops. I do understand the problem can be solved by outputting every square number up to the maximum number, but it defeats the purpose of the exercise. The 100 Doors problem goes like this:


  \$N\$ doors are closed. In the first pass, I open all of them. In the second pass, I toggle every second door. In the third pass, I toggle every third door. I continue this until I have completed the \$N\$th pass. Find all the doors that will remain open after \$N\$ passes.


Here is the code:

import java.io.IOException;
import java.util.Scanner;

public class hundredDoors {
    static boolean hasNum = false;

    public static void main(String[] args) throws IOException {
        while (!hasNum) {
            Scanner input = new Scanner(System.in);
            int numOfDoors = 0;

            System.out.print("Please enter the number of doors: ");
            if (input.hasNextInt()) {
                hasNum = true;
                numOfDoors = input.nextInt();
                if (numOfDoors &lt; 1) {
                    hasNum = false;
                    System.out.println("Please enter an integer.");
                    continue;
                }
                boolean[] doors = new boolean[numOfDoors];

                for (boolean door : doors) {
                    door = false;
                }

                for (int index = 1; index &lt;= numOfDoors; index++) {
                    for (int door = index - 1; door &lt;= numOfDoors - 1; door += index) {
                        doors[door] = !doors[door];
                    }
                }

                String output = "Doors still opened: \n";
                int loops = 0;
                for (int door = 0; door &lt;= numOfDoors - 1; door++) {
                    if (loops == 10) {
                        output += "\n";
                        loops = 0;
                    }
                    if (doors[door]) {
                        output += (door + 1 + " ");
                        loops += 1;
                    }
                }
                input.close();
                System.out.println(output);
            }

            else {
                System.out.println("Please enter an integer.");
            }
        }
    }
}


One note for this program is that \$N\$ is supplied by the user. The other is that for formatting sakes, each line will have a maximum of 10 numbers (# of door).

My question here isn't how to make it more efficient (the most efficient method is to output every square since they have an odd number of factors as explained here) but rather if the code can be more clean/clear (ie, names of indentifiers, loops can be shortened, input validation check can be better, etc).
The program is difficult to read because all code is in the main()
function. As an example, one has to jump to the end of the program in
order to understand how the “get a positive integer from the user” loop
works.

It is generally better to separate the I/O from the computation, and
have dedicated functions for a single purpose. In your example, the overall
structure could for example look like this:

static int readPositiveInteger(String prompt) throws IOException {
    // ...
}

static boolean[] openDoors(int numOfDoors) {
    // ...
}

static void printOpenDoors(boolean[] doors) {
    // ...
}

public static void main(String[] args) throws IOException {

    int numOfDoors = readPositiveInteger("Enter the number of doors: ");
    boolean[] doors = openDoors(numOfDoors);
    printOpenDoors(doors);
}


More remarks:


The naming convention for Java classes is upper camelcase, in your case
HundredDoors.
The boolean hasNum should be a local variable in main().
boolean variables are by default initialized to false, the explicit
initialization in a loop is not needed.
You create a new Scanner instance for each attempt to read a positive
integer. A single instance is sufficient if you read lines from standard
input with nextLine().
The message “Please enter an integer” should be “Please enter a positive
integer" since that is what you need and check for.
Array indices start at zero whereas the door numbers start at one.
If you allocate one additional boolean element for the doors array then
the door number can be used as array index directly, instead of adding/subtracting
one at various places. That makes the code better understandable.
The output can be written directly to standard output instead of 
concatenating it to a string first.


Putting it all together, the program could look like this:

import java.io.IOException;
import java.util.Scanner;

public class HundredDoors {

    static int readPositiveInteger(String prompt) throws IOException {
        Scanner scanner = new Scanner(System.in);
        int i = 0;
        do {
            System.out.print(prompt);
            try {
                i = Integer.parseInt(scanner.nextLine());
            } catch (NumberFormatException e){
                i = 0;
            }
            if (i &lt;= 0) {
                System.out.println("Please enter a positive integer!");
            }
        } while (i &lt;= 0);
        return i;
    }

    static boolean[] openDoors(int numOfDoors) {
        boolean[] doors = new boolean[numOfDoors + 1];
        for (int index = 1; index &lt;= numOfDoors; index++) {
            for (int door = index; door &lt;= numOfDoors; door += index) {
                doors[door] = !doors[door];
            }
        }
        return doors;
    }

    static void printOpenDoors(boolean[] doors) {
        System.out.println("Doors still opened:");
        int count = 0;
        for (int door = 1; door &lt; doors.length; door++) {
            if (doors[door]) {
                if (count == 10) {
                    System.out.println();
                    count = 0;
                }
                count += 1;
                System.out.print(door + " ");
            }
        }
        System.out.println();
    }

    public static void main(String[] args) throws IOException {

        int numOfDoors = readPositiveInteger("Please enter the number of doors: ");
        boolean[] doors = openDoors(numOfDoors);
        printOpenDoors(doors);
    }
}