Có phải là chiếu tướng không?


13

Hoàn toàn ngạc nhiên khi điều này chưa được đăng lên, với số lượng lớn các câu đố cờ vua trên trang web. Trong khi tôi nghĩ về điều này bản thân mình, tín dụng cho Anush vì đã đăng nó lên hộp cát vào tháng ba . Nhưng tôi hình dung nó đã đủ dài để tôi có thể tự mình đi trước và làm như vậy.

Một checkmate trong cờ vua là một vị trí trong đó nhà vua bị tấn công và không có động thái có thể bảo vệ nó. Nếu bạn không quen với cách các quân cờ di chuyển, bạn có thể tự làm quen trên Wikipedia .

Các thách thức

Đối với thử thách này, đầu vào của bạn sẽ là vị trí của một bàn cờ trong bất kỳ ký hiệu nào bạn thích. Để làm rõ, đầu vào của bạn sẽ mô tả các mảnh trên một bàn cờ, với màu sắc và vị trí của họ, cùng với khả năng bắt tốt qua đường vuông chụp, nếu có. (Khả năng lâu đài là không liên quan vì bạn không thể kiểm soát lâu đài.) Bạn có thể thấy ký hiệu FEN hữu ích , nhưng bất kỳ định dạng thuận tiện nào cũng tốt. Để đơn giản, bạn có thể cho rằng đó là Đen để chơi - điều này có nghĩa là Đen sẽ luôn là người chơi được kiểm tra. Một vị trí mà Trắng đang kiểm tra, chiếu tướng hoặc bế tắc sẽ được coi là không hợp lệ cho thử thách này.

Bạn phải xuất ra một giá trị trung thực nếu vị trí là checkmate và giá trị falsey nếu không. Lưu ý rằng bế tắc không phải là chiếu tướng - nhà vua phải bị tấn công!

Trường hợp thử nghiệm thật

1k5R / 6R1 / 8/8/8/8/8 / 6K1 b - -

rn2r1k1 / pp1p1pQp / 3p4 / 1b1n4 / 1P2P3 / 2B5 / P5PP / R3K2R b - -

kr5R / rB6 / 8/8/8 / 5Q2 / 6K1 / R7 b - -

2K5 / 1B6 / 8/8/8 / 7N / R7 / R3r2k b - - 0 1

8 / 4Q1R1 / R7 / 5k2 / 3pP3 / 5K2 / 8/8 b - -

2K5 / 1B6 / 8/8/8 / 4b2N / R7 / 4r2k b - -

Trường hợp kiểm tra Falsey

rnbqkbnr / pppppppp / 8/8 / 4P3 / 8 / PPPP1PPP / RNBQKBNR b KQkq -

8/8/8/8/8/8/1KQ5 / 4N3 / 1k6 b - -

2K5 / 1B6 / 8/8/8 / 7N / R7 / 4r2k b - -

8/8 / 2Q5 / 3k4 / 3Q5 / 8/8 / 7K b - -

8 / 4Q1R1 / R7 / 5k2 / 3pP3 / 5K2 / 8/8 b - e3 (Xem đó là người qua đường!)

Code golf - mã ngắn nhất tính bằng byte thắng. Chúc may mắn!


2
Đây có vẻ là một câu hỏi hay :)
Anush

1
Vì lợi ích của sự khép kín - mà tất cả các thách thức ở đây nên có - điều này cần được đưa ra một thỏa thuận tốt hơn là dựa vào các liên kết bên ngoài và / hoặc giả định một kiến ​​thức hiện có về các quy tắc và ký hiệu của cờ vua. Tôi khuyên bạn nên đưa nó trở lại Sandbox trong khi nó đang được xử lý.
Xù xì

3
@Shaggy Các liên kết bên ngoài trong thử thách này chỉ phục vụ cho thuận tiện. Tôi sẽ không liệt kê tất cả các quy tắc của cờ vua ở đây, vì hầu hết các thử thách cờ vua khác đều đoán trước kiến ​​thức về chúng. Và các liên kết lichess chỉ phục vụ như một đại diện trực quan tiện dụng của các trường hợp thử nghiệm; ký hiệu được xác định rõ bên ngoài lichess. Tôi có thể thêm hình ảnh nhưng tôi quyết định không làm như nó cảm thấy rất nhiều lộn xộn.
phân tán

1
Chúng ta có thể cho rằng bảng đã được chuyển đến thông qua một trò chơi hợp lệ không?
Đăng Rock Garf Hunter

1
Tôi đã mở lại điều này bởi vì trong khi nhiệm vụ cốt lõi là như vậy thì thử thách này có sơ đồ IO lỏng lẻo hơn (và trung thực hơn) và tiêu chí chấm điểm hơi khác (và trung thực hơn). Tôi nghĩ rằng có lẽ cái cũ nên được đóng lại như một bản sao của cái mới nhưng tôi sẽ không đập nó.
Đăng Rock Garf Hunter

Câu trả lời:


10

JavaScript (Node.js) ,  499 ... 374  370 byte

(b)(X)bX-1

Dưới đây là các giá trị dự kiến ​​cho mỗi hình vuông:

 0: empty square

 5: white pawn      6: black pawn
 9: white king     10: black king
17: white bishop   18: black bishop
33: white rook     34: black rook
49: white queen    50: black queen
65: white knight   66: black knight

640

b=>e=>(g=(c,k)=>b.map((v,p,h,s=p+(p&~7),M=t=>v&-~c?c?(B=[...b],K&=g(b[t?b[T]=b[p]:b[b[e-8]=0,e]=6,p]=0),b=B):k|=V&8:0,m=([a],[x,t,...d]=Buffer(a))=>d.map(c=>(h=n=>(V=(a+=c-66)&136?3:b[T=a+a%8>>1])&v&3||t>>!V&v>>x&n>31&&h(n-4/!V,M``))(t,a=s)))=>(v=b[p],m`##123ACQRS`,m`$?13QS`,m`%?2ACR`,m`&#!#04PTac`,c?(p-e+8.5&~1||M(),m`"!QS`,p<16?m`"&R`:m`""R`):m`"!13`))|k)(1,K=g())*K

Hãy thử trực tuyến!

Làm sao?

Ban đại diện

Chúng tôi sử dụng biểu diễn bảng 0x88 cổ điển để có thể dễ dàng phát hiện các ô vuông mục tiêu nằm ngoài giới hạn.

   |  a    b    c    d    e    f    g    h
---+----------------------------------------
 8 | 0x00 0x01 0x02 0x03 0x04 0x05 0x06 0x07 
 7 | 0x10 0x11 0x12 0x13 0x14 0x15 0x16 0x17 
 6 | 0x20 0x21 0x22 0x23 0x24 0x25 0x26 0x27 
 5 | 0x30 0x31 0x32 0x33 0x34 0x35 0x36 0x37 
 4 | 0x40 0x41 0x42 0x43 0x44 0x45 0x46 0x47 
 3 | 0x50 0x51 0x52 0x53 0x54 0x55 0x56 0x57 
 2 | 0x60 0x61 0x62 0x63 0x64 0x65 0x66 0x67 
 1 | 0x70 0x71 0x72 0x73 0x74 0x75 0x76 0x77

Di chuyển mã hóa

Mỗi bộ di chuyển được mã hóa với 5 tham số:

  • loại mảnh
  • số lượng hình vuông tối đa có thể được truy cập theo mỗi hướng
  • một lá cờ cho biết nếu được phép chụp
  • một lá cờ cho biết nếu không được phép chụp
  • một danh sách các hướng

Tất cả các tham số này được đóng gói thành một chuỗi duy nhất. Ví dụ, di chuyển hiệp sĩ được mã hóa như sau:

`&#!#04PTac`
 ||\______/
 ||    |                            +------> 0 + 1 = 1 square in each direction
 ||    |                            | +----> standard moves allowed
 ||    +---> 8 directions           | |+---> captures allowed
 ||                                / \||
 |+--------> ASCII code = 35 = 0b0100011
 |
 +---------> 1 << (ASCII code MOD 32) = 1 << 6 = 64

66

 char. | ASCII code | -66
-------+------------+-----
  '!'  |     33     | -33
  '#'  |     35     | -31
  '0'  |     48     | -18
  '4'  |     52     | -14
  'P'  |     80     | +14
  'T'  |     84     | +18
  'a'  |     97     | +31
  'c'  |     99     | +33

cung cấp cho:

 [ - ] [-33] [ - ] [-31] [ - ]
 [-18] [ - ] [ - ] [ - ] [-14]
 [ - ] [ - ] [ N ] [ - ] [ - ]
 [+14] [ - ] [ - ] [ - ] [+18]
 [ - ] [+31] [ - ] [+33] [ - ]

Tất cả các bộ di chuyển được tóm tắt trong bảng sau, ngoại trừ các ảnh chụp en-passant được xử lý riêng.

  string    | description             | N | S | C | directions
------------+-------------------------+---+---+---+----------------------------------------
 &#!#04PTac | knight                  | 1 | Y | Y | -33, -31, -18, -14, +14, +18, +31, +33
 ##123ACQRS | king                    | 1 | Y | Y | -17, -16, -15, -1, +1, +15, +16, +17
 "!13       | white pawn / captures   | 1 | N | Y | -17, -15
 "!QS       | black pawn / captures   | 1 | N | Y | +15, +17
 "&R        | black pawn / advance x2 | 2 | Y | N | +16
 ""R        | black pawn / advance x1 | 1 | Y | N | +16
 $?13QS     | bishop or queen         | 8 | Y | Y | -17, -15, +15, +17
 %?2ACR     | rook or queen           | 8 | Y | Y | -16, -1, +1, +16

Đã bình luận

b => e => (
  // generate all moves for a given side
  g = (c, k) =>
    b.map((
      v, p, h,
      // s = square index in 0x88 format
      s = p + (p & ~7),
      // process a move
      M = t =>
        // make sure that the current piece is of the expected color
        v & -~c ?
          c ?
            // Black's turn: play the move
            ( // board backup
              B = [...b],
              // generate all White moves ...
              K &= g(
                // ... after the board has been updated
                b[
                  t ?
                    // standard move
                    b[T] = b[p]
                  :
                    // en-passant capture
                    b[b[e - 8] = 0, e] = 6,
                  p
                ] = 0
              ),
              // restore the board
              b = B
            )
          :
            // White's turn: just update the king's capture flag
            k |= V & 8
        :
          0,
      // generate all moves of a given type for a given piece
      m = ([a], [x, t, ...d] = Buffer(a)) =>
        d.map(c =>
          ( h = n =>
            ( // advance to the next target square
              V = (a += c - 66) & 136 ? 3 : b[T = a + a % 8 >> 1]
            )
            // abort if it's a border or a friendly piece
            & v & 3 ||
            // otherwise: if this kind of move is allowed
            t >> !V &
            // and the current piece is of the expected type
            v >> x &
            // and we haven't reached the maximum number of squares,
            n > 31 &&
            // process this move (if it's a capture, force n to
            // -Infinity so that the recursion stops)
            h(n - 4 / !V, M``)
          )(t, a = s)
        )
    ) =>
      (
        v = b[p],
        // king
        m`##123ACQRS`,
        // bishop or queen
        m`$?13QS`,
        // rook or queen
        m`%?2ACR`,
        // knight
        m`&#!#04PTac`,
        c ?
          // black pawn
          ( // en-passant capture
            p - e + 8.5 & ~1 || M(),
            // standard captures
            m`"!QS`,
            // standard moves
            p < 16 ? m`"&R` : m`""R`
          )
        :
          // white pawn (standard captures only)
          m`"!13`
      )
    ) | k
// is the black king in check if the Black don't move?
// is it still in check after each possible move?
)(1, K = g()) * K

8/1ppp4/1pkp4/8/2Q5/8/8/7K b - -
tsh

@tsh Một lỗi nghiêm trọng hơn nhiều. Đã sửa với giá 6 byte cho bây giờ.
Arnauld

Làm thế nào để làm việc mà không có một đại diện cho bạn biết nếu en passant là có thể?
Anush

X

Aha. Cảm ơn rất nhiều.
Anush

6

Haskell , 1165 1065 1053 byte

Byte được lưu nhờ Leo Tenenbaum

n=Nothing
x?y=Just(x,y)
o(x,y)=x<0||y<0||x>7||y>7
m#k@(x,y)|o k=n|1>0=m!!x!!y
z(x,y)m p(a,b)|o(x+a,y+b)=1<0|Just g<-m#(x+a,y+b)=elem g[(p,0),(5,0)]|1>0=z(x+a,y+b)m p(a,b)
t(x,y)p(a,b)m|o(x+a,y+b)=[]|g<-(x+a,y+b)=(g%p)m++do[0|m#g==n];t g p(a,b)m
c m|(x,y):_<-[(a,b)|a<-u,b<-u,m#(a,b)==6?1],k<-z(x,y)m=or$[m#(x+a,y+b)==6?0|a<-0:s,b<-0:s]++do a<-s;[k 3(a,b)|b<-s]++(k 2<$>[(a,0),(0,a)])++[m#l==4?0|b<-[2,-2],l<-[(x+a,y+b),(x+b,y+a)]]++[m#(x-1,y+a)==p?0|p<-[0,1]]
c m=1>0
(k%p)m=[[[([p|a==k]++[m#a])!!0|a<-(,)b<$>u]|b<-u]|not$o k]
w(Just(_,1))=1<0
w x=1>0
m!u@(x,y)|g<-m#u,Just(q,1)<-g,v<-((u%n)m>>=),r<-v.t u g,k<-(do[0|n==m#(x+1,y)];(u%n)m>>=(x+1,y)%g)++(do a<-s;[0|n<m#(x+1,y+a)];v$(x+1,y+a)%g)++(do[0|(x,n,n)==(1,m#(x+1,y),m#(x+2,y))];v$(x+2,y)%g)++(do a<-s;[0|1?0==m#(x,y+a)];v((x,y+a)%n)>>=(x+1,y+a)%g)=[k,k,do a<-s;[(a,0),(0,a)]>>=r,do a<-s;b<-s;r(a,b),do a<-s;b<-[2,-2];l<-[(x+a,y+b),(x+b,y+a)];v$l%g,do a<-0:s;b<-[0|a/=0]++s;r(a,b),do a<-[x-1..x+1];b<-[y-1..y+1];[0|w$m#(a,b)];v$(a,b)%g]!!q
m!u=[]
u=[0..7]
s=[1,-1]
q m=all c$m:do a<-u;b<-u;m!(a,b)

Hãy thử trực tuyến!

Điều này không chính xác được chơi golf như bây giờ, nhưng nó là một sự khởi đầu. Với một số trợ giúp trên đường đi, giờ đây tôi đã chơi trò này khá tích cực (và đã sửa một lỗi trên đường đi).

Một điều có lẽ nghi vấn điều này là nó giả định rằng, ngoài một vị vua hay một người cầm đồ, bạn không bao giờ có thể thoát khỏi sự kiểm tra bằng cách chụp một trong những mảnh của riêng bạn. Trong cờ vua, bạn không được phép thực hiện động tác này nhưng chương trình của tôi xem xét các động tác này để lưu byte theo giả định rằng nếu bạn kiểm tra thì điều này không bao giờ có thể giúp bạn thoát khỏi nó.

Giả định này là hợp lệ vì những động thái như vậy

  1. Không thể bắt được mảnh đang tấn công nhà vua, vì mảnh mà họ bắt được có màu đen.

  2. Không thể chặn đường đi của quân cờ đang tấn công nhà vua, vì mảnh đen bị bắt sẽ đã làm điều đó.

Chúng tôi cũng bổ sung quy định bổ sung rằng nếu bạn không có vua thì bạn sẽ kiểm tra.

Chương trình này cũng đưa ra giả định rằng nếu có một con tốt có thể bị bắt, thì con tốt là mảnh cuối cùng để di chuyển và động thái đó là một động thái hợp pháp. Điều này là do chương trình không kiểm tra xem hình vuông mà nó di chuyển con tốt màu đen sang trống hay không, vì vậy nếu có một mảnh thì mọi thứ có thể hơi khó khăn. Tuy nhiên, điều này không thể có được nếu bước cuối cùng là một động thái hợp pháp và hơn nữa không thể được trình bày trong FEN . Vì vậy, giả định này có vẻ khá vững chắc.

Đây là phiên bản "vô danh" của tôi để tham khảo:

import Control.Monad
out(x,y)=x<0||y<0||x>7||y>7
at b (x,y)
  |out(x,y)=Nothing
  |otherwise=(b!!x)!!y
inLine (x,y) ps m (a,b) 
  | out (x+a,y+b) = False
  | elem (m `at` (x+a,y+b)) $ Just <$> ps = True
  | m `at` (x+a,y+b) == Nothing = inLine (x+a,y+b) ps m (a,b) 
  | otherwise = False
goLine (x,y) p (a,b)m
  | out (x+a,y+b) = []
  | otherwise = case m `at` (x+a,y+b) of
--    Just (n,1) -> []
    Just (n,_) -> set(x+a,y+b)p m
    Nothing    -> set(x+a,y+b)p m ++ goLine(x+a,y+b)p(a,b)m
checkBishop (x,y) m=or[inLine(x,y)[(3,0),(5,0)]m(a,b)|a<-[1,-1],b<-[1,-1]]
checkRook   (x,y) m=or$do
  a<-[1,-1]
  inLine(x,y)[(2,0),(5,0)]m<$>[(a,0),(0,a)]
checkKnight (x,y) m=any((==Just(4,0)).(at m))$do
  a<-[1,-1]
  b<-[2,-2]
  [(x+a,y+b),(x+b,y+a)]
checkPawn (x,y) m=or[at m a==Just(p,0)|a<-[(x-1,y+1),(x-1,y-1)],p<-[0,1]]
checkKing (x,y) m=or[at m(a,b)==Just(6,0)|a<-[x-1..x+1],b<-[y-1..y+1]]
check m
  | u:_<-[(a,b)|a<-[0..7],b<-[0..7],(m!!a)!!b==Just(6,1)] =
    checkBishop u m ||
    checkRook   u m ||
    checkKnight u m ||
    checkPawn   u m ||
    checkKing   u m
  | otherwise = True
set (x,y) p m=[[[head$[p|(a,b)==(y,x)]++[(m!!b)!!a]|a<-[0..7]]|b<-[0..7]]|not$out(x,y)]
white(Just(n,0))=True
white x=False
moves m (x,y)
 |g<-m `at` (x,y)=case g of
  Just(2,1) -> do
    a<-[1,-1]
    b<-[(a,0),(0,a)]
    set(x,y)Nothing m>>=goLine (x,y) g b
  Just(3,1) -> do
    a<-[1,-1]
    b<-[1,-1]
    set(x,y)Nothing m>>=goLine (x,y) g(a,b)
  Just(4,1) -> do
    n<-set(x,y)Nothing m
    a<-[1,-1]
    b<-[2,-2]
    l<-[(x+a,y+b),(x+b,y+a)]
    -- guard$white$n `at` l
    set l g n
  Just(5,1) -> do
    a<-[1,-1]
    c<-[(a,0),(0,a),(a,1),(a,-1)]
    set(x,y)Nothing m>>=goLine (x,y) g c
  Just(6,1) -> do
    a<-[x-1..y+1]
    b<-[x-1..y+1]
    guard$white(m `at`(a,b))||Nothing==m`at`(a,b)
    set(x,y)Nothing m>>=set(a,b)g
  Just(n,1) -> (do
    guard$Nothing==m `at` (x+1,y)
    set(x,y)Nothing m>>=set(x+1,y)g) ++ (do
      a<-[1,-1]
      guard$white$m`at`(x+1,y+a)
      set(x,y)Nothing m>>=set(x+1,y+a)g) ++ (do
        guard$(x,Nothing,Nothing)==(1,m`at`(x+1,y),m`at`(x+1,y))
        set(x,y)Nothing m>>=set(x+2,y)g) ++ (do
          a<-[1,-1]
          guard$Just(1,0)==m`at`(x,y+a)
          set(x,y)Nothing m>>=set(x,y+a)Nothing>>=set(x+1,y+a)g)
  _ -> []
checkmate m=all check$m:do
  a<-[0..7]
  b<-[0..7]
  moves m(a,b)

Hãy thử trực tuyến!


1252 byte với một chút chơi gôn (liên kết TIO quá dài để phù hợp với nhận xét này ...)
Leo Tenenbaum

@LeoTenenbaum Cảm ơn rất nhiều, tôi sẽ kết hợp điều này trong một thời gian ngắn, thật không may, có hai lỗi vô ý trong phiên bản mà bạn đã chơi golf mà bây giờ tôi đã sửa. Chắc chắn có chỗ để cải thiện theo nhiều cách với một chương trình dài như vậy.
Đăng Rock Garf Hunter

@tsh yep, tôi quên thêm vị trí của các vị vua vào nơi nó sẽ đến. cố định ngay bây giờ
Post Rock Garf Hunter

Đối với danh sách, guard x = [0|x]và bạn cũng có thể sử dụng x?y=Just(x,y)để lưu thêm một vài byte: 1129 byte
Leo Tenenbaum

1

Python 3 (PyPy) , 729 byte

F=lambda a,b:a<'^'<=b or a>'^'>=b
def m(b,P,A=0):
 yield b
 for(r,f),p in b.items(): 
  if F(P,p):continue
  *d,n,k={'R':[(0,1),8,4],'N':[(1,2),(2,1),2,4],'B':[(1,1),8,4],'Q':[(0,1),(1,1),8,4],'K':[(0,1),(1,1),2,4],'P':[(2,0),(1,0),(1,1),(1,-1),2,1],'p':[(-2,0),(-1,0),(-1,1),(-1,-1),2,1]}[p if p=='p'else p.upper()]
  if p in'pP':d=d[d!=[2,7][p=='p']+A:]
  for u,v in d:
   for j in range(k):
    for i in range(1,n):
     U=r+u*i;V=f+v*i;t=b.get((U,V),'^')
     if U<1or U>8or V<1 or V>8:break
     if F(p,t):
      B=dict(b);B[(U,V)]=B.pop((r,f))
      if t in'eE':B.pop(([U+1,U-1][t=='e'],V))
      yield B
     if t not in'^eE':break
    u,v=v,-u
M=lambda b:all(any('k'not in C.values()for C in m(B,'W',1))for B in m(b,'b'))

Hãy thử trực tuyến!


Điều này hiện không thành công cho 8/2p5/Q7/Q2k4/Q7/8/8/7K b - -(không phải checkmate).
Arnauld
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.