Tic-Tac-Toe Oyunları


15

N d oynamak için deterministik bir program oluşturun diğer yarışmacılar ile tic-tac-toe.

Programınız n(genişlik) ve d(boyut numarası) şu aralıklarda olduğunda çalışmalıdır:

n∈[3,∞)∩ℕ  ie a natural number greater than 2
d∈[2,∞)∩ℕ  ie a natural number greater than 1

n = 3; d = 2(3 2 yani 3 x 3):

[][][]
[][][]
[][][]

n = 3; d = 3(3 3 yani 3 x 3 x 3):

[][][]
[][][]
[][][]

[][][]
[][][]
[][][]

[][][]
[][][]
[][][]

n = 6; d = 2(6 2 yani 6 x 6):

[][][][][][]
[][][][][][]
[][][][][][]
[][][][][][]
[][][][][][]
[][][][][][]

Ve bunun gibi.

Giriş:

Giriş STDIN olacaktır. Girişin ilk çizgisi, iki sayılar, olacak nve dformu n,d.

Bundan sonra, yapılan hareketleri belirten koordinatlardan oluşan bir çizgi olacaktır. Koordinatlar şeklinde listelenir: 1,1;2,2;3,3. Sol üst köşe başlangıç ​​noktasıdır (2D için 0,0). Genel durumda, bu liste 1,2,...,1,4;4,0,...,6,0;...ilk sayının sola-sağa, ikinci yukarı-aşağıya, üçüncü ila üçüncü boyuta vb. Gösterdiği gibi olacaktır. İlk koordinatın Xilk dönüş, ikinci olduğu Oilk dönüş, ....

Bu ilk hamle ise, girdi bir sayı ve ardından 1 boş satır olur.

Tutarlılık için girdi her zaman yeni satırla biter. Örnek Giriş (\ n yeni satırdır):

10,10\n0,0,0,0,0,0,0,0,0,0;0,2,3,4,5,6,7,8,9,0;0,1,2,3,4,5,6,7,8,9\n

İlk hamle için:

10,10\n\n

\nyeni satır karakteri nerede .

Çıktı:

Yapmak istediğiniz hareketin, girdiyle aynı biçimde (virgülle ayrılmış bir liste) çıktı alın. Geçersiz bir hamle (yani daha önce yapılmış bir hamle) oyunun kaybedilmesine neden olur.

Not: Her koşunun aynı koşullar göz önüne alındığında aynı olacağı şekilde bir değer eklediğiniz sürece rastgele bir sayı üreteci kullanabilirsiniz. Başka bir deyişle, program deterministik olmalıdır.

Not: sadece geçerli hamlelere izin verilir.

Kazanan Oyunlar (Yeterince çok boyutlu tic tac toe oynadıysanız, bu aynıdır.)

Kazanmak için, bir oyuncunun bir çizgi boyunca tüm bitişik karelere sahip olması gerekir. Yani, bir oyuncunun nkazanan olabilmesi için bir hatta hamle yapması gerekir .

bitişik:

  • her karo bir noktadır; örneğin (0,0,0,0,0),d=5
  • bitişik karolar aynı birim d-küpünde her iki nokta olacak şekilde karolardır. Başka bir deyişle, fayanslar arasındaki Chebyshev mesafesi 1'dir.
  • başka bir deyişle, bir nokta bir noktaya pbitişikse, s'deki ilgili koordinattaki qher koordinat, birden fazla farklı değildir. Ek olarak, en azından koordinat çifti tam olarak bir farklılık gösterir.pq

Hatları:

  • Çizgiler vektörler ve bir döşemeyle tanımlanır. Bir çizgi, denklemin vurduğu her bir döşemedir:p0 + t<some vector with the same number of coordinates as p0>

Simülasyon ve Kazanma Koşulları:

  • Not vermeye hazır olup olmadığını cevabınızda belirtin. Yani, cevabınızın yapılıp yapılmadığını açıkça belirtin.

  • Cevabınız tamam olarak işaretlenmişse, kodda yapılan son düzenlemeden en az 24 saat sonrasına kadar notlandırılmaz.

  • Programlar çevrimdışı çalışmalıdır. Bir program hile yapıyorsa, otomatik olarak bir puan alır -1ve daha fazla puanlanmaz. (Birileri programlarını kandırmakla nasıl sonuçlanır?)

  • Programınız geçersiz çıktı üretiyorsa, hemen oyun için bir kayıp olarak sayılır

  • Program 1 dakika sonra çıktı üretemezse, hemen oyun için bir kayıp olarak sayılır. Gerekirse hız için optimize edin. Bir programı başka bir programdan test etmek için bir saat beklemek istemiyorum.

  • Her program iki kez her biri için diğer programlara karşı işletilecek naralığında [3,6]ve her daralıkta [2,5]bir zamanlar, Xve bir kez olarak O. Bu bir tur.

  • Bir programın kazandığı her oyun için +3puanını alır . Program bağlanırsa (tek bir turda 1 galibiyet ve 1 kayıp veya her iki oyun için de bağlar), o zaman olur +1. Program kaybedilirse, o zaman alır +0(yani değişiklik yok).

  • En yüksek puana sahip program kazanır. Beraberlik olması durumunda, en az sayıda kayıp oyunun (berabere kalan yarışmacıların dışında) olduğu program kazanır.

Not: Cevap sayısına bağlı olarak, testleri yürütmek için yardıma ihtiyacım olabilir.

İyi şanslar! Ve simülasyonlar sizin lehinize olabilir!


Kazan-denetleyicisi meydan. <---- Bu zorluk belirli bir oyunun kazanılıp kazanılmadığını kontrol etmek için programlar oluşturmaktır. Bu zorlukla çok ilgili.
Justin

Yeni icat ettiğiniz bağımsız etiket, etiket sınıflandırmasına hiçbir şey eklemez. Bence onu kaldırmalısın.
Howard

@ Tamam. Bir çok sorunun bu kısıtlamaya sahip olduğunu fark ettim, bu yüzden bir etiketin uygun olacağını düşündüm.
Justin

4
Tuhaf bir oyun. Tek kazanan hamle oynamak değil.
german_guy

(w, x, y, z) geçerli bir çıktı biçimi mi?
alexander-brett

Yanıtlar:


2

Python 3

import random as rand
import re

def generateMoves(width, dim):
    l = [0] * dim
    while existsNotX(l, width - 1):
        yield l[:]
        for i in range(dim):
            if l[i] < width - 1:
                l[i] += 1
                break
            else:
                l[i] = 0
    yield l

def existsNotX(l, x):
    for i in l:
        if i != x:
            return True
    return False

input_s = input()
dims, moves = None, None
#this is to allow input as a single paste, instead of ENTER inputting.
try:
    dims, moves = input_s.splitlines()
except ValueError:
    dims = input_s
    moves = input()

rand.seed(moves + dims)

dims = eval(dims) #change into tuple

moves = moves.split(';')
if len(moves[0]):
    moves = [eval(m) for m in moves] #change into tuples

output =[x for x in generateMoves(dims[0], dims[1]) if x not in moves]
print(re.sub('[^\\d,]', '', str(output[rand.randint(0, len(output))])))

Bu sadece rastgele bir AI. Hala mevcut olan hamlelerden bir hamle rastgele seçer.


2

Python 2.7

Bu, diğer cevaplayıcılara bir iskelet / ilham vermek için sağladığım, devam etmekte olan bir çalışmadır. Olası her kazanma çizgisini listeleyerek, daha sonra bu çizgiyi ne kadar değerli olduğuna göre puanlamak için sezgisel olarak uygulayarak çalışır. Şu anda buluşsal yöntem boştur (süper gizli çalışmalar). Ayrıca kazan ve çarpışma hatası işleme ekledim.

Sorunla ilgili notlar

Kaç tane kazanan çizgi var? 1 boyutlu durumu düşünün; 2 köşe, 1 kenar ve 1 çizgi vardır. 2 boyutta, 2 çizgiyle birleştirilen 4 köşe ve 2 * n çizgiyle birleştirilen 4 kenarımız var. 3 boyutta 4 çizgiyle birleştirilen 8 köşe, 6 * n çizgiyle birleştirilen 12 kenar ve 3*n^2çizgiyle birleştirilen 6 yüzümüz var .

Genel olarak, ABD daha sonra izin bir köşe vs. 0-yüzünü, bir kenar, bir 1-yüz, diyelim N(i)göstermektedirler i-yönü sayısını, dboyutların sayısı ve nyan uzunluğu. Sonra kazanan hat sayısı 0.5*sum(N(i)*n^i,i=0..d-1).

Vikipedi başına N(i)=2^(d-i)*d!/(i!*(n-1)!), son formül:

sum(2^(d-i-1) n^i d! / (i! * (n-i)!),i=0..d-1)

hangi wolfram | alpha çok hoşlanmıyor. Bu oldukça hızlı bir şekilde büyür, bu yüzden programımın d> 8 için yönetilebilir çalışma süresine sahip olmasını beklemiyorum.

Bazı sonuçlar (biçimlendirme için üzgünüm:

d\n 0   1    2      3      4       5        6        7         8         9
0   1   1    1      1      1       1        1        1         1         1
1   2   4    6      8      10      12       14       16        18        20
2   4   11   26     47     74      107      146      191       242       299
3   8   40   120    272    520     888      1400     2080      2952      4040
4   16  117  492    1437   3372    6837     12492    21117     33612     50997
5   32  364  2016   7448   21280   51012    107744   206896    368928    620060
6   64  1093 8128   37969  131776  372709   908608   1979713   3951424   7352101
7   128 3280 32640  192032 807040  2687088  7548800  18640960  41611392  85656080
8   256 9834 130809 966714 4907769 19200234 62070009 173533434 432891129 985263594

I / O

: Şu anda giriş olarak giriş olması gerekir tictactoe.py <ret> n,d <ret> move;move <ret>birden çok satır ve hiçbir nihai not - ;.

Çıktı (x_1,x_2,x_3...), örneğin şöyle görünür :

tictactoe.py <ret> 6,5 <ret> <ret> => 0, 0, 0, 0, 0

tictactoe.py <ret> 6,5 <ret> 0,0,0,0,0;0,0,0,0,5 <ret> => 0, 0, 0, 5, 0

# Notes on terminology:
#
# - A hypercube is the region [0,n]^d
# - An i-facet is an i-dimensional facet of a hypercube,
#   which is to say, a 0-facet is a vertex, a 1-facet an
#   edge, a 2-facet a face, and so on.
# - Any tuple {0,n}^i is a vertex of an i-hypercube
#   which is why I've used vertex to describe such
#   tuples
# - A winning line is a set of n coordinates which joins
#   two opposite i-facets
# - i-facets are opposite if they differ in every co-
#   ordinate which defines them
#
# Test Data:
#  


import numpy
import itertools

def removeDuplicates(seq):
    noDupes = []
    [noDupes.append(i) for i in seq if not noDupes.count(i)]
    return noDupes 


def listPairedVertices (i,n):
    """
    listPairedVertices returns a list L of elements of {0,n}^i which has the
    property that for every l in L, there does not exist l' such that
    l+l' = {n}^i.
    """

    vertices = numpy.array([[b*(n-1)  for b in a] for a in [
        list(map(int,list(numpy.binary_repr(x,i)))) for x in range(2**i)
    ]])
    result = []
    while len(vertices)>1:
        for j in range(len(vertices)):
            if numpy.all(vertices[j] + vertices[0] == [n-1]*i):
                result.append(vertices[0])
                vertices=numpy.delete(vertices,[0,j],axis=0)
                break
    return result


def listSequences (d,l):
    """
    listSequences returns the subset of {0,1}^d having precisely n 1s.
    """
    return numpy.array([
        r for r in itertools.product([0,1],repeat=d) if sum(r)==l
    ])


def listPaddedConstants (s,n):
    """
    listPaddedConstants takes a sequence in {0,1}^d and returns a number in
    {0..n}^sum(s) padded by s
    """
    result = numpy.zeros([n**sum(s),len(s)],dtype=numpy.int)
    for i,x in enumerate([list(z) for z in 
        itertools.product(range(n),repeat=sum(s))]):
        for j in range(len(s)):
            if s[j]: result[i][j] = x.pop()
    return result


def listWinningVectorsForDimension(d,i,n):
    """
    List the winning lines joining opposite i-facets of the hypercube.

    An i-facet is defined by taking a vertex v and a sequence s, then forming 
    a co-ordinate C by padding v with zeroes in the positions indicated by s.
    If we consider s = s_0.e_0 + s_1+e_1... where the e_j are the canonical
    basis for R^d, then the formula of the i-facet is 
        C+x_0.s_0.e_0+x_1.s_1.e_1... 
    for all vectors x = (x_0,x_1...) in R^n

    We know that winning lines only start at integral positions, and that the
    value of a will only be needed when s_j is nonempty, so the start point S
    of a winning line is in fact determined by:
     + vertex v in {0,n}^(d-i), padded by s
     + a in R^i, padded by the complement of s, s'

    Having performed the following operations, the co-ordinates of the winning
    lines are abs(S-k*s') for k in [0..n-1]
    """
    vertices = listPairedVertices(d-i,n)
    sequences = listSequences(d,i)
    result = []
    for s in sequences:
        for v in vertices:
            C = [0]*d
            j = 0
            for index in range(d):
                if s[index]: C[index] = 0
                else: 
                    C[index] = v[j]
                    j+=1
            result += [
                [numpy.absolute(S-k*(numpy.absolute(s-1))) for k in range(n)] 
                    for S in [C+a for a in listPaddedConstants(s,n)]
            ]
    return result


def AllWinningLines (d,n):
    """
    has the structure [[x_1,x_2,x_3],[y_1,y_2,y_3]] where each l_k is a
    length-d co-ordinate
    """
    result = []
    for i in range(d):
        result += listWinningVectorsForDimension(d,i,n)
    return result


def movesAlreadyMade ():
    """
    Returns a list of co-ordinates of moves already made read from STDIN
    """
    parameters = raw_input()
    moves = raw_input()
    parameters = list(map(int,parameters.split(',')))
    moves = [map(int,a.split(',')) for a in moves.split(';')] \
        if moves != '' else []
    return {'n':parameters[0], 'd':parameters[1], 'moves':moves}

def scoreLine (moves, line, scores, n):
    """
    Gives each line a score based on whatever logic I choose
    """
    myMoves          = moves[0::2]
    theirMoves       = moves[1::2]
    if len(moves)%2: myMoves, theirMoves = theirMoves, myMoves

    lineHasMyMove    = 0
    lineHasTheirMove = 0
    score            = 0

    for coord in line:
        if coord.tolist() in myMoves: 
            lineHasMyMove += 1
            if coord.tolist() in theirMoves: raise Exception('Move clash')
        elif coord.tolist() in theirMoves: lineHasTheirMove += 1

    if lineHasMyMove == len(line):
        raise Exception('I have won')
    elif lineHasTheirMove == len(line):
        raise Exception('They have won')
    elif lineHasMyMove and lineHasTheirMove: 
        pass
    elif lineHasTheirMove == len(line)-1: 
        score = n**lineHasTheirMove
    else: 
        score = n**lineHasMyMove

    for coord in line:
        if coord.tolist() not in moves: 
            scores[tuple(coord)]+=score

def main():
    """
    Throw it all together
    """
    data      = movesAlreadyMade()
    dimension = data['d']
    length    = data['n']
    lines     = AllWinningLines(dimension, length)
    scores    = numpy.zeros([length]*dimension, dtype=numpy.int)

    try: [scoreLine(data['moves'], line, scores, length) for line in lines]
    except Exception as E:
            print 'ERROR: ' + E.args[0]
            return
    print ','.join(map(
        str,numpy.unravel_index(numpy.argmax(scores),scores.shape)
        ))


if __name__ == "__main__": main() 

Düzenleme: G / Ç için mantık eklendi. Bunun artık işaretlemeye hazır olduğuna inanıyorum

Bu yorumun başlangıçta sildiğim ve sildiğim bir yer tutucu olduğunu unutmayın.


1

Python 2

import re
import itertools

input_s = raw_input()
dims, moves = None, None
#this is to allow input as a single paste, instead of ENTER inputting.
try:
    dims, moves = input_s.splitlines()
except ValueError:
    dims = input_s
    moves = raw_input()

dims = eval(dims) #change into tuple

moves = moves.split(';')
if len(moves[0]):
    moves = [eval(m) for m in moves] #change into tuples

allSpaces = [x for x in itertools.product(range(dims[0]), repeat=dims[1])]
move = None
for space in allSpaces:
    if space not in moves:
        move = space
        break
print(re.sub('[^\\d,]', '', str(move)))

Kodun çoğu Quincunx'ın rastgele AI'sıyla tamamen aynıdır . Bir hareketi rastgele seçmek yerine, ilk kullanılabilir hareketi sözlükbilimsel olarak seçer (yani (0,0, ... 0), sonra (0,0, ... 1), sonra (0,0, ... 2) , vb.).

Bu oldukça saçma bir stratejidir, ancak neredeyse her zaman rastgele oynamayı yener.

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.