Kısmen Gözlenebilir Connect-4


8

Oyun

Standart bir Connect-4 oyunu oynayacaksınız . Ne yazık ki, bu bir yazışma oyunudur ve birisi alttan başlayarak her ikinci satıra siyah bant yerleştirmiştir, böylece rakibinizin bu satırlardaki hareketlerini göremezsiniz.

Zaten dolu olan sütunlardaki herhangi bir hamle sizin sıranızı geçecek sayılır ve bir oyun dönüşten daha uzun süre çalışırsa 6 * 7berabere berabere kalır.

Mücadele Şartnamesi

Programınız bir Python 3 işlevi olarak uygulanmalıdır. İlk argüman, bilinen tahta durumunu aşağıdan yukarıya doğru 2B bir liste listesi olarak gösteren bir 'görünüm'dür; burada 1birinci oyuncu 2tarafından bir hareket, ikinci oyuncu tarafından bir hareket ve 0boş bir konum veya gizli rakibiniz tarafından hareket.

İkinci argüman endeksli bir dönüş numarasıdır 0ve paritesi size hangi oyuncunun olduğunuzu söyler.

Son argüman, Noneher oyunun başında başlatılan ve dönüşler arasındaki durumu korumak için kullanabileceğiniz keyfi bir durumdur .

Oynatmak istediğiniz sütun dizininin iki parçasını ve bir sonraki dönüşte size geri döndürülecek yeni durumu döndürmelisiniz.

puanlama

Kazanma +1, beraberlik 0ve kayıp olarak sayılır -1. Amacınız bir round-robin turnuvasında en yüksek ortalama puanı elde etmektir. Açık bir kazananı tanımlamak için gereken sayıda maç yapmaya çalışacağım.

kurallar

Herhangi bir yarışmacının aynı anda en fazla bir rakip botu olmalıdır, ancak iyileştirmeler yaparsanız girişinizi güncellemeniz uygundur. Lütfen botunuzu tur başına ~ 1 saniye düşünme süresiyle sınırlandırmaya çalışın.

Test yapmak

Denetleyicinin kaynak kodu, referans için rakip olmayan birkaç örnek botla birlikte:

import itertools
import random

def get_strides(board, i, j):
    yield ((i, k) for k in range(j + 1, 7))
    yield ((i, k) for k in range(j - 1, -1, -1))
    yield ((k, j) for k in range(i + 1, 6))
    yield ((k, j) for k in range(i - 1, -1, -1))
    directions = [(1, 1), (-1, -1), (1, -1), (-1, 1)]
    def diag(di, dj):
        i1 = i
        j1 = j
        while True:
            i1 += di
            if i1 < 0 or i1 >= 6:
                break
            j1 += dj
            if j1 < 0 or j1 >= 7:
                break
            yield (i1, j1)
    for d in directions:
        yield diag(*d)

DRAWN = 0
LOST = 1
WON = 2
UNDECIDED = 3

def get_outcome(board, i, j):
    if all(board[-1]):
        return DRAWN
    player = board[i][j]
    strides = get_strides(board, i, j)
    for _ in range(4):
        s0 = next(strides)
        s1 = next(strides)
        n = 1
        for s in (s0, s1):
            for i1, j1 in s:
                if board[i1][j1] == player:
                    n += 1
                    if n >= 4:
                        return WON
                else:
                    break
    return UNDECIDED

def apply_move(board, player, move):
    for i, row in enumerate(board):
        if board[i][move] == 0:
            board[i][move] = player
            outcome = get_outcome(board, i, move)
            return outcome
    if all(board[-1]):
        return DRAWN
    return UNDECIDED

def get_view(board, player):
    view = [list(row) for row in board]
    for i, row in enumerate(view):
        if i % 2:
            continue
        for j, x in enumerate(row):
            if x == 3 - player:
                row[j] = 0
    return view

def run_game(player1, player2):
    players = {1 : player1, 2 : player2}
    board = [[0] * 7 for _ in range(6)]
    states = {1 : None, 2 : None}
    for turn in range(6 * 7):
        p = (turn % 2) + 1
        player = players[p]
        view = get_view(board, p)
        move, state = player(view, turn, states[p])
        outcome = apply_move(board, p, move)
        if outcome == DRAWN:
            return DRAWN
        elif outcome == WON:
            return p
        else:
            states[p] = state
    return DRAWN

def get_score(counts):
    return (counts[WON] - counts[LOST]) / float(sum(counts))

def run_tournament(players, rounds=10000):
    counts = [[0] * 3 for _ in players]
    for r in range(rounds):
        for i, player1 in enumerate(players):
            for j, player2 in enumerate(players):
                if i == j:
                    continue
                outcome = run_game(player1, player2)
                if outcome == DRAWN:
                    for k in i, j:
                        counts[k][DRAWN] += 1
                else:
                    if outcome == 1:
                        w, l = i, j
                    else:
                        w, l = j, i
                    counts[w][WON] += 1
                    counts[l][LOST] += 1
        ranks = sorted(range(len(players)), key = lambda i: get_score(counts[i]), reverse=True)
        print("Round %d of %d\n" % (r + 1, rounds))
        rows = [("Name", "Draws", "Losses", "Wins", "Score")]
        for i in ranks:
            name = players[i].__name__
            score = get_score(counts[i])
            rows.append([name + ":"] + [str(n) for n in counts[i]] + ["%6.3f" % score])
        lengths = [max(len(s) for s in col) + 1 for col in zip(*rows)]
        for i, row in enumerate(rows):
            padding = ((n - len(s)) * ' ' for s, n in zip(row, lengths))
            print(''.join(s + p for s, p in zip(row, padding)))
            if i == 0:
                print()
        print()

def random_player(view, turn, state):
    return random.randrange(0, 7), state

def constant_player(view, turn, state):
    return 0, state

def better_random_player(view, turn, state):
    while True:
        j = random.randrange(0, 7)
        if view[-1][j] == 0:
            return j, state

def better_constant_player(view, turn, state):
    for j in range(7):
        if view[-1][j] == 0:
            return j, state

players = [random_player, constant_player, better_random_player, better_constant_player]

run_tournament(players)

Mutlu KoTHing!

Geçici Sonuçlar

Name                    Draws Losses Wins  Score  

zsani_bot:              40    5377   94583  0.892 
better_constant_player: 0     28665  71335  0.427 
constant_player:        3     53961  46036 -0.079 
normalBot:              38    64903  35059 -0.298 
better_random_player:   192   71447  28361 -0.431 
random_player:          199   75411  24390 -0.510 

Görünümü [-1] [j] == 0 neden kontrol ettiğinizi açıklayabilir misiniz? Onları nereye doldurduğunuzu tam olarak bilmiyorum ve python bilgim biraz paslı görünüyor.
Barbarian772

@ Barbarian772 Bu sütunda hala boşluk olup olmadığını kontrol ediyorum. Üst sıraya tam olarak uyulması için 6 sıra bulunduğunu unutmayın.
user1502040

1
Zaten tam sütunlara geçiş olarak sayılmamalısınız. Birçoğu 4 oyunu birbirine bağlayan sadece bir sütun doldurulmaz ve bir oyuncu o sütunda oynayarak kaybederse, bu, aksi takdirde bir oyuncu için zorla kazanıldığında oyunun bağlanmasını sağlar.
soktinpk

@soktinpk Bu sadece başka bir strateji katmanı değil mi? Sonuçta, Connect-4 çözülmüş bir oyundur, bu nedenle dönüş atlama faktörü, katkıda bulunanların sadece standart algoritmaları kullanamayacağı bir kural değişikliği için yeterli olabilir.
mypetlion

1
Alttan sıfır indeksleme, bantlanmış satırlar (0,2,4,6) veya (1,3,5) midir? Bazı ASCII sanatı faydalı olabilir.
SIGSTACKFAULT

Yanıtlar:


6

Bu bot, tüm kazançları alır ve rakipleri engellemek için geri düşer, ikincisi onları dikey ve yatay olarak tahmin eder veya rastgele hareketler yapar.

ithalat pprint, matematik, koleksiyonlar, kopya
def zsani_bot_2 (görünüm, dönüş, durum):
    eğer durum == Yok: # ilk kendi dönüşü - her zaman orta için
        state = (1, 2) eğer dönüş == 0 başka (2, 1) # (sembolüm, sembolünüz)
        #print (pprint.pformat (görünüm) + 'Dönüş:' + str (dönüş) + 'Oyuncu:' + str (durum [0]))
        dönüş 3, eyalet

    #locate bariz noktalar
    (1, 6) aralığında i için: # ilk satırı atla
        aralıktaki j için (len (görünüm [i])): #TODO: Zip ile optimize edin. Şimdi açıklığa kavuşun
            görünüm [i] [j]! = 0 ve görünüm [i-1] [j] == 0 ise:
                görüntüle [i-1] [j] = durum [1]
    enemy_points = matematik. zemin (dönüş / 2)
    ++ enemy_points durum [0] == 2 başka enemy_points
    known_points = sum ([görüşte i için i.count (durum [1])])
    missing_points = düşman_ noktaları - bilinen_ noktalar

    #get emin olun herhangi bir yönde kazanır
    aralıktaki j için (0, 7): #her sütun
        (4, -1, -1) aralığında i için:
            görünüm [i] [j]! = 0 ise:
                bilinen en yüksek doldurulmuş noktayı bul
        eğer ({1, 3, 5} içinde eksik_ nokta veya i + 1 yok):
            view1 = copy.deepcopy (görüntüle)
            attempt = Apply_move (görünüm1; durum [0], j)
            teşebbüs == KAZANDI:
               # print (pprint.pformat (görünüm) + 'Dönüş:' + str (dönüş) + 'Oyuncu:' + str (durum [0]) + 'kazanan hareket')
                dönüş j, durum

    #block düşman herhangi bir yönde kazanır emin olun
    (0, 7) aralığında j için:
        (4, -1, -1) aralığında i için:
            görünüm [i] [j]! = 0 ise:
                bilinen en yüksek doldurulmuş noktayı bul
        eğer (eksik_puanlar veya {1, 3, 5} 'de i + 1)):
            view1 = copy.deepcopy (görüntüle)
            attempt = Apply_move (görünüm1; durum [1], j)
            teşebbüs == KAZANDI:
              # print (pprint.pformat (görünüm) + 'Dönüş:' + str (dönüş) + 'Oyuncu:' + str (durum [0]) + 'kaydetme hareketi')
                dönüş j, durum

    #block duvarlar
    (0, 3) aralığında i için: # sütun dolduğunda arka arkaya 4 almak mümkün
        (0, 6) aralığında j için:
            view [i] [j]! = 0 ve view [i] [j] == view [i + 1] [j] ve view [i + 2] [j] == view [i + 3] [j ] == 0:
             # print (pprint.pformat (görünüm) + 'Dönüş:' + str (dönüş) + 'Oyuncu:' + str (durum [0]) + 'sütun taşıma')
                dönüş j, durum

    #block platformları, aşağıdaki satır ve bırakma noktasında mükemmel bilgi veriyorsa
    (0, 5) aralığında i için:
        (0, 3) aralığında j için:
            istatistik = koleksiyonlar. Sayıcı ([görüntüle [i] [j], görüntüle [i] [j + 1], görüntüle [i] [j + 2], görüntüle [i] [j + 3]])
            istatistikler [0] == 2 ve (istatistikler [durum [0]] == 2 veya istatistikler [durum [0]] == 2):
                (0, 3) aralığında k için:
                    görünüm [i] [j + k] == 0 ise:
                        mola
                eğer (i == 0 veya [i-1] [j + k]! = 0) 'ı görüntüleyin ve ({1, 3, 5} içinde eksik_points veya i yok):
                    #print (pprint.pformat (görünüm) + 'Dönüş:' + str (dönüş) + 'Oyuncu:' + str (durum [0]) + 'platform hareketi')
                    dönüş j + k, durum
                Başka:
                    l aralığında (k, 3):
                        görünüm [i] [j + l] == 0 ise:
                            mola
                        eğer (i == 0 veya [i-1] [j + l]! = 0) 'ı görüntüleyin ve ({1, 3, 5} içindeki eksik_points veya i yok):
                     # print (pprint.pformat (görünüm) + 'Dönüş:' + str (dönüş) + 'Oyuncu:' + str (durum [0]) + 'platform hareketi')
                            dönüş j + l, durum

    #fallback -> rastgele
    True iken:
        j = rasgele. aralık (0, 7)
        görünüm [-1] [j] == 0 ise:
            #print (pprint.pformat (görünüm) + 'Dönüş:' + str (dönüş) + 'Oyuncu:' + str (durum [0]) + 'rastgele hareket')
            dönüş j, durum

Run_game'i düzelttiğiniz için teşekkür ederiz!

Değişiklikler:

  • v2 yatay engelleme ekler - 4'lü sırada, aynı oyuncu tarafından doldurulmuş iki boş nokta ve iki nokta varsa, bunlardan birini arka arkaya üç tane olacak şekilde doldurmaya / rakipler sırasını engellemeye çalışır, umarım sonraki dönüşlerde büyük harfle yazılmalıdır.

3
Siteye hoş geldiniz. Kod değiştirmek için düzenlemeyi reddetmeye oy verdim, en iyi yorum olarak bırakılacaktı, bu şekilde OP kodla ne yapacağına karar verebilir.
Ad Hoc Garf Hunter

Ana gönderiye yorum yapmak için yeterli itibarım yok. Bir düzenlemeyi nasıl geri çekebilirim?
Syfer Polski

Düzenlemeyi geri çekmeye gerek yok (yine de yapabileceğini sanmıyorum). Gelecekte yorum yapmak yeterli olacaktır, ancak cevabınızda söylediğiniz için OP'nin görmesi muhtemeldir. Ayrıca , OP'nin reddedilmiş olsa bile önerdiğinizi ve düzenlediğinizi göreceğini düşünüyorum .
Ad Hoc Garf Hunter

Düzenlemeyi geri çekmek istememin nedeni, değişikliklerin bir satırını kaçırmamış olmasından dolayı, düzenlenen kodun tamamen çalışmadığı için. Yazımdaki düzenleme önerisine ekledim. Yardımın için teşekkürler!
Syfer Polski

2

normalBot, ortadaki lekelerin uçlardaki lekelerden daha değerli olduğu varsayımına dayanır. Böylece, seçimlerini belirlemek için ortada ortalanmış normal bir dağılım kullanır.

def normalBot(view, turn, state):
    randomNumber = round(np.random.normal(3, 1.25))
    fullColumns = []
    for i in range(7):
        if view[-1][i] != 0:
            fullColumns.append(i)
    while (randomNumber > 6) or (randomNumber < 0) or (randomNumber in fullColumns):
        randomNumber = round(np.random.normal(3, 1.25))
    return randomNumber, state

-1

Bu açıkça rakip değil, ama yine de hata ayıklama için çok yararlı ... ve şaşırtıcı derecede eğlenceli, eğer botunuzu hile için yeterince iyi biliyorsanız: D bu yüzden daha fazla başvuru ilham umutları gönderiyorum:

import math, pprint
def manual_bot(view, turn, state):
    if state == None:
        state = (1, 2) if turn == 0 else (2, 1) #(my_symbol, your symbol)

#locate obvious points
    for row in range (1, 6):
        for j in range(len(view[row])):
            if view[row][j] != 0 and view[row-1][j] == 0:
                view[row-1][j] = state[1]

#if you're second, the opponent has one more point than half the turns
    enemy_points = math.ceil(turn/2)
    known_points = sum([row.count(state[1]) for row in view])
    missing_points = enemy_points - known_points

    print(pprint.pformat(view) + ' Turn: ' + str(turn) + ' Player: ' + str(state[0]) + ' Missing points: ' + str(missing_points))
    while True:
        try:
            move = int(input("What is your move?(0-6) "))
        except ValueError:
            continue
        if move in {0, 1, 2, 3, 4, 5, 6}:
            return move, state

Izgara baş aşağıdır (alt sıra en yüksektir). Kazanan anonsları almak için, oyun kontrolörünü yama yapmanız ve kazancı iade etmeden önce bir baskı ifadesi eklemeniz gerekir:

elif outcome == WON:
    print(pprint.pformat(board) + ' Turn: ' + str(turn) +' Winner: '+ str(p))
    return p

[[0, 0, 0, 0, 0, 0, 0],
 [0, 0, 0, 0, 0, 0, 0],
 [0, 0, 0, 0, 0, 0, 0],
 [0, 0, 0, 0, 0, 0, 0],
 [0, 0, 0, 0, 0, 0, 0],
 [0, 0, 0, 0, 0, 0, 0]] Dönüş: 0 Oyuncu: 1 Eksik puan: 0
Hareketin nedir? (0-6) 3
[[0, 0, 0, 1, 0, 0, 0],
 [0, 0, 0, 2, 0, 0, 0],
 [0, 0, 0, 0, 0, 0, 0],
 [0, 0, 0, 0, 0, 0, 0],
 [0, 0, 0, 0, 0, 0, 0],
 [0, 0, 0, 0, 0, 0, 0]] Dönüş: 2 Oyuncu: 1 Eksik puan: 0
Hareketin nedir? (0-6) 2
[[0, 0, 1, 1, 0, 0, 0],
 [0, 0, 0, 2, 0, 0, 0],
 [0, 0, 0, 0, 0, 0, 0],
 [0, 0, 0, 0, 0, 0, 0],
 [0, 0, 0, 0, 0, 0, 0],
 [0, 0, 0, 0, 0, 0, 0]] Dönüş: 4 Oyuncu: 1 Eksik puan: 1
Hareketin nedir? (0-6) 4
[[0, 0, 1, 1, 1, 0, 0],
 [0, 0, 0, 2, 0, 0, 0],
 [0, 0, 0, 0, 0, 0, 0],
 [0, 0, 0, 0, 0, 0, 0],
 [0, 0, 0, 0, 0, 0, 0],
 [0, 0, 0, 0, 0, 0, 0]] Dönüş: 6 Oyuncu: 1 Eksik puan: 2
Hareketin nedir? (0-6) 1
[[2, 1, 1, 1, 1, 2, 0],
 [0, 0, 0, 2, 0, 0, 0],
 [0, 0, 0, 0, 0, 0, 0],
 [0, 0, 0, 0, 0, 0, 0],
 [0, 0, 0, 0, 0, 0, 0],
 [0, 0, 0, 0, 0, 0, 0]] Dönüş: 6 Kazanan: 1
[[0, 0, 0, 0, 0, 0, 0],
 [0, 0, 0, 0, 0, 0, 0],
 [0, 0, 0, 0, 0, 0, 0],
 [0, 0, 0, 0, 0, 0, 0],
 [0, 0, 0, 0, 0, 0, 0],
 [0, 0, 0, 0, 0, 0, 0]] Dönüş: 1 Oyuncu: 2 Eksik puan: 1
Hareketin nedir? (0-6) 2
[[0, 0, 2, 0, 0, 0, 0],
 [0, 0, 0, 0, 0, 0, 0],
 [0, 0, 0, 0, 0, 0, 0],
 [0, 0, 0, 0, 0, 0, 0],
 [0, 0, 0, 0, 0, 0, 0],
 [0, 0, 0, 0, 0, 0, 0]] Dönüş: 3 Oyuncu: 2 Eksik puan: 2
Hareketin nedir? (0-6) 3
[[0, 0, 2, 1, 0, 0, 0],
 [0, 0, 1, 2, 0, 0, 0],
 [0, 0, 0, 0, 0, 0, 0],
 [0, 0, 0, 0, 0, 0, 0],
 [0, 0, 0, 0, 0, 0, 0],
 [0, 0, 0, 0, 0, 0, 0]] Dönüş: 5 Oyuncu: 2 Eksik puan: 1
Hareketin nedir? (0-6) 4
[[0, 0, 2, 1, 2, 0, 0],
 [0, 0, 1, 2, 0, 0, 0],
 [0, 0, 0, 0, 0, 0, 0],
 [0, 0, 0, 0, 0, 0, 0],
 [0, 0, 0, 0, 0, 0, 0],
 [0, 0, 0, 0, 0, 0, 0]] Dönüş: 7 Oyuncu: 2 Eksik puan: 2
Hareketin nedir? (0-6) 1
[[0, 2, 2, 1, 2, 0, 0],
 [0, 0, 1, 2, 0, 0, 0],
 [0, 0, 1, 0, 0, 0, 0],
 [0, 0, 1, 0, 0, 0, 0],
 [0, 0, 0, 0, 0, 0, 0],
 [0, 0, 0, 0, 0, 0, 0]] Dönüş: 9 Oyuncu: 2 Eksik puan: 1
Hareketin nedir? (0-6) 2
[[0, 2, 2, 1, 2, 0, 0],
 [0, 0, 1, 2, 0, 0, 0],
 [0, 0, 1, 0, 0, 0, 0],
 [0, 0, 1, 0, 0, 0, 0],
 [0, 0, 2, 0, 0, 0, 0],
 [0, 0, 1, 0, 0, 0, 0]] Dönüş: 11 Oyuncu: 2 Eksik puan: 1
Hareketin nedir? (0-6) 4
[[0, 2, 2, 1, 2, 0, 0],
 [0, 0, 1, 2, 2, 0, 0],
 [0, 0, 1, 0, 0, 0, 0],
 [0, 0, 1, 0, 0, 0, 0],
 [0, 0, 2, 0, 0, 0, 0],
 [0, 0, 1, 0, 0, 0, 0]] Dönüş: 13 Oyuncu: 2 Eksik puan: 2
Hareketin nedir? (0-6) 4
[[0, 2, 2, 1, 2, 0, 0],
 [0, 1, 1, 2, 2, 0, 0],
 [0, 0, 1, 0, 1, 0, 0],
 [0, 0, 1, 0, 2, 0, 0],
 [0, 0, 2, 0, 0, 0, 0],
 [0, 0, 1, 0, 0, 0, 0]] Dönüş: 15 Oyuncu: 2 Eksik puan: 1
Hareketin nedir? (0-6) 3
[[0, 2, 2, 1, 2, 0, 0],
 [0, 1, 1, 2, 2, 0, 0],
 [0, 0, 1, 2, 1, 0, 0],
 [0, 0, 1, 0, 2, 0, 0],
 [0, 0, 2, 0, 0, 0, 0],
 [0, 0, 1, 0, 0, 0, 0]] Dönüş: 17 Oyuncu: 2 Eksik puan: 2
Hareketin nedir? (0-6) 5
[[0, 2, 2, 1, 2, 1, 1],
 [0, 1, 1, 2, 2, 2, 1],
 [0, 0, 1, 2, 1, 0, 0],
 [0, 0, 1, 0, 2, 0, 0],
 [0, 0, 2, 0, 0, 0, 0],
 [0, 0, 1, 0, 0, 0, 0]] Dönüş: 19 Oyuncu: 2 Eksik puan: 0
Hareketin nedir? (0-6) 
Hareketin nedir? (0-6) 6
[[0, 2, 2, 1, 2, 1, 1],
 [0, 1, 1, 2, 2, 2, 1],
 [0, 0, 1, 2, 1, 0, 2],
 [0, 0, 1, 0, 2, 0, 0],
 [0, 0, 2, 0, 0, 0, 0],
 [0, 0, 1, 0, 0, 0, 0]] Dönüş: 21 Oyuncu: 2 Eksik puan: 1
Hareketin nedir? (0-6) 1
[[0, 2, 2, 1, 2, 1, 1],
 [0, 1, 1, 2, 2, 2, 1],
 [0, 2, 1, 2, 1, 0, 2],
 [0, 1, 1, 0, 2, 0, 0],
 [0, 0, 2, 0, 0, 0, 0],
 [0, 0, 1, 0, 0, 0, 0]] Dönüş: 23 Oyuncu: 2 Eksik puan: 1
Hareketin nedir? (0-6) 3
[[0, 2, 2, 1, 2, 1, 1],
 [0, 1, 1, 2, 2, 2, 1],
 [0, 2, 1, 2, 1, 0, 2],
 [0, 1, 1, 2, 2, 0, 0],
 [0, 0, 2, 0, 0, 0, 0],
 [0, 0, 1, 0, 0, 0, 0]] Dönüş: 25 Oyuncu: 2 Eksik puan: 2
Hareketin nedir? (0-6) 6
[[0, 2, 2, 1, 2, 1, 1],
 [0, 1, 1, 2, 2, 2, 1],
 [0, 2, 1, 2, 1, 0, 2],
 [0, 1, 1, 2, 2, 0, 2],
 [0, 0, 2, 1, 0, 0, 0],
 [0, 0, 1, 1, 0, 0, 0]] Dönüş: 27 Oyuncu: 2 Eksik puan: 1
Hareketin nedir? (0-6) 5
[[1, 2, 2, 1, 2, 1, 1],
 [1, 1, 1, 2, 2, 2, 1],
 [0, 2, 1, 2, 1, 2, 2],
 [0, 1, 1, 2, 2, 0, 2],
 [0, 0, 2, 1, 0, 0, 0],
 [0, 0, 1, 1, 0, 0, 0]] Dönüş: 29 Oyuncu: 2 Eksik puan: 0
Hareketin nedir? (0-6) 5
[[1, 2, 2, 1, 2, 1, 1],
 [1, 1, 1, 2, 2, 2, 1],
 [0, 2, 1, 2, 1, 2, 2],
 [0, 1, 1, 2, 2, 2, 2],
 [0, 0, 2, 1, 0, 0, 0],
 [0, 0, 1, 1, 0, 0, 0]] Dönüş: 29 Kazanan: 2
Tur 1/1

İsim Beraberlik Kaybetmeleri Kazandı Skor
manual_bot: 0 0 2 1.000 zsani_bot_2: 0 2 0 -1.000

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.