2048 Bot Mücadelesi


19

Biz 2048 klonlama , analiz 2048'i, ama neden bunu henüz oynamadım? 2048 otomatik olarak oynamak için 555 bayt javascript snippet'i yazın, bir saat sonra en iyi puan sayılır (aşağıdaki puanlamaya bakın).

Kurmak:

Goto 2048 ve çalıştırma:

 a = new GameManager(4, KeyboardInputManager, HTMLActuator, LocalStorageManager);

a oyunu kontrol etmektir.

Kurallar:

Kurulumdan sonra oyunu kontrol etmek için konsoldan 555 bayt javascript çalıştırabilirsiniz. Oyunun kaynak kodu burada bulunabilir (yorumlar dahil).

  • Yalnızca kullanıcı için mümkün olan şeyleri yapabilir:
    • a.move(n) 4 yönden herhangi birinde önemli bir işlemi tetiklemek için.
      • 0: yukarı, 1: sağ, 2: aşağı, 3: sol
    • a.restart() oyunu yeniden başlatmak için. Oyunun ortasında yeniden başlatmaya izin verilir.
  • Oyunun durumu hakkında bilgi bulunabilir a.grid.cells. Bu bilgi salt okunur
  • Fonksiyonlardan herhangi birine bağlanma, davranışlarını herhangi bir şekilde değiştirmeye izin verilmez (veya başka herhangi bir veri değiştirilmez)
  • Harekete yalnızca 250ms'de bir izin verilir

Misal

Başlamak için çok basit bir örnek. Yorum yapmadan 181 bayt girer .

//bind into new tile function and change m(ove) variable when a tile was moved
b = a.addRandomTile.bind(a);
m = !1;
a.addRandomTile = function() { m = !0; b(); };
//number of move fails
mfs = 0;
setInterval(function() {
  //set global moved tracking variable to false
  m = !1;
  a.move(Math.floor(4 * Math.random()));
  m || mfs++;
  //restart after 10 moves failed
  10 < mfs && (mfs = 0, a.restart());
}, 250);

Puanlama ve sonuçlar

Parçacıkları bir saat boyunca çalıştıracağım ve en iyi puan sayılacaktır. Aslında, randombotyukarıda bu şekilde kazanma şansı vardır , ancak 1 saatin onu yenmek için yeterli olması gerekir:

  • Kral Bottomstacker VII : 9912
  • Kraliçe Bottomstacker V : 9216
  • Prens Bottomstacker II : 7520
  • Lord Bottom and Right : 6308
  • Köylü Randombot : 1413
  • Bottomstacker IV: 12320 Bir aralıkta iki hamle yapmak için diskalifiye edildi (250 ms içinde)

SSS

  • Neden bu meydan okuma terminal aracılığıyla dilden agnostik değil?
    • Basit bir sebepten dolayı daha eğlenceli. Bir oyunun kendisini grafiksel olarak izlemek, bir konsolun tüküren sayıları görmekten çok daha büyüleyici. Herhangi bir javascript bile bilmiyorsanız, öncelikle dil özellikleriyle ilgili olmadığı için bu zorluğa katılabilmelisiniz (sadece kodu en aza indirmek için bu aracı kullanın)

3
Sadece en iyi algoritmanın JavaScript uygulamalarının bir demet varlık sona erecek gibi görünüyor Bu burada hiç?
Jason C

2
-1 için ...best score after an hour will count... Neden sadece bir saat?
user80551

3
Her halükarda, dürüstlük adına, rastgele sayı üretecini her yanıtın test çalıştırması için aynı şekilde tohumlamayı ve aynı zamanda vadesi geçen bu sayımın varyasyonlarını ortadan kaldırmak için çalışma başına 14.400 hamle çalışmasını öneririm. zamanlama yanlışlıkları. En azından sonuçlar biraz daha deterministik ve bir KotH'a layık olabilir.
Jason C

1
750 bayt veya 550 bayt?
Peter Taylor

2
Çok kısıtlayıcı. 750 bayt, 1 saat, JavaScript.
TheDoctor

Yanıtlar:


4

Javascript kodlayamıyorum, bu yüzden cevabınızı çaldım.

//bind into new tile function and change m(ove) variable when a tile was moved
b = a.addRandomTile.bind(a);
m = !1;
a.addRandomTile = function() { m = !0; b(); };
//number of move fails
mfs = 0;
c=1;
setInterval(function() {
  //set global moved tracking variable to false
  m = !1;
  a.move(c)
  c++
  if (c>3) {c=1}
  m || mfs++;
  //restart after 10 moves failed
  10 < mfs && (mfs = 0, a.restart());
}, 250);

Benim de kullandığım stratejiyi kullanıyor.

EDIT: Güzel, sadece makinemde yaklaşık 5 dakika sonra puanınızı yendi: D

EDIT: Sadece bir kez yerine iki kez aşağı hareket etmeyi unuttum, bu kullanmanız gereken kod:

a = new GameManager(4, KeyboardInputManager, HTMLActuator, LocalStorageManager);
//bind into new tile function and change m(ove) variable when a tile was moved
b = a.addRandomTile.bind(a);
m = !1;
a.addRandomTile = function() { m = !0; b(); };
//number of move fails
mfs = 0;
c=1;
setInterval(function() {
  //set global moved tracking variable to false
  m = !1;
  if (c<=3) {n=c}
  else {n=2}
  a.move(n)
  c++

  if (c>4) {c=1} 
  m || mfs++;
  //restart after 10 moves failed
  10 < mfs && (mfs = 0, a.restart());
}, 250);

Ayrıca, gerekli olmadığında yeniden başlatıldığı bir hata var, ancak bunu nasıl düzelteceğimi bilmiyorum. EDIT: Şu anda 3116 yüksek puanı vardır (3 dakika sonra). Bence bu algoritmanın rastgele hareketler yapmaktan daha iyi olduğunu söylemek güvenli.

EDIT Daha yeni sürüm:

a = new GameManager(4, KeyboardInputManager, HTMLActuator, LocalStorageManager);
//bind into new tile function and change m(ove) variable when a tile was moved
b = a.addRandomTile.bind(a);
m = !1;
a.addRandomTile = function() { m = !0; mfs=0; b(); };
//number of move fails
mfs = 0;
c=1;
setInterval(function() {
  //set global moved tracking variable to false
  m = !1;
  if (c<=3) {n=c}
  else {n=2}
  a.move(n)
  c++
  if (c>4) {c=1} 
  m || mfs++;
  //up after 5 moves
  5 < mfs && (a.move(0));
  //restart after 10 moves failed
  10 < mfs && (mfs = 0, a.restart());
}, 250);

EDIT: Başka bir yeni sürüm, bu yukarı taşıdıktan sonra doğrudan aşağı taşır.

a = new GameManager(4, KeyboardInputManager, HTMLActuator, LocalStorageManager);
//bind into new tile function and change m(ove) variable when a tile was moved
b = a.addRandomTile.bind(a);
m = !1;
a.addRandomTile = function() { m = !0; mfs=0; b(); };
//number of move fails
mfs = 0;
c=1;
setInterval(function() {
  //set global moved tracking variable to false
  m = !1;
  if (c<=3) {n=c}
  else {n=2}
  a.move(n)
  c++
  if (c>4) {c=1} 
  m || mfs++;
  //up after 5 moves
  5 < mfs && (a.move(0), c=4);
  //restart after 10 moves failed
  10 < mfs && (mfs = 0, a.restart());
}, 250);

EDIT: Güncelleme: Bu sadece 12596 oldukça çılgın bir skor ile kişisel rekor kırdı.

EDIT: Hey, ben dip vurucu: D Ayrıca:

b=a.addRandomTile.bind(a);m=!1;a.addRandomTile=function(){m=!0;mfs=0;b()};mfs=0;c=1;setInterval(function(){m=!1;n=3>=c?c:2;a.move(n);c++;4<c&&(c=1);m||mfs++;5<mfs&&(a.move(0),c=4);10<mfs&&(mfs=0,a.restart())},250);

(Aslında bir değişiklik değil, sadece sıkıştırılmış.)

5. kez bir cazibe mi? Emin değil. Neyse:

//bind into new tile function and change m(ove) variable when a tile was moved
b = a.addRandomTile.bind(a);
m = !1;
a.addRandomTile = function() { m = !0; mfs=0; b(); };
//number of move fails
mfs = 0;
c=1;
setInterval(function() {
  //set global moved tracking variable to false
  m = !1;
  if (c<=3) {n=c}
  else {n=2}
  a.move(n)
  c++
  if (c>4) {c=1} 
  if (c==0) {c=4}
  m || mfs++;
  //up after 5 moves
  5 < mfs && (c=0);
  //restart after 10 moves failed
  10 < mfs && (mfs = 0, a.restart());
}, 250);

ve:

b=a.addRandomTile.bind(a);m=!1;a.addRandomTile=function(){m=!0;mfs=0;b()};mfs=0;c=1;setInterval(function(){m=!1;n=3>=c?c:2;a.move(n);c++;4<c&&(c=1);0==c&&(c=4);m||mfs++;5<mfs&&(c=0);10<mfs&&(mfs=0,a.restart())},250);

Başka bir yeni sürüm:

a = new GameManager(4, KeyboardInputManager, HTMLActuator, LocalStorageManager);
//bind into new tile function and change m(ove) variable when a tile was moved
b = a.addRandomTile.bind(a);
m = !1;
a.addRandomTile = function() { m = !0; mfs=0; b(); };
//number of move fails
mfs = 0;
c=1;
setInterval(function() {
  //set global moved tracking variable to false
  m = !1;
  if (c<=3) {n=c}
  else {n=2}
  a.move(n)
  c++
  if (c>4) {c=1} 
  if (c==0) {c=4}
  m || mfs++;
  //up after 5 moves
  5 < mfs && (c=0);
  //Found this in the source, as the criteria for a gameover. Might as well reset then ;)
  if (!a.movesAvailable()) {
      a.restart()
  }

}, 250);

ve:

a=new GameManager(4,KeyboardInputManager,HTMLActuator,LocalStorageManager);b=a.addRandomTile.bind(a);m=!1;a.addRandomTile=function(){m=!0;mfs=0;b()};mfs=0;c=1;setInterval(function(){m=!1;n=3>=c?c:2;a.move(n);c++;4<c&&(c=1);0==c&&(c=4);m||mfs++;5<mfs&&(c=0);a.movesAvailable()||a.restart()},250);

(Umarım bu, oyun ekranının arkasında devam etmek çok fazla bir sorun değil mi? a.over=0 sık sık yürütülen yere . Bir gün çözeceğim.)

EDIT (tekrar): Standart oyun yolunu düşürdüm ve eski işleri yapmanın eski yoluna döndüm. Şimdi birlikte 16 veya daha fazla 2 kiremit varsa her zaman bir araya ek bir test ediyorum:

a = new GameManager(4, KeyboardInputManager, HTMLActuator, LocalStorageManager);
b = a.addRandomTile.bind(a);
m = !1;
a.addRandomTile = function() {
  m = !0;
  mfs = 0;
  b();
};
mfs = 0;
c = 1;
setInterval(function() {
  m = !1;
  l = 8;
  for (x = 0;x < 4;x++) {
    for (y = 0;y < 4;y++) {
      t1 = a.grid.cellContent({x:x, y:y});
      t2 = a.grid.cellContent({x:x, y:y + 1});
      t3 = a.grid.cellContent({x:x + 1, y:y + 1});
      if (t1 & t2) {
        if (t1.value == t2.value) {
          if (t1.value > l) {
            l = t1.value;
            c = 2;
          }
        }
        if (t1 & t3) {
          if (t1.value == t2.value) {
            if (t1.value > l) {
              l = t1.value;
            }
          }
        }
      }
    }
  }
  if (c <= 3) {
    n = c;
  } else {
    n = 2;
  }
  a.move(n);
  c++;
  if (c > 4) {
    c = 1;
  }
  if (c == 0) {
    c = 4;
  }
  m || mfs++;
  5 < mfs && (c = 0);
  10 < mfs && (mfs = 0, a.restart());
}, 250);

mfs=0İçeri ekleyin addRandomTile, böylece başarılı bir hareketten sonra sayımı yeniden başlatacaktır.
David Mulder

Ve şimdi oynadığını izlerken, beklediğimden daha iyi olduğunu söyleyeyim O :): D
David Mulder

Sadece son 2 versiyonda bir aralıkta iki hamle yaptığınızı fark ettim, bu yüzden kaydettiğim 12320 puanını diskalifiye etmek zorunda kaldı. Ve evet, bir çeşit isme ihtiyacım vardı: P
David Mulder

@DavidMulder Nooooooo! (Bunun nerede olabileceğine dair bir fikrin var mı, bunu düzeltebilir miyim?)
2ıʇǝɥʇuʎs

13
Cevabınız yeni sürümle dolu , lütfen eski kodu kaldırın. Veya sürümler arasındaki farkları açıklayın. Herkes ilgileniyorsa "düzenle" günlüklerinde eski koda erişilebilecektir.
AL

3

Sağ ve Aşağı bot: 345 bayt

Kısa versiyon

b=a.addRandomTile.bind(a);m=!1;t=250;d=!0;a.addRandomTile=function(){m=!0;b();d&&setTimeout(c,t)};c=function(){d=!1;a.move(2);setTimeout(function(){m=!1;d=!0;a.move(1);m||setTimeout(function(){a.move(0);m?a.grid.cells[3][0]&&a.grid.cells[3][3]&&setTimeout(function(){a.move(1)},t):setTimeout(function(){a.move(3);m||a.restart()},t)},t)},t)};c();

Uzun versiyon

a = new GameManager(4, KeyboardInputManager, HTMLActuator, LocalStorageManager);
b = a.addRandomTile.bind(a);
m = !1;
t = 250;
d = !0;
a.addRandomTile = function() {
  m = !0;
  b();
  d && setTimeout(c, t);
};
c = function() {
  d = !1;
  a.move(2);
  setTimeout(function() {
    m = !1;
    d = !0;
    a.move(1);
    m || setTimeout(function() {
      a.move(0);
      m ? a.grid.cells[3][0] && a.grid.cells[3][3] && setTimeout(function() {
        a.move(1);
      }, t) : setTimeout(function() {
        a.move(3);
        m || a.restart();
      }, t);
    }, t);
  }, t);
};
c();

Kelimelerle

Aşağı, sonra sağa, eğer hareket edemezseniz, yukarı taşıyamazsanız (ya da sola hareket edemezseniz), hem sağ üst hem de sağ alt köşenin doluysa, sağa hareket et aksi takdirde baştan başlayın.

Mevcut yüksek puanlar

Kendi en iyi puanım 7668'di, ama bu hızdan çok daha yüksek bir hızda t=250(ve dolaylı olarak bir saatten daha uzun) yapıldı.


Bu komut dosyasının tur başına birden çok hareket gerçekleştirme eğilimi vardır.
jdstankosky

3

Her nasılsa bu sabah bu eski yarışmaya katıldım ve 2048'i sevdiğim için AI'ı seviyorum ve JS şu anda iyi bildiğim birkaç dilden biri, bir şans vereceğimi düşündüm.

Açgözlü ( 607 536 bayt)

Kısa versiyon:

C=function(x,y){return a.grid.cellContent({x:x,y:y})},h=[[1,3,2,0],[2,1,3,0]],V='value',A='addRandomTile';a=new GameManager(4,KeyboardInputManager,HTMLActuator,LocalStorageManager);b=a[A].bind(a);m=!1;f=d=X=Y=0;a[A]=function(){m=!0;f=0;b()};setInterval(function(){m=!1;for(var c=X=Y=0;4>c;c++)for(var e=0;4>e;e++)if(u=C(c,e),!!u){for(q=e+1;4>q;){v=C(c,q);if(!!v){u[V]==v[V]&&(Y+=u[V]);break}q++}for(q=c+1;4>q;){v=C(q,e);if(!!v){u[V]==v[V]&&(X+=u[V]);break}q++}}f<4&&a.move(h[X>Y+4?0:1][f]);m&&(f=0);m||f++;15<f&&(f=0,a.restart())},250);

Uzun versiyon (eski):

a = new GameManager(4, KeyboardInputManager, HTMLActuator,    LocalStorageManager);
b = a.addRandomTile.bind(a);
m = !1;
f = d = X = Y = 0;
a.addRandomTile = function() { m = !0; f = 0; b(); };
setInterval(function() {
    m = !1;
    X = Y = 0;

    for(var x=0;x<4;x++) {
        for(var y=0;y<4;y++) {
            u = a.grid.cellContent({x:x, y:y});
            if(u==null){continue;}
            q = y+1;
            while(q < 4) {
                v = a.grid.cellContent({x:x,y:q});
                if(v!=null){
                    if(u.value==v.value){
                        Y+=u.value;
                    }
                    break;
                }
                q++;
            }
            q = x+1;
            while(q < 4) {
                v = a.grid.cellContent({x:q,y:y});
                if(v!=null){
                    if(u.value==v.value){
                        X+=u.value;
                    }
                    break;
                }
                q++;
            }
        }
    }

    if(X>=Y){
        if(f==0)
            a.move(1);
        else if(f==1)
            a.move(3);
        else if(f==2)
            a.move(2);
        else if(f==3)
            a.move(0);
    } else {
        if(f==0)
            a.move(2);
        else if(f==1)
            a.move(0);
        else if(f==2)
            a.move(1);
        else if(f==3)
            a.move(3);
    }
    if(m)f=0;
    m || f++;
    if(15 < f) f=0,a.restart();
}, 250);

Daha uzun versiyon hiç golf oynamadı (değişken isimleri küçültmek dışında), bu yüzden hala okunabilirken biraz kısaltılabilir. Daha kısa versiyon 650'de sona eren Closure Compiler (link için teşekkürler!) Kullanılarak oluşturuldu. Benim tarafımdan bazı özel modifikasyonlarla, başka bir 43 tıraş olabilirim 114 bit .

Temel olarak, ızgarada olası hareketleri arar ve ne zaman bir tane bulursa değerini yatay veya dikey toplama ekler. Olası her harekette arama yaptıktan sonra, H veya V toplamının daha yüksek olup olmadığına ve zaten denediği yönlere bağlı olarak hangi yönde hareket etmesi gerektiğini belirler. Sağ ve Aşağı ilk seçimlerdir.

Buna geri dönersek, şimdi toplamlardan biri sıfır değilse, karoları bu yönde kaydırmaya yönelik ilk denemenin başarılı olacağının garanti edildiğini anlıyorum. Belki de buna dayanarak hareket karar verme bölümünü sonuna kadar basitleştirebilirim.

Bu programı bir saat boyunca bıraktım ve yüksek bir puanla bitirdim 6080. Bununla birlikte, deneme çalışmalarından birinde (minimasyon), 6492kişisel en iyi performansımın sadece 128'inin arkasında yüksek bir puan aldı 6620. Sayıları şu şekilde yığılmaya meyilli olduğundan, mantığı ara sıra sola hareket ettirilerek büyük ölçüde geliştirilebilir:

 2  4  8 16
 4  8 16 32
 8 16 32 64
16 32 64 128

( DÜZENLEME: Bir süre daha çalışmaya devam ettim ve bazı 7532noktalar başardı . Lanet olsun, programım benden daha akıllı ....)

Bir daha ilginç bir ayrıntı: bir şey kullanışlı yaratmak benim glitched girişimleri birinde, her nasılsa, böylece zaman bitti herhangi iki fayans aynı satır veya sütunda, onlar birleştirildi. Bu, rastgele 2'ler veya 4'ler tekrar tekrar en yüksek karo ile birleşerek her seferinde iki katına çıkacağı için ilginç gelişmelere yol açtı. Bir kez, bir şekilde kapatmadan önce 15 saniyede 11.000'in üzerinde puan başardı .... XD

İyileştirme için herhangi bir öneri çok açıktır!


1

Ön Cam Silecekleri: 454 bayt

Sadece Sağa, Yukarıya, Sola, Yukarı ... gider (tıpkı bir arabadaki silecekler gibi) sıkışmazsa. Sıkışırsa, silecekleri kapatıp tekrar açmayı dener. Bir saat içinde aldığım en yüksek puan 12.156 oldu - Ancak puanların çoğu 3k - 7k arasında bir yerdeydi.

Her denemeden sonra skoru konsola gönderecektir.

var move = !1;
var bad = 0;
var c = 0;
var b = a.addRandomTile.bind(a);
a.addRandomTile = function() {
    b();
    move=!0;
    bad=0;
}
setInterval(function() {
    if (!move) bad++;
    if (c>3) c=0;
    move = !1;
    if (c==3) {a.move(0);c++;}
    if (c==2) {a.move(3);c++;}
    if (c==1) {a.move(0);c++;}
    if (c==0) {a.move(1);c++;}
    if (bad>10) {a.move(2);}
    if (!a.movesAvailable()) {console.log("Score: "+a.score);a.restart();}
}, 250);

0

UpAndLeftBot

Başlıktan da anlaşılacağı gibi, David Mulder'ın işini çalarak ve bazı sayıları değiştirerek yukarı ve sola hareket eder (Javascript hakkında jack bilmiyorum, bu yüzden yapabileceğim en iyi şey budur).

a = new GameManager(4, KeyboardInputManager, HTMLActuator, LocalStorageManager);
b = a.addRandomTile.bind(a);
m = !1;
t = 250;
d = !0;
a.addRandomTile = function() {
  m = !0;
  b();
  d && setTimeout(c, t);
};
c = function() {
  d = !1;
  a.move(0); // a.move(2)
  setTimeout(function() {
    m = !1;
    d = !0;
    a.move(3); // a.move(1)
    m || setTimeout(function() {
      a.move(2);  //a.move(0)
      m ? a.grid.cells[3][0] && a.grid.cells[3][3] && setTimeout(function() {
        a.move(3); // a.move(1)
      }, t) : setTimeout(function() {
        a.move(1);  // a.move(3)
        m || a.restart();
      }, t);
    }, t);
  }, t);
};
c();

Tıpkı David Mulder'ın senaryosu gibi, bu da arada bir dönüş başına birden fazla hamle gerçekleştirir.
jdstankosky
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.