三目並べとチェス、[明確な]文字が最も少ない


9

このTic-Tac-Checゲームの形式では、チェスの駒を動かして4つ並べることが目標です。ここでの目標は、ポジションに勝利の動きがあるかどうかを把握することです。

ルール

ルールはTic-Tac-Checのルールと似ていますが、同一ではありません。

ボードは4 x 4の正方形です。各プレーヤーには、ルーク、ビショップ、ナイト、クイーンがいます。あなたの番では、2つのオプションがあります。標準のチェスのルールに従って、ボード上にある自分の駒の1つを移動できます。または、ボード上にないピースを空いている場所に置くこともできます。

既存の駒を対戦相手の駒に移動すると、その駒はボードから取り除かれ、それらに戻されます。ただし、相手の駒の上に新しい駒を置くことはできません。

1人のプレーヤーがすべての駒を一列(または列、または対角線)に配置すると、すぐに勝利します。

チャレンジ

STDINからボードを受け入れ、次のターンに白のプレイヤーが勝てるかどうかを出力する完全なプログラムを記述します。

入力

それぞれ4文字の4つのストリング。各キャラクターはスペースまたはチェスの駒です。ルーク、ビショップ、ナイト、クイーンのみが使用され、それぞれ1つ(色ごと)が表示されます。どちらのプレーヤーもすでに4列に並んでいます。

入力として、チェスの駒または文字のUnicode記号を受け入れるかどうかを選択できます。文字を選択すると、RBKQは白い部分をrbkq表し、黒い部分を表します。

出力

白いプレイヤーが次のターンに勝てる場合、出力trueまたは1。それ以外の場合は、falseまたはを出力します0

プログラム

数字Xを選択してください。プログラムには最大X個の異なる文字を含めることができ、X回を超えて出現する文字はありません。

勝利

最も低いXが勝ちます。引き分けの場合、最も少ないキャラクターが勝ちます。

これらの例は、入力が文字を使用して断片を表すことを前提としています。

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.

だからoOoコードが勝つでしょうか?
kennytm 2014年

@KennyTM Xを超える文字が表示されない可能性があるため、oOoが使用できなくなります
オプティマイザ

@オプティマイザOKルールを読み間違えました。
kennytm 2014年

2
例をもっと読みやすい形式にすることができますか?ピースの位置とそれらがどの色に属しているかを確認することは非常に困難です。
Tally

空白は許可されますか?

回答:


3

C、53文字

これは"#%&()*+,-./01234569;<=>BKQR[\]acdefghilmnoprstu{|}、スペースと改行を使用し、次のように配布されます。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倍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");}

説明

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

3つの白い部分を含む行、列、または対角線を探すことで機能します。aターゲット位置を指します(まだ白い部分を含んでいません)。次に、欠落している部分(o)が識別されますh。これは、見たときに文字列から削除しなかったものです。

駒がボード上にない場合、それは手札になければならず、スペースでのみプレイできます。それ以外の場合(ボード上で見つけた場合)、ターゲットの正方形に移動できる位置にある必要があります。動きはリバーシブルなので、必要に応じて交換しa < pます。

最初に騎士の動きをテストします-4つの正当な下向きの動きがあり、通過する改行の数を確認することで、ボードの左端と右端の回り込みを回避します。

その後、同様のアルゴリズムを使用してルークムーブをテストし、次にビショップムーブをテストします(クイーンはこれらのムーブのいずれかを使用できます)。

テストプログラム

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

カウントプログラム(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 << "`, ";
}

1
提案6+3のために916+3のために19
ceilingcat
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.