Here is finished code with an adaptive algorithm (so it learns from its mistakes). In answer to your question, I have used a canvas and create rectangles then bound a click to it.
DRAW_WEIGHT = 1 # The value for a round where there was a draw
COMPUTER_WIN_WEIGHT = 5 # The value for a round where there was a computer win
COMPUTER_LOSE_WEIGHT = -5 # The value for a round where there was a computer loss
LOG = True # Rounds be logged to improve move knowledge
import ctypes, math, threading, random, os, time, os.path
from tkinter import *
def end (mode, at = None):
global active, facts
active = False
if mode == 0: l.config (text = "Draw")
elif mode == 1:
if player == -1: l.config (text = "You lose")
else: l.config (text = "Player 1 wins")
else:
if player == -1: l.config (text = "Well done! You win!")
else: l.config (text = "Player 2 wins")
if player == -1:
log [-1].append (mode)
if LOG:
with open ("Learn.log", "w") as f: f.write ("\n".join ([" ".join ([str (j) for j in i]) for i in log]))
else:
with open ("Learn.log", "w") as f: f.write ("\n".join ([" ".join ([str (j) for j in i]) for i in log [ : -1]]))
if at:
if at [0] == 0: c.create_line (at [1] * 200 + 100, 0, at [1] * 200 + 100, 600, width = 5, fill = "blue")
elif at [0] == 1: c.create_line (0, at [1] * 200 + 100, 600, at [1] * 200 + 100, width = 5, fill = "blue")
elif at [0] == 2: c.create_line (0, 0, 600, 600, width = 5, fill = "blue")
else: c.create_line (600, 0, 0, 600, width = 5, fill = "blue")
c.create_text (300, 250, text = "Game Over", fill = "red", font = ("times", 75))
c.create_text (300, 325, text = "Click to play again", fill = "red", font = ("times", 30))
c.bind ("<Button-1>", restart)
def restart (event = None):
global places, player
c.delete (ALL)
places = [0 for i in range (9)]
for i in range (2): c.create_line (200 + 200 * i, 0, 200 + 200 * i, 600, width = 2)
for i in range (2): c.create_line (0, 200 + 200 * i, 600, 200 + 200 * i, width = 2)
if player == -1:
l.config (text = "Click on a square to go there")
c.bind ("<Button-1>", lambda event: threading.Thread (target = click, args = (event,)).start ())
else:
player = True
l.config (text = "Player 1's turn")
c.bind ("<Button-1>", lambda event: threading.Thread (target = p2click, args = (event,)).start ())
def check (mode = False):
toGo = (-1,)
for i in range (3):
now = [places [i + j * 3] for j in range (3)]
if now.count (1) == 3:
toGo = (0, i)
break
if toGo [0] == -1:
for i in range (3):
now = [places [j + i * 3] for j in range (3)]
if now.count (1) == 3:
toGo = (1, i)
break
if toGo [0] == -1:
now = [places [i + i * 3] for i in range (3)]
if now.count (1) == 3: toGo = (2,)
if toGo [0] == -1:
now = [places [2 + i * 3 - i] for i in range (3)]
if now.count (1) == 3: toGo = (3,)
if toGo [0] == -1:
for i in range (3):
now = [places [i + j * 3] for j in range (3)]
if now.count (2) == 3:
toGo = (0, i)
break
if toGo [0] == -1:
for i in range (3):
now = [places [j + i * 3] for j in range (3)]
if now.count (2) == 3:
toGo = (1, i)
break
if toGo [0] == -1:
now = [places [i + i * 3] for i in range (3)]
if now.count (2) == 3: toGo = (2,)
if toGo [0] == -1:
now = [places [2 + i * 3 - i] for i in range (3)]
if now.count (2) == 3: toGo = (3,)
if toGo [0] == -1:
if mode: end (0)
else: return True
else: end (1, toGo)
else: end (2, toGo)
return False
def click (event):
global log, active, facts
c.bind ("<Button-1>", lambda event: None)
start = time.clock ()
l.config (text = "Calculating...")
x, y = math.floor (event.x / 200), math.floor (event.y / 200)
if x == 3: x -= 1
if y == 3: y -= 1
if places [x + y * 3] == 0:
if places.count (0) == 9:
log.append ([x + y * 3])
active = True
else: log [-1].append (x + y * 3)
places [x + y * 3] = 1
c.create_line (x * 200 + 25, y * 200 + 25, x * 200 + 175, y * 200 + 175, width = 2)
c.create_line (x * 200 + 25, y * 200 + 175, x * 200 + 175, y * 200 + 25, width = 2)
toGo, movesChecked = -1, 0
if places.count (0) == 0: check (True)
else:
if check ():
for i in range (3):
movesChecked += 1
now = [places [i + j * 3] for j in range (3)]
if now.count (2) == 2 and now.count (0) == 1:
toGo = i + now.index (0) * 3
break
if toGo == -1:
for i in range (3):
movesChecked += 1
now = [places [j + i * 3] for j in range (3)]
if now.count (2) == 2 and now.count (0) == 1:
toGo = now.index (0) + i * 3
break
if toGo == -1:
movesChecked += 1
now = [places [i + i * 3] for i in range (3)]
if now.count (2) == 2 and now.count (0) == 1: toGo = now.index (0) + now.index (0) * 3
if toGo == -1:
movesChecked += 1
now = [places [2 + i * 3 - i] for i in range (3)]
if now.count (2) == 2 and now.count (0) == 1: toGo = 2 + now.index (0) * 3 - now.index (0)
if toGo == -1:
for i in range (3):
movesChecked += 1
now = [places [i + j * 3] for j in range (3)]
if now.count (1) == 2 and now.count (0) == 1:
toGo = i + now.index (0) * 3
break
if toGo == -1:
for i in range (3):
movesChecked += 1
now = [places [j + i * 3] for j in range (3)]
if now.count (1) == 2 and now.count (0) == 1:
toGo = now.index (0) + i * 3
break
if toGo == -1:
movesChecked += 1
now = [places [i + i * 3] for i in range (3)]
if now.count (1) == 2 and now.count (0) == 1: toGo = now.index (0) + now.index (0) * 3
if toGo == -1:
movesChecked += 1
now = [places [2 + i * 3 - i] for i in range (3)]
if now.count (1) == 2 and now.count (0) == 1: toGo = 2 + now.index (0) * 3 - now.index (0)
if toGo == -1:
useful = [0, 0, 0, 0, 0, 0, 0, 0, 0]
for rot in range (4):
for i in range (len (log) - 1):
movesChecked += 1
this = rotate (log [i], rot)
if len (log [i]) > len (log [-1]):
if log [-1] == this [ : len (log [-1])]:
if this [-1] == 0: value = DRAW_WEIGHT
elif this [-1] == 1: value = COMPUTER_WIN_WEIGHT
else: value = COMPUTER_LOSE_WEIGHT
useful [this [len (log [-1])]] += value
toGo = useful.index (max (useful))
while places [toGo] != 0:
movesChecked += 1
useful [toGo] = min (useful) - 1
toGo = useful.index (max (useful))
places [toGo] = 2
log [-1].append (toGo)
c.create_oval (toGo % 3 * 200 + 25, math.floor (toGo / 3) * 200 + 25, toGo % 3 * 200 + 175, math.floor (toGo / 3) * 200 + 175, width = 2)
facts = [round ((time.clock () - start) * 1000, 1), movesChecked]
facts.append (round (facts [1] / facts [0]))
if check ():
l.config (text = "Your turn")
c.bind ("<Button-1>", lambda event: threading.Thread (target = click, args = (event,)).start ())
else:
l.config (text = "This square has already been taken.")
c.bind ("<Button-1>", lambda event: threading.Thread (target = click, args = (event,)).start ())
def nerdyFacts ():
t = Toplevel ()
t.focus_force ()
t.resizable (False, False)
if os.path.isfile ("icon.ico"): t.iconbitmap ("icon.ico")
if len (facts) > 0: Label (t, text = "Just a few facts about the last move should you wish to know them:\n%sms taken to process request\n%s possible moves checked\n%s moves checked per ms" % tuple (facts)).pack ()
else: Label (t, text = "No facts to display.").pack ()
def rotate (data, mode):
if mode == 0: replace = [i for i in range (9)]
elif mode == 1: replace = [2, 5, 8, 1, 4, 7, 0, 3, 6]
elif mode == 2: replace = [8, 7, 6, 5, 4, 3, 2, 1, 0]
else: replace = [6, 3, 0, 7, 4, 1, 8, 5, 2]
return [replace [i] for i in data [ : -1]] + [data [-1]]
def remove ():
global log
if ctypes.windll.user32.MessageBoxW (0, "Do you really want to delete all of my data.\nIn doing so, I will not be able to make such informed moves.\nOn average, I say it takes about 20 rounds for me to start getting better.\nThis is only recommended if the program takes a long time to make moves.", "Naughts and crosses", 4) == 6:
if active: del log [ : -1]
else: log = []
with open ("Learn.log", "w") as f: f.write ("")
t.destroy ()
ctypes.windll.user32.MessageBoxW (0, "Data reset.", "Naughts and crosses", 0)
def p2click (event):
global player
x, y = math.floor (event.x / 200), math.floor (event.y / 200)
if x == 3: x -= 1
if y == 3: y -= 1
if places [x + y * 3] == 0:
places [x + y * 3] = int (player) + 1
if player:
c.create_line (x * 200 + 25, y * 200 + 25, x * 200 + 175, y * 200 + 175, width = 2)
c.create_line (x * 200 + 25, y * 200 + 175, x * 200 + 175, y * 200 + 25, width = 2)
else: c.create_oval (x * 200 + 25, y * 200 + 25, x * 200 + 175, y * 200 + 175, width = 2)
l.config (text = "Player %s's turn" % str (int (player) + 1))
player = not player
if places.count (0) == 0: check (True)
else: check ()
def start (players):
global player
if players == 1:
player = -1
t = Label (root, text = "Data information", font = ("times", 12))
t.pack ()
t.bind ("<Button-1>", lambda event: threading.Thread (target = dataLog).start ())
else: player = True
restart ()
def dataLog ():
global t
t = Toplevel ()
t.resizable (False, False)
t.focus_force ()
if os.path.isfile ("icon.ico"): t.iconbitmap ("icon.ico")
if active: l = log [ : -1]
else: l = log
if len (l) == 0: Label (t, text = "I have no data to analyse.\nTherefore, I cannot display any extra information.").pack ()
else:
wins, loses, draws = 0, 0, 0
for i in l:
if i [-1] == 0: draws += 1
elif i [-1] == 1: loses += 1
else: wins += 1
wins, loses, draws = round (wins * 100 / len (l)), round (loses * 100 / len (l)), round (draws * 100 / len (l))
last = math.ceil (len (l) / 2)
last_wins, last_loses, last_draws = 0, 0, 0
if last > 50: last = 50
for i in l [len (l) - last : ]:
if i [-1] == 0: last_draws += 1
elif i [-1] == 1: last_loses += 1
else: last_wins += 1
last_wins, last_loses, last_draws = round (last_wins * 100 / last), round (last_loses * 100 / last), round (last_draws * 100 / last)
Label (t, text = "I have %s round/s of data to analyse.\n(%s virtual rounds)\n\nOf these:\n%s%s are user wins\n%s%s are computer wins\n%s%s are draws\n\nIn the last %s round/s:\n%s%s are user wins\n%s%s are computer wins\n%s%s are draws\n" % (len (l), len (l) * 4, wins, "%", loses, "%", draws, "%", last, last_wins, "%", last_loses, "%", last_draws, "%")).pack ()
Button (t, text = "Clear data", command = lambda: threading.Thread (target = remove).start ()).pack ()
active, facts = False, ()
if os.path.isfile ("Learn.log"):
with open ("Learn.log") as f:
read = f.read ()
if read != "": log = [[int (j) for j in i.split (" ")] for i in read.split ("\n")]
else: log = []
else: log = []
try: ctypes.windll.shcore.SetProcessDpiAwareness (True)
except: pass
root = Tk ()
root.title ("Naughts and crosses")
root.resizable (False, False)
if os.path.isfile ("icon.ico"): root.iconbitmap ("icon.ico")
l = Label (root, text = "", font = ("times", 20))
l.bind ("<Button-1>", lambda event: nerdyFacts ())
l.pack ()
c = Canvas (root, width = 600, height = 600, bg = "white")
c.pack ()
c.create_text (300, 200, text = "How many players are there?", font = ("times", 30))
p1 = (c.create_rectangle (150, 350, 250, 450, fill = "blue"),
c.create_text (200, 400, text = "1", font = ("times", 40), fill = "red"))
p2 = (c.create_rectangle (350, 350, 450, 450, fill = "red"),
c.create_text (400, 400, text = "2", font = ("times", 40), fill = "blue"))
for i in p1: c.tag_bind (i, "<ButtonRelease-1>", lambda event: start (1))
for i in p2: c.tag_bind (i, "<ButtonRelease-1>", lambda event: start (2))
root.mainloop ()
In general, I say it should take you playing about 50 matches before it gets better (or you can use the data below which is rounds I have played and save it to a file called learn.log
):
1 0 7 4 8 6 2 3 1
3 2 0 6 4 5 8 2
3 2 0 6 4 5 8 2
3 2 0 6 4 5 8 2
3 2 0 6 4 5 8 2
3 2 0 6 4 5 8 2
3 2 0 6 4 5 8 2
3 2 0 6 4 5 8 2
3 2 0 6 4 5 8 2
3 2 0 6 4 5 8 2
3 2 0 6 4 5 8 2
3 2 0 6 4 5 8 2
3 2 0 6 4 5 8 2
1 0 8 2 7 4 6 2
1 0 8 3 6 7 2 5 4 2
1 2 6 0 7 4 8 2
1 3 6 0 7 4 8 2
4 0 8 1 2 5 6 2
8 0 2 5 4 6 3 1 7 0
3 0 7 1 2 4 8 5 6 2
0 1 4 8 6 3 2 2
0 2 8 4 6 3 7 2
0 3 4 8 2 1 6 2
0 4 8 1 7 6 2 5 3 0
0 4 3 6 2 1 7 5 8 0
8 0 2 5 6 7 4 2
8 1 4 0 2 5 6 2
8 2 0 4 6 3 7 2
8 3 4 0 6 7 2 2
8 4 0 1 7 6 2 5 3 0
8 4 2 5 3 0 1 6 7 0
8 4 0 1 7 6 2 5 3 0
8 4 6 7 1 0 2 5 3 0
8 4 1 0 6 7 2 5 3 0
0 4 8 1 7 6 2 5 3 0
0 4 8 1 7 6 2 5 3 0
0 4 2 1 7 3 6 5 1
1 4 0 2 6 3 8 5 1
6 0 2 4 8 5 7 2
2 0 4 6 3 5 8 1 7 0
2 0 6 4 8 5 7 2
2 1 4 6 8 5 7 0 3 0
2 1 4 6 8 5 0 2
2 3 4 6 0 1 8 2
2 4 0 1 7 3 5 8 6 0
2 4 5 8 0 1 7 3 6 0
2 4 1 0 8 5 6 3 1
2 4 6 0 8 5 7 2
2 4 6 1 7 8 5 0 1
2 4 6 1 7 8 0 3 5 0
2 4 6 1 7 8 0 3 5 0
6 1 4 2 0 3 8 2
6 2 8 7 0 3 4 2
6 3 4 2 8 7 0 2
6 4 7 8 0 3 2 5 1
6 4 3 0 8 7 1 2 5 0
6 4 2 0 8 5 7 2
6 4 2 1 7 8 5 0 1
6 4 2 1 7 8 0 3 5 0
8 4 0 1 7 6 2 5 3 0
4 1 2 6 8 5 0 2
4 2 6 0 1 7 8 3 5 0
2 4 7 0 8 5 6 2
4 2 6 0 1 7 3 5 8 0
2 4 7 1 8 5 6 2
2 5 3 0 7 1 6 8 4 2
0 4 7 1 6 3 8 2
8 4 3 0 6 7 1 2 5 0
7 0 2 1 8 5 6 2
0 4 7 2 6 3 8 2
3 1 8 0 2 5 6 7 4 2
7 1 2 0 8 5 6 2
3 2 8 0 1 4 6 7 5 0
2 6 0 1 3 4 7 5 8 0
1 4 3 0 8 2 6 7 5 0
3 2 8 0 7 1 1
1 4 5 0 8 2 6 7 3 0
3 2 8 0 4 1 1
0 5 4 8 2 1 6 2
4 2 0 8 5 3 7 1 6 0
8 4 3 0 2 5 6 7 1 0
3 2 5 4 7 6 1
6 4 5 0 8 2 7 2
6 4 8 7 2 1 1
1 4 5 0 8 2 6 7 3 0
3 2 7 0 1 4 6 8 1
7 2 3 0 4 1 1
1 4 3 0 8 2 6 7 5 0
7 2 0 1 6 3 8 2
0 6 5 1 4 3 8 2
4 2 6 0 1 7 3 5 8 0
8 4 3 0 5 2 6 1 1
4 2 0 8 5 3 7 1 6 0
6 4 5 1 7 8 0 3 2 0
2 6 8 5 4 0 3 1 7 0
3 2 8 0 4 1 1
4 2 8 0 1 7 3 5 6 0
1 4 8 0 2 5 3 6 7 0
0 7 5 1 4 3 8 2
1 4 6 0 8 7 5 2 3 0
2 6 7 0 3 1 5 8 4 2
2 7 4 6 8 5 0 2
2 8 7 0 4 1 6 2
1 4 6 0 8 7 5 2 3 0
4 2 7 1 0 8 6 5 1
1 4 6 0 8 7 2 5 3 0
7 2 0 3 8 6 4 2
0 8 2 1 7 3 6 4 5 0
1 4 6 0 8 7 2 5 3 0
0 8 1 2 5 3 7 4 6 0
0 8 7 1 4 2 5 3 6 0
0 8 4 1 6 3 2 2
0 4 8 1 7 6 2 5 3 0
5 0 3 4 8 2 1 6 1
1 4 5 0 8 2 6 7 3 0
3 2 5 4 6 0 1 8 1
3 2 5 4 6 0 1 8 1
4 2 5 3 0 8 7 1 6 0
0 4 8 1 7 6 2 5 3 0
4 2 0 8 5 3 6 1 7 0
0 4 8 1 7 6 2 5 3 0
0 4 8 1 7 6 2 5 3 0
0 4 6 3 5 1 7 8 2 0
0 4 5 1 7 2 6 3 8 2
0 4 5 2 6 3 8 7 1 0
0 4 5 2 6 3 7 8 1 0
0 4 8 1 7 6 2 5 3 0
0 4 5 2 1 6 1
3 2 8 0 1 4 6 7 5 0
5 0 6 1 2 8 4 2
5 0 6 2 1 3 7 4 8 2
3 2 8 0 1 4 6 7 5 0
5 1 0 2 6 3 8 7 4 2
0 4 8 1 7 6 2 5 3 0
5 6 0 8 7 4 3 2 1
5 6 0 8 7 4 2 1 3 0
5 6 2 8 7 0 3 4 1
7 0 2 6 3 4 8 5 1 0
6 4 8 7 1 2 3 0 5 0
5 6 1 8 7 4 0 2 1
4 0 8 6 3 5 1 7 2 0
2 4 0 1 7 6 3 8 5 0
4 0 2 6 3 5 1 7 8 0
0 4 8 1 7 6 2 5 3 0
4 0 2 6 3 5 8 1 7 0
4 0 6 2 1 7 5 3 8 0
5 6 0 8 7 4 2 1 3 0
6 4 8 7 1 2 0 3 5 0
0 4 6 3 5 8 1 2 7 0
0 4 8 1 7 6 2 5 3 0
6 4 3 0 8 7 1 2 5 0
1 8 6 2 5 4 0 3 7 0
1 8 4 7 6 2 5 3 0 0
0 4 8 1 7 6 2 5 3 0
4 0 6 2 1 7 8 3 5 0
4 0 1 7 2 6 8 3 1
4 0 2 6 3 5 8 1 7 0
4 0 8 6 3 5 2 7 1 0
0 4 8 1 7 6 2 5 3 0
4 0 3 5 2 6 8 1 7 0
4 0 6 2 1 7 8 3 5 0
0 4 1 2 6 3 8 5 1
0 4 2 1 7 3 5 8 6 0
0 4 1 2 6 3 8 5 1
0 4 1 2 6 3 5 8 7 0
5 6 4 3 0 8 7 1 2 0
0 4 1 2 6 3 5 8 7 0
0 4 2 1 7 3 5 8 6 0
0 4 5 2 6 3 8 7 1 0
0 4 3 6 2 1 7 5 8 0
0 4 7 5 3 6 2 1 8 0
0 4 2 1 7 3 5 8 6 0
0 4 8 1 7 6 2 5 3 0
4 0 8 6 3 5 2 7 1 0
4 0 6 2 1 7 8 3 5 0
4 0 1 7 3 5 8 2 6 0
8 4 0 7 1 2 6 3 5 0
0 4 1 2 6 3 5 8 7 0
0 4 2 1 7 3 5 8 6 0
4 0 6 2 1 7 5 3 8 0
0 4 1 2 6 3 5 8 7 0
6 4 2 3 5 8 0 1 7 0
4 0 1 7 2 6 8 3 1
0 4 8 1 7 6 2 5 3 0
8 4 0 7 1 2 6 3 5 0
0 4 8 1 7 6 2 5 3 0
4 0 8 6 3 5 2 7 1 0
0 4 5 2 6 3 8 7 1 0
6 4 5 1 7 8 0 3 2 0
3 2 8 0 1 4 6 7 5 0
4 0 8 6 3 5 1 7 2 0
6 4 1 0 8 7 2 5 3 0
7 0 2 6 3 4 8 5 1 0
4 0 8 6 3 5 7 1 2 0
4 0 6 2 1 7 8 3 5 0
0 4 6 3 5 8 2 1 7 0
0 4 5 2 6 3 7 8 1 0
4 0 1 7 8 2 5 3 6 0
3 2 4 5 8 0 6 1 1
4 0 8 6 3 5 2 7 1 0
4 0 1 7 2 6 3 8 1
8 4 0 7 1 2 5 6 1
3 2 1 0 7 4 5 8 1
3 2 0 6 8 4 1
3 4 0 6 2 1 7 5 8 0
3 4 2 6 8 5 0 1 7 0
3 4 6 0 2 8 1
4 0 1 7 3 5 2 6 8 0
3 4 6 0 7 8 1
2 4 6 5 3 0 1 8 1
3 4 2 6 0 1 7 8 5 0
3 4 2 6 8 5 0 1 7 0
3 4 7 6 2 0 8 5 1 0
1 4 2 0 8 5 3 7 6 0
4 0 1 7 2 6 3 8 1
4 0 8 6 3 5 1 7 2 0
0 4 8 1 7 6 2 5 3 0
0 4 1 2 6 3 5 8 7 0
5 4 3 0 8 2 6 1 1
5 4 3 0 8 2 1 6 1
5 4 0 2 6 3 8 7 1 0
7 4 0 8 1 2 6 5 1
4 0 8 6 3 5 1 7 2 0
0 4 8 1 7 6 2 5 3 0
1 4 7 6 2 0 3 8 1
1 4 0 2 6 3 5 7 8 0
0 4 8 1 7 6 2 5 3 0
0 4 1 2 6 3 5 8 7 0
3 4 1 6 5 2 1
3 4 1 6 2 0 8 5 7 0
8 4 2 5 3 0 1 6 7 0
3 4 0 6 1 2 1
3 4 1 6 2 0 8 5 7 0
1 4 7 6 2 0 8 3 1
1 4 6 0 8 7 3 2 5 0
4 0 1 7 6 2 5 3 8 0
1 4 5 0 7 8 1
1 4 5 0 8 2 6 7 3 0
5 4 1 2 6 8 0 3 7 0
0 4 2 1 7 3 5 8 6 0
4 0 1 7 2 6 8 3 1
4 0 1 7 6 2 3 5 8 0
0 4 8 1 7 6 2 5 3 0
7 4 1 2 6 8 5 0 1
4 0 1 7 8 2 5 3 6 0
0 4 1 2 6 3 5 8 7 0
4 0 1 7 3 5 2 6 8 0
4 0 1 7 2 6 3 8 1
4 0 8 6 3 5 1 7 2 0
4 0 1 7 6 2 5 3 8 0
4 0 6 2 1 7 5 3 8 0
0 4 2 1 7 3 5 8 6 0
0 4 6 3 2 5 1
2 4 6 5 3 0 8 7 1 0
4 0 1 7 2 6 8 3 1
4 0 2 6 3 5 8 1 7 0
0 4 8 1 7 6 2 5 3 0
3 4 5 8 1 0 1
2 4 5 8 0 1 7 6 3 0
7 4 8 6 5 2 1
4 0 6 2 1 7 5 3 8 0
5 4 8 2 6 7 1 3 0 0
4 0 3 5 7 1 8 2 1
4 0 2 6 3 5 8 1 7 0
0 4 1 2 6 3 5 8 7 0
4 0 1 7 2 6 8 3 1
0 4 6 3 5 8 1 2 7 0
0 4 3 6 2 1 8 7 1
0 4 3 6 2 1 7 5 8 0
3 4 1 6 8 2 1
3 4 1 6 2 0 8 5 7 0
3 4 0 6 2 1 7 5 8 0
4 0 1 7 6 2 3 5 8 0
0 4 1 2 6 3 8 5 1
0 4 1 2 6 3 5 8 7 0
0 4 1 2 6 3 5 8 7 0
0 4 1 2 5 6 1
0 4 1 2 6 3 5 8 7 0
4 0 1 7 2 6 8 3 1
4 0 2 6 3 5 1 7 8 0
0 4 1 2 6 3 5 8 7 0
1 4 0 2 6 3 5 7 8 0
2 4 1 0 8 5 3 7 6 0
4 0 1 7 2 6 8 3 1
8 4 0 7 1 2 6 3 5 0
4 0 1 7 2 6 8 3 1
4 0 1 7 6 2 8 3 5 0
4 0 1 7 3 5 6 2 8 0
4 0 6 2 1 7 8 3 5 0
4 0 1 7 2 6 8 3 1
4 0 2 6 3 5 1 7 8 0
4 0 1 7 6 2 3 5 8 0
4 0 3 5 7 1 2 6 8 0
0 4 8 1 7 6 5 2 1
6 4 0 3 2 5 1
2 4 0 1 7 6 5 8 3 0
2 4 0 1 7 6 8 5 3 0
0 4 8 1 7 6 2 5 3 0
1 4 7 6 2 0 3 8 1
5 4 1 2 3 6 1
5 4 1 2 6 8 0 3 7 0
0 4 1 2 6 3 5 8 7 0
0 4 1 2 6 3 5 8 7 0
1 4 0 2 5 6 1