Giter Site home page Giter Site logo

cubekit's Introduction

CubeKit

A Simple Next-Gen Rubik's Cube Simulator

Why?

As a speedcubing enthusiast and programmer, I realized that I could give the programming community a Javascript-based Rubik's Cube simulator that could do whatever I wanted it to quickly and easily.

Installation

Installation is very simple. Simply cd into your chosen directory and run this command:

npm install cubekit

Because of the way NPM is structured, cubekit uses CJS module declarations.

As simple as that! Cubekit is ready to use!

Usage

Cubekit is centralized on simplicity and modularity. You can import everything you need and not bother with everything else. There are two main classes: Cube and Parser

Structure

Cubekit is built on a vector and rotation-matrix model of a Rubik's Cube. This idea is originally from user156217 on Stack Exchange.

Here's how it works.

The position vector

The Cube class is composed of different pieces, each with a position vector. In theory, it would be ideal to represent the position $\vec{l}$ as a column matrix, as follows:

$$\vec{l} = \begin{bmatrix} x\\\ y\\\ z \end{bmatrix}$$

However, because expressing column matricies in code is tedious (To access, say, y in let l = [[x],[y],[z]], you need to write l[1][0]), I actually represent our vector as a row matrix. We transpose the matrix into a column, do operations, and transpose back to a row when I need to operate on the "column."

The rotation matricies

By multiplying each vector by a rotation matrix, we are able to "turn" the piece. The 3D rotation matricies used are as follows:

$$R_x(\theta) = \begin{bmatrix} 1 & 0 & 0\\\ 0 & \cos(\theta) & -\sin(\theta)\\\ 0 & \sin(\theta) & \cos(\theta) \end{bmatrix}$$ $$R_y(\theta) = \begin{bmatrix} \cos(\theta) & 0 & \sin(\theta)\\\ 0 & 1 & 0\\\ -\sin(\theta) & 0 & \cos(\theta) \end{bmatrix}$$ $$R_z(\theta) = \begin{bmatrix} \cos(\theta) & -\sin(\theta) & 0\\\ \sin(\theta) & \cos(\theta) & 0\\\ 0 & 0 & 1 \end{bmatrix}$$

By multiplying these matricies onto our position vector, we are able "turn" our piece!

$$(R_x(\theta)\cdot\vec{l}^\intercal)^\intercal = (\begin{bmatrix} 1 & 0 & 0\\\ 0 & \cos(\theta) & -\sin(\theta)\\\ 0 & \sin(\theta) & \cos(\theta) \end{bmatrix}\cdot\begin{bmatrix} x & y & z \end{bmatrix}^\intercal)^\intercal$$

Moving the "stickers"

Other than just the actual position of the piece, the "stickers" also move. We can simply keep track of all the colors using a simply array. We can let the first index be the x colors, second index the y colors, and the third index the z colors. It would look something like this: this.colors=[cx, cy, cz]. In order to turn it properly, the following things have to occur:

  • When turning the x axis by 90°, swap the y and z colors
  • When turning the y axis by 90°, swap the x and z colors
  • When turning the z axis by 90°, swap the x and y colors

And there we have it! All our pieces now have their own "turning" logic built in!

Performing a layer turn

Currently, all our pieces have their own rotation logic. However, what if we want to perform an actual turn? Well, its really quite simple. For example, if we want to perform an "R" turn, all we have to do is select all of the pieces with an x equal to 1, and rotate those pieces along the x axis by 90°. On the inside, each one of the cube.R() function calls look like this:

Cube.turn(
	(x) => x === 1,
	(y) => y !== undefined,
	(z) => z !== undefined,
	"x",
	Math.PI/2
)

The first three parameters look at the conditions of what each one of the x, y, and z parameters need to be to do this turn. The 4th parameter tells the function what axis to turn it on, and the last one is simply the angle to turn it, in radians. You can actually use the Cube.turn() function, as it is public!

Conclusion

While this algorithm is very programatically simple, there is a good bit of math behind it. However, one of the cons is that searching for a particular piece may be slower than usual. Nonetheless, it is a very elegant approach!

Cube

This is where the main magic happens. Simply declare a new cube, initialize, and you're all set up.

let { Cube, StandardMoves, WesternColors } = require("cubekit");
let myCube = new Cube(StandardMoves);
myCube.init(WesternColors);

Let's break down the things that are going on here:

Color Schemes

Because the Rubik's cube doesn't necessarily have a "definite" color scheme (even though most manufacturers use the Western Color scheme), Cubekit supports custom color scheme support. The predefined colors are:

  • WesternColors
  • JapaneseColors You can also define your own colors:
const MyAmazingColors = {
	x: ["R", "B"], // Negative x, positive x
	y: ["W", "Y"], // Negative y, positive y
	z: ["L", "M"], // Negative z, positive z
};

In theory, what you put in each individual string doesn't matter. I recommend a single letter that represents something.

The positive x axis is pointing towards you. The positive z axis is pointing towards your right. The positive y axis is pointing upwards.

Importing Moves

You may notice that we are also using something called StandardMoves. Beacuse of the modular structure, you only import what you need. Cubekit currently supports

  • StandardMoves (R, L, U, D, F, B, and all of their double and inverse moves)
  • WideMoves (Rw, Lw, Uw, Dw, Fw, Bw, and all of their double and inverse moves)
  • WideMovesUNSAFE (r, l, u, d, f, b, and all of their double and inverse moves)
    • We do not recommend this one, as the lowercase letters may be confusing

cubekit's People

Contributors

evanzhoudev avatar

Watchers

 avatar  avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.