Tic-Tac-Toe und Schach mit den wenigsten [unterschiedlichen] Charakteren

9

In dieser Form des Spiels Tic-Tac-Chec besteht das Ziel darin, Schachfiguren zu bewegen, um vier in einer Reihe zu erhalten. Ihr Ziel hier ist es herauszufinden, ob eine Position einen Gewinnzug hat.

Regeln

Die Regeln sind ähnlich, aber nicht identisch mit denen von Tic-Tac-Chec.

Das Brett ist 4 mal 4 Quadrate. Jeder Spieler hat einen Turm, einen Bischof, einen Ritter und eine Königin. In Ihrem Zug haben Sie zwei Möglichkeiten. Sie können eine Ihrer Figuren, die sich bereits auf dem Brett befindet, nach den Standardschachregeln bewegen. Oder Sie können ein Stück, das noch nicht auf dem Brett liegt, an einem freien Platz platzieren.

Wenn Sie eine vorhandene Figur auf die Figur eines Gegners verschieben, wird deren Figur vom Brett genommen und zu ihm zurückgebracht. Sie dürfen jedoch keine neue Figur auf die Figur eines Gegners legen.

Sobald ein Spieler alle Teile in einer Reihe (oder Spalte oder Diagonale) hat, gewinnt er.

Herausforderung

Schreiben Sie ein vollständiges Programm, das ein Board von STDIN akzeptiert und ausgibt, ob der weiße Spieler in der nächsten Runde gewinnen kann.

Eingang

Vier Zeichenfolgen mit jeweils 4 Zeichen. Jeder Charakter ist entweder ein Leerzeichen oder eine Schachfigur. Es werden nur Türme, Bischöfe, Ritter und Königinnen verwendet, von denen höchstens einer (pro Farbe) erscheinen darf. Keiner der Spieler hat bereits einen Vierer in Folge.

Sie können wählen, ob Sie die Unicode-Symbole für die Schachfiguren oder Buchstaben als Eingabe akzeptieren möchten. Wenn Sie Buchstaben auswählen, werden RBKQweiße und rbkqschwarze Teile dargestellt.

Ausgabe

Wenn der weiße Spieler in der nächsten Runde gewinnen kann, geben Sie trueoder aus 1. Ansonsten Ausgabe falseoder 0.

Programm

Wählen Sie eine Zahl X. Ihr Programm darf höchstens X verschiedene Zeichen enthalten, und kein Zeichen darf mehr als X Mal erscheinen.

Gewinnen

Das niedrigste X gewinnt. Bei einem Unentschieden gewinnen die wenigsten Charaktere.

Beispiele

In diesen Beispielen wird davon ausgegangen, dass die Eingabe Buchstaben verwendet, um die Teile darzustellen.

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
quelle
Also wird oOo Code gewinnen?
Kennytm
@KennyTM Kein Zeichen darf mehr als X-mal erscheinen, macht oOo unbrauchbar
Optimizer
@Optimizer OK Entschuldigung, die Regeln falsch verstanden.
Kennytm
2
Könnten die Beispiele in ein besser lesbares Format gebracht werden, ist es ziemlich schwierig zu erkennen, welche Positionen die Stücke haben und zu welcher Farbe sie gehören.
Tally
Ist Leerzeichen erlaubt?

Antworten:

3

C, 53 verschiedene Zeichen

Dies verwendet "#%&()*+,-./01234569;<=>BKQR[\]acdefghilmnoprstu{|}Raum und Zeilenumbruch, verteilt wie folgt: 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, 3 × Q, 2 × R8 × [, 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 ×o33 × 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");}

Erläuterung

#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");
}

Es funktioniert, indem nach einer Zeile, Spalte oder Diagonale gesucht wird, die drei der weißen Teile enthält. azeigt auf die Zielposition (enthält noch kein weißes Stück). Dann wird das fehlende Teil ( o) identifiziert - es ist das, das wir nicht aus der Zeichenfolge entfernt haben, hals wir es sahen.

Wenn sich das Stück nicht auf dem Brett befindet, muss es in der Hand sein und kann nur in ein Feld gespielt werden. Andernfalls (wenn wir es auf dem Brett gefunden haben) muss es sich in einer Position befinden, in der es sich in das Zielfeld bewegen kann. Da Bewegungen reversibel sind, tauschen wir sie bei Bedarf aus, damit a < p.

Wir testen zuerst Ritterbewegungen - es gibt vier legale Abwärtsbewegungen, und wir vermeiden es, uns um den linken / rechten Rand des Bretts zu wickeln, indem wir die Anzahl der Zeilenumbrüche überprüfen, die wir passieren.

Danach testen wir Turmbewegungen und dann Bischofsbewegungen mit einem ähnlichen Algorithmus (und eine Königin kann jede dieser Bewegungen verwenden).

Testprogramm

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");
}

Zählprogramm (in 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
quelle
1
Vorschlagen 6+3für 9Und 16+3für19
Deckenkatze