kral + kale vs kral


16

İyi oynanan başka bir satranç oyununun sonu. Sen beyaz oyuncusun ve hala bir kalen ve kralın var. Rakibin sadece kralı kaldı.

Beyaz olduğunuz için sıra sizde. Bu satranç maçını oynamak için bir program oluşturun. Çıktısı bir dizi hareket, bir gif animasyonu, ASCII sanatı veya istediğiniz herhangi bir şey olabilir.

Oldukça açık görünüyor, ama açıkça belirteceğim: oyunu kazanmak zorundasın (sınırlı sayıda hamle ile). Bu pozisyondan kazanmak her zaman mümkündür. Bu kitabı kaybetmeyin. STALEMAT ETMEYİN.

Programınız başlangıç ​​konumu ve her siyah hareket için bir insan girişini kabul edebilir veya etmeyebilir (bunun yasal bir konum olduğunu, yani kralların birbirine değmediğini güvenle varsayabilirsiniz). Değilse, rastgele bir başlangıç ​​pozisyonu ve kara kral için rastgele hareketler yeterli olacaktır.

Puan

Puanınız, kod + bonusunuzun bayt cinsinden uzunluğu olacaktır. Herhangi bir dile izin verilir, en düşük puan kazanır.

Bonus

Programınız hem insan tanımlı bir başlangıç ​​konumuna hem de rastgele bir konuma izin veriyorsa -50. İnsanlar stdin, dosya, GUI aracılığıyla girebilirsiniz ...

Programınız hem bir insan hem de rastgele bir oyuncunun kara kralı hareket ettirmesine izin veriyorsa -100

Harici bir satranç çözücüsüne veya yerleşik bir satranç kütüphanesine güveniyorsanız +12345

İyi şanslar!

Güncelleme!

Ek kural: Maç, mat arkadaşına kadar oynanmalıdır. Siyah istifa etmez, satranç tahtasının dışına atlamaz ve uzaylılar tarafından kaçırılmaz.

İpucu

Muhtemelen yardım alabilirsiniz bu soruya üzerinde chess.se .


2
50 hamle kuralı geçerli mi?
Komintern

1
@Victor Birkaç gidişim oldu, ama henüz işe yaramadı. Kaba kuvvet açıkça çok yavaş, alfa-beta da çünkü pozisyon derecelendirmelerinin manzarası oldukça düz; ve bir döngüde takılma eğilimindedir. Retrograd analiz işe yarayacaktır, ancak çok yavaş ilerleyecektir. Bir sonraki denemem, Bratko'nun KRK için algoritmasını kullanacağım, çünkü kaçındım çünkü özel durumlar yığını, golf için harika değil.
bazzargh

1
@victor Ben de buna bakıyorum. Bu tam olarak ilginç çünkü tanımlaması basit ve yapılması zor. Buna karşılık program kısa olmayacak, bu yüzden kod golf etiketi iki kat zor görünüyordu. Programım çalışırsa yakında göreceksiniz.
Level River St

1
@Victor sorun optimal olmaya çalışmakla ilgili değildi, oyun tarihini düşünmeden herhangi bir 'en iyi' hamleyi seçme girişimi döngülere yol açtı. Oyun test etmek gerekir her pozisyondan sona erer. Bratko + varyantları optimal değildir, ancak muhtemelen sona erer. Az önce (yani inşa oyun sonu tablo) retrograd analizi çalışılıyor, bakışlar aslında umut verici ve bir güzel olan optimum. Ayrıca oldukça kısa çıkıyor.
bazzargh

2
Herkes ilham gerekir (ya da sadece meraklı), bir 1433 karakter bulabilirsiniz komple satranç motoru en home.hccnet.nl/hgmuller/umax1_6.c
Komintern'i

Yanıtlar:


11

Haskell 1463-100 = 1363

Sadece bir cevap almak. Bu, çözümü matematiksel konumdan geri döndüğümüz konuma geri döndürerek çözümü retrograd yol olarak bulur. Satranç programında retrograd analizinin tanımından farklıdır - bir başlangıç ​​seti ile başlamak ve geriye doğru hareketlerle genişletmek yerine hiçbir kareler görülmedikçe, kullanılmayan tüm karelerle başlar ve ileri hareketleri deneyerek bu ayarı azaltır. Bu, geleneksel yoldan daha az zaman tasarrufu sağlayacak, ancak denediğimde bellek kullanımı benim için patladı.

ghc -O2Oyunsonu tablosu hesaplaması için kabul edilebilir performans için derleyin ; oyun ilk hamleden sonra anında gerçekleşir. Argüman olarak beyaz kral, kale, kara kral kareleri sağlayın. Bir hareket için, sadece bir kare istiyor ve return tuşuna basarsanız sizin için bir tane seçecek. Örnek oturum:

$ time  printf "\n\n\n\n\n\n\n\n"|./rook8 e1 a1 e8
("e1","a7","e8")[d8]?
("d2","a7","d8")[c8]?
("d2","h7","c8")[b8]?
("c3","h7","b8")[a8]?
("b4","h7","a8")[b8]?
("c5","h7","b8")[a8]?
("b6","h7","a8")[b8]?
("b6","h8","b8") mate

real    0m8.885s
user    0m8.817s
sys 0m0.067s

Kod:

import System.Environment
import qualified Data.Set as S
sp=S.partition
sf=S.fromList
fl=['a'..'h']
rk=[0..7]
lf=filter
m=map
ln=notElem
lh=head
pl=putStrLn
pa[a,b]=(lh[i|(i,x)<-zip[0..]fl,a==x],read[b]-1)
pr(r,c)=fl!!r:show(c+1)
t f(w,r,b)=(f w,f r,f b)
km(a,b)=[(c,d)|c<-[a-1..a+1],d<-[b-1..b+1],0<=c,c<=7,0<=d,d<=7]
vd (w,r,b)=b`ln`km w&&w/=r&&b/=w&&b/=r
vw p@(_,r,b)=vd p&&r`ln`km b&&(ck p||[]/=bm p)
vb p=vd p&&(not.ck)p
rm (w@(c,d),(j,k),b@(u,x))=[(w,(j,z),b)|z<-rk,z/=k,j/=c||(k<d&&z<d)||(d<k&&d<z),j/=u||(k<x&&z<x)||(x<k&&x<z)]
kw(w,r,b)=m(\q->(q,r,b))$km w
xb(w,r,_)b=(w,r,b)
wm p=lf(\q->q/=p&&vw q)$rm p++(m(t f)$rm$t f p)++kw p
bm p@(_,_,b)=lf(\q->q/=p&&vb q)$m(xb p)$km b
c1((c,d),(j,k),(u,x))=j==u&&(c/=j||(k<x&&d<k)||(k>x&&d>k))
ck p=c1 p||(c1$t f p)
mt p=ck p&&[]==bm p
h(x,y)=(7-x,y)
v=f.h.f
f(x,y)=(y,x)
n p@((c,d),_,_)|c>3=n$t h p|d>3=n$t v p|c>d=n$t f p|True=p
ap=[((c,d),(j,k),(u,x))|c<-[0..3],d<-[c..3],j<-rk,k<-rk,u<-rk,x<-rk]
fr s p=S.member(n p)s
eg p=ef(sp mt$sf$lf vw ap)(sf$lf vb ap)
ps w mv b0=sp(\r->any(fr b0)$mv r)w
ef(b0,b1)w=let(w1,w2)=ps w wm b0 in(w1,b0):(if S.null w2 then[]else ef(f$ps b1 bm w2)w2)
lu((w1,b0):xs)p=if fr w1 p then lh$lf(fr b0)$wm p else lu xs p
th(_,_,b)=b
cd tb q=do{let{p=lu tb q};putStr$show$t pr p;if mt p then do{pl" mate";return()}else do{let{b1=pr$th$lh$bm p};pl("["++b1++"]?");mv<-getLine;cd tb$xb p (pa$if""==mv then b1 else mv)}}
main=do{p1<-getArgs;let{p2=m pa p1;p=(p2!!0,p2!!1,p2!!2)};cd(eg p)p}

Düzenlendi: Son oyun tablosunu hatırlamak ve argümanları kullanmak için kod tekrar tekrar test etmek için çok daha az acı düzeltildi.


2
yan etkileri olan haskell kodu? nasıl olabilir, sapkın! : p
Einacio

sonunda ciddi bir tane!
izabera

bu bulmaca kötü @izabera!
bazzargh

Güzel! Üzerinde çalıştığım girişimden çok daha iyi. El Ajedrecista'yı 50 hareket eşini sağlayacak kadar geliştirmeye çalışıyordum, ancak bir algoritmaya göre gerçekten kötü.
Komintern

Sucky performansının çoğu benden oyun sonu tablosunu ( y) hatırlamıyor . Bu, zaten tüm oyunsonunu düşündüğümüzde ikinci hamlenin hızlı olmadığı açıktır. Bu akşam pub'a gidiyorum ama yarın şansım olursa bunu daha az korkunç hale getireceğim.
bazzargh

7

C, Şu anda 2552 rahatsız olmayan boşluk karakteri

Sayı bana 2552 toplam karakter altında golf olabilir gösterir, ama zaten küçük bir cevap (ki yenmek için zor olacak) verilen bunu yapmak için rahatsız etmeden önce dikkatlice düşünün. Tahtayı görüntülemek için yaklaşık 200 karakter ve hem başlangıç ​​konumu hem de hareketin kullanıcı girişini kontrol etmek için yaklaşık 200 karakter var (test için ihtiyacım var, ancak ortadan kaldırabilir).

Burada oyun ağacı yok, sadece kodlanmış algoritma, bu yüzden anında hareket ediyor.

Başlangıç ​​pozisyonları, sağ üst köşeden numaralandırılmış sıra (1-8) sütun (1-8) olarak girilir ve program aynı şemada çalışır. Ekranınızı saat yönünün tersine 90 derece döndürürseniz, standart Yazışma Satranç sayısal kare gösterimini izler. Kara kralın zaten kontrol altında olduğu pozisyonlar yasadışı olarak reddedilir.

Siyah hareketler 0 ila 7 arasında bir sayı olarak girilir, 0 kuzeyde bir hareket, 1 kuzeydoğuda bir harekettir ve saat yönünde çalışır.

Kara kralı kısıtlamak için sadece beyaz kralın koruması altındaki kaleyi kullanan yaygın olarak bilinen algoritmayı takip etmez. Kale, kara kralı yalnızca dikey anlamda kısıtlar (ve kovalanırsa yatay olarak kaçar.) Beyaz kral kara kralı yatay hareketle kısıtlar. Bu, iki beyaz parçanın birbirlerinin yoluna girmediği anlamına gelir.

Hataların çoğunu ve olası sonsuz döngülerden ütülenmiş gibiyim, şimdi oldukça iyi çalışıyor. Yarın tekrar oynayacağım ve düzeltilmesi gereken başka bir şey olup olmadığını göreceğim.

#include "stdafx.h"
#include "stdlib.h"
#include "string.h"

int b[2], w[2], r[2], n[2],s,t,i,nomate;
int v[2][8] = { {-1,-1,0,1,1,1,0,-1}, {0,1,1,1,0,-1,-1,-1} };
int u[5] = { 0, 1, -1, 2, -2 };
char empty[82] = "        \n--------\n--------\n--------\n--------\n--------\n--------\n--------\n--------\n";
char board[82];

int distance(int p[2], int q[2]){
    return __max(abs(p[0]-q[0]),abs(p[1]-q[1]));
}

int sign(int n){
    return (n>0)-(0>n); 
}

// from parameters p for white king and q for rook, determines if rook is/will be safe
int rsafe(int p[2],int q[2]){
    return  distance(p, q)<2 | distance(q,b)>1;
}

void umove(){
    t=0;
    while (t != 100){
        printf("Enter number 0 to 7 \n");
        scanf_s("%d", &t); t %= 8;
        n[0] = b[0] + v[0][t];
        n[1] = b[1] + v[1][t];
        if (distance(w, n) < 2 | (n[0] == r[0] & (n[1]-w[1])*(r[1]-w[1])>0) 
            | ((n[1] == r[1]) & (n[0]-w[0])*(r[0]-w[0])>0) | n[0] % 9 == 0 | n[1] % 9 == 0)
            printf("illegal move");
        else{ b[0] = n[0]; b[1] = n[1]; t = 100; };
    }
}

void imove(){
    t=0;
    // mate if possible
    if (distance(b, w) == 2 & b[0] == w[0] & (b[1] == 1 | b[1] == 8) & r[0]!=w[0]){
        n[0] = r[0]; n[1] = b[1];
        if (rsafe(w, n)){
            r[1] = n[1]; 
            printf("R to %d %d mate!\n", r[0], r[1]);
            nomate=0;
            return;
        }
    }

    //avoid stalemate
    if ((b[0] == 1 | b[0] == 8) & (b[1] == 1 | b[1] == 8) & abs(b[0] - r[0]) < 2 & abs(b[0]-w[0])<2){
        r[0] = b[0]==1? 3:6;
        printf("R to %d %d \n", r[0], r[1]);
        return;
    }

    // dont let the rook be captured. 
    if(!rsafe(w,r)) 
    {
        if (w[0] == r[0]) r[1] = w[1] + sign(r[1]-w[1]);
        else r[1] = r[1]>3? 2:7;
        printf("R to %d %d \n", r[0], r[1]);
        return;
    }

    // if there's a gap between the kings and the rook, move rook towards them. we only want to do this when kings on same side of rook, and not if the black king is already on last row.
    if (abs(w[0]-r[0])>1 & abs(b[0] - r[0]) > 1 & (b[0]-r[0])*(w[0]-r[0])>0 & b[0]!=1 & b[0]!=8){
        n[0] = r[0] + sign(b[0] - r[0]); n[1] = r[1];
        if (rsafe(w, n)) r[0] = n[0]; 
        else r[1] = r[1]>3? 2:7;
        printf("R to %d %d \n", r[0], r[1]);
        return;

    }
    // if kings are far apart, or if they not on the same row (except if b 1 row from r and w 2 rows from r), move king
    if ((w[0]-r[0])!=2*(b[0]-r[0]) | abs(b[0]-w[0])>1 | distance(w,b)>2){
        for (i = 0; i<8; i++) if (v[0][i] == sign(b[0] - w[0]) & v[1][i] == sign(b[1] - w[1])) t = i;
        s = 1 - 2 * (w[0]>3 ^ w[1] > 3);
        for (i = 0; i < 5; i++){
            n[0] = w[0] + v[0][(t + s*u[i] + 8) % 8];
            n[1] = w[1] + v[1][(t + s*u[i] + 8) % 8] *(1-2*(abs(w[0]-b[0])==2));
            if (distance (n,b)>1 & distance(n, r)>0 & rsafe(n,r) & n[0]%9!=0 & n[1]%9!=0
                & !(n[0]==r[0] & (w[0]-r[0])*(b[0]-r[0])>0)) i = 5;
        }
        if (i == 6) {
            w[0] = n[0]; w[1] = n[1]; printf("K to %d %d \n", w[0], w[1]); return;
        }
    }

    //if nothing else to do, perform a waiting move with the rook. Black is forced to move his king.
    t = r[1]>3? -1:1;
    for (i = 1; i < 5; i++){
        n[0] = r[0]; n[1] = r[1] + t*i;
        if (rsafe(w, n)){ r[1] = n[1]; i=5; }
    }
    printf("R to %d %d \n", r[0], r[1]);
}

int _tmain(){

    do{ 
        t=0;
        printf("enter the row and col of the black king ");
        scanf_s("%d%d", &b[0], &b[1]);
        printf("enter the row and col of the white king ");
        scanf_s("%d%d", &w[0], &w[1]);
        printf("enter the row and col of the rook");
        scanf_s("%d%d", &r[0], &r[1]);
        for (i = 0; i < 2; i++) if (b[i]<1 | b[i]>8 | w[i]<1 | w[i]>8 | w[i]<1 | w[i]>8)t=1;
        if (distance(b,w)<2)t+=2;
        if ((b[0] == r[0] & (b[1]-w[1])*(r[1]-w[1])>0) | ((b[1] == r[1]) & (b[0]-w[0])*(r[0]-w[0])>0)) t+=4;
        printf("error code (0 if OK) %d \n",t);
    } while(t);

    nomate=1;
    while (nomate){
        imove();
        strncpy_s(board, empty, 82);
        board[b[0] * 9 + b[1] - 1] = 'B'; board[w[0] * 9 + w[1] - 1] = 'W'; board[r[0] * 9 + r[1] - 1] = 'R'; printf("%s", board);      
        if(nomate)umove();
    }
    getchar(); getchar();

}

İşte tipik bir yüzey (montaj ilişkisi bazen kartın sağ veya sol kenarında herhangi bir yerde olabilir.)

resim açıklamasını buraya girin


6

Bash, 18 (veya -32?)

Tamam, bu şaka yanıtı. Siyah iyi bir satranç oyuncusu olduğundan ve Beyaz'ın da iyi bir satranç oyuncusu olduğunu bildiğinden, yapılacak tek mantıklı şeyin olduğuna karar verir:

echo Black resigns

Bu, spesifikasyonu karşılayan beyaz kazanmayla sonuçlanır.

Teknik olarak mevcut pozisyonları argüman olarak da girebilirsiniz, program onları görmezden gelir, bu yüzden tartışmasız bu -50 bonusu için hak kazanabilir.


Komik, ama kuralları güncelledim. Şah Mat oyununa kadar oynamak artık zorunlu.
izabera

1
Btw orijinal soru açıkça programınızın bir insan veya rastgele bir oyuncu için siyah izin verebilir ve sizin rastgele değildir.
izabera

2
Standart gösterimi kullanarak, 1-0biraz daha kısa çıktı alabilirsiniz .
daniero

1
@ Optimum kaybederken gerçek olan gerçek, genellikle en uzun süre dayanmak demektir.
PyRulez

@PyRulez, wikipedia'ya göre , "Her iki oyuncu istediği zaman istifa edebilir ve rakibi oyunu kazanır." Artı, bu sadece bir şaka cevabı, çok ciddiye alma.
user12205
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.