rubiks-cube-solver
Version:
Outputs a solution using the Fridrich Method for a given cube state.
185 lines (147 loc) • 4.75 kB
JavaScript
import { BaseSolver } from '../BaseSolver';
import { RubiksCube } from '../../models/RubiksCube';
import {
getDirectionFromFaces, getFaceOfMove, getRotationFromTo, getMoveOfFace
} from '../../utils';
const CROSS_COLOR = 'u';
const R = (moves) => RubiksCube.reverseMoves(moves);
class CrossSolver extends BaseSolver {
constructor(...args) {
super(...args);
this.phase = 'cross';
}
solve() {
let crossEdges = this._getCrossEdges();
for (let edge of crossEdges) {
let partition = this._solve({ edge });
this.partitions.push(partition);
}
return this.partitions;
}
isSolved() {
let edges = this._getCrossEdges();
for (let edge of edges) {
if (!this.isEdgeSolved(edge)) {
return false;
}
}
return true;
}
isEdgeSolved(edge) {
let otherColor = edge.colors().find(color => color !== 'u');
let otherFace = edge.faces().find(face => face !== 'up');
const matchesMiddle = otherFace[0] === otherColor;
const isOnCrossFace = edge.getColorOfFace('up') === 'u';
return isOnCrossFace && matchesMiddle;
}
/**
* Finds all edges that have 'F' as a color.
* @return {array}
*/
_getCrossEdges() {
return this.cube.edges().filter(edge => edge.hasColor(CROSS_COLOR));
}
/**
* 6 Cases!
* 1) The edge's UP color is on the UP face.
* 2) the edge's UP color is on the DOWN face.
* 3) The edge's UP color is not on the UP or DOWN face and the other color is on the UP face.
* 4) The edge's UP color is not on the UP or DOWN face and the other color is on the DOWN face.
* 5) The edge's UP color is not on the UP or DOWN face and the other color is on the RELATIVE RIGHT face.
* 6) The edge's UP color is not on the UP or DOWN face and the other color is on the RELATIVE LEFT face.
*
* @param {cubie} edge
*/
_getCaseNumber({ edge }) {
if (edge.getColorOfFace('up') === CROSS_COLOR) {
return 1;
} else if (edge.getColorOfFace('down') === CROSS_COLOR) {
return 2;
}
if (edge.faces().includes('up')) {
return 3;
} else if (edge.faces().includes('down')) {
return 4;
}
let crossFace = edge.getFaceOfColor(CROSS_COLOR);
let otherFace = edge.getFaceOfColor(edge.colors().find(color => color !== CROSS_COLOR));
let direction = getDirectionFromFaces(crossFace, otherFace, { up: 'up' });
if (direction === 'right') {
return 5;
} else if (direction === 'left') {
return 6;
}
}
_solveCase1({ edge }) {
if (this.isEdgeSolved(edge)) {
return;
}
let face = edge.faces().find(face => face !== 'up');
this.move(`${face} ${face}`, { upperCase: true });
this._solveCase2({ edge });
}
_solveCase2({ edge }) {
let solveMoves = this._case1And2Helper({ edge }, 2);
this.move(solveMoves, { upperCase: true });
}
_solveCase3({ edge }) {
let prepMove = this._case3And4Helper({ edge }, 3);
this.move(prepMove, { upperCase: true });
this._solveCase5({ edge });
}
_solveCase4({ edge }) {
let prepMove = getRotationFromTo(
'down',
edge.getFaceOfColor('u'),
getFaceOfMove(edge.getColorOfFace('down'))
);
this.move(prepMove, { upperCase: true });
let edgeToMiddle = R(edge.getFaceOfColor('u'));
this.move(edgeToMiddle, { upperCase: true });
this._solveCase5({ edge });
}
_solveCase5({ edge }) {
let solveMoves = this._case5And6Helper({ edge }, 5);
this.move(solveMoves, { upperCase: true });
}
_solveCase6({ edge }) {
let solveMoves = this._case5And6Helper({ edge }, 6);
this.move(solveMoves, { upperCase: true });
}
_case1And2Helper({ edge }, caseNum) {
let crossColorFace = caseNum === 1 ? 'up' : 'down';
let currentFace = edge.faces().find(face => face !== crossColorFace);
let targetFace = getFaceOfMove(edge.getColorOfFace(currentFace));
let solveMoves = getRotationFromTo(crossColorFace, currentFace, targetFace);
if (caseNum === 2) {
let edgeToCrossFace = getMoveOfFace(targetFace);
solveMoves += ` ${edgeToCrossFace} ${edgeToCrossFace}`;
}
return solveMoves;
}
_case3And4Helper({ edge }, caseNum) {
let prepMove = edge.faces().find(face => !['up', 'down'].includes(face));
if (caseNum === 4) {
prepMove = R(prepMove);
}
return prepMove;
}
_case5And6Helper({ edge }, caseNum) {
let otherColor = edge.colors().find(color => color !== 'u');
let currentFace = edge.getFaceOfColor(otherColor);
let targetFace = getFaceOfMove(otherColor);
let prepMove = getRotationFromTo('up', currentFace, targetFace);
let edgeToCrossFace = getMoveOfFace(currentFace);
if (caseNum === 6) {
edgeToCrossFace = R(edgeToCrossFace);
}
return `${R(prepMove)} ${edgeToCrossFace} ${prepMove}`;
}
_getPartitionBefore({ edge }) {
return { edge: edge.clone() };
}
_getPartitionAfter({ edge }) {
return { edge };
}
}
export { CrossSolver };