Tic Tac Torus'un Optimal Oyunları


31

Bu meydan okuma Tic Tac Toe oyunuyla ilgili, ancak bir torus oynandı.

Nasıl oynanır

Gerekli oyun tahtasını oluşturmak için düzenli bir Tic Tac Toe oyun tahtasından başlayabilirsiniz. Önce sol ve sağ kenara birleştirerek bir silindire katlayın. Sonra üst ve alt kenara birleştirerek torus içine katlayın. İşte böyle bir oyun tahtasının birkaç hamle oynadığı basit bir görselleştirmesi (Sick Paint becerileri!).

Tic Tac Torus

Bir torus üzerindeki Tic Tac Toe'nun kuralları normal Tic Tac Toe ile aynıdır. Her oyuncu sırayla Xs ve Os. Bir satırda aynı sembol, ilkinde bir sütun, bir köşegen veya bir köşegen içinde bir tane kazanır.

Bir torusun görselleştirilmesi oldukça zor olduğu için, tahtayı tekrar bir kağıda yansıtıyoruz. Şimdi oyunu normal Tic Tac Toe olarak oynayabiliriz. Aradaki tek fark, kırılmış bir köşegen içerisinde aynı 3 sembolle kazanabilmenizdir. Örneğin, Oyuncu 1 (X), aşağıdaki kartı kazanır. Bunu torus üzerindeki görünümü biraz değiştirerek kolayca görebilirsiniz.

Oyuncu 1 (X), bir kırık diyagonaldaki 3 X yüzünden kazanır

Senin ilgi varsa, bir Torus üzerinde Tic Tac Toe oynayabilir Torus Games . Windows, Mac ve Android sürümü var.

Optimal Oyunlar

Bu meydan okumada en iyi oyunlara ilgi vardı. Optimal oyun, her iki oyuncunun da optimal bir strateji oynadığı bir oyundur. Normal bir Tic Tac Toe tahtasında optimal oyunlar her zaman berabere biter. Büyüleyici bir torus panosunda her zaman ilk oyuncu kazanır. Aslında, bir torus tahtası üzerindeki bir oyun asla berabere bitemez (oyuncular en iyi şekilde oynamazsa).

En uygun strateji gerçekten kolaydır:

  • Sembolünüzü koyarak kazanabilirsiniz, yapın.
  • Aksi halde rakibinizin bir satır / sütun / điagonal içinde iki sembolü varsa, onu engellemeyi deneyin. Aksi takdirde, ne istersen yap.
  • Aksi takdirde ne istersen onu yap.

Her optimum oyun tam olarak 7 hamleden oluşur ve bu hamleler aşağıdaki şekilde tanımlanabilir:

  1. Oyuncu 1, gemide herhangi bir yere X yerleştirir (9 seçenek)
  2. Oyuncu 2, tahtanın herhangi bir yerine O yerleştirir (8 seçenek)
  3. Oyuncu 1, gemide herhangi bir yere X yerleştirir (7 seçenek)
  4. 2. Oyuncu hareketi zorlanabilir (1 seçenek), eğer değilse, O'yu herhangi bir yere yerleştirir (6 seçenek)
  5. Oyuncu 1 hamlesine zorlandı (1 seçenek)
  6. Oyuncu 2 bir çatala yakalandı (Oyuncu 1 iki farklı şekilde kazanabilir), bu nedenle Oyuncu 2, Oyuncu 1'i bir şekilde engellemeli (2 seçenek)
  7. Oyuncu 1 son hamlesini yapar ve kazanır (1 seçenek)

Öngörülen panomuzda 9 * 8 * 1 * 6 * 1 * 2 * 1 + 9 * 8 * 6 * 1 * 1 * 2 * 1 = 1728 farklı optimum oyun bulunmaktadır. Burada tipik bir optimal oyun görebilirsiniz:

En uygun oyun örneği

Tahtanın her bir hücresini rakamlarla etiketlersek 0-8, bu oyunu rakamlarla tanımlayabiliriz 3518207. İlk önce bir X, hücre 3'teki (orta sıra, sol sütun), hücre 5'teki bir O'dan (orta sıra, sağ sütun), hücre 1'deki bir X'den (üst sıra, orta sütun), ...

Bu rakam gösterimini kullanarak otomatik olarak bir sipariş oluşturduk. Şimdi tüm 1728 optimal oyunlarını sıralayabiliriz ve listeyi alırız:

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

Meydan okuma

Bu liste işinizin bir parçası. k0 ile 1727 arasında bir sayı alacaksınız ve bu koyunu o sıralanan listenin rakamıyla göstermeniz gerekiyor.

kKarşılık gelen oyunu hesaplayan sayıyı (tamsayı) alan bir fonksiyon veya program yazın . Girişi STDIN, komut satırı argümanı, prompt veya function argümanı üzerinden okuyabilir ve sonucu (7 basamak) okunabilir bir formatta (örn. 0123845Veya [0, 1, 2, 3, 8, 4, 5]) yazdırabilir veya bir dize (insan tarafından okunabilir format) veya bir tamsayı (hepsini içeren) kullanarak döndürebilirsiniz. 10 tabanındaki rakamlar) veya herhangi bir dizi / liste biçiminde.

Meydan okuma türü kod golf. Bu nedenle en kısa kod kazanır.


Neden 2. oyuncunun ilk hamlesinin 1. oyuncunun ilk hareketi ile aynı satırda veya sütunda olması gerekiyor? Beynimde ilk oyuncunun ilk hareketinin aynı köşegenlerden biri olduğu kafamda birkaç oyun oynamıştım ve aynı optimal oyun modelini takip ediyorlar. Bana öyle geliyor ki, toroidal tahtanın yönlerinden biri de satır, sütun ve köşegenlerin oyun üzerinde simetrik etkileri olduğu.
Runer112

@ Runer112 En uygun stratejiyi çok basitleştirin. Şimdi tek kural rakibinizi engellemek, aksi halde ne istersen onu yapmak.
Jakube

7
Sadece bir yorum: aslında burada daha az benzersiz oyun var. Tercüme simetrisi, ilk hareketin konumunu alakasız kılar (görüşünüzü her zaman ortalayabilirsiniz), bu yüzden 9'a bölün ve tahtanın dönüşü yalnızca 2 farklı ikinci hareket (çapraz veya bitişik kare) yapar. çoğu 48 farklı oyun. Yansıma simetrisini hesaba katarsanız, daha da aşağı iner. Bu torus versiyonu normalden çok daha sıkıcı. Uzak golf.
orion

@orion Aslında torus'un sarılması, 'torus panosunda' ilk 'rect olarak' 0 'düşünmemizi ve genel olarak dokuz alanın hepsini ayırt etmemizi yasaklamaması. Dünya'nın tam karşısında Perşembe olduğu yerde tek bacak olabiliriz, yerine bir bacak Çarşamba (yerel saatte 24 saat fark!) - ve Dünya'nın yuvarlak olması ve olmamasına rağmen hepsi bir "başlangıç ​​noktası" ...
pawel.boczarski

@Rodney Nope, bu bir değil, yedi değil. Hesaplamayı dene.
Jakube

Yanıtlar:


6

JavaScript (ES6), 266 308 317 334 341

Bir dize döndüren bir işlev. Düzenleme M işlevi için aritmetik bir çözüm bulundu (sonunda!)

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]

Çok saf , birçok yönden kısaltılabilir . Basitçe mümkün olan tüm yasal değerleri sıralar ve n yerinde bulduklarını verir. M fonksiyonu iki hücre arasındaki pozisyonu döndürür, yani karşı oyuncuyu bloke etmek için zorunlu harekettir.

Daha okunabilir

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

Octave, 467 369 363 309 297 karakter

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,:);

İlgili tek değişiklik, şu anki oyuncunun kazanıp kazanamayacağını asla kontrol etmememizdir, sadece rakibin bir sonraki dönüşünü kazanma ihtimalini kontrol ederiz . Gibi sadece oynatıcıyı açmak 1 isimli 7 çevirmek kazanabilirsiniz , bu algoritma optimal değildir oyun üretecektir tek yerdir, ancak böyle bir durumu filtrelemek için çok kolaydır. Basitçe, eğer oyuncu 1 tarafından kazanılırsa oluşturulan her oyunu doğrularız - eğer değilse, 7. sıradaki hareket yanlıştı, bu yüzden bu oyunu optimal oyun masasına eklemiyoruz.

(Bu kuralın ürettiği oyunların yarısı yanlış . , 7. sırada, oyuncu 1 her zaman iki oyuncuyu engellemek için iki seçeneğe sahiptir, ancak yalnızca bir tanesi onu anında kazanmasını sağlar).

kullanın:

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

Ungolfed kodu gibi görünüyor:

 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
küçük ipucu: eski sürümleri aynı mantık kullanıyorlarsa, bunlar düzenleme geçmişinde depolandığından, hala kullanılabilir olmaları için
kesebilirsiniz
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.