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

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

ただいまの
回答率

90.45%

  • JavaScript

    21057questions

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

マインスイーパの周囲の爆弾の数を数える関数count()について

解決済

回答 3

投稿

  • 評価
  • クリップ 1
  • VIEW 347

Tanakakko

score 1

前提・実現したいこと

現在javascriptでマインスイーパーを作成しております。
しかし、参考にしている本のコード解説だけでは意味がわからない箇所があります。
for分の条件式let j= y-1; j<=y+1; j++
そして、cell[j] && cell[j][i]の部分です。

該当のソースコード

let cell: Cell[][]=[];
function count(x: number,y: number){
    let b =0; //爆弾の数
    for(let j= y-1; j<=y+1; j++){ 
        for(let i =x-1; i<=1; i++){
            if (cell[j] && cell[j][i]){ 
                    if(cell[j][i].bomb) b++; 
            }
        }
    }
    return b;
}

参考図


このような図とともに「if(cell[j]&&cell[j][i])」は、iとjがマス目の外になった場合、たとえば、jが1のような場合に、爆弾を数えないようにするための処理。という記述がありました。
しかしこの意味がわかりません。どうかご回答願います。

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

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

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

    クリップを取り消します

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

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

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

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

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

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

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

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

    質問の評価を下げる

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

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

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

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

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

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

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

    詳細な説明はこちら

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

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

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

回答 3

checkベストアンサー

+2

i = x-1; i<=1; i++ について

質問では

for分の条件式let j= y-1; j<=y+1; j++

がわからないとありますが、他の回答に対するコメントを読むとi = x-1; i<=1; i++の方のようなのでこちらについて。
参考にされている本にこれが書かれているのであれば、誤植です。正しくは

for (let i = x - 1; i <= x + 1; i++) {


です。

cell[j] && cell[j][i] について

3x3 のマインスイーパーを考えてみます。

cell[0][0], cell[1][0], cell[2][0]
cell[0][1], cell[1][1], cell[2][1]
cell[0][2], cell[1][2], cell[2][2]

そして cell[0][0](左上のセル)の周囲の爆弾を数えるためにcount関数を呼び出してみます。

count(0, 0)

x=0y=0ですから実際に走るコードとしては以下のようになります。

let b = 0;
for (let j = -1; j <= 1; j++) { 
  for (let i = -1; i <= 1; i++) {
    if (cell[j] && cell[j][i]) {
      if (cell[j][i].bomb) b++;
    }
  }
}
return b;

ここで if (cell[j] && cell[j][i])がない場合を考えます。つまり

let b = 0;
for (let j = -1; j <= 1; j++) { 
  for (let i = -1; i <= 1; i++) {
    if (cell[j][i].bomb) b++;
  }
}
return b;

だったとして、これが実行される場合を考えてみます。このとき if (cell[j][i].bomb) 文の中身は実行順に

  1. j = -1i = -1 => cell[-1][-1].bomb
  2. j = -1i = 0 => cell[-1][0].bomb
  3. j = -1i = 1 => cell[-1][1].bomb
  4. j = 0i = -1 => cell[0][-1].bomb
  5. j = 0i = 0 => cell[0][0].bomb
  6. j = 0i = 1 => cell[0][1].bomb
  7. j = 1i = -1 => cell[1][-1].bomb
  8. j = 1i = 0 => cell[1][0].bomb
  9. j = 1i = 1 => cell[1][1].bomb

となります。一番上のcell[-1][-1].bombは、そもそもcell[-1]undefinedであるためにcell[-1][-1]を参照することができず、

Cannot read property '-1' of undefined` 


のようなエラーが発生します。上から4番目のcell[0][-1].bomb については、cell[0]自体はアクセス可能ですが、cell[0][-1]undefinedなため、cell[0][-1].bombについて

Cannot read property 'bomb' of undefined


のようなエラーが発生します。

こうしたアクセスできないプロパティへの参照が起こらないようするために、undefinedとなっていないかどうかを先に確かめているのがif (cell[j] && cell[j][i])の条件式です。上記リストのうち、1,2,3についてはif文の中の&&の前の時点でfalseだと判定されてif文の中は実行されません(&&についてはMDN等を参照ください)。つまり上記のエラーが発生する前にループの次の処理にうつります。また4,7についてはif文の中の&&の後ろでfalseと判定され、やはりif文の中は実行されません。最終的には5, 6, 8, 9、つまり↓で●のついているところの爆弾の数がカウントされ、エラーで止まることなく欲しい情報が得られるようになっています。

●cell[0][0], ●cell[1][0], cell[2][0]
●cell[0][1], ●cell[1][1], cell[2][1]
cell[0][2], cell[1][2], cell[2][2]

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2019/06/13 19:39

    ご回答ありがとうございます。大変わかりやすく、理解できました!

    キャンセル

+2

全てのコードみないと分からないので、勘で回答します。
見た目上は3×3のマスしかないけど

□□□
□□□
□□□

実際にはその外側にマスを用意してるのでしょう。

■■■■■
■□□□■
■□□□■
■□□□■
■■■■■


爆弾のあるところと、外枠(黒いマス)は押せないマスとして判定しているのでしょう。
で、押せないマス=爆弾としてカウントしてしまうと間違った数でカウントされてしまうから、
枠外(黒いマス)は爆弾としてカウントしないようにする
という意味かなと

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2019/06/12 20:25

    ご回答ありがとうございます。なるほど、外側に押せない仮想のマスを作成するのですね。大変丁寧な説明ありがとうございました。cell[j]&&cell[j][i]部分そして、i =x-1; i<=1; i++のコードがそれをどう実装しているのかの解説もしていただけませんでしょうか

    キャンセル

+1

端に来るとチェックすべき領域が減るためのの処理でしょうね

この手の処理はダミー領域をつくっておくといつも同じ処理ですみます。
つまり3*3の領域であれば5*5の範囲をもち端の1列(1行?)はさわれないように
しておけば済みます

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2019/06/12 20:25

    ご回答ありがとうございます。なるほど、外側に押せない仮想のマスを作成するのですね。大変丁寧な説明ありがとうございました。cell[j]&&cell[j][i]部分そして、i =x-1; i<=1; i++のコードがそれをどう実装しているのかの解説もしていただけませんでしょうか

    キャンセル

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

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

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

  • JavaScript

    21057questions

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