Đảo ngược một bảng Minesweeper


32

Minesweeper là một trò chơi máy tính phổ biến mà bạn có thể đã lãng phí thời gian để chơi, khi bạn cố gắng tiết lộ các ô là các mỏ trong một lưới hình chữ nhật dựa trên gợi ý về số lượng mỏ mà mỗi ô không phải của tôi có. Và trong trường hợp bạn chưa chơi nó, hãy làm như vậy ở đây .

Một thực tế toán học tiện lợi về lưới Minesweeper (còn gọi là bảng) là:

Một bảng và bổ sung của nó có cùng tổng số mỏ . ( Bằng chứng )

Điều đó có nghĩa là nếu bạn có lưới Minesweeper hoàn toàn được tiết lộ, tổng tất cả các số trên lưới đó, tức là tổng của mỏ , sẽ bằng tổng số của phần bù của lưới, là lưới nơi mọi mỏ đã được thay thế với một cái không phải của tôi và mỗi cái không của tôi được thay thế bằng một cái mỏ.

Ví dụ: đối với lưới Minesweeper

**1..
34321
*2**1

tổng số mỏ là 1 + 3 + 4 + 3 + 2 + 1 + 2 + 1 = 17.

Phần bù của lưới là

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

trong đó có tổng cộng 2 + 4 + 3 + 4 + 4 = 17 một lần nữa.

Viết chương trình lấy lưới Minesweeper tùy ý ở dạng văn bản, trong đó *đại diện cho một mỏ và 1thông qua 8đại diện cho số lượng mỏ nằm cạnh một ô không phải của tôi. Bạn có thể sử dụng .hoặc 0hoặc (dấu cách) để biểu diễn các ô không có hàng xóm của tôi, tùy bạn chọn. Bạn có thể giả định rằng lưới đầu vào sẽ được đánh dấu chính xác, tức là mỗi ô không phải của tôi sẽ biểu thị chính xác tổng số mỏ ngay lập tức liền kề với nó theo đường trực giao hoặc theo đường chéo.

Chương trình của bạn cần phải in bổ sung của lưới điện trong các định dạng tương tự (sử dụng cùng một ., 0hoặc như bạn mong đợi trong dữ liệu).

Mã ngắn nhất tính bằng byte thắng.

  • Thay vì một chương trình, bạn có thể viết một hàm lấy lưới đầu vào dưới dạng chuỗi và in hoặc trả về lưới bổ sung.
  • Một dòng mới ở đầu vào hoặc đầu ra là tốt, nhưng không nên có các ký tự khác ngoài các ký tự tạo thành lưới.
  • Bạn có thể giả sử lưới 1 × 1 sẽ là đầu vào nhỏ nhất.

Các trường hợp thử nghiệm

Tất cả các đầu vào và đầu ra có thể được hoán đổi vì phần bù của phần bù là lưới ban đầu. Các lưới có thể được xoay cũng như cho các trường hợp thử nghiệm thêm.

Đầu vào:

111
1*1
111

Đầu ra:

***
*8*
***

Đầu vào:

.

Đầu ra:

*

Đầu vào:

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

Đầu ra:

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

Đầu vào: ( Ví dụ về nút thắt )

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

Đầu ra:

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

TI-BASIC không thể chấp nhận một dòng đầu vào trống. Việc sử dụng một dấu phân cách kết thúc (ví dụ ?) trên dòng sau khi dòng cuối cùng của bảng có thể chấp nhận được hay tôi có thể lấy số lượng dòng đầu vào thông qua dòng lệnh?
lirtosiast

@ThomasKwa Một dấu phân cách kết thúc nghe có vẻ tốt cho TI-BASIC và các ngôn ngữ khác có giới hạn dòng mới lạ.
Sở thích của Calvin

Câu trả lời:


12

Bình thường, 39 38 byte

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

Dùng thử trực tuyến: Trình diễn

Các thuật toán chính là thực sự đơn giản. Tôi chỉ đơn giản lặp lại qua từng ô, lấy hộp 3x3 xung quanh (hoặc nhỏ hơn khi ô nằm ở viền) và in một ngôi sao hoặc số lượng không phải sao trong hộp đó.

Giải trình:

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

Thực sự gọn gàng, +1
MKII

22

CJam, 58 57 byte

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

Đầu vào không nên kết thúc bằng một nguồn cấp dữ liệu. Đầu ra chứa 0cho các tế bào mà không có mỏ gần đó.

Hãy thử trực tuyến trong trình thông dịch CJam .

Ý kiến

Chúng tôi bắt đầu bằng cách đệm ma trận đầu vào với một hàng và một cột dấu hoa thị.

Đối với đầu vào

*4*
**2

kết quả này trong

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

Bây giờ chúng tôi tạo ra tất cả các sửa đổi có thể có do xoay các hàng và cột 0, -1 hoặc 1 đơn vị lên / trái:

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

Chúng tôi loại bỏ "vị trí đệm" từ mỗi vòng quay, nghĩa là

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

và tạo thành một ma trận đơn bằng cách ghép các ký tự tương ứng của mỗi phép quay:

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

Ký tự đầu tiên của mỗi vị trí là ký tự gốc của nó.

  • Nếu nó không phải là dấu hoa thị, nó phải được thay thế bằng dấu hoa thị.

  • Nếu đó là dấu hoa thị, số lượng dấu hoa thị trong chuỗi đó là số lượng mỏ lân cận.

Làm thế nào nó hoạt động

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
Tôi sợ - điều này thật tuyệt vời.
Deusovi

Thưa ông, vừa phá hệ thống. +1! Tôi có thể hỏi nơi bạn tìm thấy lý thuyết này?
GamrCorps

9
@IonLee Cái này là tất cả của tôi. Thực sự đó là một ý tưởng khá đơn giản: Thay vì kiểm tra các ô xung quanh một ô đã cho, chúng tôi di chuyển toàn bộ lưới xung quanh và quan sát những gì rơi vào ô.
Dennis

Bravo! Tôi sẽ không bao giờ nghĩ về điều đó.
GamrCorps

7

Ruby, 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]<=>?*]}}

Ungolfed trong chương trình thử nghiệm:

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

Tháng Mười, 76

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

Giải trình

  • Chuyển đổi chuỗi đầu vào thành ma trận của chuỗi bằng strsplitcell2mat.

  • Lấy ma trận logic chứa 1nơi không có *trong ma trận gốc.

  • Lấy tích chập của nó với ma trận 3x3 là 1.

  • Đắp mặt nạ với ma trận logic nghịch đảo và đặt *vào vị trí của mặt nạ.

  • Lưu ý: Các tế bào không có hàng xóm của tôi được đại diện là 0.

Chấp hành

>> 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
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.