チックタックトーラスの最適ゲーム


31

この課題はTic Tac Toeのゲームについてですが、トーラスでプレイします。

遊び方

必要なゲームボードを作成するには、通常のTic Tac Toeゲームボードから始めます。最初に、左端と右端を結合して、シリンダーに折ります。次に、上端と下端を結合してトーラスに折ります。これは、いくつかの動きをプレイしたこのようなゲームボードの簡単な視覚化です(シックペイントスキル!)。

チックタックトーラス

トーラス上のTic Tac Toeのルールは、通常のTic Tac Toeと同じです。各プレイヤーは、XとOを交互に配置します。行、列、または対角線に3つの同じシンボルがある最初のものが勝ちです。

トーラスの視覚化は非常に難しいため、ボードを紙に投影し直します。これで、通常のTic Tac Toeとしてゲームをプレイできます。唯一の違いは、壊れた対角線で3つの同じシンボルで勝つことができるということです。たとえば、プレーヤー1(X)は次のボードに勝ちます。これは、トーラスのビューを少し変更することで簡単に確認できます。

プレイヤー1(X)は、1つの壊れた対角線に3つのXがあるために勝ちます

興味があれば、トーラスゲームズのトーラスでTic Tac Toeをプレイできます。Windows、Mac、Androidのバージョンがあります。

最適なゲーム

この課題では、最適なゲームに興味がありました。最適なゲームとは、両方のプレイヤーが最適な戦略をプレイするゲームです。通常のTic Tac Toeボードでは、最適なゲームは常に引き分けになります。トーラスボードでは、常に最初のプレイヤーが勝ちます。実際、トーラスボードでのゲームは引き分けに終わることはありません(プレイヤーが最適でない場合も)。

最適な戦略は本当に簡単です。

  • シンボルを配置して勝つことができるなら、それをしてください。
  • それ以外の場合、対戦相手が1つの行/列/対角線に2つのシンボルを持っている場合は、ブロックしようとします。それ以外の場合は、必要なことを行います。
  • それ以外の場合は、必要なことを行います。

最適なゲームはすべて7つの動きで構成されており、これらの動きは次のように説明できます。

  1. プレーヤー1は、ボード上の任意の場所にXを配置します(9つの選択肢)
  2. プレイヤー2はボード上の任意の場所にOを配置します(8つの選択肢)
  3. プレーヤー1は、ボード上の任意の場所にXを配置します(7つの選択肢)
  4. プレイヤー2の移動は強制される可能性があり(1選択肢)、そうでない場合はOを任意の場所に配置します(6選択肢)
  5. プレイヤー1の移動が強制されます(1選択肢)
  6. プレイヤー2はフォークに引っ掛かる(プレイヤー1は2つの異なる方法で勝つことができる)ので、プレイヤー2はプレイヤー1を1つの方法でブロックする必要がある(2つの選択肢)
  7. プレイヤー1が最後の動きを決めて勝ちます(1選択肢)

予想されるボードには、9 * 8 * 1 * 6 * 1 * 2 * 1 + 9 * 8 * 6 * 1 * 1 * 2 * 1 = 1728種類の最適ゲームがあります。ここでは、1つの典型的な最適なゲームを見ることができます。

最適なゲームの例

ボードの各セルに数字0-8でラベルを付けると、このゲームを数字で説明できます 3518207。最初に、Xはセル3(中央行、左列)に配置され、セル5のO(中央行、右列)、セル1のX(上部行、中央列)、...

この数字表記を使用して、注文を自動的に生成しました。これで、1728の最適なゲームをすべて並べ替えて、リストを取得できます。

Game 0000: 0123845
Game 0001: 0123854
Game 0002: 0124735
Game 0003: 0124753
Game 0004: 0125634
   ...
Game 0674: 3518207
   ...
Game 1000: 5167423
Game 1001: 5167432
Game 1002: 5168304
   ...
Game 1726: 8765034
Game 1727: 8765043

チャレンジ

このリストはあなたの仕事の一部です。k0から1727までの1つの数字を受け取りk、ソートされたリストの数字表記でth番目のゲームを返す必要があります。

数字k(整数)を受け取る関数またはプログラムを作成して、対応するゲームを計算します。STDIN、コマンドライン引数、プロンプトまたは関数引数を介して入力を読み取り、結果(7桁)を読み取り可能な形式(たとえば0123845または[0, 1, 2, 3, 8, 4, 5])で印刷するか、文字列(人間が読み取り可能な形式)または整数(すべてを含む10を基数とする数字、または任意の配列/リスト形式。

チャレンジタイプはcode-golfです。したがって、最短のコードが優先されます。


プレーヤー2の最初の動きが、プレーヤー1の最初の動きと同じ行または列にある必要があるのはなぜですか?頭の中でいくつかのゲームをプレイしましたが、プレーヤー2の最初の動きは同じ対角線のいずれかであり、同じ最適なゲームパターンに従います。トロイダルボードの側面の1つは、行、列、および対角線がゲームに対称的な影響を与えることです。
Runer112

@ Runer112最適戦略を大幅に簡素化しました。唯一のルールは、可能であれば対戦相手をブロックすることです。
ジャクベ

7
ただのコメント:実際、ここで可能なユニークなゲームははるかに少ないです。並進対称性により、最初の動きの位置は無関係になります(常にビューを中央に配置できるため)。したがって、9で割ると...ボードの回転は2つの異なる2番目の動き(対角または隣接する正方形)になります...ほとんどの48の異なるゲーム。反射対称性を考慮すると、さらに対称性が低下します。このトーラスバージョンは、通常のものよりも退屈です。離れてゴルフ。
オリオン

@orion実際、トーラスがラップするという事実は、トーラスボード上の「最初の」長方形として「0」を考えることを禁じておらず、一般的に9つのフィールドすべてを区別します...しかし、「経線0」がグリニッジにあることに同意します地球の反対側では、木曜日の場所に1本の足、水曜日の場所に1本の足(現地時間で24時間の違い!)-地球は丸く、 「出発点」...
pawel.boczarski

@ロドニー・ノープ、それは7ではなく1です。計算してみてください。
ジャクベ

回答:


6

JavaScriptの(ES6)、266 308 317 334 341

文字列を返す関数。 編集関数Mの算術解を見つけました(ついに!)

F=(n,x=[],M=(a,b,t=-a-b)=>(a-b)%3?a<3&b<3?3+t:a>5&b>5?21+t:12+t:9+t+a%3*3)=>
[for(a of z='012345678')for(b of z)for(c of z)for(d of z) 
a-b&&c-a&&c-b&&(b-(y=M(a,c))?d==y:d-a&&d-b&&d-c)&&(
f=M(c,e=M(b,d)),g=M(a,e),g<f?[f,g]=[g,f]:0,r=a+b+c+d+e,x.push(r+f+g,r+g+f))]
&&x[n]

非常に素朴で、多くの方法で短縮できます。可能なすべての有効な値を列挙し、場所nで見つかったものを返します。M関数は、2つのセルの間の位置を返します。これは、反対のプレイヤーをブロックするための必須の動きです。

より読みやすい

F=(n,x=[],
  M=(a,b,t=-a-b)=>(a-b)%3? 
     a<3&b<3?
       3+t // first row
       :a>5&b>5?
          21+t // last row
          :12+t // middle row and diags
     :9+t+a%3*3 // columns
  )=>
  [for(a of z='012345678') // enumerate the first 4 moves
     for(b of z)
       for(c of z)
         for(d of z) 
           a-b&&c-a&&c-b // avoid duplicates
           &&(b-(y=M(a,c))?d==y:d-a&&d-b&&d-c) // and check if d must block a-c or it's free
           &&(
             e=M(b,d), // forced to block b-d
             f=M(c,e),g=M(a,e),g<f?[f,g]=[g,f]:0, // f and g could be in the wrong order
             r=a+b+c+d+e, // start building a return string
             x.push(r+f+g,r+g+f) // store all values in x
  )]&&x[n] // return value at requested position

3

オクターブ、467 369 363 309 297文字

297:

global t=0*(1:9)m=dec2bin([15;113;897;1170;1316;1608;2370;2216;2580])-48 a;
function g(s,p)global a t m;
if nnz(s)<8&&any((t==1)*m>2)a=[a;s];return;end;q=t==3-p;
(r=sort(~q.*(1:9)*m(:,find([3 1]*([q;t==p]*m)==6)')))||(r=find(~t));
for i=r t(i)=p;g([s i+47],3-p);t(i)=0;end;end;g('',1);f=@(n)a(n+1,:);

関連する唯一の変更点は、現在のプレイヤーが勝つことができるかどうかをチェックせず、次のターンに勝つための対戦相手の可能性のみをチェックすることです。だけで勝つことができるプレーヤー1の番ですが7ターン、これはアルゴリズムが最適ではないゲームを生成する唯一の場所ですが、それはこのような状況をフィルタリングすることは非常に簡単です。プレーヤー1が勝った場合に生成された各ゲームを確認します。勝てなかった場合、ターン7の動きは間違っていたため、このゲームを最適なゲームテーブルに追加しません。

(このルールによって生成されたゲームのちょうど半分が偽です。、7ターン目ではプレイヤー1はプレイヤー2をブロックする可能性が常に2つありますが、ただ1つだけが即座に勝ちます。

つかいます:

$ octave
octave:1>> source script.m
octave:2>> f(634)
ans = 3270148

改変されていないコードは次のようになります。

 global t=0*(1:9);
 global m=dec2bin([15;113;897;1170;1316;1608;2370;2216;2580])-48;
 global allgames;
 allgames=[];

 function r=canbewon(by)
  global t m
  q=[t==by;t==(3-by)]*m;
  g=(find([3 1]*q==6))';
  r=sort((~(t==by).*(1:9)) * m(:,g));
 end

 function games_starting_with(s)
 global allgames t;
 if 7==numel(s) && any((t==1)*m==3) # it's 7th move and first player won
  allgames=[allgames;s];
  return;
 end;
 poss=(find(~t));                  # for now all free slots are possible
 player=1+mod(numel(s),2);
 moves = canbewon(3-player);
 if numel(moves) poss=moves; end;  # ... no, we must block the other player
 for i=poss
  t(i)=player;
  games_starting_with([s char(i+47)]);
  t(i)=0;
 end
end

games_starting_with('');
f=@(n)(allgames(n+1,:));

1
小さなヒント:古いバージョンが同じロジックを使用している場合、これらは編集履歴に保存されているので、それらはまだ利用可能です
-masterX244
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.