1. 程式人生 > 其它 >3D Tic-Tac-Toe

3D Tic-Tac-Toe

技術標籤:課外學習

3D Tic-Tac-Toe

一、問題描述

有一個三維空間中3X3X3的遊戲板,玩家可以輪流在這每個單元格中畫上“X”或者“O”,在經典的玩法中,如果有一個玩家填滿了一行或者一個對角線,那麼遊戲結束。但是現在遊戲將一直進行直到每個格子都填上。現在請你設計一種玩法使遊戲結束時,同一種元素填滿的行數或者對角線數最少。

二、建立模型

(一)關鍵變數

  1. i s X i j k isX_{ijk} isXijk∈[0,1]: ( i , j , k ) (i,j,k) (i,j,k
    )
    是 X ( i s X i j k isX_{ijk} isXijk=1) 或者O ( i s X i j k isX_{ijk} isXijk=0)。
  2. i s L i n e l isLine_l isLinel∈[0,1]:如果 l l l這一行或者對角線填滿同一種元素( i s L i n e l isLine_l isLinel=1)否則( i s L i n e l isLine_l isLinel=0)。

(二)目標函式

M i n i m i z e Minimize Minimize Z = ∑ l ∈ L i n e s i s L i n e l Z=\sum_{l\in Lines}isLine_l

Z=lLinesisLinel

(三) 約束變數

  1. ∑ i j k i s X i j k = 14 ∑_{ijk}isX_{ijk}=14 ijkisXijk=14

一共二十七個位置,假設X先走,那麼X有十四個,O有13個。

  1. i s L i n e l = 0 ⟹ i s X [ l 0 ] + i s X [ l 1 ] + i s X [ l 2 ] > = 1 isLine_l=0⟹isX[l0]+isX[l1]+isX[l2]>=1 isLinel=0isX[l0]+isX[l1]+isX[l2]>=1 ∀ l ∈ L i n e s ∀l∈Lines
    lLines

    i s L i n e l = = 0 ⟹ i s X [ l 0 ] + i s X [ l 1 ] + i s X [ l 2 ] < = 2 isLinel==0⟹isX[l0]+isX[l1]+isX[l2]<=2 isLinel==0isX[l0]+isX[l1]+isX[l2]<=2 ∀ l ∈ L i n e s ∀l∈Lines lLines

由於如果不是同一種元素,那麼三個值加起來就不會是0或者3。

三、程式碼

import gurobipy as gp
from gurobipy import GRB

lines = []
size = 3

for i in range(size):
    for j in range(size):
        for k in range(size):
            if i == 0:
                lines.append(((0,j,k), (1,j,k), (2,j,k)))
            if j == 0:
                lines.append(((i,0,k), (i,1,k), (i,2,k)))
            if k == 0:
                lines.append(((i,j,0), (i,j,1), (i,j,2)))
            if i == 0 and j == 0:
                lines.append(((0,0,k), (1,1,k), (2,2,k)))
            if i == 0 and j == 2:
                lines.append(((0,2,k), (1,1,k), (2,0,k)))
            if i == 0 and k == 0:
                lines.append(((0,j,0), (1,j,1), (2,j,2)))
            if i == 0 and k == 2:
                lines.append(((0,j,2), (1,j,1), (2,j,0)))
            if j == 0 and k == 0:
                lines.append(((i,0,0), (i,1,1), (i,2,2)))
            if j == 0 and k == 2:
                lines.append(((i,0,2), (i,1,1), (i,2,0)))
lines.append(((0,0,0), (1,1,1), (2,2,2)))
lines.append(((2,0,0), (1,1,1), (0,2,2)))
lines.append(((0,2,0), (1,1,1), (2,0,2)))
lines.append(((0,0,2), (1,1,1), (2,2,0)))

model = gp.Model('Tic_Tac_Toe')
isX = model.addVars(size, size, size, vtype=GRB.BINARY, name="isX")
isLine = model.addVars(lines, vtype=GRB.BINARY, name="isLine")

x14 = model.addConstr(isX.sum() == 14)


for line in lines:
    model.addGenConstrIndicator(isLine[line], False, isX[line[0]] + isX[line[1]] + isX[line[2]] >= 1)
    model.addGenConstrIndicator(isLine[line], False, isX[line[0]] + isX[line[1]] + isX[line[2]] <= 2)

model.setObjective(isLine.sum())


model.optimize()

'''
 ARGUMENTS:
      GRB.GENCONSTR_INDICATOR (option 1):
        binvar (Var): Antecedent variable of indicator constraint
        binval (Boolean): Value of antecedent variable that activates the linear constraint
        lhs (float, Var, or LinExpr): Linear expression of constraint triggered by the indicator
        sense (char): Sense of constraint triggered by the indicator (e.g., GRB.LESS_EQUAL)
        rhs (float): Right-hand side of linear constraint triggered by the indicator
        name (string): Constraint name (default is no name)

      GRB.GENCONSTR_INDICATOR (option 2):
        binvar (Var): Antecedent variable of indicator constraint
        binval (Boolean): Value of antecedent variable that activates the linear constraint
        lhs (TempConstr): Linear constraint triggered by indicator
        name (string): Constraint name (default is no name)

    RETURN VALUE:
      The created general constraint object.

    EXAMPLE:
      genconstr = model.addGenConstrIndicator(z, 0, 2*x1 - 1.5*x2 + 3.0*x3 == 4.5, name="myIndicatorConstr")
'''

參考:gurobi中國.