キヌイッシュ三目並べ


19

人間のプレイヤーに対して3 * 3ボードで三目並べの完璧なゲームをプレイする選択した言語でプログラムを作成します。ただし、すべての動きは、前の反復から生成された異なるプログラムなければなりません

人間の入力をどのように、どのような形で評価するかはあなた次第ですが、標準入力から読み取る必要があります。同様に、どのプレイヤーが開始するかを決定する方法を自由に選択できます(たとえば、最初に尋ねる、またはコンピューターが開始することを知らせる無効な動きを人間に入力させる、または他のアイデアを許可する)。

動きを検証する必要はありません。あなたはかなりプレイしている人間の対戦相手であると想定できます。

基本的に、ボードの状態に対応するプログラムがあります。状態は認識可能な方法で出力されますが、少なくとも次の詳細レベルが予想されます。

X..
00X
x..

人間のプレーヤーが彼の動きを入力した後、プログラムは同じ言語のソースファイル(標準出力またはファイル)としてそれ自体の次の反復を生成し、終了する必要があります。そのソースファイル以外の場所に情報を保存することはできません。(プログラムが生成されたプログラムをビルドして実行する必要はありません。ユーザーが実行できますが、禁止されていません)。生成されたプログラムがビルドおよび実行されると、同様に動作し、状態を表示し、ユーザー入力を待機します。

ゲームの終わりに、明確に特定できる方法で結果を印刷する必要があります(勝ったか同点か)。

完璧なプレーとは、プログラムが負けてはならないことを意味し、勝つことを強制する可能性がある場合、勝つべきです。

最短のコードが勝ち、最初の有効なエントリから少なくとも10日後に勝者が選択されます。

プログラムが次の反復の構築と起動を処理できる場合、スコアが10%減少します。(おそらく、それだけの価値はないことを知っています)もちろん、プログラム自体は、次の反復がユーザーからの動きを受け入れるまでに終了しなければなりません。

珍しい珍しいトリックを使用する場合は、コードに簡単な説明を投稿してください。


2
いいチャレンジですが、オプトアウトするつもりです。
ジョンドヴォルザーク

「すべての動きは異なるプログラムでなければなりません」。「各ゲームは、元のプログラムの新しい別個のインスタンスによって開始および管理される必要があります」という意味ですか?
DavidC

1
@DavidCarraher:いいえ。すべてのゲームだけでなく、すべての動き。ボードの例の下の説明を確認してください。コンピューターが移動する必要がある場合(ボードの状態が変化する場合)、プログラムはソースファイルを生成する必要があります。ソースファイルは、ビルドおよび実行されると、次の状態になります。その後、元のプログラムは終了します。新しく生成されたプログラムは、移動すると同様に動作します。ソースファイルが作成され、ビルドおよび実行されると、次の状態になります。生成されたソースファイルを除き、情報の保存は許可されないため、反復の間に違いがあるクインのようなものです。
-vsz

回答:


13

Perl、933文字

$m=<<'';$_='         ';
sub h{/^(?:...)*(\d)\1\1/|/^.?.?(\d)..\1..\1/|/(\d)...\1...\1/|/^..(\d).\1.\1/&&$1}
sub r{substr($_,$p-1,1)=pop}sub p{my$w=pop;my@b=(0,h==$w||h&&-1);if(!$b[1]&&/ /){$b[1]=-9;
while(/ /g){local($_,$p)=($_,pos);r$w;$r=-(p($w^1))[1];@b=($p,$r)if$r>$b[1]}}@b}
if(($w=h||!/ /)||!@ARGV){$w--&&print+(nobody,X,O)[$w]," wins\n";s/(...)/$1\n/g;
tr/ 23/.XO/;print}else{$w=3;$w^=1for/\d/g;($p=pop)?r($w^1)&&!h&&(($p)=p$w)&&r$w:s/ /2/;
print"\$m=<<'';\$_='$_';\n$m\n$m"}

sub h{/^(?:...)*(\d)\1\1/|/^.?.?(\d)..\1..\1/|/(\d)...\1...\1/|/^..(\d).\1.\1/&&$1}
sub r{substr($_,$p-1,1)=pop}sub p{my$w=pop;my@b=(0,h==$w||h&&-1);if(!$b[1]&&/ /){$b[1]=-9;
while(/ /g){local($_,$p)=($_,pos);r$w;$r=-(p($w^1))[1];@b=($p,$r)if$r>$b[1]}}@b}
if(($w=h||!/ /)||!@ARGV){$w--&&print+(nobody,X,O)[$w]," wins\n";s/(...)/$1\n/g;
tr/ 23/.XO/;print}else{$w=3;$w^=1for/\d/g;($p=pop)?r($w^1)&&!h&&(($p)=p$w)&&r$w:s/ /2/;
print"\$m=<<'';\$_='$_';\n$m\n$m"}

スクリプトの真ん中の空白行は実際にそこにある必要があることに注意してください。(長い行の終わりでの改行は、読みやすさ以外は必要ありません。また、文字数には含まれません。)

使用法:プログラムを引数なしで実行すると、現在のゲームの状態が表示されます。最初はボードが空なので、出力は次のようになります。

...
...
...

1から9の間の引数を使用してプログラムを実行し、その正方形を移動として要求します。プログラムは独自の動きを行い、新しい状態で置換スクリプトを出力します。したがって、たとえば:

$ perl ./qttt 5 > ./qttt-2
$ perl ./qttt-2
O..
.X.
...

最初のターンでのみ、0コンピュータが最初の動きを取るべきであることを示すために動きを与えることができます。最初のプレイヤーは常にになることに注意してくださいX

ゲームが終了すると、ディスプレイ出力にはその旨のメモが含まれます。

$ perl ./qttt-4 6 > ./qttt-5
$ perl ./qttt-5
O wins
OXX
OOX
X.O

このプログラムは、ゲームツリーの標準的なミニマックス検索を実行することで機能します。(三目並べは、実行のたびに完全なゲームツリーを生成できるほど小さいゲームです。)これの例外は、コンピューターが最初に移動するときです。この場合、左上隅への最初の移動は困難です。コード化。

このプログラムは適切なクインのように機能することに注意してください。スクリプトは、出力を生成するために独自のソースファイルにアクセスしません。


1
それは美しいです!長い間、巨大なヒアドキュメントをじっと見つめていたのに気付いていなかったので、ダブルテイクをしました。
ジェシースミス
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.