Search code examples
javascriptalgorithmrubiks-cube

Random move javascript scrambler for the Rubik's Cube


I am currently working on a web-timer, and I have some issues with my scrambling-algorithm algorithm. As it is the first version, I only want the scrambler to be random move and not random state, as it is too much complicated to make, and it will come in a future update. I have an algorithm that basically makes an array of random moves that it chooses from the possibilities, and then checks if two of the same letters (or moves) are not next to one another. That all works fine, But I have no clue how to add something that would avoid cases as follow: "D U D" for example. Two same moves separated by another move are acceptable For example "D R D", but not "D U D", as it would be equal to "D2 U", and thus, be a wasted move.

Information fro non-cubers:

each letter represents its face that gets moved when the letter is read. For example: "L U L": "L" would mean to rotate the left face clockwise once, then "U" would mean to rotate the Upper face clockwise, and finally "L" again would mean to rotate the left face again. if a letter is followed by an apostrophe, then it means that the face should be rotated counter-clockwise. If it is followed by a "2", it means that the face should be rotated two times in a row. L is left, R is right, F is front, B is back, D is down, U is Up

Here's the code:

		function generate_scramble() {
			var scramble_length = 20;
			var scramble = new Array();

			var possible_letters = new Array(" D", " U", " B", " F", " R", " L");
			var possible_switches = new Array("", "2", "'");

			var array_of_randoms = new Array();

			for (var i = 0; i < scramble_length; i++) {
				var random_letters = Math.floor(Math.random() * possible_letters.length);
				var random_switches = Math.floor(Math.random() * possible_switches.length);

				array_of_randoms.push(random_letters);

				if (array_of_randoms[array_of_randoms.length - 1] == array_of_randoms[array_of_randoms.length - 2]) {
					if (array_of_randoms[array_of_randoms.length - 1]  < 5) {
						array_of_randoms[array_of_randoms.length - 1]++;
					} else {	
						array_of_randoms[array_of_randoms.length - 1]--;
					}
				}
			random_letters = array_of_randoms[array_of_randoms.length - 1];
			scramble.push(possible_letters[random_letters] + possible_switches[random_switches])
			}
			document.getElementById("scramble").innerHTML = "Scramble: " + scramble.join("");
		}

		generate_scramble();
	<p id="scramble">
		Scramble: 
	</p>
	<button onclick="generate_scramble()">
		New Scramble
	</button>


Solution

  •  const directions = [
       ["D", "U"],
       ["L","R"],
       ["F","B"]
     ];
    
     const times = ["", "'", "2"];
    
     const random = (array, exclude) => {
       do {
          var n = Math.floor( Math.random() * array.length );
       } while(array[n] === exclude)
       return array[n];
    }
    
    const scramble = new Array(20);
    var direction;
    for(var i = 0; i < scramble.length; i++){
      direction = random(directions, direction);
      scramble[i] = random(direction) + random(times);
     }
    

    You could reduce many false moves by always changing the direction it moves. So D U D wouldnt appear cause D and U go into the same direction.