3
\$\begingroup\$

I was wondering if there was a way I could shorten this code that gets input from the user about the state of their 2×2×2 Rubik's Cube to solve it. I want it to still be informative so any user knows what to do, the thing is the method is pretty long.

static public int[][] scanCube(){

    int counter0 = 0;
    Scanner in = new Scanner(System.in);

    int[][] input = new int [6][4];

    System.out.println("Welcome to the 2x2x2 cube solver :)\n \n"
            + "Please enter your cube");
    System.out.println(" 0 = white \n 1 = orange \n 2 = green \n 3 = red\n 4 = blue\n 5 = yellow\n");
    System.out.println("Enter the colors for the TOP side\n");

    while(counter0 < 4){
        input[0][counter0] = Integer.parseInt(in.nextLine());
        counter0++;     
    }
    System.out.println(" 0 = white \n 1 = orange \n 2 = green \n 3 = red\n 4 = blue\n 5 = yellow\n");
    System.out.println("Enter the colors for the LEFT side");

    //reset the counter
    counter0 = 0;
    while(counter0 < 4){
        input[1][counter0] = Integer.parseInt(in.nextLine());
        counter0++;
    }
    System.out.println(" 0 = white \n 1 = orange \n 2 = green \n 3 = red\n 4 = blue\n 5 = yellow\n");
    System.out.println("Enter the colors for the FRONT side");
    //reset the counter
    counter0 = 0;
    while(counter0 < 4){
        input[2][counter0] = Integer.parseInt(in.nextLine());
        counter0++;
    }
    System.out.println(" 0 = white \n 1 = orange \n 2 = green \n 3 = red\n 4 = blue\n 5 = yellow\n");
    System.out.println("Enter the colors for the RIGHT side");
    //reset the counter
    counter0 = 0;
    while(counter0 < 4){
        input[3][counter0] = Integer.parseInt(in.nextLine());
        counter0++;
    }
    System.out.println(" 0 = white \n 1 = orange \n 2 = green \n 3 = red\n 4 = blue\n 5 = yellow\n");
    System.out.println("Enter the colors for the BACK SIDE");
    //reset the counter
    counter0 = 0;
    while(counter0 < 4){
        input[4][counter0] = Integer.parseInt(in.nextLine());
        counter0++;
    }
    System.out.println("NOTE: Rotate cube back to starting position before rotating the cube\n"
            + "for the bottom side input\n");

    System.out.println(" 0 = white \n 1 = orange \n 2 = green \n 3 = red\n 4 = blue\n 5 = yellow\n");
    System.out.println("Enter the colors for the BOTTOM side");
    //reset the counter
    counter0 = 0;
    while(counter0 < 4){
        input[5][counter0] = Integer.parseInt(in.nextLine());
        counter0++;
    }
    return input;
}
\$\endgroup\$
  • 1
    \$\begingroup\$ Well, it's probably easier to just say "put the data in a text file where the rows are the top, left, front, right, back and bottom side" and then read it. That would shorten the code :-) Or you could do the same interactively and let the user input all lines together (separated by whatever character, or not separated considering they are fixed width). \$\endgroup\$ – ChatterOne Aug 24 '16 at 14:13
2
\$\begingroup\$

You can store the sides on an array and loop over that, something roughly like this:

import java.util.Scanner;

public class scanCube {

    public static void main(String[] args) {
        String[] sides = { "TOP", "LEFT", "FRONT", "RIGHT", "BACK", "BOTTOM" };
        int side_index = 0;
        Scanner in = new Scanner(System.in);

        int[][] input = new int [6][4];
        System.out.println("Welcome to the 2x2x2 cube solver :)\n \n"
                + "Please enter your cube");

        for (String side: sides) {
            System.out.println("Enter the colors for the " + side + " side");
            System.out.println(" 0 = white \n 1 = orange \n 2 = green \n 3 = red\n 4 = blue\n 5 = yellow\n");
            int counter = 0;
            while(counter < 4){
                input[side_index][counter] = Integer.parseInt(in.nextLine());
                counter++;
            }
            side_index++;
        }
    }
}

I would personally add a String.split so that the user can input the numbers for a single side on a single line, without having to hit enter every time.

If you want to have an alternative approach, with this the user can enter something like 0312 and it will be split and assigned to the array.

Keep in mind that this is just the general idea, not complete / nice code.

import java.util.Scanner;

public class scanCube {
    public static void main(String[] args) {
        String[] sides = { "TOP", "LEFT", "FRONT", "RIGHT", "BACK", "BOTTOM" };
        int side_index = 0;
        int max_colors_per_side = 4;
        Scanner in = new Scanner(System.in);

        int[][] input = new int [sides.length][max_colors_per_side];
        System.out.println("Welcome to the 2x2x2 cube solver :)\n \n"
                + "Please enter your cube");

        while (side_index < sides.length) {
            System.out.println("Enter the colors for the " + sides[side_index] + " side");
            System.out.println(" 0 = white \n 1 = orange \n 2 = green \n 3 = red\n 4 = blue\n 5 = yellow\n");
            String[] side_colors = in.nextLine().toString().split("");

            if (side_colors.length != max_colors_per_side+1) { // Account for CR/LF
                System.out.println("Invalid input!");
            } else {
                for (int i = 1; i <= max_colors_per_side; i++) {
                    // You should check here also that the input is valid (0..3)
                    input[side_index][i-1] = Integer.parseInt(side_colors[i]);
                }
                side_index++;
            }
        }
    }
}

You should also check that the user didn't input something presumably wrong like a cube with 10 white squares, because the amount of squares should be the same for every color.

\$\endgroup\$
  • \$\begingroup\$ Thank I like your idea its concise :) so you are saying if I was to do Integer.parseInt(in.String.split()); so that the user doesn't have to hit enter each time they change the side of their cube? \$\endgroup\$ – cuber Aug 24 '16 at 14:55
  • \$\begingroup\$ I'm saying that the user could input for each side something like 0231 and then hit enter. It's up to you to you split it, then decide if you want to ask for another side, or ask again because the input was not valid. I'll add a small example. \$\endgroup\$ – ChatterOne Aug 24 '16 at 15:51
2
\$\begingroup\$
    counter0 = 0;
    while(counter0 < 4){
        input[1][counter0] = Integer.parseInt(in.nextLine());
        counter0++;
    }

It would be more idiomatic to write this as

    for (int i = 0; i < SQUARE_COUNT_PER_SIDE; i++) {
        input[1][i] = Integer.parseInt(in.nextLine());
    }

This also has the side effect of limiting the scope of the loop iteration variable to the loop itself.

Replaced the magic number 4 with SQUARE_COUNT_PER_SIDE.

This isn't to say that you shouldn't eliminate the need for this by entering multiple squares at once. Note that if you are iterating over a string, you could say

    String side = in.nextLine().trim();
    if (side.length() != SQUARE_COUNT_PER_SIDE) {
        throw new IllegalArgumentException("Must have " + SQUARE_COUNT_PER_SIDE + " entries per side.");
    }

    for (int i = 0; i < SQUARE_COUNT_PER_SIDE; i++) {
        input[1][i] = side.at(i) - '0';
        if (input[1][i] < 0 || COLOR_COUNT >= input[1][i]) {
            throw new IllegalArgumentException("Must pick a valid color.");
        }
    }

Note that this adds error handling for invalid inputs that isn't explicit in the original. Without that, these ten or eleven lines would only be four.

If you want an array of characters from a string, the easiest way is to say something like

    char[] squares = in.nextLine().toCharArray();

Now squares is a perfectly normal character array. Manipulate as you will. The nextLine method already returns a String. You don't have to call toString on it.

\$\endgroup\$
0
\$\begingroup\$

Something more graphical.

System.out.println(
    "Describe the cube, use space, w=white, o=orange, g=green, b=blue, y=yellow");
System.out.println("[1]    ..  top");
System.out.println("[2]    ..");
System.out.println("[3] .. .. .. ..  left front right back");
System.out.println("[4] .. .. .. ..");
System.out.println("[5]    ..");
System.out.println("[6]    ..  bottom");

String[] lines = new String[6];
BufferedReader in = new BufferedReader(System.in);
for (int lineno = 0; lineno < 6; ++lineno) {
    System.out.printf("[%d]%n", lineno + 1);
    String line = in.readLine();
    ...
}
\$\endgroup\$
  • \$\begingroup\$ One thing I do is after the user enters the numbers for the cube state I have a method that covers the numbers and replaces them with letters. so that it looks something like this. GR OG RW BR WB WY OO GY RO WB YB YG \$\endgroup\$ – cuber Aug 24 '16 at 14:47

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.