C, obecnie 2552 niekomentowanych znaków spoza białej przestrzeni
Liczenie wskazuje mi, że mógłbym zagrać w golfa poniżej 2552 znaków, ale biorąc pod uwagę, że jest już mniejsza odpowiedź (która będzie trudna do pokonania), zastanowię się nad tym ostrożnie, zanim się tym zajmę. To prawda, że jest około 200 znaków do wyświetlania tablicy, a kolejne 200 do sprawdzania danych wprowadzanych przez użytkownika zarówno pozycji początkowej, jak i ruchu (które potrzebuję do przetestowania, ale mogę je wyeliminować).
Nie ma tu drzewa gry, tylko zakodowany algorytm, więc porusza się natychmiast.
Pozycje początkowe są wprowadzane jako wiersz (1-8) kolumna (1-8) ponumerowana od prawej górnej części, a program działa na tym samym schemacie. Jeśli więc obrócisz ekran o 90 stopni w kierunku przeciwnym do ruchu wskazówek zegara, będzie on zgodny ze standardową notacją kwadratową w szachach korespondencyjnych. Pozycje, w których czarny król jest już pod kontrolą, są odrzucane jako nielegalne.
Czarne ruchy są wprowadzane jako liczby od 0 do 7, przy czym 0 oznacza ruch na północ, 1 na północny wschód i tak dalej, zgodnie z ruchem wskazówek zegara.
Nie postępuje zgodnie z powszechnie znanym algorytmem, który wykorzystuje wieżę wyłącznie pod ochroną białego króla, aby ograniczyć czarnego króla. Wież ogranicza czarnego króla tylko w sensie pionowym (i ucieknie poziomo, jeśli zostanie ścigany). Biały król ogranicza czarnego króla w ruchu poziomym. Oznacza to, że dwa białe elementy nie wchodzą sobie w drogę.
Wydaje mi się, że usunąłem większość błędów i możliwych nieskończonych pętli, teraz działa całkiem dobrze. Zagram jutro ponownie i zobaczę, czy jest coś jeszcze, co wymaga naprawy.
#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();
}
Oto typowe wykończenie (kolega może czasem wystąpić w dowolnym miejscu po prawej lub lewej krawędzi planszy).