詰めキューブのWebアプリを作った話

目次

 

こんにちは、うえしゅうです。

先日「詰めキューブ」のWebアプリを公開しました。
その公開の経緯や使用した技術などを紹介していこうと思います。

 

詰めキューブとは?

そもそも詰めキューブが何であるか知らない方も多いと思うので説明をアプリから引用します。

詰めキューブとは、あと数手で解けるスクランブルを最少の手数で解くスピード競技です

つまり少ない手数のFMCみたいなものですね。

詰めキューブはやってみるとわかるんですが5手あたりから難しくなっていき、6手以上になると相当難しく一部のFMCer以外は太刀打ちできないような難易度になっていきます。一応アプリでは8手スクランブルまで実装していますが、7手以上が解ければ相当すごく自慢できるレベルに達していると思います。

 

アプリを作った経緯

自分はもともとFMCが得意だったので詰めキューブにも自信があり、他人の崩したスクランブルでも6手くらいであれば数十秒で直すことができました。また詰めキューブの難しい問題作成も得意で、6手だけど難しいスクランブルを作って友達に解かせたりしていました。なので自分は解く側よりも出題する側のほうが多かったです。

しかし詰めキューブの一番の欠点は誰かに問題を考えてもらわないと競技が成立しないという点です。また解く側にスクランブルを教えてはいけないので、解く側が回し間違えたりしたら出題者にもう一度スクランブルしてもらう必要があるので非常にめんどくさいです。

自分は面白い詰めキューブの問題を解きたいのに自分はいつも出題者側で遊べないし、かといって一人ではそもそも遊ぶことすらできないという矛盾。

そこで詰めキューブアプリを考えました。

コンピュータにスクランブルを作成してもらえれば自分ひとりでも遊べるというのはナイスアイデアでした。

また自分はプログラミングが趣味なんですが、ちょうどWebのフロントエンド開発に興味があってこの技術を使えば詰めキューブアプリが作れるんじゃないかと思いついたのがアプリ作成の経緯です。

 

冗長なスクランブル作成の裏側

詰めキューブアプリを作るにあたって一番重要なのが冗長なスクランブル作成です。例えば詰めキューブの解が5手だとしたら、その5手がスクランブルから推測できないような長めのスクランブルが必要になるのです。

自分の考えたスクランブル作成方法を紹介します。

  1. 詰めキューブの正解となる解法のスクランブル( = S )をランダムで出力する
  2. Sの最後に事前に決められたスクランブル手順「B' D' L' F' U' R' B' D' L' F' U' R'」( = A )をくっつける
  3. S + Aをスクランブルとしてキューブの解法生成プログラム(min2phase)にかけて解法( = B )を導き出す
  4. S + A + B = 完成、となるがこれは逆からたどるとB' + A' + S' = 完成、とも言いかえられる。つまりB' + A’を回せば残り数手で完成するS’の状態に持ち込めるため、B' + A’が最終的なスクランブルとなる。

ここでAは12手、Bは約20手であるためスクランブルB' + A’はだいたい30手強となります。スクランブルとしては結構長いためもっと短くできないかというご意見もいただきました。しかし今のところそれは難しいです。

なぜスクランブルが長くなってしまうのか。

まず上記の説明でS + Aを解法生成プログラムにかけてBを出すと説明しましたが、S + Aがだいたい16手以下だとプログラムは解法としてS + Aのまるっきり逆のA' + S’を出してしまうのです。そうなると最終的にはスクランブルとしてSそのものが出力されて解法が丸わかりになってしまいます。仮にSが5手だとするとAは少なくとも16 – 5 = 11手以上である必要があります。これがAが12手である理由です。

また、解法生成プログラムの特徴として解法は必ず2フェーズのいわゆるDomino Reductionで生成されます。そのためもし仮にAをR2やU、DみたいなDomino Reductionのフェーズ2の動きのみで構成してしまうと、S + Aが16手以上であるにも関わらず解法Bが逆手順のA' + S’になってしまう可能性があります。なのでAはEOをたくさん崩す動きが絶対に必要となり「B' D' L' F' U' R' B' D' L' F' U' R'」を採用することに決めました。この手順Aは逆再生すると「R U F L D B R U F L D B」となりプライムがなくてなんとなく見栄えが良かったというのも採用した理由になります。

このような理由でスクランブルは約30手強となります。もしもっと短いスクランブルを生成できる方法を考えた!という方がいましたらTwitterで僕に教えて下さい。

追記:
記事公開後にAsato君がスクランブルを短くする方法を提案してくれました。Asato君自作のTwo-Phaseプログラムを使ってフェーズ1の探索を0手からではなく10手から始めることで、少ない手数のスクランブルの入力でも20手前後の解法を生成することが可能になりました。Asato君提案ありがとうございます。

 

使用した技術

言語JavaScript
フレームワークReact
ライブラリMaterial-UI (UIフレームワーク)
React Router (ルーティング)
Moment.js (時間表示)
react-i18next (多言語対応)
react-share (SNSシェアボタン作成)
min2phase (解法生成)
cubejs (逆手順生成)
公開場所GitHub Pages

JavaScriptは昔から使っていましたが、最近流行りのReactというフレームワークが作りやすそうということで勉強がてらアプリを作りました。

学習は主に公式チュートリアルや本を読んでおり、最近ではFull stack openという海外の大学の教材が面白くて取り組んでいます。またHcon作成者のH氏さんはReact  + Material-UIでいろんなアプリを作成して過程をQiitaにあげており大変参考になりました。

また、本アプリはGitHubでソースを管理しており、静的サイトなのでそのままGitHub Pagesで公開しました。静的サイトなのにこれだけ動きや遷移のあるモダンな作りのサイトを作れるって、やっぱりReactってすごいですね。

 

作った感想

もともとこのアプリの構想は1年以上前から考えていましたがその頃はまだ技術スキルがなくて作れませんでした。仕事や趣味でプログラミングの知識をつけてやっと作ることができたので完成してよかったと思っています。

自分が遊ぶためだけに作ったアプリですが、Twitterで公開したところ結構な人が遊んでくださったみたいでとても嬉しいです。Twitterのシェアボタンをつけたのもアプリを拡散してもらうためだったのでつけておいてよかったです。

また何かアイデアを思いついたら面白いWebアプリを作るかもしれないのでその時はまた遊んでくださると嬉しいです。

 

では。