Tic-Tac-Toe e Xadrez, com menos caracteres [distintos]

9

Nesta forma de jogo Tic-Tac-Chec, o objetivo é mover peças de xadrez para obter quatro em linha. Seu objetivo aqui é descobrir se uma posição tem uma jogada vencedora.

Regras

As regras são semelhantes, mas não idênticas, às do Tic-Tac-Chec.

O tabuleiro é de 4 por 4 quadrados. Cada jogador tem uma torre, bispo, cavaleiro e rainha. Por sua vez, você tem duas opções. Você pode mover uma de suas peças já no tabuleiro, seguindo as regras padrão do xadrez. Ou você pode colocar uma peça ainda não no quadro, em qualquer lugar desocupado.

Se você mover uma peça existente para a peça do oponente, a peça é retirada do tabuleiro e devolvida a eles. No entanto, você não pode colocar uma nova peça em cima da peça de um oponente.

Assim que um jogador tiver todas as suas peças seguidas (ou coluna ou diagonal), ele vence.

Desafio

Escreva um programa completo que aceite uma placa do STDIN e mostre se o jogador branco pode vencer no próximo turno.

Entrada

Quatro strings de 4 caracteres cada. Cada personagem é um espaço ou uma peça de xadrez. Somente gralhas, bispos, cavaleiros e rainhas são usadas e, no máximo, uma de cada (por cor) pode aparecer. Nenhum dos jogadores já tem quatro em linha.

Você pode optar por aceitar como entrada os símbolos Unicode para as peças de xadrez ou letras. Se você escolher letras, RBKQrepresenta peças brancas e rbkqpeças pretas.

Resultado

Se o jogador branco puder vencer no próximo turno, produza trueou 1. Caso contrário, saia falseou 0.

Programa

Escolha um número X. Seu programa pode conter no máximo X caracteres distintos e nenhum caractere pode aparecer mais de X vezes.

Ganhando

O menor X vence. Em caso de empate, o menor número de personagens vence.

Exemplos

Estes exemplos assumem que a entrada usa letras para representar as peças.

rkb 


RB Q
true - the white player can place the knight to complete the bottom row.
-----------------------------------
rk    


RBbQ
false - the black bishop prevents the white knight from completing the row.
-----------------------------------
rk  
 K  

RBbQ
true - the white knight can capture the black bishop and complete the row.
-----------------------------------
rkRB

 Qb 
K   
true - the white rook can move down one to complete the diagonal.
Ypnypn
fonte
Então, oOo código vai ganhar?
Kennytm
@KennyTM Nenhum caractere pode aparecer mais do que X vezes o tornará inútil
Optimizer
@Optimizer OK desculpe mal as regras.
Kennytm
2
Se os exemplos forem colocados em um formato mais legível, é bastante difícil ver quais são as posições das peças e a que cor elas pertencem.
Tally
O espaço em branco é permitido?

Respostas:

3

C, 53 caracteres distintos

Isso usa "#%&()*+,-./01234569;<=>BKQR[\]acdefghilmnoprstu{|}espaço e nova linha, distribuídos da seguinte forma: 24 × \n, 33 × , 20 × ", 2 × #, 3 × %, 16 × &, 46 × (, 46 × ), 13 × *, 12 × +, 35 × ,, 10 × -, 2 × ., 2 × /, 18 × 0, 9 × 1, 4 × 2, 4 × 3, 4 × 4, 4 × 5, 3 × 6, 3 × 9, 34 × ;, 6 × <, 46 × =, 2 × >, 2 × B, 2 × K, 2 × , 3 × Q, 2 × R, 8 × [, 1 × \, 8 × ], 39 × a, 23 × c, 5 × d, 19 × e, 15 × f, 1 × g, 22 × h, 36 × i, 5 × l, 1 × m, 35 × n, 9 ×o, 33 × p, 44 × r, 20 × s, 43 × t, 15 × u, 8 × {, 14 × |, 8 × }.

#include <stdio.h>
#include <string.h>
int n(char*a,char*e,int i)
{int c=0;for(;a<e;)c+=*a++=="\n"[0];return c==i;}

int p(char *t, int r, int u)
{char h[]=" RBQK";char*p=t+r;char*a;int c=0;
for(int i=0;i<=3;++i,p+=u){char*s=strchr(h,*p);if(s&&s==h==0){++c;*s=" "[0];}else{a=p;}}
if(c-3)return 0;
char o=h[strspn(h, " ")];
p=strchr(t, o);
if(p==0)return*a==" "[0];
if(p<a){char*s=p;p=a;a=s;}
if(o=="K"[0])return(p-a)==3&&n(a,p,1)||(p-a)==2+5&&n(a,p,1)||(p-a)==9&&n(a,p,2)||(p-a)==11&&n(a,p,2);
if((p-a)%5==0||n(a,p,0))return (int)strchr("RQ", o);
return((p-a)%4==0&&n(a,p,(p-a)/4)||(p-a)%6==0&&n(a,p,(p-a)/6))&&strchr("BQ",o);}

int f(char *t)
{for(int i=0;i<4;++i)if(p(t,i,5)||p(t,i*5,1))return 1;
return p(t,0,6)||p(t,3,4);}

int main()
{char t[20];fread(t,19,1,stdin);t[19]=0;
if(f(t))puts("true");else puts("false");}

Explicação

#include <stdio.h>
#include <string.h>

/* count newlines */    
int n(char *a, char *e)
{
    int c = 0;
    for (;a<e;) c += *a++=='\n';
    return c;
}

/* check a single row, column or diagonal */
int p(char *t, int start, int stride)
{
    char h[] = " RBQK"; /* pieces not in line */
    char *p = t+start;
    char *a;
    int c = 0;
    for (int i = 0;  i <= 3;  ++i, p+=stride) {
        char *s = strchr(h, *p);
        if (s && s == h == 0) {
            /* a white piece */
            ++c;
            *s = " "[0];
        } else {
            /* candidate target square */
            a = p;
        }
    }

    /* did we find three white pieces in this line? */
    if (c != 3)
        return 0;

    char o = h[strspn(h, " ")];

    p = strchr(t, o);

    if (p==0)
        return *a == " "[0];

    /* ensure a < p */
    if (p < a) {
        char *s = p;
        p = a;
        a = s;
    }

    /* knight moves */
    if (o == 'K')
        return (p-a)==3 && n(a,p)==1
            || (p-a)==7 && n(a,p)==1
            || (p-a)==9 && n(a,p)==2
            || (p-a)==11 && n(a,p)==2;

    /* rook moves */
    if ((p-a)%5 == 0 || n(a,p)==0)
        return 0==strchr("RQ", o)==0;

    /* bishop moves */
    return
        ((p-a)%4==0 && n(a,p)==(p-a)/4 ||
         (p-a)%6==0 && n(a,p)==(p-a)/6)
        && strchr("BQ", o);
}

/* main predicate function */
int f(char *t)
{
    /* try rows and columns */
    for (int i = 0;  i < 4;  ++i)
        if (p(t, i, 5) || p(t, i*5, 1))
            return 1;
    /* try diagonals */
    return p(t, 0, 6) || p(t, 3, 4);
}

int main()
{
    char t[20];
    fread(t, 19, 1, stdin);
    t[19]=0;
    if (f(t)) puts("true"); else puts("false");
}

Ele trabalha procurando uma linha, coluna ou diagonal contendo três das peças brancas; aaponta para a posição de destino (ainda não contém uma peça branca). Então a peça que falta ( o) é identificada - é a que não removemos da corda hcomo a vimos.

Se a peça não estiver no tabuleiro, ela deve estar na mão e só pode ser jogada em um espaço. Caso contrário (se o encontrarmos no quadro), ele deverá estar em uma posição em que possa se mover para o quadrado alvo. Como os movimentos são reversíveis, trocamos, se necessário, para que a < p.

Testamos os movimentos de cavaleiro primeiro - há quatro movimentos legais para baixo e evitamos envolver as bordas esquerda / direita do quadro verificando o número de novas linhas que passamos.

Depois disso, testamos movimentos de torre e, em seguida, movimentos de bispo, usando um algoritmo semelhante (e uma rainha pode usar qualquer um desses movimentos).

Programa de teste

int expect_true(char *board)
{
    if (strlen(board) != 19) {
        fprintf(stderr, "Wrong length board:\n%s\n\n", board);
        return 1;
    }
    if (!f(board)) {
        fprintf(stderr, "Expected true, but got false, for\n%s\n\n", board);
        return 1;
    }
    return 0;
}

int expect_false(char *board)
{
    if (strlen(board) != 19) {
        fprintf(stderr, "Wrong length board:\n%s\n\n", board);
        return 1;
    }
    if (f(board)) {
        fprintf(stderr, "Expected false, but got true, for\n%s\n\n", board);
        return 1;
    }
    return 0;
}


int main()
{
    return
        + expect_true("rkb \n"
                      "    \n"
                      "    \n"
                      "RB Q")
        + expect_false("rk  \n"
                       "    \n"
                       "    \n"
                       "RBbQ")
        + expect_true("rk  \n"
                      " K  \n"
                      "    \n"
                      "RBbQ")
        + expect_true("rk  \n"
                      "    \n"
                      "K   \n"
                      "RBbQ")
        + expect_true("rkRB\n"
                       "    \n"
                       " Qb \n"
                       "K   ")
        + expect_true("rk  \n"
                      "    \n"
                      "K   \n"
                      "RBbQ");
}

Programa de contagem (em C ++)

#include<algorithm>
#include<iostream>
#include<map>

int main()
{
    std::map<char,int> m;
    for (int c;  (c = getchar()) != EOF; )
        ++m[c];

    for (auto e: m)
        std::cout << e.first;

    std::cout << "\n distributed as follows: ";
    for (auto e: m)
        std::cout << e.second << "×`" << e.first << "`, ";
}
Toby Speight
fonte
1
Sugerir 6+3para 9And 16+3for19
ceilingcat 14/03