เกมโอเอกซ์


15

สร้างโปรแกรมที่กำหนดในการเล่น n dโอเอกซ์กับผู้เข้าแข่งขันอื่น ๆ

โปรแกรมของคุณควรทำงานเมื่อn(ความกว้าง) และd(หมายเลขมิติ) อยู่ในช่วงเหล่านี้:

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

n = 3; d = 2(3 2คือ 3 จาก 3):

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

n = 3; d = 3(3 3เช่น 3 โดย 3 โดย 3):

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

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

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

n = 6; d = 2(6 2คือ 6 จาก 6):

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

และอื่น ๆ

การป้อนข้อมูล:

อินพุตจะเป็น STDIN บรรทัดแรกของการป้อนข้อมูลจะเป็นตัวเลขสองnและในรูปแบบdn,d

หลังจากนี้จะเป็นบรรทัดที่ประกอบด้วยพิกัดที่ระบุการเคลื่อนไหวที่ได้ทำไปแล้ว พิกัดจะแสดงรายการในแบบฟอร์ม: 1,1;2,2;3,3. มุมซ้ายบนเป็นจุดกำเนิด (0,0 สำหรับ 2D) ในกรณีทั่วไปรายการนี้จะเหมือนกับ1,2,...,1,4;4,0,...,6,0;...หมายเลขแรกแทนซ้าย - ขวา - เนสส์ลำดับที่สองจากด้านล่าง - อันดับที่สามผ่านทางมิติที่ 3 ฯลฯ โปรดทราบว่าพิกัดแรกคือXเทิร์นแรกวินาที เป็นOเทิร์นแรก, ....

หากนี่เป็นการย้ายครั้งแรกอินพุตจะเป็นตัวเลขตามด้วยบรรทัดว่าง 1 บรรทัด

เพื่อความสอดคล้องอินพุตจะลงท้ายด้วยการขึ้นบรรทัดใหม่เสมอ ตัวอย่างอินพุต (\ n คือบรรทัดใหม่):

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

สำหรับการย้ายครั้งแรก:

10,10\n\n

ที่\nเป็นตัวละครขึ้นบรรทัดใหม่

เอาท์พุท:

แสดงการเคลื่อนไหวที่คุณต้องการในรูปแบบเดียวกับอินพุต (รายการที่คั่นด้วยเครื่องหมายจุลภาค) การย้ายที่ไม่ถูกต้อง (เช่นที่ได้ดำเนินการไปแล้ว) จะส่งผลให้สูญเสียเกม

หมายเหตุ: คุณสามารถใช้ตัวสร้างตัวเลขสุ่มได้ตราบใดที่คุณเริ่มต้นด้วยค่าที่การรันแต่ละครั้งจะเหมือนกันในเงื่อนไขเดียวกัน กล่าวอีกนัยหนึ่งโปรแกรมจะต้องกำหนดขึ้น

หมายเหตุ: อนุญาตให้ทำการย้ายที่ถูกต้องเท่านั้น

เกมที่ชนะ (หากคุณเล่น Tic Tac Toe หลายมิติมากพอก็จะเหมือนกัน)

เพื่อให้มีการชนะผู้เล่นคนหนึ่งจะต้องมีสี่เหลี่ยมที่อยู่ติดกันทั้งหมดตามแนว นั่นคือผู้เล่นนั้นจะต้องมีการnเคลื่อนไหวในบรรทัดเพื่อเป็นผู้ชนะ

ตั้งอยู่ใกล้เคียง:

  • กระเบื้องแต่ละจุด เช่น (0,0,0,0,0) เป็นจุดd=5
  • ไพ่ที่อยู่ติดกันคือไพ่เช่นกันซึ่งพวกเขาทั้งสองจุดบนหน่วย d-cube เดียวกัน กล่าวอีกนัยหนึ่งระยะทาง Chebyshevระหว่างแผ่นคือ 1
  • กล่าวอีกนัยหนึ่งถ้าจุดpอยู่ติดกับจุดqจากนั้นทุกพิกัดในพิกัดpที่สอดคล้องกันในqความแตกต่างจากมันไม่เกินหนึ่ง นอกจากนี้อย่างน้อยในการประสานงานคู่แตกต่างกันโดยหนึ่ง

บรรทัด:

  • เส้นถูกกำหนดโดยเวกเตอร์และกระเบื้อง เส้นคือแต่ละไทล์ที่กระทบกับสมการ:p0 + t<some vector with the same number of coordinates as p0>

เงื่อนไขการจำลองและการชนะ:

  • ระบุคำตอบของคุณหากพร้อมสำหรับการให้เกรด นั่นคือระบุอย่างชัดเจนว่าคำตอบของคุณเสร็จสิ้นหรือไม่

  • หากคำตอบของคุณถูกทำเครื่องหมายว่าเสร็จสิ้นแล้วคำตอบนั้นจะไม่ถูกให้คะแนนจนกว่าอย่างน้อย 24 ชั่วโมงหลังจากแก้ไขรหัสล่าสุด

  • โปรแกรมจะต้องทำงานแบบออฟไลน์ หากโปรแกรมพบว่ามีการโกงโปรแกรมจะได้รับคะแนนโดยอัตโนมัติ-1และจะไม่ถูกทำคะแนนเพิ่มเติม (ใครจะจบลงด้วยการโกงโปรแกรมของพวกเขา?)

  • หากโปรแกรมของคุณสร้างผลลัพธ์ที่ไม่ถูกต้องระบบจะนับการสูญเสียทันทีของเกม

  • หากโปรแกรมของคุณล้มเหลวในการสร้างผลผลิตหลังจาก 1 นาทีมันจะถูกนับทันทีว่าเป็นความสูญเสียสำหรับเกม หากจำเป็นให้ปรับความเร็วให้เหมาะสม ฉันไม่ต้องการรอหนึ่งชั่วโมงเพื่อทดสอบโปรแกรมอื่น

  • แต่ละโปรแกรมจะทำงานกับโปรแกรมอื่น ๆ สองครั้งสำหรับแต่ละnในช่วง[3,6]และแต่ละคนdในช่วง[2,5]เมื่อเป็นและครั้งเดียวX Oนี่คือหนึ่งรอบ

  • สำหรับแต่ละเกมที่โปรแกรมชนะจะได้+3คะแนน หากโปรแกรมเชื่อมโยง (ชนะ 1 และแพ้ 1 ในรอบเดียวหรือความสัมพันธ์สำหรับการเล่นเกมทั้งสอง) +1แล้วจะได้รับ หากโปรแกรมสูญหายก็จะได้รับ+0(เช่นไม่มีการเปลี่ยนแปลง)

  • โปรแกรมที่มีคะแนนสูงสุดจะเป็นผู้ชนะ หากมีการเสมอกันโปรแกรมที่มีจำนวนเกมที่แพ้น้อยที่สุด (จากผู้แข่งขันที่ผูก) จะชนะ

หมายเหตุ: ขึ้นอยู่กับจำนวนคำตอบฉันอาจต้องการความช่วยเหลือในการทดสอบ

โชคดี! และแบบจำลองอาจทำงานในความโปรดปรานของคุณ!


ความท้าทายของตัวตรวจสอบ Win <---- ความท้าทายนี้คือการสร้างโปรแกรมเพื่อตรวจสอบว่าเกมนั้นชนะหรือไม่ มันเกี่ยวข้องกับความท้าทายนี้มาก
Justin

ตนเองมีแท็กที่คุณเพิ่งคิดค้นไม่ได้เพิ่มอะไรให้จำแนกแท็ก ฉันคิดว่าคุณควรลบมัน
Howard

@ ฮาวาร์ดโอเค ฉันสังเกตเห็นว่าคำถามจำนวนมากมีข้อ จำกัด ดังนั้นฉันจึงคิดว่าแท็กจะเหมาะสม
จัสติน

4
เกมที่แปลก การย้ายที่ชนะเท่านั้นไม่สามารถเล่นได้
german_guy

(w, x, y, z) เป็นรูปแบบเอาต์พุตที่ถูกต้องหรือไม่
alexander-brett

คำตอบ:


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))])))

นี่เป็นเพียงการสุ่มไอ มันสุ่มเลือกการย้ายออกจากการเคลื่อนไหวที่ยังคงมีอยู่


2

Python 2.7

นี่คือการส่งงานที่กำลังดำเนินการซึ่งฉันกำลังเสนอเพื่อให้โครงกระดูก / แรงบันดาลใจให้กับผู้ตอบคำถามอื่น ๆ มันทำงานได้โดยการแสดงรายการทุก ๆ เส้นชนะที่เป็นไปได้ ปัจจุบันฮิวริสติกนั้นว่างเปล่า (ผลงานลับสุดยอด) ฉันได้เพิ่มการจัดการข้อผิดพลาด win และ clash ด้วย

หมายเหตุเกี่ยวกับปัญหา

มีผู้ชนะกี่เส้น พิจารณากรณี 1 มิติ มี 2 ​​จุดยอด 1 ขอบและ 1 บรรทัด ใน 2 มิติเรามี 4 จุดเชื่อมต่อโดย 2 เส้นและ 4 ขอบเชื่อมด้วย 2 * n บรรทัด ใน 3 มิติเรามี 8 จุดเชื่อมต่อโดย 4 เส้น 12 ขอบเชื่อมด้วย 6 * n เส้นและ 6 ใบหน้าเชื่อมต่อกันด้วย3*n^2เส้น

โดยทั่วไปให้เราเรียกจุดยอด a-facet, edge 1-facet, และอื่น ๆ จากนั้นให้N(i)แสดงจำนวน i-facets, dจำนวนมิติและnความยาวด้าน 0.5*sum(N(i)*n^i,i=0..d-1)แล้วจำนวนบรรทัดที่ชนะคือ

ต่อวิกิพีเดียN(i)=2^(d-i)*d!/(i!*(n-1)!)ดังนั้นสูตรสุดท้ายคือ:

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

ซึ่งวุลแฟรม | อัลฟาไม่ชอบมาก สิ่งนี้มีขนาดใหญ่มากอย่างรวดเร็วดังนั้นฉันไม่คาดหวังว่าโปรแกรมของฉันจะสามารถจัดการรันไทม์สำหรับ d> 8 ได้

ผลลัพธ์บางส่วน (ขออภัยเกี่ยวกับการจัดรูปแบบ:

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

ในขณะที่การป้อนข้อมูลที่จะต้องมีการป้อนข้อมูลเป็น: tictactoe.py <ret> n,d <ret> move;move <ret>- ;บันทึกหลายบรรทัดและไม่มีขั้นสุดท้าย

เอาท์พุทดูเหมือน(x_1,x_2,x_3...)เช่น:

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() 

แก้ไข: สำหรับ I / O, ตรรกะเพิ่มเติม ฉันเชื่อว่าตอนนี้พร้อมที่จะทำเครื่องหมาย

โปรดทราบว่าความคิดเห็นนี้เคยเป็นตัวยึดตำแหน่งที่ฉันลบและลบ


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)))

ส่วนใหญ่ของรหัสที่เป็นเหมือนกับQuincunx สุ่ม AI แทนที่จะสุ่มเลือกย้ายมันเลือกย้ายที่มีอยู่เป็นครั้งแรก lexicographically (เช่น (0,0, ... 0) จากนั้น (0,0, ... 1), จากนั้น (0,0, ... 2) ฯลฯ )

นี่เป็นกลยุทธ์ขยะค่อนข้างสวย แต่มันก็มักจะเล่นแบบสุ่ม

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.