質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

91.06%

  • JavaScript

    13305questions

    JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

  • アルゴリズム

    333questions

    アルゴリズムとは、定められた目的を達成するために、プログラムの理論的な動作を定義するものです。

  • ゲーム開発

    149questions

Javascriptで、5×6のパネルで連続するパネルを計算する方法をご教示いただきたいです

解決済

回答 8

投稿 編集

  • 評価
  • クリップ 2
  • VIEW 402

clark

score 11

現在3マッチパズルゲームを開発しております。
ゲームを開始すると5×6のパネルの中に、4種類ほどの異なるパネルがランダムで並びます。
(例として、「剣」「盾」「コイン」「ポーション」とさせてください)

これをユーザーが消していってゲームが進行するのですが、
同じ種類のパネルを3つ以上選択した場合にその選択したパネルを消すことができます。
ななめに選択はできず、縦か横へ連続して3つ以上選択した場合に限ります。

こういう仕様ですので、ゲームを開始した際に、

「この5×6のパネルの中で最低でもどこか1箇所は、同じ種類のパネルが3つ以上連続している」

必要があるのですが、そのアルゴリズムが考えつかず、質問させていただいている次第です。
どなたか解決方法がお分かりの方がおられましたらご教示いただけないでしょうか?

よろしくお願いいたします。

【追記】
説明不足ですみません。
上記の、

「5×6のパネルの中で4種類ほどの異なるパネルがランダムで並んでおり、
最低でもどこか1箇所は、同じ種類のパネルが3つ以上連続している」

こちらを判定する Javascript での具体的なコードを示していただけると大変助かります。

【解決】
ご回答いただき、ありがとうございました。
現在みなさまからいただいたアドバイスを参考にコードを作成しております。
私の中で一番しっくりとくる回答をいただいた方をベストアンサーとさせていただきましたが、
その他の方からいただいた回答も大変参考になりました。
誠にありがとうございました。

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

質問への追記・修正、ベストアンサー選択の依頼

  • 退会済みユーザー

    2017/12/20 19:41

    複数のユーザーから「やってほしいことだけを記載した丸投げの質問」という意見がありました
    「質問を編集する」ボタンから編集を行い、調査したこと・試したことを記入していただくと、回答が得られやすくなります。

  • clark

    2017/12/22 09:51

    現在ご回答いただいた内容でコードを作成しております。 解決し次第報告させてください。 よろしくお願いいたします。

    キャンセル

回答 8

checkベストアンサー

+3

 DungeonRaid

はい、おっしゃる通り、DungeonRaid をかなり参考にしております。

下記リンク先を読んで、概ね要件は理解できました。

要件をまとめると、次のようになりますね。

  • 指で上下左右に隣接するパネルをなぞる
  • 指を離した段階で3つ以上のパネルが連結していれば連結パネルを消去し、空きスペースに上からパネルが落ちてくる
  • 常に隣接パネル(3つ以上)が一つ以上存在しなければならない

 パターン化

3つのパネルが隣接する組み合わせは次の6通りだけです。

■
■
■

■■■

■
■■

 ■
■■

■■
 ■

■■
■

従って、上記6パターンに合致する隣接パネルが一つ以上存在する事が保証できれば良い、という事になります。
隣接パネルを探すには起点となる座標から上記パターンと一致するか、確認していけば良い。
各々で起点となる座標は3個あるので、単純計算で18通りありますが、計算できない量ではないでしょう。

そして、落ちてくるパネルのパターンですが、これは更に少なく、4つだけです。

■
■
■

■■■

■■
 ■

■■
■

※なお、ここでは「4つ以上が連結した隣接パネル」を考慮する必要はありません。
3つのパネルが隣接すれば、詰みにならない事が確定するからです。

 単純な解決法

さて、もうお分かりかと思いますが、パネルが落ちてきた結果、詰みにならない一番簡単な解決法は「落ちてくるパネルを全て同色にすること」です。
落ちてくるパネルは必ず隣接する為、同色にすれば必ず隣接パネルとして消せます。
ただし、この解決法はゲーム性を著しく損なう悪手です。
「落ちてくるパネルが同色になること」にユーザはすぐに気が付きますので、パネルが落ちてきた瞬間に落ちたパネルを指をなぞるだけの単純作業と化します。
常にパネルを消せる状態にするという性質上、「同時に消したパネル数が多い程点数が高くなる」のような点数制を採用している可能性が高い為、タイムアタックモードで制限時間内に点数を競うゲームであった場合に、「落ちてくるパネルを消すだけのユーザ」は4つ以上を消すユーザに点数で負けてしまうので、結果的には使われないでしょうが、それでも同色パネルが常に落ちてくるとランダム性が損なわれるので、ゲーム性は落ちてしまうと思います。

 もう少し、煮詰めた解決法

とりあえずの対策としては、下記方法が考えられます。

  • パネルが落ちる前に残りパネルで消せる状況か確認
  • 消せるパネルが存在しないなら、空白のパネルに隣接したパネルと同色パネルを1~2個落として隣接パネルを完成させ、残りはランダムにパネルを選ぶ

隣接パネルは「パターン化」の方法を使って、18通りの組み合わせを試していきます。

 ランダム性と難易度設定

ここまでは「パターン通りのパネル配置になっているか」で確認する方法を書いてきましたが、おそらく一番いいのは全ての隣接パネルをキャッシュしておき、パネルが消えて落ちる度に部分的に更新して、全体を常に把握しておくことです。
「単純な解決法」では単純ゲームと化してしまうリスクに触れましたが、単純に乱数でランダムにパネルを選んで最低ライン(一つは隣接パネルを作る)を守る方式だと、乱数に難易度が影響されて「時の運」に左右されすぎだからです。
出来れば、難易度も制作側のコントロール下にあってほしいものです。
隣接パネルを探す単純なアルゴリズムに次があります。

  1. 起点となる座標を決め、座標を配列(adjacentPanel)にキャッシュする
  2. 上下左右のパネルを確認し、同色パネルなら配列に座標をキャッシュする(この時、上下左右を確認した座標は配列 checkedPanel に格納しておく)
  3. adjacentPanel.length === checkedPanel.length になるまで 2. を繰り返す

上記作業を繰り返し、全ての adjacentPanel を配列 allPanel に格納します。
そして、パネルを消した時には消したパネルの上方に位置するパネルに隣接するパネルの情報を全て消去し、残ったパネルで隣接パネルがないか計算します。
隣接パネルが存在するなら、ランダムにパネルを落とし、そうでないなら、残ったパネルに隣接するパネルを落とします。
最後に落としたパネルと隣接するパネルを含めて再計算します。
汎用性を上げる為には、配列 allPanel から任意の座標を含んだ adjacentPanel を返す関数を作っておくと良いでしょう。

この方法を採用した場合、常にN個以上の隣接パネルが存在する状態を作り出すことが可能となります。
パネルを落とすたびに全パネルを計算する方法も勿論ありますが、それではコストが高いので、再計算する範囲を最小限に抑えるのがこの方法の良いところです。
ユーザに難易度選択をさせる事が期待されるゲームなのであれば、下記の方式で難易度設定する事が可能です。

  • Hard … 常に1個以上の隣接パネルが存在する
  • Normal … 常に3個以上の隣接パネルが存在する
  • Easy … 常に5個以上の隣接パネルが存在する

Re: clark さん

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/12/22 09:45

    丁寧にご説明いただきありがとうございます、大変参考になります。
    アドバイスいただいた「隣接パネルを探す単純なアルゴリズム」を作成し、
    試してみようと思います。
    誠にありがとうございます。

    キャンセル

  • 2017/12/22 10:43 編集

    単純なアルゴリズムは個人的には推奨しませんが、解決法の一つではありますね…。
    上級ユーザはおそらく落ちてくるパネル周辺に同色パネルを残しておき、落ちてきたパネルと同色だった場合に一気に消して点数を稼ごうとします。
    「同色の隣接パネルをいかにして上方に配置できるか」を競うゲームとなりそうですね。

    キャンセル

  • 2017/12/22 13:37

    横からすみません、clarkさんの言う「隣接パネルを探す単純なアルゴリズム」は、think49さんの回答の「単純な解決法」のことではなく、「ランダム性と難易度設定」にある文章の引用ではないでしょうか。

    キャンセル

  • 2017/12/22 17:44

    To: Lhankor_Mhy さん
    ご指摘ありがとうございます。
    一言一句一致するので、その解釈が正しそうですね。

    キャンセル

+3

いちばん手っ取り早い方法としては、「まず最初に3連続をランダムな箇所・色で入れておいて、それからランダムに残りを埋める」という手法があります。

Windowsのマインスイーパーの場合、1回目は絶対に地雷を踏まないようになっていますが、クリックした瞬間に生成する、あるいは1回目のクリックで地雷があればどこかに移動する、といった方法で対応しているものと思われます。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/12/20 15:02

    ご回答いただきありがとうございます、勉強になります。

    「まず最初に3連続をランダムな箇所・色で入れておいて、それからランダムに残りを埋める」

    こちらの方法は最初にパネルを用意する際には使用できると思うのですが、
    ユーザーがいくつかパネルを消した際には、現在残っているパネルと補充分とを合わせて連続するパネルを考えるので、
    この方法は最初しか使用できないと思うのですが、いかがでしょうか?

    キャンセル

  • 2017/12/20 15:09

    補充するときも、常にどこかで3連続させないといけない縛りがあるのでしょうか。

    キャンセル

  • 2017/12/20 15:25

    はい、ゲームの仕様上3つ以上連続した同じ種類のパネルを消しながらゲームを進行しますので、
    ユーザーがパネルを消し、その分の新しいパネルが補充される際にも、毎回、

    「この5×6のパネルの中で最低でもどこか1箇所は、同じ種類のパネルが3つ以上連続しているかどうか」

    の判定が必要になってくると思います。
    (もしユーザーが操作できるパネルが存在しない場合、ゲームが進行できなくなってしまいますので)

    ですので上記を判定する計算式などお分かりでしたらご教示いただきたい次第です。

    キャンセル

  • 2017/12/20 15:51

    フィールドの状況や消し方によっては「どうパネルを補充しても、消せるようにならない」可能性もあると思うのですが、そのあたりは問題ないのでしょうか。

    キャンセル

  • 2017/12/20 16:09

    なるほど、そうですね、考えておりませんでした、ありがとうございます。
    このような3マッチパズルのアルゴリズムは、ランダムでパネルを配置しているわけではなく、
    内部で計算して配置しているのでしょうか?

    キャンセル

  • 2017/12/20 18:19

    最後まで消せるというのは要件にありませんでした。消した場合にどう補充されるのかが書かれていないので誰も答えられないかと思います。
    消せなくなっても構わない(勝手に入れ替える等する)というのがふつうではないでしょうか?

    キャンセル

  • 2017/12/20 18:30

    すみません、パネルを消した場合は、パネル間に隙間がある場合は下詰めになるようパネルが移動し、
    不足分が上から降りてくる形です。
    できれば消せなくなるような状態にはしたくなく、毎回判定処理を入れようと思っているのですが、
    重くなりそうなのでこちらで良い案がないか質問させていただきました。

    キャンセル

+3

多分パネルは消したあとに上から補充されるんですよね?ゲームプレイ中に「手詰まり」が起きたとき、おそらくシャッフルや全入れ替えのような処理をすることになると思います。

だったら、「手詰まりかどうか」を判定する処理、および「シャッフルや全入れ替え」の処理は必ず必要になりますよね?その2つの処理があれば、無理に「絶対1箇所は消せる場所があるパターンをつくるアルゴリズム」を考える必要はなく、「初期配置」で「手詰まりかどうか」を確認して、「手詰まり」でなくなる状態まで「シャッフルや全入れ替え」を繰り返せば要望の「この5×6のパネルの中で最低でもどこか1箇所は、同じ種類のパネルが3つ以上連続している」ということが実現できますよね?

var panels; // 5x6のパネルの入った配列

// 配列の左上から「右に3つ」、または「下に3つ」連続したものを探す
var find = false; // 見つかったかどうか
for(var i = 0; i < 5 && !find; i++) { // 縦
  for(var j = 0; j < 6 && !find; j++) { // 横
    var type = panels[i][j]; // 剣、盾、コイン、ポーションのいずれか
    // 横方向に+1、+2した場所と同じかどうかを調べる
    if(j <= 6 - 3 && panels[i][j + 1] == type && panels[i][j + 2] == type) {
      find = true;
    }
    // 縦方向に+1、+2した場所と同じかどうかを調べる
    else if(i <= 5 - 3 && panels[i + 1][j] == type && panels[i + 1][j] == type) {
      find = true;
    }
  }
}
if(!find) {
  // 1箇所も連続した場所が見つからない
}

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/12/20 15:07

    ご回答いただきありがとうございます。

    ご回答いただいた内容ですが、おっしゃられている、

    「手詰まりかどうか」を確認する

    これがつまり、

    「この5×6のパネルの中で最低でもどこか1箇所は、同じ種類のパネルが3つ以上連続している」
    かどうかを確認する

    となると思います。
    こちらの計算方法でなるべくスマートな(処理の早い)計算式などご存知でしたらご教示いただけないでしょうか?

    キャンセル

  • 2017/12/20 15:15

    質問の書き方だと「配置方法」のアルゴリズムを求めているように見えたので勘違いしていました。ちょっと参考程度のコードを書きます。

    キャンセル

  • 2017/12/20 15:27

    説明不足で申し訳ありません。
    求めているのは、具体的な計算式になります。
    よろしくお願いいたします。

    キャンセル

  • 2017/12/20 15:41

    具体的なコードをいただきありがとうございます、大変参考になります。
    ただすみません、私の説明が悪かったのですが、「3つ以上の連続したパネル」は、
    縦一列、横一列とは限らない状況です。

    ■■


    や、


    ■■

    のような形も考えられるので、そちらも考慮に入れなければいけないことになっております。
    こちらのような判定をスマートにするにはどのようにしたらよいでしょうか?

    キャンセル

  • 2017/12/20 15:52

    まず疑問なのですが、「連続した」という判定はそもそもどうやっているのですか?「連続したパネルを消す」処理が出来ているなら「連続した」という判定が出来ているはずですよね?それともなにも出来ていない状態でこの質問をされたということでしょうか?一から私が説明する必要がありますか?

    キャンセル

  • 2017/12/20 16:04

    連続したパネルを消す処理はできておりますが、
    パネルを配置・再配置した際に、

    「最低でもどこか1箇所は、同じ種類のパネルが3つ以上連続している」

    をチェックする処理は別物になると考えております。
    数学な得意な方などおられたら何かいい計算式をいただけるかと思い質問させていただいた次第です。

    キャンセル

  • 2017/12/20 16:08

    前提として「手詰まり」が起きないようにしたいのか、「手詰まり」が起きたときに「シャッフル」「リセット」といった挙動が行われるのか、という点がはっきりしていません。手詰まりが起きないように配置するアルゴリズムと、手詰まりを検知するアルゴリズムは全く違います。

    キャンセル

  • 2017/12/20 16:28

    はい、すみません、
    手詰まりが起きての対処だと必要な処理が増えてしまいますので、

    「手詰まりが起きないように配置する」

    アルゴリズムをご教示いただきたい次第です。

    現在5×6(=30)のパネルをループで回し、
    配置しているのですが、その再に上記を実現するアルゴリズムを組み込みたいと考えております。

    キャンセル

  • 2017/12/20 16:34

    そのアルゴリズムは私には難しすぎます。よしんば作れたとしても、ほぼ手詰まりな状態で生きながらえるものが降り続けるという状況に陥り、ゲームとして破綻すると思います。最悪の場合、縦3つを消したら同じ模様の縦3つのものが補充される、を延々繰り返すような状況にもなりえます。それを解消して、ユーザに爽快感を持たせるには「ユーザが取りうる行動を何手か先まで予測してパネルを追加する」という非常に高度な設計が必要になります。それでもやりますか?もしその方法をteratailで聞いても「誰も難しすぎて答えない」と思いますよ。

    キャンセル

  • 2017/12/20 16:42

    そうなのですね、それほど高度なアルゴリズムだとは考えておりませんでした。
    何か別の解決策がないか考えてみます、ご回答いただきありがとうございました。

    キャンセル

  • 2017/12/20 16:46

    「恣意的に必ず消せる場所を用意する」と偏りが生まれて面白くなくなります。仕様からちょっと考慮したほうが良いかと思います。

    キャンセル

  • 2017/12/20 16:57

    なるほど、アドバイスありがとうございます。
    参考にさせていただきますm(__)m

    キャンセル

+3

興味深いですね。
DungeonRaidのようなゲームだと思いますが、3マッチである以上、補充パネルは3枚以上で縦横につながった状態で落ちてくるはずです。
ですので、補充パネルに3枚連結を仕込めば、手詰まりはありえないということになります。
 
以上の前提から、
・補充前が手詰まり → 3枚連結を仕込む
・それ以外 → ランダム
で問題ないはずです。
 
なので、必要な処理は、盤面が手詰まりかどうか判定すればよいので、
1.あるパネルの隣接パネルに同じパネルが2枚以上ある → 手詰まりではない
2.あるパネルの隣接パネルに同じパネルが2枚以上ない → 次のパネルを照会
という単純なものになるのではないかと思います。
 
 
 
なお、初期盤面の問題も同様で、手詰まりだったら連結3枚を差し替えれば済みます。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/12/20 18:15

    はい、おっしゃる通り、DungeonRaid をかなり参考にしております。
    現在作成途中なのですが、

    1.あるパネルの隣接パネルに同じパネルが2枚以上ある → 手詰まりではない
    2.あるパネルの隣接パネルに同じパネルが2枚以上ない → 次のパネルを照会

    の処理をできる限りスマートに(できるだけ軽く)判定できる方法を模索している段階で、
    知識のある方に何か良い案がないか質問させていただいた次第です。
    当面、現在までにいただいたアドバイスを考慮して開発を進めてみます。
    ありがとうございます。

    キャンセル

  • 2017/12/20 19:07

    > 1.あるパネルの隣接パネルに同じパネルが2枚以上ある → 手詰まりではない
    > 2.あるパネルの隣接パネルに同じパネルが2枚以上ない → 次のパネルを照会
    > の処理をできる限りスマートに(できるだけ軽く)判定できる方法を模索している段階で

    私が回答した手順をすでに思いついていたなら、そのように質問に書いておけば話が早かったと思いますし、私も時間を浪費せずに済んだと思いますが?

    キャンセル

+2

質問者さんのJavascriptについての熟練度が全く分かりませんが、これについて全く手が付けられないのであればプログラムの前に、いわゆる「アルゴリズム」について一通り目を通した方がよいと思います。

この手のパズルゲーム系には必須のものですし、他にも必ず生きますので。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

+2

「連続したパネルを消す処理は出来ている」ということは、
「指定した位置のパネルが連続しているかの判定は出来ている」ということですよね?
ということは
「盤面のマス1つ1つに対して判定を行う」ことで、1つ以上連続があるかどうかは分かります。
(最小1回、最大27回で完了します)

それを踏まえた流れは以下の通り。

  1. パネルが消される。(=穴が開く)
  2. 穴部分に入る予定のパネルをランダムに決める。
  3. 全てのマスに対して連続判定。→もし1つ以上連続部分があれば6へ。
  4. (連続部分が無い場合)穴の周囲の1マスをランダムに決める。
  5. 決めたマスと連続するように、「決めたマスの隣」と「更にその隣」のパネルを、決めたマスのパネルに変更。
  6. 実際に穴に入る部分のパネルを表示する。

とはいえ、全てのマスに対して連続判定を行うのは重いので、
n回に1回は全体の判定をせずに「穴の周囲を1つ決定→決めたマスと連続するようにパネル指定→生成」でもいいかもしれません。
つまり「新たに表示されるパネルは必ず消せる」状態になるのですが、ゲームバランスによって確率調整が必要かと思います。

そして上記が実用に足る速度が出せるかは分からないですし、今思い付いたアイデアなので参考までに。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/12/20 18:37

    ご回答いただきありがとうございます。
    参考にさせていただきます。

    キャンセル

  • 2017/12/20 19:47

    色々見返しまして、具体的な回答は他の方にお任せしますが、
    とりあえず質問内容を変更した方がいいと思います。

    >ゲームを開始した際に、〜必要があるのですが、そのアルゴリズムが考えつかず
    とあるので、回答やコメントを追わない人はこれに対して回答してしまうと思います。

    また、既に動作中のコードがあり、その改善がしたいというなら現状のコードを提示してください。
    回答者の二度手間になります。

    キャンセル

+1

補填のこと等は置いといて、要件としての「判定ロジック」を書いてみます。

5*6程度ならば1パネルづつ、前後左右に同じパネルが配置されているかチェックして2つ以上同じものがあればtrue、とかどうでしょうか。
L時のような3つ揃いも対応できていると思います。

//4種類の数値(剣」「盾」「コイン」「ポーション」に置き換えてください)をつかった行列データを定義
//今回は4,5行目あたりに2の当たりが仕込まれています
const mtx56 = [
    [ 1, 1, 2, 3, 2 ],
    [ 2, 4, 1, 2, 1 ],
    [ 2, 1, 4, 3, 2 ],
    [ 4, 1, 3, 1, 2 ],
    [ 3, 2, 2, 3, 4 ],
    [ 1, 1, 2, 3, 4 ],
];

/** 2次元配列のindexの値を取得 */
function get2(arr, x, y){
  return arr && arr[x] && arr[x][y] ? arr[x][y] : undefined;
}

/** 指定座標の前後左右の値をチェックする */
function check( cell, i, j ){
  //前後左右の座標値を設定
  const around = {
    top : [i-1, j],
    right: [i, j+1],
    bottom: [i+1, j],
    left: [i, j-1],
  };
  //マトリックスデータから前後左右の値を収集
  const values = [
    get2(mtx56, around.top[0] , around.top[1] ),
    get2(mtx56, around.right[0] , around.right[1] ),
    get2(mtx56, around.bottom[0] , around.bottom[1] ),
    get2(mtx56, around.left[0] , around.left[1] ),
  ];
  //チェック中値と同じ値だけ抽出し、2件以上ならばtrue
  return values.filter( val => val === cell ).length >= 2;
}

console.time( 'check' );
//メイン処理開始( 実装時は関数化 )
const isSafe = mtx56.some((row, i) =>{
  return row.some( (cell, j) => check(cell, i, j) )
});

console.timeEnd( 'check' );
console.log(isSafe);

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/12/20 18:35

    具体的なコードをいただき、ありがとうございます、大変助かりますm(__)m
    いただいたコードをテスト、分析してみます。
    ありがとうございます。

    キャンセル

0

素朴な疑問ですが、今見えているパネルパターンの中に3つ以上の同じ絵柄の連続した状態があるかどうかをなぜ知る必要があるのでしょうか?

ゲーム進行中においても「手詰まりが起きないように配置する」ということですが・・・ゲームなのだから「手詰まり=負け」もあるんですよね?

最初の一回は「最低でもどこか1箇所は、同じ種類のパネルが3つ以上連続している必要がある」べきですが、その後のゲーム進行(消したところを埋める絵柄の発生)はランダムでいいのではないでしょうか?

1回で終わってしまっても、それは「運が無かったですね!次のゲームでがんばってください」でよくないですか?

?ばかりですみません・・・

「どこを消せばゲームを続けていくことができるか?」というユーザーの戦略性こそがこのゲームの面白さのように思います

なので、maisumakunさんのおっしゃるように
「まず最初に3連続をランダムな箇所・色で入れておいて、それからランダムに残りを埋める」
ということだけしてあげればよいのではないでしょうか

もう少しゲーム性(面白さ)を出すなら、一定の頻度で追加されるパネルの絵柄が揃ったものを出してあげたりすると、ユーザーも「ラッキー!」と感じてもっと続けたいと思ってくれるかも

それとも、絶対終わらないゲームを作りたいってことなのでしょうか

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/12/20 18:43

    まだしっかりとゲームの仕様を決めていないのですが、
    パズル要素とは別にプレイヤーが選択する要素を取り入れ、
    その選択によってゲームを進めていくようなゲームにしたいと考えております。
    ですので、パズル要素自体は「手詰まりしてはいけない」ものとなります。

    キャンセル

  • 2017/12/20 19:14

    なるほど、まだいろいろと要素があるのですね
    そのあたりをよく考えないまま回答してしまい失礼しました

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 91.06%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る

  • JavaScript

    13305questions

    JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

  • アルゴリズム

    333questions

    アルゴリズムとは、定められた目的を達成するために、プログラムの理論的な動作を定義するものです。

  • ゲーム開発

    149questions