dnekblog

”でぃーねっく”と読みます。スマホのアプリを作ってます。

運ゲー排除マインスイーパー💣脱Unity計画(Android編)&SATによるソルバー改良

この記事は KMC Advent Calendar 2018 - Adventar の6日目(12/6)の記事です。

5日目の記事は、id:opesanさんの聖地巡礼記2018 - おぺの日記でした。

神戸異人館は何年か前に行ったのですが、確かFateの遠坂邸とかもありましたよね(Rewriteもアニメは見てました)。

目次

はじめに

KMC6年目のdamaです。 Twitter等ではDNEK(でぃーねっく) (@dnek_) | Twitterと名乗っています。 道を踏み外して京都大学文学研究科修士2回生となっているはずが、更に踏み外してフリーランスのようなことをしつつ自分のアプリも作っています。

この記事を読むのが面倒な人は、とりあえずアプリだけインストールして行って下さると嬉しいです。

更に1年経ってみて

毎年12/6にKMC Advent Calendarの記事だけを書くのもこれで4年目になりますが、去年はこんな感じでした。

今回のタイトルと矛盾していますね。

脱Unity

今までの記事でマルチプラットフォーム対応ゲームエンジンとしてヨイショしてきたUnityですが、色々あってオサラバすることにしたのでその経緯を綴っていこうと思います。

プライバシーポリシー

若干話題が逸れますが、↑の去年の記事から引用します。

そもそもプライバシーポリシーって何かと言うと、「私はあなたのこういう個人情報をこういう方法で使おうと思ってるんですが、いいですか?」という契約文書です。 日本語だと個人情報保護方針というやつですね。 法的な話もありますが、とりあえずPlayStoreやAppStoreでは、「アプリが個人情報を扱うならそれについてポリシーを示せ」と決められているのです。

Unityで漢字パズルアプリを作ったよ(Android/iOS) - dnekblog

実はUnambiSweeperの方も既にFirebase Analyticsを使っているので、早い内にポリシーを示すように更新するつもりです。

Unityで漢字パズルアプリを作ったよ(Android/iOS) - dnekblog

いつ削除祭りがあるのか分からないので、自分のためにもユーザーのためにも先んじて対応しておこうと思います。

Unityで漢字パズルアプリを作ったよ(Android/iOS) - dnekblog

そして10月のツイートです。

誠に申し訳ございませんでした🙇

Unityつらい

そういうわけで散々更新をサボりまくっていた私も流石にマズいと思い1年ぶりにUnityのプロジェクトを開いたのです。

とりあえずビルドしてアプリを起動しプレイしようとレベル選択ボタンを押すと、・・・アプリが落ちる。

どうやら1年前の私はリリース以降何かをイジってそのまま放置していたみたいなのですが、何をどうイジったのか全く分からない。 エラーログを読んでも何故落ちるのか分からない。 そもそもバージョン管理をしていなかったのが悪いのだが。

それでももっと根を詰めて時間を掛ければ直るのかもしれませんが、ここでUnityを続けて行くかどうかの天秤が傾き、

  • バージョン管理が面倒くさい(これは古い情報かもしれません)

  • 単純な2D描画しかしないのにファイルサイズが大きくなり過ぎる

  • アプリの起動も遅くなる

  • ビルドも遅い

  • iOS/Androidを共通化した分、それぞれの痒いところに手が届きにくい(結局ネイティブコードを書かないといけない)

  • AndroidのManifest, Gradle, ProGuard辺りの設定が面倒

  • Androidのタッチレスポンスが若干遅い(マインスイーパーのようなアクションゲーにおいては致命的?)

  • ScrollViewの動きがもっさりしている

  • uGUIが微妙(リップルエフェクトが無いとか)

  • PlayerPrefs(データのセーブ/ロードを扱うクラス)にBooleanが無い(Intで代用していた)

などなど後の方はどうでも良いかもしれませんが、こんなものに時間を掛けるよりもネイティブでそれぞれ最適化した方が早く良いものができるだろ、と思いUnityを捨てる決意をした訳です。

ちなみに言うと、最近お仕事でSwiftを触っているため学習コストが下がったというのもあります。

Kotlin

脱UnityということでiOSAndroidをそれぞれネイティブで作っていくのですが、どちらから作るかといえば当然削除されてしまったAndroidです。

そして今回は色々改めるということでKotlinデビューをすることにしました。

KotlinというのはJavaを簡潔・安全になるように改良したイケイケ言語で、Android Studioでも標準で使えるようになっており既存のJavaコードをKotlinに変換してくれる機能も付いています。

一つ個人的に不満な点として、三項演算子がありません。

Javaだと

hoge = a > b ? a : b;

となるのが、Kotlinだと

hoge = if (a > b) a else b

という感じになります。

それでも型推論付き静的型付けとかnull安全とか文字列テンプレートとか総合的にはKotlinが勝っていると思います。

また、Kotlin 1.3からstableになったCoroutinesというものがあります。

blog.jetbrains.com

これは「特定のスレッドに束縛されない、中断可能な計算処理インスタンス」で、とりあえず非同期処理が簡単に書けて便利です。

私はマインスイーパーソルバーをUIスレッドの外で動かしたり、マインスイーパーソルバー内で並列処理をするのに使っています。

描画処理

さて、脱Unityにおいて一番問題となるのが描画処理です。

UnambiSweeperは元々Android Javaでネイティブアプリとして書いていたのですが、当時描画に使っていたSurfaceViewがゴミであることが分かりUnityに移行した経緯があります。

様々なView達

ここにAndroidでの描画方法が大体まとまっています。

quesera2.hatenablog.jp

内容を補足しつつざっくりまとめると、

  • (Custom) View

    • 元々低速だったがAndroid4.0以降ハードウェアアクセラレーションが適用されてまあまあ速い
  • SurfaceView

    • 別スレッドから描画できるので高速だったが、ハードウェアアクセラレーションが適用されないので今では通常のViewに負けている
  • TextureView

    • SurfaceViewの代替としてAndroid4.0で登場し通常のViewに組み込める上にOpenGLで描画してくれるが、Bitmapを延々と生成するだけでメモリ消費が半端なく電力消費もヤバい
    • Android7.0以降ではSurfaceViewもViewと同期できるようになりTextureViewは下位互換と化した

というわけで結論としてはCustomViewを使え、もっと高速に描画したいなら今流行りのVulkanを使えということらしいです。

私としては、VulkanはAndroid7.0以降が必要なので現在のシェアを考えると却下、CustomViewも十分な速度が出るか不安でした。

GLSurfaceView

じゃあどうするのかと言うと、↑の記事で奇特と一蹴されてしまったGLSurfaceViewを使います。

まあ奇特と書かれている通り、私も以前は面倒臭そうと思って見て見ぬふりをしていましたが、 OpenGL ESで描画出来て速いということを否定する意見は見当たらなかったので思い切って学んでみることにしました (ちゃんと設計すればTextureViewみたいにメモリも食わない)。

最初に雰囲気を掴むのにこのサイトが良かったので紹介しておきます。

独学で 1 ヶ月間 OpenGL を学んで得た基礎知識のまとめ ~ 2D 編 ~ · けんごのお屋敷

OpenGL ESにはいくつかバージョンがあり1.0と2.0以降でほとんど別物になってるようですが、2.0はAndroid2.2以降で使えるので今ならまず問題ないでしょう。

OpenGL ES  |  Android Developers

実際に学んでみたところ、確かにコーディング量自体は多いのですが、やっていること自体は合理的で納得できるものでした。 少なくとも2Dの範囲であれば努力に見合う成果が得られると思います。

VBO/IBO

また、↑の入門記事には載っていませんが、大量のマスを効率的に描画するのにVBOとIBOをガンガン使っています。

VBO (Vertex Buffer Object) 及びIBO (Index Buffer Objext) は、何度も繰り返し使う頂点座標及びインデックスを予め登録しておくためのものですが、 インターネット上にあまり良い資料が無くて苦労したのでざっくりと使い方を書いておきます(入門記事を読んでいる前提で説明します)。

object BufferUtil {
    fun convert(data: FloatArray): FloatBuffer {
        val bb = ByteBuffer.allocateDirect(data.size * 4)
        bb.order(ByteOrder.nativeOrder())

        val floatBuffer = bb.asFloatBuffer()
        floatBuffer.put(data)
        floatBuffer.position(0)

        return floatBuffer
    }

    fun convert(data: ShortArray): ShortBuffer {
        val bb = ByteBuffer.allocateDirect(data.size * 2)
        bb.order(ByteOrder.nativeOrder())

        val shortBuffer = bb.asShortBuffer()
        shortBuffer.put(data)
        shortBuffer.position(0)

        return shortBuffer
    }
}

BufferUtilはHello World in OpenGL! · けんごのお屋敷JavaコードをKotlinに変換して使わせていただいています。

fun makeBufferObject(buffer: Buffer, size: Int, target: Int): Int {
    val id = IntArray(1)

    GLES20.glGenBuffers(1, id, 0)
    GLES20.glBindBuffer(target, id[0])
    GLES20.glBufferData(target, buffer.capacity() * size, buffer, GLES20.GL_STATIC_DRAW)
    GLES20.glBindBuffer(target, 0)

    return id[0]
}

bufferにはBufferUtilで配列をconvertしたもの、sizeにはバッファーの1要素のバイト数(Floatなら4、Shortなら2)、targetにはVBOならGLES20.GL_ARRAY_BUFFER、IBOならGLES20.GL_ELEMENT_ARRAY_BUFFERを入れます。

fun getVerticesId(left: Float, right: Float, top: Float, bottom: Float) =
    makeBufferObject(
        BufferUtil.convert(floatArrayOf(left, top, left, bottom, right, top, right, bottom)),
            4, GLES20.GL_ARRAY_BUFFER)

頂点座標はこのようにまとめておくと良いでしょう。

あとはvertexIdとindexIdを保持しておき、レンダラーのonDrawFrame()

GLES20.glBindBuffer(GLES20.GL_ELEMENT_ARRAY_BUFFER, indexId)
GLES20.glEnableVertexAttribArray(attLocPosition)
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, verticesId)
GLES20.glVertexAttribPointer(attLocPos, 2, GLES20.GL_FLOAT,false, 0, 0)
// unbind with 0.
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, 0)
GLES20.glDrawElements(GLES20.GL_TRIANGLE_STRIP, 4, GLES20.GL_UNSIGNED_SHORT, 0)

みたいにすればOKです(最後は雰囲気で)。

ソルバー改良

こうしてネイティブにすることによる懸念は消え去ったわけですが、折角作り直すのだから他の部分も改善しよう、 ということで一番大事だと思ったのが、ソルバーの改良です。

運ゲー排除とは

運ゲー排除マインスイーパーは、プレイヤーの皆さんに論理的に解ける盤面を提供するために、 各盤面が論理的に解けるかどうかの判定を内部で行っています。

もう少し詳しく言うと、内部にマインスイーパーを解くAI(ソルバー)が居て、 このソルバーくんは論理的に解ける所まで解いていって、これ以上は論理的に考えても分からん、となったら運ゲーだと判定してくれます。 逆に最後まで解けたら、これは運ゲーではないと判定します。

そして実際にプレイヤーに盤面を提供する流れは、

  1. プレイヤーが最初に開けたいマスをタップする

  2. そのマスと周囲8マス以外にランダムに地雷をバラ撒く

  3. ソルバーくんが解く

  4. 運ゲーと判定されたら2に戻る、運ゲーではないと判定されたらプレイヤーに提供してゲーム開始

となっています。

さて、ここで問題となるのは、このソルバーくんに論理的に解けるはずの盤面を解かせてみても運ゲーと判定してしまうことがあるということです。

要するに、今までのソルバーくんは運ゲーを「これは論理的に解ける」と誤解してしまうことは無くても、 よく考えたら論理的に解けるはずでも「ちょっと自分の頭では分からんな」となることがある訳です。

これの何が問題かと言うと、本来出題されるべき難しい盤面が出題されず、全体的なレベルが下がってしまっているということです。

ソルバーの仕組み

そもそもマインスイーパーのソルバーってどうやって実装するんでしょう?

申し訳ないのですが、詳しいことは秘密です。私の収入源なので。

ただ、おおまかなポイントを何個か紹介していきたいと思います。

全探索

まず、一番ナイーブな方法として全探索があります。

つまり、ある時点で開いていないマスに地雷を配置する全てのパターンを列挙し、 どのパターンでも地雷が配置されないマスがあったらそこは安全と判断して開き、次の時点を考えるというのを繰り返すものです。

これは絶対に運ゲーが排除できる単純かつ素晴らしい方法ですが、計算に物凄い時間が掛かる可能性があります。

例えば↓の盤面では、開いていないマスが421個、その中に地雷が99個隠れています。

実際にはこうなっています。

これが分かっていないとして、一体何パターンの配置を考えれば良いのかと言うと

_{421}C_{99}=243332982655566090675703797315807061004280051114317154993140882340226279607571333586485745193293500

ざっと2\cdot10^{98}通りといったところです。

大体の目安として1000万通り処理するのに1秒掛かるとすると、7\cdot10^{83}年以上掛かります。

少なくとも我々が生きている間に計算が終わることはないでしょう。

隣接マス

よく考えてみると、上の方の数字マスに隣接しているマス以外はどこに地雷があったところで運ゲーかどうかの判断には関わり得ないですよね?

すると、今回考慮に入れるべきマスは数字マスに隣接している42マスとなり、この中に0〜42個を入れる組み合わせを考えれば良くなります。

つまり42マスそれぞれについて地雷があるかどうかを考えてみれば良いので、

2^{42}=4,398,046,511,104 通りになります。

これなら約5日間で済むので、生きている内に分かりそうです。

地雷数確定マス

ただ、生きている内と言っても1回プレイするのに何日も待ちたくは無いですよね。

そこでもっと人間的な手法を導入してみましょう。

まずは開いていないマスの数と地雷数が一致する場合です。

特に角が1であるような場合は分かりやすく、 そこが地雷だと確定するのでその隣にも1があればそこに隣接する他のマスは全て安全となります。

当たり前の話をしてしまいましたが、まずはこういう所から考えて、少しでも組み合わせを減らしていくことが大事です。

隣接数字マス

次に、ちょっとマインスイーパーをやったことがある人なら皆やっているであろう、数字マス同士の比較です。

例えば、有名なパターンとして1 2 1が並んでいたらそれぞれの1の下に地雷があって2の下は安全、みたいなのがありますね。

これをもう少し一般化することで、かなりのパターンが解けるようになります。

今回の盤面であれば、自明なものもありますがとりあえず数字マスは全部で36個見えています。

共通の隣接未開マスを持つ数字マス同士を2個ずつ比較していくと、大体100通りくらいに収まるでしょう。

3個以上の隣接数字マス

ただ、この方法では解けないパターンが存在します。

例えばこんなパターンがあるとします。

?  ?  ?  ?
?  3  2  💣
?  2  2  1
?  💣 1

これはどの2つの数字マス同士を比較しても情報が出ません。

しかし、左上の3と左下の2、右上の2の3個を同時に比較することで、

💣 ?  ? ✅
?  3  2  💣
?  2  2  1
✅ 💣 1

これだけ推定できます。ここまで来れば恐らく他のマスも解けるでしょう。

これで解決と思うかもしれませんが、この比較する数字マスを3個以上に増やしてしまうと、結局数字マスの組み合わせが爆発的に増えてしまい何日も掛かってしまうことになるのです。

SATソルバー

そういうわけで結局部分的に全探索する羽目になる場合があるのですが、 実は比較的効率良く組み合わせを探索する方法があります。

それがSATです。

充足可能性問題 - Wikipedia

詳しくはWikipediaでも読んで欲しいのですが、とある組み合わせの問題を、 イイ感じに真偽値を組み合わせた形に変形させることで高速に解けるようにするというものです。

数独ソルバーなんかは大体このSATを使っているはずです。

軽くて速いことで有名なMiniSatというSATソルバーがあるのですが、これのJavaラッパーがあったので使わせていただきました。

github.com

現時点で私以外⭐を付けていませんが、とても役に立っています。ありがとうございます。

残り地雷数

実はマインスイーパーにおける情報は数字マスだけではありません。

残りの地雷数によって配置が確定することがあるのです。

例えばこういうパターンがよくあります。

壁    1  1  1
壁 1  2  💣 1
壁 ?  ?  2  1
壁 ?  ?  1
壁 壁 壁 壁 壁

これは一見すると運ゲーですが、残り地雷数が1個か3個の場合、1通りに確定します。 なお、2個の場合は運ゲーです。

実はこの残り地雷数を考慮した処理が一番面倒で、ここが特に企業秘密になります。

厳密モード

こうしてソルバーくんは運ゲーの盤面と運ゲーでない盤面を完璧に判定することが出来るようになったのでした。

無事出題される盤面の難易度は改善されたのですが、これにより「厳密モード」というものが実現可能になりました。

「厳密モード」というのは簡単に言うと、運ゲープレイを禁止するモードです。

たとえ地雷が無いマスであっても論理的に地雷が無いと分かるマスでなければタップした時点でゲームオーバーになります。

つまりこういう感じです。

リツイートお願いします!!!

こうして、より知的でスリリングなマインスイーパーが遊べるようになりました。

その他

スクショ共有

↑のツイートにも書いていますが、スクショ共有機能を追加しました。

GLSurfaceViewと通常のViewでスクショの撮り方が異なるので実装がちょっと大変でした。

遊び方動画

Unity版のアプリにも遊び方の説明は載せていたのですが、文が淡々と箇条書きされていて読む気しないだろうなぁ、と思っていたので、頑張って動画にしてみました。

www.youtube.com

雑コラですが英語版も作ってあります。

www.youtube.com

最初はiMovieで無料で作ってやるぜと思っていたのですが、何故か縦向きの動画を編集することができなかったので、Final Cut Pro Xのフリートライアル版を使って作りました。

動画制作って大変だなぁと思いました。

現状&まとめ

現状ですが、管理画面でまとまった統計が出なくなったので詳しくは計算していないです。 多分UnambiSweeper Android版の総インストール数は18,000くらいだと思います。

評価は現時点で☆4.185(総評価数: 151)となっています。 皆さんありがとうございます。

iOSの方はまだまだ少ないので早くネイティブ化してユーザーを増やしたいところです。

お金欲しい・・・。

また、他にも色々アプリを作っていく予定なので、こういうアプリを作って欲しい等のご意見がありましたら、Twitterとかで教えて下さい。

twitter.com

終わりに

長文駄文失礼致しました。

最後にもう一度アプリへのリンクを載せておきますので、是非お試し下さい。

さて、明日の記事はid:CHY72さんの「太古のPython(Python0.9)を眺めてみる」です!

Pythonはあまり触ったことがないですが、Pで始まる言語を見るとなんだか面白そうな予感がしてきますね。

変わったみたいです。

chy72.hatenablog.com

KMC Advent Calendar 2018 - Adventarの他の記事はこちらからどうぞ。

Unityで漢字パズルアプリを作ったよ(Android/iOS)

この記事は KMC Advent Calendar 2017 - Adventar の6日目(12/6)の記事です。このカレンダーの内容はkyp(id:kypa)さんの尽力によって下の記事に逐一まとめられる(予定な)ので、良ければ参照してください。 kyp(id:kypa)さん、がんばってくださいね。

5日目の記事は、nna774さんのいい旅行 わるい旅行 - /dev/nona (いっと☆わーくす!)でした。

dnek_さんずっとアプリ作っててすごいですね。

ずっとと言っても年に一本しか新作を出していないのです……。

京都-大阪間を別の交通手段で行き来しているみたいですが、私は毎月箕面へけん玉をしに行くのに普通に阪急の土休日回数券を使ってしまっています。 まあ毎回ふらっと観光するまでも無く疲れるんだけど。

でも温泉にはそのうち行きたい!!

はじめに

過去にKMC会長をしていた記憶が怪しいdamaです。 Twitter名はDNEK(でぃーねっく) (@dnek_) | Twitterアプリ開発に使っている名前もDNEKです。 今は京大文学研究科のM1ですが、本当に院生なのか怪しい生活をしています。

また1年経ってみて

今年で3年目ですが、毎年12/6にKMCのAdventCalendarで記事を書いています(そもそもこれしか書いていないぞ)。 去年はこんな感じでした。

このアプリについて書いています。

今回の記事では、タイトル通り新作アプリの紹介をしてから、このアプリについて補足もします。

ニジウメ

これです。

ちなみに「にじよめ」は関係ないです。

どんなアプリか

こういうやつです(雑)。

おそらくほとんどの方が解いたことがあると思われる定番の漢字パズルです。

ちなみに「和同開珎」という名前が付いているそうですが、勝手に「二字熟語穴埋めパズル」、略して「ニジウメ」という名前を付けてしまいました。 だってこの方が分かりやすいもん。

一応知らない人のために説明しておくと、十字に並んだ漢字四字それぞれと組み合わせて二字熟語になる漢字1字を当てはめるパズルです。 例えば上の問題では、「平?」「電?」「?海」「?砂」がそれぞれ二字熟語になるように「?」に入る漢字を考えます。

文字の並び方と真ん中の穴が似ているから和同開珎なんですね。 ちなみにアプリアイコンの「ニジウメ」の文字配置もちゃんとこれに合わせています。

Wadogin.jpg
By As6022014 - As6022014が撮影, CC 表示 3.0, Link

wikipedia:和同開珎より

さらにどうでも良いことですが、この真ん中に当てはまる漢字は無さそうですね……。

このアプリの良いところ

和同開珎は、日本人しか作らないという理由もあるとは思いますが、マインスイーパーに比べて競合アプリが少ないです。

そして今回の僕のアプリも運ゲー排除ほど目立った特徴は無いです。

しかしそれでも主張したい差別化ポイントは幾つかあるので一応挙げていきたいと思います。

  • ちゃんと考えて問題を作った

実はこれ、一番主張したい部分です。

既存のアプリだと、個人的には物足りない問題が多いです。

例えばこれ。

おそらくほとんどの人が、「遷」を見れば真っ先に「遷移」を思い付くでしょう。 「遷都」派も居そうだけど、これを思い付く人はきっとその次の瞬間くらいに「遷移」も思い付きますよね。

個人的に、こういう問題はあまり面白くないと思います。 瞬発力を鍛えるのには良いかも知れませんが。

敢えて答えは言いませんが、コレなんか露骨ですよね。

そしてもっと良くないのがコレ(別のアプリです)。

この問題、私はよく考えた結果、「正解は「意」だ!」と思い喜んで入力して判定してもらったのですが、この通りGAME OVERになりました。 いや、「来意」「同意」「意味」「意趣」って完全に合ってるじゃん。何それ?

モザイクが薄いのでおそらく目の良い方なら分かると思いますが、なんと正解は「旨」だったのです! 「来旨」とか「同旨」とか確かにあるけどさぁ、「旨趣」もまぁ「趣旨」と微妙に使い分けることもあるし……。 でもこれが正解で「意」が間違いなのはおかしいだろ!!

とまぁこのように、いわゆる"重解"が発生しないように意識して作らないと、解く人がとてもガッカリすることになるのです。

こういうどちらかというとマイナーな漢字で被ることは珍しいのですが、「上」「中」「下」「人」「日」「水」あたりはかなり被りがちなので特に注意が必要です。

ちなみに、PlayStoreやAppStoreを眺めていると、問題の自動生成を謳っているものが幾つか見受けられます。 マインスイーパーであれば自動生成で結構なのですが、この漢字パズルを適当に自動生成してしまうのは良くないと思います。 上記2つの問題が発生しがちですからね。

まあ数歩譲って二字熟語の辞書データを全部突っ込んでおき、重解チェックをしながら出題するのであればある程度マシにはなるかもしれませんが、私はこの手のパズルは作者の言葉選びのセンスが光るものだと思っているので、よく考えて作っています。

じゃあお前はセンスあんのか?となるかと思いますが、実際に解いてみて判断して下さい(宣伝)。 一応私が漢検準1級であり、京大の言語学専修で学んでいるということと、問題は多少難しめに作っているということは言っておきます。

……1級じゃないんかい。

ただ私の問題も100%重解が無いとは限らないので、もし発見してしまった場合はこっそりメールかTwitterのDMで教えて下さい……。

  • ヒント機能

これは上の方のスクショを見たときに気付かれるだろうと思うのですが、左上と右下に、1つずつ「ヒントをみる」ボタンが付いています。 察しの良い方はこの位置で気付くと思うのですが、このボタンを押すと、ボタンが消えて代わりに漢字が追加で表示されます。

このタイプのヒントの出し方は他では見たことがなく、我ながら良い方法を思い付いたなと思っています。 もし他で見掛けたら教えて欲しいです。

ちなみに、このヒントは使える熟語が足りなかった所為でヒントらしく簡単に解けるよう配慮したために、露骨に分かりやすくなっているものも時々あります。 そういうものだと思って適宜使っていただけるとありがたいです。

ついでに実装の話を少しすると、最近(?)流行りの動画リワード広告というものをここで使っており、動画広告を見る対価としてヒントが見られるようになっています。 完全に慈善事業で作っているわけではないので、この辺は許してください🙏

また、ちょっと前に問題になってストアからの駆逐対象となっている”リワード広告”は似て非なるものですのでご留意下さい。 私の使っている動画リワード広告はGoogle AdMob提供のちゃんとした広告です。

この辺りは別に記事を用意したのでそちらを参照して下さい。

http://dnek.hatenablog.com/entry/2017/12/06/140449dnek.hatenablog.com

  • 各問の未既読・正答済みかどうかを表示

書いた通りの内容で、僕のアプリでは、メニューから問題を選んで解くようになっており、そのメニューの各問の右下に、「まだ」とか「とけた」という標示がされるようになっています。

問題を解く画面でも、右上に正答済みであることが表示されます。

  • 300問ある

300問あります。

かなり時間掛けてます。 多分1問10分くらい。

同じかそれ以上の時間を掛けて楽しんでいただけると幸いです。

1000問を目指して頑張っています。

常用漢字だけでも2000字以上はあるし、ストックは問題ないはず。

プライバシーポリシー

実は今回初めて、プライバシーポリシーというものを書きました。

以下に全文が載ってます。

Privacy Policy|DNEK

ちゃんと英語版も書きました。

最近のGoogle翻訳は賢いので、Google翻訳で英語にした後、不自然な部分を自分でちょちょっと修正することによりとても素早く良い訳が出来上がります(それを判断する英語力は必要です)。

ちなみに何故今になって書いたのかというと、たまたまプライバシーポリシーが必要であることに気付いたからです。

そもそもプライバシーポリシーって何かと言うと、「私はあなたのこういう個人情報をこういう方法で使おうと思ってるんですが、いいですか?」という契約文書です。 日本語だと個人情報保護方針というやつですね。

法的な話もありますが、とりあえずPlayStoreやAppStoreでは、「アプリが個人情報を扱うならそれについてポリシーを示せ」と決められているのです。

正直広告はその形態によって微妙なところがあるようですが、少なくとも私はFirebase Analyticsというものを使って匿名化されたユーザーデータ(プレイ時間とかどんな操作をしたかとか)を集めているので、書かないといけなかったわけです。

実はUnambiSweeperの方も既にFirebase Analyticsを使っているので、早い内にポリシーを示すように更新するつもりです。

あと、Googleが今年の8月になってプライバシーポリシーの示し方を明確化してきていまして、こちらに分かりやすく書いてあります。

特に重要そうなのが、

  • アプリ内で開示しなければなりません。Play の掲載情報やウェブサイトでの開示だけでは不十分です。

という部分と、

  • 同意を求めるダイアログを明確に表示する必要があります。

という所です。

私がこれのために何時間かを費やし、完成させたものがこちらです。

まあ最初の1回だけになることかと思いますが、是非ともご確認下さい。

ちなみにですが、市場に出回っているアプリの大半、特に個人開発っぽいアプリのほとんどにはプライバシーポリシーの記載がありません。 初回起動時に同意を求めているものとなると本当に僅かです。

いつ削除祭りがあるのか分からないので、自分のためにもユーザーのためにも先んじて対応しておこうと思います。

運ゲー排除マインスイーパ

こちらも1年の間に多少変わったことがあったので、補足しておきます。 ここは技術的な話しか無いです。

Metalの件

前回の記事を書いた時点で、iPhoneの一部機種においてMetalというCGAPIを使うと描画がおかしくなるバグがありました。

その後……

Metal: Fixed a crash on startup on some iOS devices. (857032)

この通りUnity5.5.1で修正されたらしいので今は普通にMetalも使っています。

ブラーエフェクトの変更

使ってくれている人はご存知かと思いますが、UnambiSweeperでは画面の上に画面を出すときに、手前を半透明にして奥にブラーを掛けています。

これを以前はImage EffectというアセットのBlur (Optimized) というのを使っていました。

詳しい説明は省くのですが、これをブラーが掛かっていない状態から程よく掛かっている状態まで一様に変化させるために、何故か複数のパラメータをいじる必要があったのです。

まあ、それはそれとして、Unityが2017にバージョンアップすると、なんとこのImageEffectが使えなくなっていたのです(自分で無理やり持ってくれば使えないことはない)。

で、UnityがPost Processing Stackという代わりのものを用意してくれていたのですが、これの2Dでの使い方がよく分からず、面倒くさいなぁと思い、良いサードパーティプラグインが無いかなぁと思って探していたら、ありました。

これです。

こいつは使い方がシンプルで分かりやすい上に、なんと1つのパラメータをいじるだけで、一様にブラー度を変化させることが出来るのです!(元々そうあって欲しかった……)

ちなみにモバイルの場合はSuperBlurFastの方を使え、とか書いてありますが、実際に使ってみると変化させた過程がすごく汚い感じになったので要注意です。 僕が何かミスってるだけかもしれないけど。

なんか他にもあった気がするけど、かなり長くなってしまった気がするしこの辺にしときます。

現状&まとめ

さて、現状なんですが、出したばかりのニジウメはまだとして、UnambiSweeperの方はAndroidは総インストール数12,000を超えております。 評価は現時点で☆4.231(総評価数: 121)となっています。 皆さんありがとうございます。 iOSの方は1,000インストールに少し足りないくらいという感じで、もうちょっと頑張って欲しいなぁと思います。

で、前回通り、最近の広告収入もぶっちゃけると、今年の3月から今までの9ヶ月くらいは大体月1万円くらい入っています。 行く行くはこれで生活出来るくらいになれば良いなぁと夢想しております。

そのためにもこれからもっとアプリを出していく予定です。 また、こういうアプリを作って欲しい等のご意見がありましたら、Twitterとかで教えて下さい。

twitter.com

終わりに

今年も長々と失礼致しました。

最後にもう一度アプリへのリンクを載せておきます。

さて、明日はnojimaさんです!

nojimaさんは僕がKMCに入った年にOBになられた、6代上の元会長さんなのですが、どういう記事を書いてくださるのか楽しみですね!

KMC Advent Calendar 2017 - Adventarの他の記事はこちらからどうぞ。

運ゲー排除マインスイーパーをiOSにも対応させた話とか

この記事は KMC Advent Calendar 2016 - Adventar 6日目(12/6)の記事です。

www.adventar.org

5日目の記事は、id:tyageさんの嘘つきPHP ZipArchive::addGlobと壊れたファイルパス – 弱いでした。

blog.tyage.net

はじめに

過去にKMCで会長をしていたのか今となっては怪しいdama*1です。 今は4回生なので一応卒論を書いているのですが、一緒にKMCに入った仲間たちがほとんど留年してしまっていて寂しい感じです。

1年経ってみて

ちょうど1年前の12/6に同じくKMCのAdventCalendarでこんな記事を書きました。

dnek.hatenablog.com

このアプリについて書いています(iOS版は後述)。

play.google.com

長ったるいまともなブログ記事を書いたのは確か初めてだったのですが、予想よりもかなり多くの方々に閲覧・反応していただけたようで良かったです。 それから1年経つ間に色々とやったことややっていないことがあるので適当にその辺の話をしようと思います。

KMC効果

実はこのアプリを初めてリリースしたのは1年前に記事を書いた日の数週間前だったのですが、記事を書いてからDL数が桁違い*2に増えた記憶があります。

総DL数は数百程度だったものの、おかげさまで新着無料ゲーム総合で200位以内に入ることができました。

KMCの知名度のおかげだと思います。感謝。

「五億円ゲット」

正月早々2本目のアプリをリリースしました。

「五億円」という経済指標は、日本人の平均生涯賃金とされる2億円の2倍を超えており、手に入れれば一生余裕を持って過ごすことができる額となっています。 2015年の京都大学11月祭では京都大学五億円同好会のブースも出展され、その人気は今も揺らぐことはありません。

そんな中、年末に唐突に思い立ち大晦日まで作業をし2016年元日にリリースしてしまったものがこちらです。

play.google.com

1円玉から500円玉までの硬貨が並んでおり、タップする毎に溜まっていくというクソゲーです。

同じくクソゲーでありながら何故か大ヒットした「100万の○〇〇」*3というアプリがあるのですが、500円玉を100万回タップすればぴったり5億円だし難易度的に丁度良いだろうと思い、作ってしまいました。

1硬貨あたり3種類の硬貨効果音を心を込めて録音したので、その音を聴いて楽しむのがオススメです。

当然流行ることはなく未だにDL数は2桁しかありません。 それでも何故かずっと続けている知人が二人も居りしかも電車内で無音でプレイしているらしく、正直意味が分からないです(遊び方は自由です)。

当然全く期待していないので一度もアプデしていないしiOSに対応する気も無いですが、もし万が一流行ることがあったら考えてみようと思います。

ユニバーサルアプリキャンペーン

良いものを作りたいと思ってUnambiSweeperを作ったのは本当で、特に手を抜いたつもりもありません。 それでもお金が欲しいという気持ちは割りとあるので、アプリ内に広告を表示させていただいており、多少の宣伝もしています。

最初はお金をかけずに宣伝したいと考えてレビューサイトにお願いしまくったのですが、案の定全く載せてもらえませんでした。 Twitterでは主にKMCの力によりそれなりの宣伝ができたのですが、やはり限度があるといった感じです。

結局3月にユニバーサルアプリキャンペーンを使ってみることにしました。 ユニバーサル(ryというのは、簡単な設定をするだけで、Googleさんがアプリ内広告とかYouTubeとかGoogle検索の検索結果とかで良い感じに宣伝してくれるやつです。 課金方式はCPC(クリック毎)になっています。

とりあえず\11,000くらい突っ込んでみたのですが、割とすぐに400DLくらい行きました。 インストール単価は27円くらい。

それで広告収入がどうなったかというと、全く増えませんでした。むしろ減った。アイエエェ……

理由を考えて見るに、主に以下の3つかなと思います。

  • 主に海外のクリック単価の低い地域に向けて宣伝していたため当然収益も低い
  • Twitterやストア内検索経由でDLしたユーザーに比べてすぐにアンインストールする人が多い
  • 自然減

貧乏学生なのでインストール単価数百円の先進国に向けて宣伝するのは多少気が引けるのですが、また余裕ができたら試してみようかなと思っています。

Unity再び

去年の記事にも書いたのですが、最初のUnambiSweeperは1回生のときにWindows向けに作りました。 その後なんとなくUnityに移植し、去年になってAndroid版を作ったという感じです。

Android版はJava & AndroidStudioで開発していたのですが、ちょっと問題がありました。 何故か電力消費が激しく、また一部端末(どうも機種依存では無さそう)で動作が著しく重くなるというものです。 恐らくSurfaceViewが原因なのですが、去年の記事が完全なブーメランとなっている気がします。

何とかしようと色々考えたのですがよく分からず、面倒なのでいっそUnityに移植してついでにiOSにも対応しようという結論に至りました。

そもそも1回生のときにUnityに移植したのではと思われるかもしれないですが、当時はPCで遊ぶことしか考えていなかったため、タッチ操作・画面移動・GooglePlayゲーム・広告対応などやらないといけないことが色々あった訳です。 また、当時のUnityで作ったスマホアプリはかなり重く、最近IL2CPP*4に対応してやっとまともになったので使う気になったというのもあります。

iOS対応

Unityはマルチプラットフォーム対応ゲームエンジンでほとんどのコードを共通化できるすごいやつなのですが、多少はAndroidiOSで個別に対応しないといけないこともあります。

というのも、Android版ではランキングや実績のためにGooglePlayGamesServicesを使っていたわけですが、折角iOSにも対応しているのに実装してもAppStoreでリジェクトされてしまうらしく、iOSでは泣く泣くGamecenterを使うことにしました。 まあ個別に書くだけでそれぞれの実装は大して難しくないのですが。

ちなみにPlayGamesの方は以下のプラグインを使い、iOSはUnity標準のusing UnityEngine.SocialPlatforms;すればいけます。

github.com

もう一つ、ヴァイブレーションはHandheld.Vibrate();で鳴らせるのですが、Androidで任意の時間鳴らすにはネイティブコードを書く必要あります。 適当なプラグインを入れても良いですが、大した実装ではないのでこの辺を参考に自分で書けば良いと思います。

ameblo.jp

一方でAdMob広告やSNSでの共有、ネイティブダイアログなんかはプラグインで簡単にいけます。

GoogleMobileAdsは割りと頻繁に更新されていて、丁度今朝Version 3.1.3がリリースされていました。

github.com

SNS共有はこれが一番使い勝手が良いと思います。

github.com

ネイティブダイアログはこちら。 ただ、3つ以上の選択肢が出せないので他に良いプラグインがあれば教えて欲しいです。

github.com

Android版のバージョン管理

通常UnityでAndroid向けにビルドするとARM/x86両方のアーキテクチャに対応するapkが出力されますが、これが結構重いので、Player SettingsのDevice Filterで設定してそれぞれ専用のapkをビルドした方が良いです。Bundle Version Codeも分けておくようにしましょう。

そうすると複数のapkを同じアプリとして公開する必要が出てくるので、Developer Console上で設定をします。 当該アプリページのAPKタブ内右上にある「アドバンスモードに切り替える」ボタンを押すと、複数apkを端末によって振り分けられるようになります。

ちなみにUnambiSweeperはAndroid2.3.3以降に対応していたのですが、Google Play Games plugin for UnityがAndroid4.0以降対応だったため、今後更新はしないものの前バージョンのapkも残し、4.0未満でもインストール出来るようにしています。

HP

プレイスコアをSNSで共有するとき、末尾にハッシュタグ#UnambiSweeperとアプリURLを付けさせてもらっています。 Android版ではPlayストアのURLをGoogle URL Shortenerで短縮したものを使っていたのですが、 iOSにも対応するにあたり片方のOSのURLだけ共有されても困るので、HP内にアプリ紹介ページを作りそこから各ストアへ飛んでもらうことにしました。 ただ、当時使っていた忍者ホームページ*5だと微妙に長い上に広告も表示されてなんか嫌だったので、新しく作り直すことにしました。

最近(?)は便利なもので、Freenomというサービスで、.tk/.ml/.ga/.cf/.gqといった主にアフリカのトップレベルドメインが無料で取得できるようになっています。

Freenom - 誰でも利用できる名前

辞書登録されているようなものでなければ、最短4文字のドメインを取得することができます。 私はdnek.cfを取得しました。 今の所、最低年1回の契約更新を忘れなければ使い続けられるはずです。

後はホームページサービスですが、ウェブクロウという無料・広告無し・商用可・独自ドメイン対応の良い感じのやつがあります。

www.webcrow.jp

これらを登録したら後はネームサーバーを設定してあげれば簡単に広告無しで短いドメインのHPが手に入ります。

.htaccessもちゃんと使える*6のでリネームして.htmlを消すようにし、http://dnek.cf/unambiという短いURLが出来ました。 めでたい。

Metal

試行錯誤とサボりを繰り返しつつなんとか10月末にリリースすることができました。

しかしすぐにとある知人からバグ報告がありスクショを見せてもらったのですが、スタート画面がうまく表示されずまともに使えない状況でした。

ググってみるとこんな記事が見つかりました。

answers.unity3d.com

要はiPhone5s(他の機種もあるかも)だとUGUI*7がMetal*8で上手く描画出来ないらしいので、使わないように設定したら直りました。 一安心。バグ報告感謝。

現状&まとめ

以上のような感じで色々とやってきたわけですが、現在は総インストール数が4,400+、評価が☆4.259(総評価数: 81)といった感じです。

更にぶっちゃけてしまうと、最近の広告収入は百数十円/日、約5千円/月、総計で5万円弱といったところです。 Android : iOS = 3 : 2くらい。 多いと思う方も少ないと思う方もいると思いますが、とりあえずお小遣い程度にはなっています。

アプリの完成度はゲームとしてちゃんと遊べるくらいになっていると思いますが、まだまだ改善の余地があるので今後もアプデを続けていきたいと思います。 あとこの記事を書いている途中で気付いたのですが、Unity5.5の安定版が11/30にリリースされていたらしいので、GoogleMobileAdsの更新も兼ねて後で試してみようと思います。

他にもアプリのアイデア自体はいくつかあるのでどんどん作っていきたいです。また、こういうの作って欲しい等ありましたらTwitterとかで教えて下さい。

twitter.com

あとこちらもインストールよろしくお願いします。

play.google.com

また、宣伝していただける場合は以下の紹介ページをご利用下さい。

UnambiSweeper|DNEK

終わりに

今年も長文駄文失礼致しました。

さて、明日はid:yu3marsさんです!

KMC Advent Calendar 2016 - Adventarの他の記事はこちらからどうぞ。

www.adventar.org

*1:damaはKMC内でのID、DNEKは主にTwitterとかで使っている名前

*2:1桁/日→2桁/日

*3:筆者による伏せ字

*4:中間言語からC++に変換して良い感じにしてくれるやつ

*5:実はUnambiSweeperのパッケージ名にその名残がある

*6:忍者ホームページでは使えなかった

*7:Unity標準のGUI

*8:一部のApple製品で使われているCGAPI

運ゲー排除マインスイーパーをAndroidアプリにした話と市場に対する雑感

(2016/12/18追記) 続きです。

dnek.hatenablog.com


この記事は KMC Advent Calendar 2015 - Adventar 6日目(12/6)の記事です。

www.adventar.org

5日目の記事は、id:Pasta-KさんのWebExtension現状確認してみた - Pastalablog in はてなでした。

はじめに

最近KMCで代表*1の任期が満了となり、晴れて平部員に昇格した*2dama*3です。

github.com

ちょっと前にPietのIDEのようなものを作っていました(宣伝)が、最近Androidアプリを作ってリリースしてみた(宣伝)ので、その辺で色々思ったことを書こうと思います。 ちょっとだけ開発上の知見っぽいものも書きます(マインスイーパー以外でも役に立ちそう?)。

マインスイーパーの欠陥

さて、ある程度マインスイーパーで遊んだことがある人であればご存知だと思いますが、マインスイーパーには運ゲーという致命的欠陥(偏見?)があります。

f:id:dnek:20151202050012p:plain

例えば↑の画像では、右下の2マスのうちどちらに地雷が埋まっているのかは完全に五分五分です。 このような単純な例を含め、特に上級においては頻繁に運ゲーが発生します。

頑張って考えて解いていたゲームがいきなり非論理的要素によって中断されてしまうのは非常に理不尽なことです。 ですが私はこの運ゲーの存在によって元々論理的に解けるはずの盤面がきちんと解かれなくなることの方が問題であると思います。

つまりどういうことかというと、とても複雑であるが論理的に解ける盤面でも、絶対に運ゲーが無いという保証が無い故にその検証にかける時間を惜しまれ運任せにされてしまう場合があるのです。

ある程度プレイしている人にとってこの運ゲーの存在は当たり前のことかと思いますが、そもそも運ゲーが無いことが保証されていれば、どれだけ論理的思考に時間を使おうとする意識が高まるでしょうか。

UnambiSweeper

この理不尽とオサラバするため、私が1回生の時*4に作ったのがUnambi Sweeper*5です。 Unambiというのは"Unambiguous"*6の略です。

当時はWindows向けにVB.NET書いたり*7、なんとなくUnityに移植したり*8していました。 必ず論理的に解けるようにしたのに加え、私のようなキーボードプレイヤー*9*10のために操作性を改善*11したりしました。

そしてAndroid

実はUnambiSweeperを作った頃、Androidを触ろうとしたがEclipseでの開発に手間取って頓挫した記憶があります*12

それから時は流れてKMC春合宿2015

このAdvent Calenderの作成者でもあるid:nonyleneさんのスライド発表を見ました。

www.slideshare.net

実はそこでAndroid Studioの存在を知ったのです。 Eclipseはダメだったけどこれならイケそう、と思い、しばらく触れていなかった*13UnambiSweeperをAndroidに移植してみようと思い立ったのです。

そして半年ほど勉強しつつ頑張ってリリースしたものがこちら。

是非遊んでみてください!!!

で終わるわけではない。

UnambiSweeperの良い所

とりあえず運ゲーにならないというだけでも他のマインスイーパアプリではなくUnambiSweeperを選んでいただけることと思いますが、そもそもマインスイーパーとしての完成度が他とは違います(多分)。

UnambiSweeperの良い所

類似アプリの良くない所

というわけでここから今までよりも自信過剰な発言をしていきます。

現状、PlayStoreにて「マインスイーパー」で検索してみると、有象無象のマインスイーパーアプリが出て来ます。

gyazo.com

リリース時期にもよるでしょうが、初めの方に表示されるアプリには10万、100万DLレベルのものがいくつもあります。

ですが、これらの人気アプリでも(評価が高いものでも)実際に遊んでみると特に遊ぶ価値はない気がしますが色々と不完全な部分が見つかります。

以下、気付いたものを挙げていきます(すべて5万DL以上のアプリで確認できるものです)

  • ボタンがフィールド上に重ねて置いてあってミスタッチし易い

おそらく現状で一番まともだと思われる類似アプリ(100万DL)でほぼ唯一気になった点です。 UnambiSweeperでは、画面の上下端に半透明のカバーをしてその上にボタンなどのUIを設置しています。

  • プレイ画面が表示された瞬間にタイマーがスタートする

これはなかなか致命的な問題だと思うのですが、100万DLのものを含めいくつかのアプリで確認できます。

  • 最初に開けたマスの周囲に地雷が存在する

普通に考えれば分かることですが、最初に開いたマスの周囲8マスのいずれかに地雷が存在すれば、そこは数字マスとなり周囲のマスは自動的に開かれません。 つまり初めから運ゲー状態となるわけです。 これはおそらく半分以上の類似アプリで確認できる問題です。 由々しき状況です。 ちなみにWindows付属のマインスイーパーではVistaから改善がなされています。 特に実装上難しいものではないですし、マインスイーパーを実装する上で最低限のマナーだと私は思っています。

  • 最初に開けたマスに地雷が存在する

最初に開けたマスに地雷が存在するものもあります。論外です。

  • 周囲一気消しが出来ない

マインスイーパーでは、数字マスの周囲にその数字と同数のフラグが立っている場合、そのマスに旗立てと同等の操作*14を行うことでそれ以外のマスを一気に開けることが出来ます。 フラグを使うプレイヤー*15にとっては必須と言えるこの機能を有していないアプリも数多くあります。

  • 地雷/フラグ切り替えが出来ない

多くのアプリでは、デフォルトで「タップ = マスを開く」、「ロングタップ = 旗を立てる」という仕様になっています。 ですが、フラグを使うプレイヤーは上記の周囲一気消しを用いるため旗立ての操作をすることの方が多いし、単純に一々ロングタップするよりも操作を入れ替えてタップで旗を立てる方が速いです。 そのため、切り替えボタンがあると便利なのですが実装されていないアプリもいくらか存在します。

  • 動作が重い

SurfaceViewGLSurfaceViewで実装しましょう。あるいは画像をあらかじめcreateScaledBitmap)などでScaleしてから描画しましょう。とかそんな所だと思います。

  • タップしにくい

触れてから少し指を動かしただけでスクロールと見做されてしまい中々タップできないという問題です。 これはおそらくMotionEventのACTION_MOVEをそのまま使ってしまっているのが原因だと思われます。 特に複雑な実装をしようと思わないのであれば、GestureDetector.SimpleOnGestureListenerのonSingleTapUpやonScrollなどを使えば良いと思います。

但し一度タップしてからすぐに近くの場所をタップした場合これはダブルタップと見做され、onSingleTapUpでは2回目のタップを検出することが出来ません。 一応GestureDetector.OnDoubleTapListenerというものが存在するのですが、これでも何故か2回目のタップをスクロールと分けて検出することが出来ません。 そのため、私はACTION_MOVEで初期タップ位置からの距離を計算してスクロールになるかどうかを判定しています。 この距離は

ViewConfiguration.get(getContext()).getScaledTouchSlop()

などで取得することが出来ます。 ViewConfigurationでは他にも色々な値が取得できるので一度確認してみると良いと思います。

  • ピンチイン/アウトが変

いくらかのアプリではピンチ(二指ズーム)が出来ます。 しかしその多くはフィールドの中心を基準に拡縮しているため、フィールドの端の方で拡大した状態からピンチアウトしようとすると、中心に吸い寄せられるように縮小されてしまいます。 これは、ピンチ時にタッチしている2点間の中心を取得することで改善することが出来ます。

  • よく分からないUI

ズームが出来ない代わりに、タッチ位置の周囲を拡大して表示するようなUIを実装しているもの(10万DL)がありますが、正直かなり操作しにくいです。 もう少し素直なズーム機能を実装してほしいものです。

  • よく分からない盤面デザイン

フィールドのサイズは画面一杯で固定、マスのサイズを設定するとそれに応じて画面に入るだけのマスが詰められる、難易度を変えると地雷の密度が変わる、というちょっと不思議な盤面のデザインをしているものがあります(50万DL)。 これに関しては好みによるのかもしれませんが、同じ難易度でマスの数が変わりまくるというのは良くないのでは、と思います。

UnambiSweeperの良い所(再)

さて、だいぶ長々と文句を言って来ましたが、上記の問題点をすべてクリアしているのはおそらくUnambiSweeperだと思います。割りとマジで。 もしそうでないAndroidアプリがあれば教えていただけると幸いです。

さて、実は今までありそうでなかった、おそらくUnambiSweeper独自の機能があります。

  • 残りの安全なマスの数が分かる

普通は左上か左下に、「地雷の数 - 旗の数」が表示されているものと思います。 これは旗を使うプレイヤーにとっては有用なのですが、私のような旗を使わないプレイヤーにとってはあまり役に立つものではありません。 そこで、まだ開かれていない安全なマスの数を併記するようにしました。

  • ゲームオーバー時にどこが安全だったか分かる

ゲームオーバー時、論理的に考えて次に開いても問題がなかったマスをチェックマークで表示する機能を実装しています。 これは、論理的に必ず解けることが保証されているUnambiSweeperだからこそ出来るものです。

数々の問題点をクリアしている上に、上記の機能を有し運ゲーも発生しないUnambiSweeperって結構スゴイのでは?、と勝手に思ってしまいます。

お願い

これを書いている現在、UnambiSweeperのインストール数は20ちょっとしかありません。 もっとインストールして欲しいと云うのもありますが、正直他の類似アプリがこんなにDLされてしかもそれなりの高評価を得ている状況は非常にマズイと思います。

単純にプロモーションの差なのかなと思っています。

もしも私の主張に同意してくださる方がいらっしゃれば、是非とも他のアプリを駆逐してUnambiSweeperを台頭させることに協力していただければと思います。

というわけで、↓DL&レビューよろしくお願いします!!!

twitterはこちら。 DNEK(でぃーねっく) (@dnek_) | Twitter

(2016/12/18追記) 続きです(再掲)。

dnek.hatenablog.com

終わりに

長文駄文失礼致しました。

さて、明日の記事は、id:asRagiさんの神主講演に行った話 - らぎメモです!

KMC Advent Calendar 2015 - Adventarの他の記事はこちらからどうぞ。

www.adventar.org

*1:KMCでは前年の会長が自動的に代表に繰り上がる

*2:KMCのカースト最底辺が会長、次点が代表(要出典)

*3:damaはKMC内でのID、DNEKは主にAndroid Developerとして使っている名前

*4:2015年度現在は3回生なので2年前

*5:現状"Unambi Sweeper"と離して書いてしまうと検索にかからないので、ここだけ"Unambi Sweeper"書いておく(2015/12/10)

*6:両義的でない、の意

*7:NF2013とC85で出展した

*8:UnityなのでUnimbiSweeperと名付けた

*9:キーボードプレイは速さと正確さを兼ね備えた最強のプレイスタイル

*10:特に中級以上でオススメ

*11:Fキーで旗を立てられるようにしたりマスを開くタイミングをKeyUpからKeyDownにしたり

*12:当時、UnityからAndroid向けに出力するのもなんか嫌だと思ってた気がする、なんでかな?

*13:実はUnambiSweeperを作ってハマり過ぎたため自ら封印していた

*14:PCで云う右クリックなど

*15:ちなみに私はNF(non-flagging)プレイヤーです

初めまして。

初めまして。DNEKです。

最近Androidアプリを作っています。

とりあえず現在UnambiSweeperというものを公開しているのでよろしければ遊んで見て下さい。

簡単に云うと、運ゲーにならないマインスイーパー」です。操作性もいい感じだと思うのでよろしくお願いします。

Get it on Google Play

 

それから少し前にPietのエディタも作ったのでこちらもよろしくお願いします。

github.com