【问题标题】:Minesweaper algorithm solution扫雷算法解决方案
【发布时间】:2018-01-02 19:55:39
【问题描述】:

这是一个关于this codefight callenge 的问题。

要求参赛者检查扫雷场(表示为 2D 阵列)是否有效。

详情: 扫雷游戏板的每个单元格可以是:

  • 地雷(显示为 9)
  • 或表示其周围单元格中地雷数量的数字 (当该单元格在至少一个角上与该单元格相交时,该单元格被视为围绕另一个单元格)(显示为 0 - 8)

我的方法(有效):

  • 循环遍历所有项目
  • 检查邻居是否有地雷(并计算地雷的数量,如果有的话)
  • 将发现的地雷数量与图块上的数量进行比较
  • 返回false,如果数字不相等,否则继续

有人可以向我解释一下这种方法是如何工作的吗?

minesweeper1 = g =>
!g.some((r,i) =>
      r.some((c,j) =>
            c < 9 && (f = d => d-- ? f(d) - ((g[i + ~-(d/3)] || 0)[j + d%3 - 1] > 8) : c)(9)
           )
     )

我了解多少:

  • g是二维数组,代表字段
  • .some 将测试,如果数组中的元素将通过测试
  • r 是字段中的单个单行
  • c 是每一行中的每一个元素
  • 什么是 i 和 j?计数器?
  • 什么是d?
  • 写这么神秘的代码有什么好处?

【问题讨论】:

  • 代码写得这么晦涩的原因可能只有两个——1:有人想让代码不要太清晰,别人看不到,或者2:为了节省下载大小(对于这么少的代码来说几乎没用,但如果它是一些更大的代码库的一部分可能会有意义)-@all 如果您知道任何原因,请添加其他原因!
  • @Sventies 你想炫耀你仍然能够理解那里写的内容;)我真的不明白为什么人们总是这样做。这可能会使代码超短,但我无法理解它了
  • 一点也不。它不完全理解它,我希望我会,如果我这样做了,我会给你一个正确的答案而不是评论。只是想我可能会帮助您简短回答您的一个问题 - 最后一个问题。
  • 回答你的最后一点:google code golf 你会找到喜欢这种代码的人(包括我自己;)),所以答案可能是:只是为了好玩:0
  • @User12547645 我很确定 i 和 j 是索引(分别是行号和列号),其中 r 和 c 是值本身。变量 d 在 lambda(匿名函数)“f”中声明,我认为它后来被使用并传递了值“9”。

标签: javascript arrays algorithm ecmascript-6 minesweeper


【解决方案1】:
minesweeper1 = mainarray => // an arrow function, that gets the two d array passed
!mainarray.some((row,rownumber) =>
  row.some((field,columnumber) =>//checking the 2d array if some of the fields
        field < 9 && (//is not a mine
          recursive = d => //and the magic recursive function is true
            d-- 
            ? recursive(d) /* get the value of one lower d*/ - ((mainarray[rownumber + ~-(d/3)] || 0)[columnnumber + d%3 - 1] > 8) /* subtract one if this magic is true */
             : field//if d=-1 it returns field
         )(9)//the starting point of the recursive function d=9
   ))

所以它基本上会检查某些字段是否不是地雷(字段

field //the current value as start value

//d=0
- (mainarray[rownumber - Math.floor(d/3)-1][columnnumber + d%3 ] >8)
//d=1
 - (mainarray[rownumber - Math.floor(d/3)-1][columnnumber + d%3 ] >8)
//...
//repeat until d=9

(如果您想知道 ~-(d/3) 它会执行以下操作:

0-2: ~-([0,1,2]/3) = ~-0 = -(-0)-1 = -1
3-5: ~-([3,4,5]/3) = ~-1 = -(-1)-1 = 0
6-8: ~-([6,7,8]/3) = ~-2 = -(-2)-1 = 1

)

所以基本上这个函数会通过这个模式(0是field,X是当前检查的位置)

d=0
X - -
- 0 -
- - -

d=1
- X -
- 0 -
- - -

d=2
- - X
- 0 -
- - -

d=3
- - -
X 0 -
- - -

...

然后,如果有一个地雷 (>8),它会从字段中减去 1 (true)。所以如果字段是4,并且周围有4个地雷,它会做4-1-1-1-1,所以整个都是0,这是假的:

两个例子(字段是中间的):

9 9 9
9 4 1
1 1 0

所以递归函数将返回 0 (falsy) (4-1-1-1-1)

9 9 9
2 4 1
0 0 0

这将返回 1(真实)(4-1-1-1)

所以这个递归函数可以重命名为countaroundiswrong

!mainarray.some((row,rownumber) =>
  row.some((field,columnumber) =>
    fieldismine() && countaroundiswrong(mainarray,field,rownumber,columnumber)
  )
)

所以如果有一个地雷,并且周围的计数是错误的,那么就会找到一些字段并且整个事情都是正确的,然后被反转并且结果是错误的。一种不神秘的方式:

function countaroundiswrong(mainarray,field,col,row){
 for(var x=-1;x<2;x++){
  for(var y=-1;y<2;y++){
    if(mainarray[row+x] && mainarray[row+x][col+y]){
      if(mainarray[row+x][col+y] >8){
         field--;
      }
    }
   }
  }
  return field;
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-10-10
    • 1970-01-01
    • 1970-01-01
    • 2018-07-30
    相关资源
    最近更新 更多