4x4 Hexの完璧なゲームをプレイする


10

バックグラウンド

六角K×K六角形のタイルの菱形でプレイされる2プレーヤーの抽象戦略ゲームです。菱形の反対側の2つの側面は白く色付けされ、他の2つは黒く、2人のプレーヤー(黒と白)は交互に色のトークンを空いているタイルに配置します。最初に自分の色の反対側の間にパスを構築することに成功したプレーヤーが勝者です。ゲームは引き分けで終了することはできず、最初のプレイヤーはボードのサイズに関係なく勝利戦略を持っていることが知られています(詳細はWikipediaのページを参照してください)。

タスク

この課題では、ボードサイズをに固定し、ボードをK = 4次のグリッドとして表します。太い線は隣接するタイルを示します。

4x4グリッド。

あなたの仕事は、最初のプレーヤーのための勝利戦略を作成することです。あなたは黒か白のどちらかを選ぶことができます。これは、相手のプレーヤーがどのような合法的な動きをしても、あなたのプレーは勝利をもたらさなければならないことを意味します。入力はゲームの位置(ボード上のトークンの配置)であり、出力は以下に指定された形式での合法的な動きです。勝者戦略を自分で見つけたい場合は、このネタバレを読まないでください。

白が最初であると仮定して、1つの可能な勝利戦略の概要。 最初に5を選択します。その後、5から一番下の行へのパスがある場合、または黒が任意の時点で0または1を選択している場合、空いている0または1のいずれかを選択して応答します。黒が9または13を選択する場合、10を選択してから、14または15のいずれかが空くようにします。黒が9、13、または14を選択しない場合、9を選択し、次に13または14のいずれかが空いていることを選択します。黒が14を選択した場合は、15を選択して応答します。次に、空の場合は10を選択します。黒が10を選択した場合は11で応答します。黒が6を選択した場合は7で応答し、次に空いている2または3のいずれかを応答します。黒で6が選択されていない場合は選択して、5から最下行までのパスを作成します。

入出力

入力は16文字の文字列でWBE、白、黒、空を表します。上に列挙したように、それらはボードのタイルを表しています。以下から入力方法(出力方法も決定します)を選択できます。

  1. STDINからの入力、STDOUTへの出力。
  2. 1つのコマンドライン引数として入力し、STDOUTに出力します。
  3. 16文字の1文字のコマンドライン引数として入力し、STDOUTに出力します。
  4. 名前付き関数の引数として入力し、戻り値として出力します。

次のトークンが移動する番なので、出力は次のトークンを配置するタイルを表します。次の出力形式から選択できます。

  1. ゼロベースのインデックス(上の画像で使用されているもの)。
  2. 1から始まるインデックス。
  3. プレーヤー用に選択した、またはユーザーが選択した文字列にE置き換えられた入力文字列。WB

ルール

あなたの戦略は決定論的でなければなりません。戦略を使用して空のボードから到達できないゲームの位置、またはいずれかのプレイヤーがすでに勝っている位置を正しく処理する必要はなく、クラッシュする可能性があります。逆に、あなたの戦略を使用して到達可能なボードでは、合法的な動きを返さなければなりません。

これはコードゴルフなので、最小バイト数が優先されます。標準の抜け穴は許可されていません。

テスト中

手作業で行うのは非常に面倒なので、エントリを検証するためのPython 3コントローラを作成しました。あなたはここでそれを見つけることができます。最初の3つの入力形式とPython 3関数(他の言語の関数はプログラムにラップする必要があります)、3つの出力形式すべて、および両方のプレーヤーをサポートしています。戦略が勝っていない場合は、見つかった敗北ゲームを出力するので、プログラムを微調整できます。


この課題は、電卓プログラムを書いているときに三目並べAIを圧縮しようとしていることを思い出させます。 ticalc.org/archives/files/fileinfo/354/35408.html
Sparr

2
Incorrect response 'WWWWWWWWBBBBBBBB' to message 'WWWWWWWWBBBBBBBB'.私はずっと前に勝っていたはずですか、それとも間違っていますか?
SebastianHöffner、2015年

@SebastianHöffnerコントローラのバグのようです。時間があるときに修正しようと思います。
Zgarb 2015年

@SebastianHöffnerバグが修正されました。
Zgarb

回答:


6

マーベラス、973b

これは、問題のヒント戦略の単純な実装です。これは、ボードが16のコマンドライン/メインボードパラメータとして提供されることを想定しておりhex.mbl B W E E E W E E E B E E E E E E、白の次の移動のゼロインデックス位置を出力します。

00 }1 }0
&G B? W!
&0 &G &G
!!
00 }0 }1
&H B? W!
&1 &H &H
!!
.. }D .. }9 }9 }D }E }A }D }9 }A .. }E }F }5
}9 B! }E E? W? E? .. E? B? B? W? .. E? .. E?
B! ?0 B! &M &N &O E? &I \\ .. &J .. &K E? &5
?0 ++ ?0 &9 .. &D &P &A &I /\ &J .. &E &L !!
++ .. ++ !! .. !! &E !! \/ &L /\ &K !! &F
\\ .. // .. .. .. !! .. .. \/ .. \/ .. !!
.. =3 \/
&M /\ &N
\/ &O /\ &P
}0 }1 }6 .. }6 .. }7 &7 }2 }3 }A }A }B }E }F
..
..
..
..
..
..
..
..
..
.. .. .. .. .. .. .. .. .. .. .. .. .. B? W!
.. .. .. .. .. .. .. .. .. .. .. .. .. &Q &Q
.. .. .. .. B? .. E? W? E? .. E? B? E? &F \/
.. .. .. &S /\ &T &S &T &U E? &A &R &R !!
.. .. .. &7 .. .. \/ .. &2 &V !! &B \/
.. .. .. !! .. .. &U /\ &V &3 .. !!
.. .. .. .. .. .. .. .. .. !!
.. .. ..
.. .. E?
E? .. &6
&X E? !!
!! &Y
.. !!
}4 }8 }C
\/ \/ \/
30 30 31 31 32 33 35 36 37 39 31 30 31 31 31 33 31 34 31 35
&0 &X &1 &Y &2 &3 &5 &6 &7 &9 &A &A &B &B &D &D &E &E &F &F
:W?
}0
^4
=1
{0
:B?
}0
^0
=0
{0
:E?
}0
^1
=0
{0
:W!
}0
^4
=0
{0
:B!
}0
^0
>0
{0

より良い分岐とコードの再利用の排除で、おそらくこれから約200文字をゴルフできると思います。


16個のコマンドライン引数のオプションを追加し、検証スクリプトを更新したので、このソリューションをテストできます。
Zgarb 2015年

マーベラス+1(PPCGはこれらのキャラクターを追加するとコメントが改善されたと考えています)
Rohan Jhunjhunwala

1

Python 3、100b

b=input()
i=b.find('B')
if b[i]in'BW'and'E'in b:i-=1+(b[i-1]is'W')*4
print((b[:i]+'B'+b[i+1:])[:16])
  • プレイヤー:BLACK
  • メソッド:STDIN / STDOUT、MODIFIED_BOARD

戦略は、まずBボード上でa を検索することです。何もない場合-1、これはを返します。これは、Pythonではと同じlast indexです。したがって、空のボードでは、最初のインデックスはになりindex=-1、ここから動き始めます。

左のフィールド(index-1)が空いている場合、次の移動はそこに行きます。撮ったら左に上がります。上に移動する必要はありません。移動すると、テンポが失われ、ゲームに負けます。

フルボード(Eどこにもない)では、私は動きません。

print最初は少し奇妙なようだ:私は(私はスライスを経由して行う)新しいボードを構築するために持っていますが、私は16個の文字をカットする必要があります。これは私が負のインデックスで作業するので遺物でありb[i+1:]、ホールボードと予想される残りを返し、残りを切り捨てることが重要になります。もう1つの方法は、たとえばを取得するなど(b.find('B')+16)%16、正のインデックスを使用することですが、(+16)%16は1バイト大きくなり()[:16]ます。

非ゴルフ:

board = input()
index = board.find('B')
if board[index] in 'BW' and 'E' in board:
    index -= 1 + (board[index-1] is 'W') * 4
print((board[:index] + 'B' + board[index+1:])[:16])

テスト

16進コントローラーテストスイートを実行しているときに、奇妙な動作が発生しました。

OUT: EEEEEEEEEEEEEEEB
OUT: WEEEEEEEEEEEEEBB
OUT: WWEEEEEEEEEEEBBB
OUT: WWWEEEEEEEEEBBBB
OUT: WWWWEEEEEEEBBBBB
OUT: WWWWWEEEEEBBBBBB
OUT: WWWWWWEEEBBBBBBB
OUT: WWWWWWWEBBBBBBBB
OUT: WWWWWWWWBBBBBBBB

Incorrect response 'WWWWWWWWBBBBBBBB' to message 'WWWWWWWWBBBBBBBB'.

私は4ターン後に勝つべきだったと思うか、同じボードでフルボードに答えるのが正しい応答であると思います。何が問題なのかわからないので、深く掘り下げませんでした。「特別な」ケースがすべてカバーされているかどうかを確認したいだけです。しかし、誰かがスペース4かそこらで始まる状況を隠す必要がないので、それはとにかく問題ではありません。

85b

ただし、ボード全体をチェックしないようにする場合(つまり、'E' in b除外する場合は、85バイトのみを使用するようにコードをさらに簡略化できます)。

b=input();i=b.find('B')
if i!=-1:i-=1+(b[i-1]is'W')*4
print((b[:i]+'B'+b[i+1:])[:16])

ただし、これは次のようになります。

Incorrect response 'WWWBWWWWBBBBBBBB' to message 'WWWWWWWWBBBBBBBB'.

これはカウントされる場合とカウントされない場合があり、有効な動作ではないことがわかったので、私はより長く正解を選ぶことにしました。

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