Skip to content

Instantly share code, notes, and snippets.

@slanterns
Last active December 23, 2019 18:39
Show Gist options
  • Select an option

  • Save slanterns/0ceb2833fdf5ee61329849928bdae4c9 to your computer and use it in GitHub Desktop.

Select an option

Save slanterns/0ceb2833fdf5ee61329849928bdae4c9 to your computer and use it in GitHub Desktop.
import math
class Tboard():
def __init__(self, data):
self.data = data
self.complete = False
self.rotateCnt = 0
self.mirrored = False
self.impo = False
def hash(self):
return sum([self.data[i] * (2 ** i) for i in range(9)])
def fold(self):
return [[self.data[3 * i + j] for j in range(3)] for i in range(3)]
def foldRev(self):
return [[self.data[3 * j + i] for j in range(3)] for i in range(3)]
def flatten(self, foldedList):
return [foldedList[i][j] for i in range(3) for j in range(3)]
def judgeLine(self, line):
return all([(True if i == 1 else False) for i in line])
def judge(self):
foldBoard = self.fold()
foldRevBoard = self.foldRev()
resultList = [any([self.judgeLine(line) for line in foldBoard]),
any([self.judgeLine(line) for line in foldRevBoard]),
self.judgeLine([self.data[4 * i] for i in range(3)]),
self.judgeLine([self.data[2 * (i + 1)] for i in range(3)])]
return any(resultList)
def mirror(self):
temp = self.fold()
tempMirroredFolded = [[temp[i][2 - j] for j in range(3)] for i in range(3)]
tempMirroredFoldedFlattened = Tboard(self.flatten(tempMirroredFolded))
tempMirroredFoldedFlattened.mirrored = not self.mirrored
tempMirroredFoldedFlattened.rotateCnt = self.rotateCnt
return tempMirroredFoldedFlattened
def rotate(self):
temp = self.fold()
tempMirroredRotated = [[temp[2 - j][i] for j in range(3)] for i in range(3)]
tempMirroredRotatedFlattened = Tboard(self.flatten(tempMirroredRotated))
tempMirroredRotatedFlattened.rotateCnt = self.rotateCnt + 1
tempMirroredRotatedFlattened.mirrored = self.mirrored
return tempMirroredRotatedFlattened
game = {'A':Tboard([0] * 9), 'B':Tboard([0] * 9), 'C':Tboard([0] * 9)}
def parseable(cStr):
if len(cStr) != 2:
return False
if cStr[0] not in 'ABC':
return False
if cStr[1] not in [str(i) for i in range(9)]:
return False
return True
def check(game):
for lable in game.keys():
if game[lable].judge():
game[lable].complete = True
def printBlock(board, num):
if board[num] == 0:
return num
else:
return 'X'
def move(lable, number):
if (not game[lable].complete) and game[lable].data[number] == 0:
game[lable].data[number] = 1
return True
return False
def cusPrint(game):
(a, b, c) = (game['A'], game['B'], game['C'])
print(" ".join(('' if a.complete else 'A') + ('' if b.complete else 'B') + ('' if c.complete else 'C')))
for i in range(3):
if not a.complete:
print(printBlock(a.data, 3 * i + 0), printBlock(a.data, 3 * i + 1), printBlock(a.data, 3 * i + 2), end='')
if not b.complete or not c.complete:
print(' ', end='')
if not b.complete:
print(printBlock(b.data, 3 * i + 0), printBlock(b.data, 3 * i + 1), printBlock(b.data, 3 * i + 2), end='')
if not c.complete:
print(' ', end='')
if not c.complete:
print(printBlock(c.data, 3 * i + 0), printBlock(c.data, 3 * i + 1), printBlock(c.data, 3 * i + 2), end='')
print()
return
def decode(hashC):
tempL = []
for _ in range(9):
tempL.append(hashC % 2)
hashC = hashC // 2
return Tboard(tempL)
def match(tb, solutionSet):
if tb.hash() in solutionSet.keys():
return (tb, solutionSet[tb.hash()])
if tb.rotate().hash() in solutionSet.keys():
return (tb.rotate(), solutionSet[tb.rotate().hash()])
if tb.rotate().rotate().hash() in solutionSet.keys():
return (tb.rotate().rotate(), solutionSet[tb.rotate().rotate().hash()])
if tb.rotate().rotate().rotate().hash() in solutionSet.keys():
return (tb.rotate().rotate().rotate(), solutionSet[tb.rotate().rotate().rotate().hash()])
if tb.mirror().hash() in solutionSet.keys():
return (tb.mirror(), solutionSet[tb.mirror().hash()])
if tb.mirror().rotate().hash() in solutionSet.keys():
return (tb.mirror().rotate(), solutionSet[tb.mirror().rotate().hash()])
if tb.mirror().rotate().rotate().hash() in solutionSet.keys():
return (tb.mirror().rotate().rotate(), solutionSet[tb.mirror().rotate().rotate().hash()])
if tb.mirror().rotate().rotate().rotate().hash() in solutionSet.keys():
return (tb.mirror().rotate().rotate().rotate(), solutionSet[tb.mirror().rotate().rotate().rotate().hash()])
def undo(ttb, solution):
tsolu = decode(solution)
if (ttb.rotateCnt % 4) == 0:
tsolu = tsolu
elif (ttb.rotateCnt % 4) == 1:
tsolu = tsolu.rotate().rotate().rotate()
elif (ttb.rotateCnt % 4) == 2:
tsolu = tsolu.rotate().rotate()
elif (ttb.rotateCnt % 4) == 3:
tsolu = tsolu.rotate()
if ttb.mirrored:
tsolu = tsolu.mirror()
return tsolu
def getNextStep(tb, solutionSet):
(ttb, solution) = match(tb, solutionSet)
tsolu = undo(ttb, solution)
dif = tsolu.hash() - tb.hash()
nextStep = int(math.log2(dif))
return nextStep
def rest(game):
return sum([(0 if game[lable].complete else 1) for lable in game.keys()])
solutionSet1 = {17:21, 149:157, 29:157, 18:82, 90:346, 114:370, 161:417, 419:427, 1:257, 259:387, 261:325, 2:130, 138:170, 134:198, 426:427}
solutionSet2 = {3:7, 5:7, 17:273, 257:273, 33:161, 18:146, 130:146, 160:161, 163:167, 165:167, 177:433, 417:433}
def main():
cusPrint(game)
move('A', 4) # Our first step
print("Player 1: A4")
cusPrint(game)
impoDetered = False
while True:
p2LastMove = ()
while True: # Opponent's turn
tStr = input("Player 2: ")
if not parseable(tStr):
print("Invalid move, please input again")
else:
(lable, number) = (tStr[0], int(tStr[1]))
if not move(lable, number):
print("Invalid move, please input again")
else:
p2LastMove = (lable, number)
break
check(game)
if rest(game) == 0:
print("Player 1 wins game")
break
cusPrint(game)
# Our turn
if game[p2LastMove[0]].hash() == 2 ** p2LastMove[1]: # p2 moves to an empty board
move(('B' if p2LastMove[0] == 'C' else 'C'), 4)
print("Player 1: " + ('B' if p2LastMove[0] == 'C' else 'C') + "4")
cusPrint(game)
if rest(game) == 2 and (not impoDetered):
restGameLables = [lable for lable in game.keys() if not game[lable].complete]
if (game[restGameLables[0]].hash() == 16) ^ (game[restGameLables[1]].hash() == 16):
game[restGameLables[(0 if game[restGameLables[0]].hash() == 16 else 1)]].impo = True
impoDetered = True
continue
if rest(game) == 2 and (not impoDetered):
restGameLables = [lable for lable in game.keys() if not game[lable].complete]
if (game[restGameLables[0]].hash() == 16) ^ (game[restGameLables[1]].hash() == 16):
game[restGameLables[(0 if game[restGameLables[0]].hash() == 16 else 1)]].impo = True
impoDetered = True
if rest(game) == 3:
nextStep = getNextStep(game[p2LastMove[0]], solutionSet2)
move(p2LastMove[0], nextStep)
print("Player 1: " + p2LastMove[0] + str(nextStep))
check(game)
cusPrint(game)
if rest(game) == 2 and (not impoDetered):
restGameLables = [lable for lable in game.keys() if not game[lable].complete]
if (game[restGameLables[0]].hash() == 16) ^ (game[restGameLables[1]].hash() == 16):
game[restGameLables[(0 if game[restGameLables[0]].hash() == 16 else 1)]].impo = True
impoDetered = True
elif rest(game) == 2:
if game[p2LastMove[0]].impo:
nextStep = getNextStep(game[p2LastMove[0]], solutionSet1)
move(p2LastMove[0], nextStep)
print("Player 1: " + p2LastMove[0] + str(nextStep))
check(game)
cusPrint(game)
else:
nextStep = getNextStep(game[p2LastMove[0]], solutionSet2)
move(p2LastMove[0], nextStep)
print("Player 1: " + p2LastMove[0] + str(nextStep))
check(game)
cusPrint(game)
else:
(restGameLable,) = [lable for lable in game.keys() if not game[lable].complete]
nextStep = getNextStep(game[restGameLable], solutionSet1)
move(restGameLable, nextStep)
print("Player 1: " + restGameLable + str(nextStep))
check(game)
cusPrint(game)
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment