Tic-Tac-Toe dan Catur, dengan karakter [berbeda] paling sedikit

9

Dalam bentuk permainan Tic-Tac-Chec ini, tujuannya adalah untuk memindahkan bidak catur menjadi empat berturut-turut. Tujuan Anda di sini adalah untuk mengetahui apakah suatu posisi memiliki langkah kemenangan.

Aturan

Aturannya mirip, tetapi tidak identik, dengan aturan Tic-Tac-Chec.

Papan adalah 4 dengan 4 kotak. Setiap pemain memiliki benteng, uskup, ksatria, dan ratu. Pada gilirannya, Anda memiliki dua opsi. Anda dapat memindahkan salah satu karya Anda di papan, mengikuti aturan catur standar. Atau Anda dapat menempatkan potongan yang belum ada di papan tulis, di tempat kosong mana pun.

Jika Anda memindahkan bagian yang ada ke bagian lawan, bagian mereka diambil dari papan dan dikembalikan ke mereka. Namun, Anda tidak boleh menempatkan keping baru di atas kepingan lawan.

Segera setelah satu pemain memiliki semua bagian mereka dalam satu baris (atau kolom, atau diagonal), mereka menang.

Tantangan

Tulis program lengkap yang menerima papan dari STDIN, dan berikan output apakah pemain putih bisa menang pada giliran berikutnya.

Memasukkan

Empat string masing-masing 4 karakter. Setiap karakter adalah spasi atau bidak catur. Hanya benteng, uskup, ksatria, dan ratu yang digunakan, dan paling banyak satu dari masing-masing (per warna) dapat muncul. Tidak ada pemain yang memiliki empat-dalam-baris.

Anda dapat memilih apakah akan menerima sebagai input simbol Unicode untuk bidak catur, atau huruf. Jika Anda memilih huruf, RBKQmewakili potongan putih, dan rbkqmewakili potongan hitam.

Keluaran

Jika pemain putih dapat menang pada giliran berikutnya, keluaran trueatau 1. Kalau tidak, output falseatau 0.

Program

Pilih angka X. Program Anda mungkin berisi paling banyak X karakter yang berbeda, dan tidak ada karakter yang muncul lebih dari X kali.

Kemenangan

X menang terendah. Dalam kasus seri, karakter paling sedikit menang.

Contohnya

Contoh-contoh ini menganggap input menggunakan huruf untuk mewakili potongan.

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
sumber
Jadi kode oOo akan menang?
kennytm
@KennyTM Tidak ada char yang muncul lebih dari X kali akan membuat oOo tidak berguna
Pengoptimal
@Optimizer OK maaf salah membaca aturan.
kennytm
2
Jika contoh-contoh itu dimasukkan ke dalam format yang lebih mudah dibaca, cukup sulit untuk melihat apa posisi dari potongan-potongan itu dan pada warna apa yang mereka miliki.
Tally
Apakah spasi putih diizinkan?

Jawaban:

3

C, 53 karakter berbeda

Ini menggunakan "#%&()*+,-./01234569;<=>BKQR[\]acdefghilmnoprstu{|}, ruang dan baris baru, didistribusikan sebagai berikut: 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");}

Penjelasan

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

Ini bekerja dengan mencari baris, kolom atau diagonal yang berisi tiga keping putih; amenunjuk ke posisi target (belum mengandung potongan putih). Kemudian bagian yang hilang ( o) diidentifikasi - itu adalah bagian yang tidak kami hapus dari tali hsaat kami melihatnya.

Jika potongan itu tidak ada di papan, itu harus ada di tangan, dan itu hanya bisa dimainkan di ruang kosong. Kalau tidak (jika kami menemukannya di papan tulis), itu harus dalam posisi di mana ia dapat bergerak ke kotak target. Karena gerakan dapat dibalik, kami bertukar jika perlu, jadi itu a < p.

Kami menguji gerakan ksatria terlebih dahulu - ada empat gerakan hukum ke bawah, dan kami menghindari membungkus tepi kiri / kanan papan dengan memverifikasi jumlah baris baru yang kami lewati.

Setelah itu, kami menguji gerakan rook, dan kemudian uskup bergerak, menggunakan algoritma yang sama (dan seorang ratu dapat menggunakan salah satu dari gerakan ini).

Program uji

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

Program penghitungan (dalam 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
sumber
1
Menyarankan 6+3untuk 9Dan 16+3untuk19
ceilingcat