Грайте в дійсний шаховий хід, даючи дошку на stdin


11

Програма грає білого кольору.

Приклад stdin:

8 ║♜ ♞ ♝ ♛ ♚ ♝ ♞ ♜
7 ║♟ ♟ ♟ ♟ … ♟ ♟ ♟
6 ║… … … … … … … …
5 ║… … … … ♟ … … …
4 ║… … … … … … … …
3 ║… … ♘ … … … … …
2 ║♙ ♙ ♙ ♙ ♙ ♙ ♙ ♙
1 ║♖ … ♗ ♕ ♔ ♗ ♘ ♖
——╚═══════════════
—— a b c d e f g h

Приклад stdout:

8 ║♜ ♞ ♝ ♛ ♚ ♝ ♞ ♜
7 ║♟ ♟ ♟ ♟ … ♟ ♟ ♟
6 ║… … … … … … … …
5 ║… … … … ♟ … … …
4 ║… … … … ♙ … … …
3 ║… … ♘ … … … … …
2 ║♙ ♙ ♙ ♙ … ♙ ♙ ♙
1 ║♖ … ♗ ♕ ♔ ♗ ♘ ♖
——╚═══════════════
—— a b c d e f g h

Будь-який дійсний хід - це нормально. "En passant" та кастинг ігноруються. Добре показувати повідомлення про помилки або нічого не друкувати, якщо немає дійсного руху.

Відповідь з найбільшою кількістю голосів виграє.


Я маю на увазі стандартне повідомлення про помилку, викликане збоєм якоїсь вбудованої функції мови. Так це нормально? - Чи обов'язково програма може зробити будь-який законний крок? Можливо, спеціальні ходи для виведення та пішаки повинні бути необов’язкові з певним бонусом?
перестали повертати проти годинника,

2
@leftaroundabout: Щоразу, коли ви зможете замок, ви можете просто перемістити грак, а не пропустити логіку для цього хоча б.
гаммар

2
... і подумавши про це ще раз, для "перехідного" кроку потрібна інформація про те, що було зроблено попередні кроки, про які не можна зробити висновок лише з позицій фігур, тому я думаю, що це може бути безпечно відмовитись від цього. Однак, чи є подвійний перший хід, можна зробити висновок з рангу пішака, тож ви, можливо, захочете включити це.
гаммар

@hammar: ти маєш рацію, я не думав про це. Подвійний хід також не важливий, за винятком одного випадку: коли ви можете пройти два кроки, ви також можете пройти один, тому він стає важливим лише тоді, коли ви перебуваєте в перевірці, а подвійний хід - єдиний хід, який охоплює короля. Крім того, навіть коли вам не потрібно використовувати кожен крок, вам все одно потрібно врахувати, що чорний може відповісти з будь-якою можливістю.
перестала повертати проти годинника,

9
Чи відкликається відставка як законний крок? :)
гніблер

Відповіді:


16

Я не скаржуюся на нагороди, але якщо чесно ... моє рішення тут насправді не все так здорово. Ugoren's краще, крім відсутності підтримки Unicode. Не забудьте переглянути всі відповіді перед голосуванням, якщо ви натрапили на це питання лише зараз!
У всякому разі.

Хаскелл, 893 888 904 952 (без лиття)

862 (без подвійних ходів пішаків)

(Ви не вказували, чи повинен це бути код гольфу, але мені здається, що слід)

χ=w⋈b;w="♙♢♤♔♕♖♗♘";b="♟♦♠♚♛♜♝♞"
μ=t⤀ζ++((\(x,y)->(x,-y))⤀)⤀μ;q c|((_,m):_)<-((==c).fst)☂(χ⋎μ)=m
t(x:y:l)=(d x,d y):t l;t _=[];d c=fromEnum c-78
ζ=["NM","NL","MMOM","MMMNMONMNOOMONOO",σ⋈δ,σ,δ,"MLOLPMPOOPMPLOLM"]
σ=l>>=(\c->'N':c:c:"N");δ=[l⋎l,reverse l⋎l]>>=(>>=(\(l,r)->[l,r]))
l="GHIJKLMOPQRSTU"
α c|c∊"♢♤"='♙'|c∊"♦♠"='♟'|c∊χ=c;π('♙':_)=6;π _=1
(⋎)=zip;(⤀)=map;(∊)=elem;(✄)=splitAt;(☂)=filter;(⋈)=(++)
φ r@(x,y)p a
 |x>7=φ(0,y+1)p a
 |y>7=[]
 |c<-a✠r=(c⌥r)p a y⋈φ(x+1,y)p a
(c⌥r)p a y
 |c==p!!0=(a☈r)c χ++const(y==π p)☂(a☈r)(p!!1)χ++(a☈r)(p!!2)('…':w)
 |c∊p=(a☈r)c χ
 |True=[]
a✠(x,y)=a!!y!!(x*2);o(x,y)=x>=0&&x<8&&y>=0&&y<8
(n➴a)(x,y)|(u,m:d)<-y✄a,(l,_:r)<-(x*2)✄m=u⋈(l⋈(n:r):d)
(a☈r@(x,y))c b=(α c➴('…'➴a)r)⤀((\r->o r&&not((a✠r)∊b))☂((\(ξ,υ)->(x+ξ,y+υ))⤀q c))
main=interact$unlines.uncurry((⋈).zipWith((⋈).(:" ║"))['8','7'..]
 .head.((all(any('♔'∊)).φ(0,0)b)☂).φ(0,0)w.(drop 3⤀)).(8✄).lines

Коли у вас встановлений GHC (наприклад, як частина платформи Haskell ), ви можете робити просто

$ runhaskell def0.hs < examplechessboard.txt
8 ║♜ ♞ ♝ ♛ ♚ ♝ ♞ ♜
7 ║♟ ♟ ♟ ♟ … ♟ ♟ ♟
6 ║… … … … … … … …
5 ║… ♘ … … ♟ … … …
4 ║… … … … … … … …
3 ║… … … … … … … …
2 ║♙ ♙ ♙ ♙ ♙ ♙ ♙ ♙
1 ║♖ … ♗ ♕ ♔ ♗ ♘ ♖
——╚═══════════════
—— a b c d e f g h

Тепер це божевільно :) Я це перевірю :)
Христо Христов

Будь-яка ідея, як перевірити цю дивовижність? Ideone.com не впорається з цим ...
Христо Христов

@HristoHristov: дивно це не працює на Ideone. Ймовірно, це стосується символів, що не належать до ASCII.
перестала повертати проти годинника,

так, це проблема з ідеоном
Христо Христов

14
Вітаємо, вам вдалося зробити так, щоб Haskell виглядав як APL. :-)
Ільмарі Каронен

11

C, 734 672 640 символів

Символи рахуються без знімного пробілу.
Формат файлу, який я використовував, не є запитом, а спрощений ASCII.
Мені потрібно додати підтримку символів Unicode, це коштувало б декількох характерів.

char*r=" kpnbrq  KPNBRQ $ ,&)$wxy()879()8(6:GI(",B[256],*b=B,i;
e(x,d,m,V,c,r,n,p){
    for(r=0,p=b[x];m/++r;){
        n=x+d*r;
        if(p==2+8*(d<0)||n&136||!(b[n]?r=8,8^p^b[n]^8&&c&65^64:c&65^65)
            ? r=m,0
            : V?v(n,x):b[n]==1)
            return b[x]=0,b[n]=p%8-2||n/16%7?p:p+4;
    }
    return d>0&&e(x,-d,m,V,c);
}
d(x,v,m,i)char*m;{
    return(i=*m-40)?e(x,i%64,b[x]%8-2?b[x]&4?7:1:(x/16-1)%5|i%2?1:2,v,i)||d(x,v,m+1):0;
}
v(t,f){
    bcopy(B,b+=128,128);
    b[t]=b[f];b[f]=0;
    i=a(1,63);
    b=B;
    return!i;
}
a(c,n){
    return b[i=n*2-n%8]&&b[i]/8==c&&d(i,!c,r+r[b[i]%8+15]-10)||n--&&a(c,n);
}
main(){
    for(;gets(b);b+=8)for(;*b;b++)*b=strchr(r,*b)-r;b=B;
    for(i=64*!a(0,63);i<64;i++%8-7||puts(""))putchar(r[b[i*2-i%8]]);
}

Формат файлу вводу / виводу:
повинно бути рівно 8 рядків з точно 8 символів. pnbrqkвикористовуються для білих шматочків, PNBRQKдля чорних шматочків, для пробілів:

RNBQKBNR
PPPP PPP

 n  P


pppppppp
r bqkbnr

Логіка досить проста:
для кожного можливого руху кожного білого шматка спробуйте кожен можливий хід кожного чорного шматка.
Якщо жоден чорний хід не захоплює білого короля, білий хід дійсний.

Дошка підтримується як char[256], розглядається як матриця 16х16, де використовується лише верхній лівий 8х8. Позиції та вектори руху зберігаються в 8-бітових цілих числах ( x:4,y:4). Додатковий біт дозволяє використовувати просту арифметику ( new_pos = old_pos + steps*direction), з легким виявленням краю дошки ( &0x88робить магію). r[]кодує три речі:

  1. Перші 15 байт відображають внутрішні шматки коду (K = 1, P = 2, N = 3, B = 4, R = 5, Q = 6) на літери.
  2. Наступні 6 байт відображають внутрішні шматки коду до зрушень в останній частині (K і Q однакові, B - їхній хвіст).
  3. Останні 16 байт кодують рух усіх фрагментів, як '('+vector.

Функції:

  1. mainчитає дошку, перетворює букви у внутрішній код, дзвонить, aщоб знайти білі ходи, друкує дошку.
  2. aрекурсивно петлі на 64 квадрати. Для кожного фрагмента потрібного кольору (параметра c) він знаходить правило руху для фрагмента та дзвонить d.
  3. dрекурсивно цикли за кодованим правилом руху, що представляє собою список векторів, що викликають eкожен з них. Це дає eвихідне положення, вектор та межу діапазону (7 для шматочків вище B, 2 для пішаків другого рангу, 1 в іншому випадку).
  4. eвипробовує всі рухи вздовж вектора. Якщо переміщення можливо (тобто пішаки рухаються вперед, всередині дошки, не блокуються, пішака захоплює по діагоналі), перевіряє одну з двох речей. Для білих рухів запустіть vдля підтвердження переміщення. На чорні ходи перевіряє, чи захоплений білий король. Якщо це правда, хід відтворюється на дошці.
  5. vпідтверджує білий хід. Він копіює дошку вбік, виконує переміщення для тестування і aзнову закликає шукати чорні ходи.

Нарешті, рішення з правильним стиснутим кодуванням можливих рухів! І це приємно швидко. Ви не думаєте, що можете додати обгортку Unicode і все ж бути коротшою, ніж мій код?
перестали повертати проти годинника,

@leftaroundabout, певно, можу. Основна проблема полягає в тому, що я працюю в командному рядку Linux, де ви не бачите Unicode, тому налагодження було б прикро. У мене також є версія, яка економить близько 40 байтів (я скоро оновлю), тому у мене є багато символів, з якими можна працювати.
угорен

@ugoren: Невже будь-який напівдорогий сучасний дистрибутив Linux підтримує UTF-8 поза коробкою?
Хан

@han, я працюю в Windows і підключаюся до Linux за допомогою SSH, а Unicode не працює. Я можу записати у файл і відкрити в Windows, але це вже не цікаво.
угорен

Чи буде це компіляція з gcc? Я використовую Geany для Windows з MinGW, і він збиратиметься з купою помилок та попереджень, але він не будуватиме / запускати.eg: C: \ Users \ xxx \ AppData \ Local \ Temp \ ccpBG9zy.o: codegolfchess.c :(. text + 0x2d8): невизначене посилання на "bcopy" collection2: ld повернув 1 статус виходу
rpd

5

Python 2.6, 886 - 1425 символів

Моя початкова версія (в редакції) вийшла на 886 символів, але не задовольнила специфікацію повністю (вона не перевіряла на те, щоб уникнути мат, не розглядала навіть можливі рухи чорних шматочків).

Зараз це робиться (і я виправив кілька помилок в оригіналі). На жаль, це коштує в символах: 1425 зараз, але все ще мало місця для вдосконалення. Ця версія повинна бути набагато більш міцною в обробці крайових справ, ніж попередня.

#-*-coding:utf8-*-
import sys;e=enumerate
B,W=["♟","♜","♞","♝","♛","♚"],["♙","♖","♘","♗","♕","♔"]
R={"♙":[11,42],"♖":[28],"♘":[31],"♗":[8],"♕":[8,28],"♔":[1,21]}
def F(w):return sum([[(i,j)for j,p in e(o)if p==w]for i,o in e(Z)],[])
def G(x,y):
 P=Z[x][y];D=P in W;L=[]
 for o in R[P]if D else R[unichr(ord(P.decode('utf8'))-6).encode('utf8')]:
  r,k="%02d"%o        
  for g,h in[[(-1,-1),(1,1),(-1,1),(1,-1)],[[(1,-1),(1,1)],[(-1,-1),(-1,1)]][D],[(-1,0),(1,0),(0,-1),(0,1)],[(-2,-1),(-2,1),(-1,-2),(-1,2),(1,-2),(1,2),(2,-1),(2,1)],[(-1,0)]][int(r)]:
   J=0
   for i in range(int(k)):
    T=x+(i+1)*g;U=y+(i+1)*h
    if T<0 or T>7 or U<0 or U>7:break
    M=Z[T][U]
    if not J:L.append((T,U,P,M))
    else:break
    if r in"02"and(M in W+B):
     J=1
     if not((D and M in B)or(not D and M in W)):L.pop()
    elif(r=="1"and not((D and M in B)or(not D and M in W)))or(r=="4"and((i==1 and x!=6)or M!="…")):L.pop()
 return L  
Z=[[y for y in l[5:].split()]for l in sys.stdin.readlines()[:-2]]
Q=[]
for p in R:
 for i,j in F(p):
  for M,L,c,_ in G(i,j):
   O=Z[M][L];Z[i][j]="…";Z[M][L]=c;E=[];map(E.extend,map(F,B))
   if not any(any(1 for _,_,_,I in G(v,h)if I==["♔","♚"][c in B])for v,h in E):Q.append((i,j,M,L,c))
   Z[i][j]=c;Z[M][L]=O
(x,y,X,Y,p)=Q[0];Z[x][y]="…";Z[X][Y]=p
for i,h in e(Z):print`8-i`+' ║'+' '.join(h)
print"——╚"+"═"*16+"\n—— a b c d e f g h"

Приклад введення та виведення:

# ВХОД

8 ║♜ ♞ ♝… ♚ ♝ ♞ ♜
7 ║♟ ♟ ♟ ♟… ♟ ♟ ♟
6 ║……………………
5 ║………… ♟………
4 ║………………… ♙ ♛
3 ║…………… ♙……
2 ║♙ ♙ ♙ ♙ ♙… ♙…
1 ║♖ ♘ ♗ ♕ ♔ ♗ ♘ ♖
——╚═══════════════
—— abcdefgh
# ВИХІД

8 ║♜ ♞ ♝… ♚ ♝ ♞ ♜
7 ║♟ ♟ ♟ ♟… ♟ ♟ ♟
6 ║……………………
5 ║………… ♟………
4 ║………………… ♙ ♛
3 ║…………… ♙ ♙…
2 ║♙ ♙ ♙ ♙ ♙………
1 ║♖ ♘ ♗ ♕ ♔ ♗ ♘ ♖
——╚════════════════
—— abcdefgh

Це 886 байт, але всього 854 символів. (Моя програма має понад 1 КБ, завдяки багатьом операторам, що не належать до ASCII!) - Чи збираєтесь ви ще додати чек на те, щоб взяти короля?
перестали повертати проти годинника,

@leftaroundabout: Я додав королівські чеки (що змушує мене також враховувати можливі ходи чорного кольору, і додає багато символів ...). Ну добре, ця версія повинна бути більш міцною навколо крайових корпусів (наскільки я тестував).
ChristopheD
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.