Last active
December 23, 2019 18:39
-
-
Save slanterns/0ceb2833fdf5ee61329849928bdae4c9 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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