C, в настоящее время 2552 некомментированных непробельных символа
Подсчет указывает на то, что я могу сыграть в гольф ниже 2552 общих символов, но, учитывая, что уже есть ответ меньшего размера (который будет трудно победить), я тщательно обдумаю это, прежде чем потрудиться сделать это. Это правда, что есть около 200 символов для отображения доски и еще 200 символов для проверки пользовательского ввода как начальной позиции, так и движения (что мне нужно для тестирования, но можно устранить).
Здесь нет дерева игр, только жестко закодированный алгоритм, поэтому он движется мгновенно.
Начальные позиции вводятся в виде строки (1-8) столбца (1-8), пронумерованного сверху справа, и программа работает по той же схеме. Поэтому, если вы поверните экран на 90 градусов против часовой стрелки, он будет следовать стандартным обозначениям числовых квадратов «Шахматы по переписке». Позиции, где черный король уже находится под контролем, отклоняются как незаконные.
Черные ходы вводятся как числа от 0 до 7, где 0 - это движение на север, 1 на северо-восток и т. Д. По часовой стрелке.
Он не следует общеизвестному алгоритму, который использует исключительно ладью под защитой белого короля, чтобы ограничить черного короля. Ладья только ограничивает черного короля в вертикальном смысле (и убегает горизонтально, если преследуется). Белый король ограничивает черного короля в горизонтальном движении. Это означает, что две белые фигуры не мешают друг другу.
Кажется, я сгладил большинство ошибок и возможных бесконечных циклов, теперь он работает довольно хорошо. Завтра я снова поиграюсь с этим и посмотрю, есть ли что-то, что нужно исправить.
#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();
}
Вот типичное завершение (мат может иногда происходить в любом месте на правом или левом краю доски.)