Şampiyon ol


11

Tic-Tac-Latince!

Bu gerçek bir hikaye, bu yüzden isimler değiştirildi.

Latin öğretmenim Bay Latin, kendi tescilli (şaka yok) tic tac toe varyantını yarattı. Buna tic-tac-latin diyelim. Oyun basit, aslında dört dört ızgara üzerinde oynanan tic tac toe.

Resmi kural beyanı

Çizgi, satır, sütun veya diyagonaldir. 'X' ve 'O' olmak üzere iki sembol vardır, ancak bir veya her ikisi farklı bir sembolün yerine kullanılabilir.
Sembolünüzden üç ve diğer karakterlerden birine sahip olduğunuzda bir puan alırsınız.

Bu düzenlemeler şunları yapar:

---Ö
-Ö--
xxxo
XOOX

O -XX
- O -
- X -
--- O

Bunlar puan vermez:

----
XXXX
----
OOOO

----
xxx-
----
OOO-

Oyun, bir oyuncu diğerinden daha fazla puana sahip olduğunda kazanılır. Oyun sadece tahta dolduğunda berabere biter.

Meydan okuma

Bu oyunu çözün. İşiniz, hangisi en iyi sonuç olursa olsun, kazanmayı veya kravatını garanti etmenin bir yolunu sağlamaktır.

Çözümünüz birinci veya ikinci başlatmayı seçebilir (ve bu nedenle sembolünü seçebilir). Kullanıcı girişlerinin hareket ettiği ve ilgili ekranın değiştiği interaktif bir oyunun uygulanması zorunlu değildir. Ayrıca, oyun durumu olarak girdi alan ve yeni bir kart veya hareketlerinin bir açıklamasını veren bir işlev veya program da olabilir . Her iki seçenek de yapılan hamle başına yaklaşık on saniye içinde çalışmalıdır.


Oynatıcınızı herhangi bir hamle sırasına göre oynamak en iyi sonucu vermelidir. Bu, giriş konumunun oynatıcınızla oynatılabilecek konum olduğunu varsayabileceğiniz anlamına gelir. Başvurular deterministik olmalı ve mutlaka bir iyimserlik kanıtı sunmaları gerekmemektedir, ancak eğer kırılırlarsa (dövülerek) başvurunuz geçersiz kabul edilir (bırakabilirsiniz, ancak başlığa ekleyebilirsiniz (çatlar)).
Bu önemsiz bir görevdir, bu nedenle herhangi bir geçerli başvuru etkileyici ve kabul edilen bir kene layıktır, ancak kod golfünü birincil kazanan kriter haline getireceğim.

Kazanan, bir kazanan seçilene kadar bu listenin aşağısına giderek seçilir.

  • Her zaman kazanan en kısa çözülmüş uygulama
  • En kısa uygulama

1
"Önce oyunun kalitesine bakılıyor" Bunun öznel olduğunu düşünmüyor musunuz?
user48538

Oynamak için bir arayüz sağlama görevi, mükemmel bir oyuncu yazmanın çevresel bir parçası gibi görünüyor. Sadece mevcut oyun durumunu girdi olarak geçirmeyi ve kodun kazanan bir hamle çıkmasını, hatta mükemmel oyun altında bir değerlendirmeyi (kazan, çiz, kaybet) gerektirmesini öneririm.
xnor

1
Bir çözüm, verimsiz bir kaba kuvvet araması yaparak golf olabilir. Kod çok yavaş çalışıyorsa iyi misiniz?
xnor

1
" Eğer skor yaparsanız ve bu süreçte rakibiniz için skor almazsanız oyunu kazanırsınız. " Bu, rakibimin yaptığı gibi değil sadece bir parça yerleştirdiğimde kazanabileceğim anlamına mı geliyor? Bir hamle her iki oyuncu için de kazanma çizgileri yaratırsa ne olur: oyun çizilir veya oynanır?
Peter Taylor

1
@RohanJhunjhunwala Oyun durumunun izin verilen girişini açıklığa kavuşturmalısınız, aksi takdirde insanlar şu anda tanımlanmamış giriş biçiminden yararlanabilir ve çözümlerine çok yardımcı olan bir biçim seçebilir.
Sadece ASCII

Yanıtlar:


6

Perl, 147 bayt (rakip olmayan, hareket başına 10 saniyeden fazla sürer)

İçin +4 içerir -0p

Program çalıyor X. Mükemmel bir oyun oynayacak.

Kartı STDIN'e girin, örneğin:

tictaclatin.pl
-X-O
-X--
X-X-
O--O
^D

Çıkış, tümüyle Xdeğiştirilen tahta ile aynı olacaktır Ove tersi de geçerlidir. Boş noktalar, X'in orada oynayacağı sonucu gösteren bir sayı ile doldurulacaktır, 1yani sonuç bir galibiyet, 2beraberlik ve 3kayıp olacaktır. Bitmiş bir oyun, renkleri tersine çevirerek aynı pozisyonu döndürür.

Bu örnekte çıktı:

1O1X
1O33
O3O3
X33X

Bu yüzden pozisyon, Xüst ve sol boyunca 3 noktada oynarsa kazanır . Diğer tüm hamleler kaybeder.

Oyunun bir hamleden sonra nasıl devam ettiğini bilmek istiyorsanız, bu kafa karıştırıcı çıktı aslında kullanışlıdır. Program her zaman oynadığı Xiçin takas Xve Ohamle görmek gerekir O. Burada, örneğin Xsol üstte oynayarak kazandığı oldukça açıktır , ancak üstte Xüçüncü pozisyonda oynarsa ne olur ? Çıktıyı kopyalayın, Oseçtiğiniz hareketin yerine koyun ve diğer tüm sayıları -tekrar değiştirin , böylece burada:

-OOX
-O--
O-O-
X--X

Sonuçlanan:

3XXO
3X33
X3X3
O33O

Açıkçası her hamle Okaybetmeli, öyleyse sol üstte oynarsa nasıl kaybeder? Bunu tekrar Osol üst köşeye koyarak ve rakamları aşağıdaki gibi değiştirerek yapın -:

OXXO
-X--
X-X-
O--O

Giving:

XOOX
1O33
O3O3
X33X

X'in kazanması için tek bir yolu var:

XOOX
OO--
O-O-
X--X

verilmesi

OXXO
XX33
X3X3
O33O

Durum Oümitsiz kalıyor. Her hamlenin Xhemen kazanmasına izin verdiğini görmek artık çok kolay . En azından arka arkaya 3 O almaya çalışalım:

OXXO
XX--
X-X-
O-OO

Giving:

XOOX
OO13
O3O3
X3XX

Xtek kazanan hamleyi oynar ( XXXObunun üçüncü sütun boyunca yapıldığına dikkat edin :

XOOX
OOO-
O-O-
X-XX

İşte çıktı:

OXXO
XXX-
X-X-
O-OO

çünkü oyun çoktan bitmişti. Kazanımı üçüncü sütunda görebilirsiniz.

Gerçek program tictaclatin.pl:

#!/usr/bin/perl -0p
y/XO/OX/,$@=-$@while$|-=/(@{[map{(O.".{$_}O"x3)=~s%O%Z|$`X$'|Z%gr}0,3..5]})(?{$@++})^|$/sx;$@<=>0||s%-%$_="$`O$'";$$_||=2+do$0%eg&&(/1/||/2/-1)

Boş panoya uygulandığında bu, bilgisayarımda 30Gb ve 41 dakika süren 9506699 pozisyonlarını değerlendirir. Sonuç:

2222
2222
2222
2222

Böylece her başlangıç ​​hareketi çekilir. Yani oyun berabere bitiyor.

Aşırı bellek kullanımı çoğunlukla yinelenen kullanımdan kaynaklanır do$0. Bu 154 baytlık sürümü düz bir işlev kullanarak kullanmak için 3Gb ve 11 dakika gerekir:

#!/usr/bin/perl -0p
sub f{y/XO/OX/,$@=-$@while$|-=/(@{[map{(O.".{$_}O"x3)=~s%O%Z|$`X$'|Z%gr}0,3..5]})(?{$@++})^|$/sx;$@<=>0||s%-%$_="$`O$'";$$_||=2+&f%eeg&&(/1/||/2/-1)}f

ki bu daha katlanılabilir (ama yine de çok fazla, bir şey hala bellek sızdırıyor olmalı).

Bir dizi hızlandırmayı birleştirmek, bu 160 baytlık sürüme yol açar (boş tahta için 5028168 konum, 4 dakika ve 800M):

#!/usr/bin/perl -0p
sub f{y/XO/OX/,$@=-$@while$|-=/(@{[map{(O.".{$_}O"x3)=~s%O%Z|$`X$'|Z%gr}0,3..5]})(?{$@++})^|$/osx;$@<=>0||s%-%$_="$`O$'";$a{$_}//=&f+1or return 1%eeg&&/1/-1}f

Sonuncusu 0bir galibiyet (karıştırmayın O), 1beraberlik ve 2kayıp için kullanır. Bunun çıktısı da daha kafa karıştırıcı. Renk değişimi olmayan bir galibiyet durumunda X için kazanan hamleyi doldurur, ancak giriş oyunu zaten kazanılmışsa, renk değişimi hala devam eder ve herhangi bir hamleyi doldurmaz.

Tabii ki tüm versiyonlar hızlanır ve kart dolarken daha az bellek kullanır. Daha hızlı sürümler, 2 veya 3 hamle yapılır yapılmaz 10 saniyenin altında bir hamle üretmelidir.

Prensip olarak, bu 146 baytlık sürüm de çalışmalıdır:

#!/usr/bin/perl -0p
y/XO/OX/,$@=-$@while/(@{[map{(O.".{$_}O"x3)=~s%O%Z|$`X$'|Z%gr}0,3..5]})(?{$@++})^/sx,--$|;$@<=>0||s%-%$_="$`O$'";$$_||=2+do$0%eg&&(/1/||/2/-1)

ama benim makinede bir perl hata tetikler ve çekirdek dökümü.

İlke olarak yapılan 6 baytlık konum önbelleği $$_||=kaldırılırsa, ancak yalnızca neredeyse doldurulmuş kartlar için çalışacak kadar çok zaman ve bellek kullanırsa, tüm sürümler prensip olarak çalışmaya devam edecektir . Ama teoride en azından 140 baytlık bir çözümüm var.

Eğer koyarsanız $\=hemen önce: (3 bayt maliyet) $@<=>0: Daha sonra her çıkış kartı bütün kurulu durumuna göre takip edilecektir 1için Xgalibiyet, 0beraberlik için ve -1kayıp.

Yukarıda belirtilen en hızlı sürüme dayanan etkileşimli bir sürücü. Sürücünün oyun bittiğinde mantığı yoktur, bu yüzden kendinizi durdurmanız gerekir. Golfçü kodu olsa biliyor. Önerilen hamle, hiçbir -şeyle değiştirilmeden geri dönerse oyun biter.

#!/usr/bin/perl
sub f{
    if ($p++ % 100000 == 0) {
        local $| = 1;
        print ".";
    }
y/XO/OX/,$@=-$@while$|-=/(@{[map{(O.".{$_}O"x3)=~s%O%Z|$`X$'|Z%gr}0,3..5]})(?{$@++})^|$/osx;$@<=>0||s%-%$_="$`O$'";$a{$_}//=&f+1or return 1%eeg&&/1/-1}

# Driver
my $tomove = "X";
my $move = 0;
@board = ("----\n") x 4;
while (1) {
    print "Current board after move $move ($tomove to move):\n  ABCD\n";
    for my $i (1..4) {
        print "$i $board[$i-1]";
    }
    print "Enter a move like B4, PASS (not a valid move, just for setup) or just press enter to let the program make suggestions\n";
    my $input = <> // exit;
    if ($input eq "\n") {
        $_ = join "", @board;
        tr/OX/XO/ if $tomove eq "O";
        $p = 0;
        $@="";
        %a = ();
        my $start = time();
        my $result = f;
        if ($result == 1) {
            tr/OX/XO/ if $tomove eq "O";
            tr/012/-/;
        } else {
            tr/OX/XO/ if $tomove eq "X";
            tr/012/123/;
        }
        $result = -$result if $tomove eq "O";
        my $period = time() - $start;
        print "\nSuggested moves (evaluated $p positions in $period seconds, predicted result for X: $result):\n$_";
        redo;
    } elsif ($input =~ /^pass$/i) {
        # Do nothing
    } elsif (my ($x, $y) = $input =~ /^([A-D])([1-4])$/) {
        $x = ord($x) - ord("A");
        --$y;
        my $ch = substr($board[$y],$x, 1);
        if ($ch ne "-") {
            print "Position already has $ch. Try again\n";
            redo;
        }
        substr($board[$y],$x, 1) = $tomove;
    } else {
        print "Cannot parse move. Try again\n";
        redo;
    }
    $tomove =~ tr/OX/XO/;
    ++$move;
}

Güzel cevap. Bunu test etmem için kolay bir yol sağlayabilir misiniz? İdeal olarak interaktif bir versiyonunu görmek isterim ... (bu kendi merakım için bir çıkıntıdır).
Rohan Jhunjhunwala

@RohanJhunjhunwala Ok, basit bir interaktif sürücü ekledi
Ton Hospel

Değişken '$ move' prog.pl:2 adresinde bildirilmedi
Rohan Jhunjhunwala

İnsanların uygulayabileceği sezgisel bir çözüm var mı?
Rohan Jhunjhunwala

@RohanJhunjhunwala Sadece sürücü programını tekrar kontrol ettim. İyi çalışır, $move11. satırda ilan edilir. Bir insan sezgiselliği olup olmadığı hakkında hiçbir fikrim yok. Bu program sadece oyun ağacında minimas yapar, herhangi bir stratejik bilgiye sahip değildir .
Ton Hospel

2

JavaScript (ES6) 392 bayt

a=>b=>(c="0ed3b56879a4c21f",r=[],k=f=>r.push([a.filter(f),b.filter(f)]),[0,1,2,3].map(i=>k(n=>n%4==i)+k(n=>(n/4|0)==i)),k(n=>n%5==0),k(n=>n&&n-15&&!(n%3)),g=r.find(o=>(o[0].length==1&&o[1].length==2)||(o[0].length==2&&o[1].length==1)),g?parseInt(c[30-[...g[0],...g[1]].map(i=>parseInt(c[i],16)).reduce((p,c)=>p+c)],16):[...a,...b].indexOf(15-a[0])+1?15-a.find(i=>b.indexOf(15-i)==-1):15-a[0])

kullanım

"Bot" ikinci oynar.

Bu şekilde numaralandırılmış bir 4x4 ızgara çizin:

+----+----+----+----+
|  0 |  1 |  2 |  3 |
+----+----+----+----+
|  4 |  5 |  6 |  7 |
+----+----+----+----+
|  8 |  9 | 10 | 11 |
+----+----+----+----+
| 12 | 13 | 14 | 15 |
+----+----+----+----+

Bunu tarayıcı konsolunda çalıştıralım: f=Kodun önüne koy

Yani, eğer başlamak 1istersem, koşardım f([1])([])ve bana verecek 14.

İyi hamle ... Daha 2sonra oynarsam ne olur ? f([2,1])([14]). Geri dönecek 13.

Lemme teslim olmayı dene. Oyna 3. f([3,2,1])([14,13]). Ah 0! Beni yakaladın!

Oyna 0? f([0,2,1])([14,13]). 15Tamam, oynamaya devam edelim ...

Not

  1. Etkileşimli oyna. İle başlayın f([your-step])([]).

  2. Bir sonraki adımınızı ekleyin. (Yukarıdaki demoya bakın)

  3. "Bot" adımlarını girdi Yardım. Rastgele bir ayar verirseniz size iyi sonuçlar vermez. (Gibi f([1,2,4])([14,12])verecek 14- Hey bot 13ikinci hamlesinde oynamak istedi !

Kısa özet

Teslim olmadığınız sürece, bot ayna hareketi yapar.

Bana oyun kurallarını ve golf ipuçlarını yanlış okuduğumu söylediğin için teşekkürler @EHTproductions: P

Şimdi de şah mat olup olmadığını tespit edecek. Evetse, engelleyin!

Öncelikleri: Blok> Ayna> (yedek) bir aynayı yeniden üretmenin yollarını arar


Gerçekten "ayna hamle" taktik gibi :) Yanlış anlama olabilir, ama 3,2,1sizin 0için ve bot sizin için bir kazanç değil mi?
ETHproductions

Hata! Ben "bir tür 3 ve bir diğeri 1 desen yakalayan" olarak yanlış anladım. Lemme çözümü biraz değiştir .. Thanks @ETHproductions.
Güneşli Pun

Golf ipuçları bir çift: golf [0,1,2,3].map(i=>{k(n=>n%4==i);k(n=>Math.floor(n/4)==i);})olabilir [0,1,2,3].map(i=>k(n=>n%4==i)+k(n=>(n/4|0)==i)).
ETHproductions

Bunun kazanılabilir olduğunu sanmıyorum
Rohan Jhunjhunwala

0 - 14 - 12-13 çatlak
Rohan Jhunjhunwala
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.