1


こんにちは
「マインゲーム」のエミュレーションを作成しようとしています


行列
0 0 0 0
0 0 -1 0
0 0 0 -1
0 -1 0 -1 があるとします。


ここで、-1 と等しくない各セルは地雷の数を表す必要があり
ます。コードは for(int i=0;i

for(int j=0;j<N;j++)
 if(box[i][j]!=-1)
  {
  switch (i)
 {
 case 0: 
 iLEFT=0;
 iRIGHT=1;break;
 case 3:
 iRIGHT=0;
 iLEFT=1;
 break;
 case 1:
 iLEFT=1;
 iRIGHT=1;
 break;
 case 2:
 iLEFT=1;
 iRIGHT=1;
 break;
 default:
  iLEFT=1;
 iRIGHT=1; 
   break;
}



switch (j)
  {
case 0:
   jLEFT=0;`
   jRIGHT=1;
   break;
case 3:
   jRIGHT=0;
   jLEFT=1;
   break;
   case 1:
   jLEFT=1;
   jRIGHT=1;
    break;
    case 2:
    jLEFT=1;
    jRIGHT=1;
    break;
    default:
    jLEFT=1;
    jRIGHT=1;
     break;
  } 

// checking neighbor 
     if(box[i][j+jRIGHT]==-1)
         count+=1;
            if(box[i][j-jLEFT]==-1)
         count+=1;              
                    if(box[i+iRIGHT][j]==-1)
                 count+=1;
            if (box[i-iLEFT][j]==-1)
              count+=1; 
                if(box[i-iLEFT][j-jLEFT]==-1)
                {
                    if(i-iLEFT!=i) // trying to avoid double checking
                     count+=1;
                }
                if(box[i+iRIGHT][j-jLEFT]==-1)
                {
                    if(i+iRIGHT!=i)  //trying to avoid double checking
                     count+=1;
                }
                if (box[i-iLEFT][j+jRIGHT]==-1)
                {
                    if(i!=iLEFT) //trying to avoid double checking
                      count+=1;
                }

                if (box[i+iRIGHT][j+jRIGHT]==-1)
                {

                    if(i!=iRIGHT) //trying to avoid double checking
                      count+=1;
                }

                   box[i][j]=count;
                   count=0;
        }


私のアルゴリズム

iLEFT 現在の行ステップは左に進みます。
iRIGHT 現在の行を右に移動します。
jLEFT と JRIGHT の列は同じ
i=0 と仮定すると、i=1 の場合、1 ステップだけ右 (下)
にステップアップでき、j についても同じです。


"Case statement" update iLEFT/iRIGTH and jLEFT/jRIGHT for for for enable side steps
now "if" statement check left/right up/done box[i][j] の 2 つの対角線 (常に 1 つのステップのみ)
count counting performance of - box[i][j] の 1 つの値の隣人


同じセルをまだ二重チェックしていることがわかります
0 1 1 1
0 1 -1 2
1 2 4 -1
2 -1 4 -1

4

2 に答える 2

2

また、問題にどのようにアプローチしているかをよりよく理解できるように、コードとともにアルゴリズムの概要を説明する必要があります。付随するアルゴリズムがなければ、このコードを理解するのは非常に困難です。

アルゴリズムを平易な英語で概説できますが、疑似コードである必要はありません。問題と解決策をよりよく理解するのに役立ちます。たとえば、次のようなものです。

  1. 各鉱山を見てください
  2. すべての非鉱山の隣人を増やします

境界条件をチェックする方法を複雑にしすぎていると思います。地雷原が各方向に無限に大きいと仮定しましょう。次に任意のランダムを選択するcell(i,j)と、次の8 つのネイバーになります。

cell(i-1, j-1) // top-left
cell(i-1, j)   // top
cell(i-1, j+1) // top-right
cell(i, j-1)   // left
cell(i, j+1)   // right
cell(i+1, j-1) // bottom-left
cell(i+1, j)   // bottom
cell(i+1, j+1) // bottom-right

実際の有限長のケースに戻りましょう。セルが境界内にあるかどうかを事前に計算する代わりに、常に 8 つの隣接セルをすべてチェックし、無効なものを破棄することをお勧めします。

セルが有効かどうかをチェックする関数は、次のように簡単に記述できます。

bool is_cell_valid(int x, int y, int rows, int cols) {
    if(x < 0 || x >= cols) {
        return false;
    }
    if(y < 0 || y >= rows) {
        return false;
    }
    return true;
}

私はついにあなたのアルゴリズムを理解しました:)

  1. 鉱山以外の各セルを見てください
  2. その値を隣接する地雷の数に変更します

変更されているすべての変数をチェックしていないため、二重チェックが行われています。たとえば、この条件では、iLEFT と jLEFT を使用して左上のセルに移動しています。両方の変数が使用されているため、両方がゼロでないことを確認する必要があります。

if(box[i-iLEFT][j-jLEFT]==-1)
{
    if(i-iLEFT!=i) // trying to avoid double checking
        count+=1;
}

上記は代わりに

if(iLEFT != 0 && jLEFT != 0)
{
    if(box[i-iLEFT][j-jLEFT]==-1)
        count+=1;
}

このチェックは、対角セルだけでなく、8 つのセルのそれぞれに適用する必要があります。


これは、(x, y) のセルに隣接する 8 つのセルすべてを通過するための小さな代替手段であり、隣接するセルごとに if を使用しません。

for(int i = -1; i < = 1; i++) {
    for(int j = -1; j <= 1; j++) {
        if(i == 0 && j == 0) {
            continue;
        }
        if(is_cell_valid(x + i, y + j, N, N);
            // cell is adjacent and within boundaries
            // do whatever calculations are needed
        }
    }
}
于 2010-01-17T12:59:39.223 に答える
0

私はあなたのアルゴリズムの図を含めることを2番目にします。これは、以前にマインスイーパゲームを作成したことがある方法とは異なり、非常に読みやすくなります。これは、生成関数の概要になる可能性があります

  1. 空のグリッド(ゼロでいっぱい)から始めます
  2. 各爆弾を空の場所にランダムに挿入します(まだ爆弾を持っていません)
  3. すべての非爆弾ネイバーをインクリメントします

追加機能 は、最初のクリック後に爆弾の生成を遅らせるため、ユーザーが最初にクリックしたセルに爆弾を配置しないようにすることができます

ここにコードスニペットがあります

var i = 0
while (i < bombsNum){
    //generate a random location for the bomb
    var col=Math.floor(Math.random()*cols);
    var row=Math.floor(Math.random()*rows);

    //if new location is already a bomb
    if (cellsData[row][col] == -1) continue;

    //if new location is near the start region    
    if (col == startCol-1 || col == startCol || col == startCol +1){
        if (row == startRow -1 || row == startRow || row == startRow+1)
            continue;
    }

    i++;
    cellsData[row][col] = -1;
    //increment all the neighbors cells and make sure to handle the special cases cells (cells at the corner)
}
于 2010-01-17T13:25:47.480 に答える