反转扫雷板


32

扫雷(Minesweeper)是一种流行的计算机游戏,您可能已经浪费了时间在游戏中,尝试根据每个非地雷单元具有多少个相邻地雷的提示来显示矩形网格中的地雷单元。如果您还没有玩过,请在这里进行

关于扫雷网格(又称木板)的一个漂亮的数学事实是:

一个董事会及其补编具有相同的地雷总数。(证明

这就是说,如果您拥有一个完全显示的扫雷网格,则该网格上所有数字的总和,即“ 地雷总数”,将等于该网格补码的地雷总数,即每个地雷都已被替换的网格一个非地雷,每个非地雷都被一个地雷取代。

例如,对于扫雷网格

**1..
34321
*2**1

矿山总数为1 + 3 + 4 + 3 + 2 +1 + 2 +1 = 17。

网格的补充是

24***
*****
3*44*

总共有我的2 + 4 + 3 + 4 + 4 = 17。

编写一个程序,以文本形式获取任意的扫雷网格,该网格*表示一个地雷,并1通过8表示与非地雷单元相邻的地雷数。您可以选择使用.0 (空格)来表示没有地雷邻居的像元。您可以假设输入网格将被正确标记,即每个非地雷单元将准确地表示正交或对角线紧邻其的地雷总数。

你的程序需要打印电网的补相同的格式(使用相同的.0 如您在输入拼音)。

以字节为单位的最短代码获胜。

  • 除了编写程序,您还可以编写一个函数,该函数将输入网格作为字符串并打印或返回补码网格。
  • 输入或输出中的尾随换行符很好,但除了构成网格的字符外,不应有其他字符。
  • 您可以假设1×1的网格将是最小的输入。

测试用例

由于补数的补数是原始网格,因此可以交换所有输入和输出。网格也可以旋转以用于进一步的测试案例。

输入:

111
1*1
111

输出:

***
*8*
***

输入:

.

输出:

*

输入:

*11*1.1**1...1***1.....1*****1..........

输出:

1**2***11*****1.1*******1...1***********

输入:(剪切结示例

**212*32
333*33**
1*22*333
222222*1
*33*2232
2**22*2*

输出:

24***4**
***7**64
*8**7***
******8*
4**7****
*33**5*3

TI-BASIC不能接受空行的输入。是否可以?在板的最后一行之后的行上使用结束定界符(例如),还是可以通过命令行获取输入行数?
lirtosiast 2015年

@ThomasKwa对于TI-BASIC和其他具有奇怪的换行限制的语言,结束符听起来不错。
加尔文的爱好

Answers:


12

Pyth,39 38字节

j.es.eh-+K\*l-s:RtWYY+Y2:+K.zk+k3KZb.z

在线试用:演示

主要算法非常简单。我只是简单地遍历每个单元格,取出周围的3x3框(或在单元格位于边界时较小的框),然后在该框中打印一个星号或非星号。

说明:

j.es.eh-+K\*l-s:RtWYY+Y2:+K.zk+k3KZb.z  implicit: .z = list of input strings
 .e                                 .z  map each index k, line b of .z to:
    .e                             b      map each index Y, char Z of b to:
         K\*                                assign "*" to K
                         +K.z               insert K at the front of .z
                        :    k+k3           slice from k to k+3
               :RtWYY+Y2                    take the slice from Y-1 or 0 
                                            to Y+2 for each line
              s                             join, this gives the 3x3 rectangle
                                             (or smaller on the border)
             -                   K          remove all "*"s
            l                               take the length
        +K                                   "*" + ^
       -                          Z         remove Z from this string
      h                                     and take the first char
                                            (if cell=mine take the number, 
                                             otherwise take the number)
  s                                       join the chars of one line
j                                       join by newlines

真正整洁,+ 1
MKII 2015年

22

CJam,58 57字节

0WX]2m*qN/{'*f+z}2*f{\~@m<fm<W<}:..+{W<{_'*#'*@'*-,?}/N}/

输入不应以换行符结尾。输出包含0没有附近地雷的单元格。

CJam解释器中在线尝试。

理念

我们首先在输入矩阵上填充星号的一行和一列。

输入

*4*
**2

这导致

*4**
**2*
****

现在,我们生成所有可能的修改,这些修改导致将行和列0,-1或1单位向上/向左旋转:

*4** **** **2* **4* **** ***2 4*** **** *2**
**2* *4** **** ***2 **4* **** *2** 4*** ****
**** **2* *4** **** ***2 **4* **** *2** 4***

我们从每次旋转中丢弃“填充位置”,即

*4* *** **2 **4 *** *** 4** *** *2*
**2 *4* *** *** **4 *** *2* 4** ***

并通过串联每个旋转的相应字符形成一个矩阵:

******4** 4*******2 **24*****
*******4* *4****2** 2***4****

每个位置的第一个字符是其原始字符。

  • 如果它不是星号,则必须用星号替换。

  • 如果是星号,则该字符串中非星号的数量就是相邻地雷的数量。

怎么运行的

0WX]2m*   e# Push the array of all vectors of {0,-1,1}^2.
qN/       e# Read all input from STDIN and split at linefeeds.
{'*f+z}2* e# Append a '*' to each row and transpose rows with columns. Repeat.
f{        e# For each vector [A B], push the modified input Q; then:
  \~      e#   Swap Q with [A B] and dump A and B on the stack.
  @m<     e#   Rotate the rows of Q B units up.
  fm<     e#   Rotate each row of the result A units left.
  W<      e#   Discard the last row.
}         e# This pushes all nine rotations with Manhattan distance 1.
:..+      e# Concatenate the corresponding characters for each position.
{         e# For each row:
  W<      e#   Discard the character corresponding to the last column.
  {       e#   For each remaining string:
    _'*#  e#     Find the first index of '*' in a copy.
    '*    e#     Push '*'.
    @'*-, e#     Count the non-asterisks in the string.
    ?     e#     Select '*' if the index is non-zero, the count otherwise.
  }/      e#
  N       e#   Push a linefeed.
}/        e#

7
我很害怕-这太神奇了。
Deusovi

先生,您刚刚破坏了系统。+1!请问您在哪里找到这个理论?
GamrCorps

9
@IonLee这就是我一个人。实际上,这是一个非常简单的想法:我们没有检查给定单元周围的单元,而是移动了整个网格并观察掉入该单元的内容。
丹尼斯

太棒了!我永远不会想到这一点。
GamrCorps

7

露比119

->s{w=1+s.index('
')
s.size.times{|c|t=0;9.times{|i|(s+?**w*2)[c+i/3*w-w+i%3-1]<?0||t+=1}
print [t,?*,'
'][s[c]<=>?*]}}

取消测试程序中的:

f=->s{
  w=1+s.index("\n")                          #width of board
  s.size.times{|c|                           #iterate through input
    t=0;                                     #number of digits surrounding current cell
    9.times{|i|                              #iterate through 3x3 box (centre must be * if this ever gets printed.)
      (s+"*"*w*2)[c+i/3*w-w+i%3-1]<"0"||t+=1 #copy of s has plenty of * appended to avoid index errors
    }                                        #add 1 every time a number is found.
  print [t,"*","\n"][s[c]<=>"*"]             #if * print t. if after * in ACSII it's a number, print *. if before, it's \n, print \n
  }
}


f['**212*32
333*33**
1*22*333
222222*1
*33*2232
2**22*2*']

2

八度,76

m=@(s)char(conv2(b=(cell2mat(strsplit(s)'))~='*',ones(3),'same').*~b-6*b+48)

说明

  • 使用strsplit和 将输入字符串转换为字符串矩阵cell2mat

  • 获取包含原始矩阵中1不存在的逻辑*矩阵。

  • 将其与1的3x3矩阵进行卷积。

  • 用逆逻辑矩阵对其进行遮罩,并*代替遮罩。

  • 注意:没有地雷邻居的像元表示为0

执行

>> m(['**100' 10 '34321' 10 '*2**1'])   %// `10` is newline
ans =

24***
*****
3*44*

>> m(['24***' 10 '*****' 10 '3*44*'])
ans =

**100
34321
*2**1
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.