import tensorflow as tf import matplotlib.pyplot as plt import csv import random import numpy as np #井字棋的打印函数 def print_board(board): symbols = ['O',' ','X','N'] board_plus1 = [int(x) + 1 for x in board] print(' ' + symbols[board_plus1[0]] + ' | ' + symbols[board_plus1[1]] + ' | ' + symbols[board_plus1[2]]) print('___________') print(' ' + symbols[board_plus1[3]] + ' | ' + symbols[board_plus1[4]] + ' | ' + symbols[board_plus1[5]]) print('___________') print(' ' + symbols[board_plus1[6]] + ' | ' + symbols[board_plus1[7]] + ' | ' + symbols[board_plus1[8]]) #变化之后的棋盘 以及最佳落子点 通过旋转棋盘 得到对应的图形记录 def get_symmetry(board, response, transformation): if transformation == 'rotate180': new_response = 8 - response return(board[::-1], new_response) elif transformation == 'rotate90': new_response = [6, 3, 0, 7, 4, 1, 8, 5, 2].index(response) tuple_board = list(zip(*[board[6:9], board[3:6], board[0:3]])) return([value for item in tuple_board for value in item], new_response) elif transformation == 'rotate270': new_response = [2, 5, 8, 1, 4, 7, 0, 3, 6].index(response) tuple_board = list(zip(*[board[0:3], board[3:6],board[6:9]]))[::-1] return([value for item in tuple_board for value in item], new_response) elif transformation == 'flip_v': new_response = [6, 7, 8, 3, 4, 5, 0, 1, 2].index(response) return(board[6:9] + board[3:6] + board[0:3], new_response) elif transformation == 'flip_h': # flip_h = rotate180, then flip_v new_response = [2, 1, 0, 5, 4, 3, 8, 7, 6].index(response) new_board = board[::-1] return(new_board[6:9] + new_board[3:6] + new_board[0:3],new_response) else: raise ValueError('Method not implmented.') #加载文件中的棋盘和最佳落子点数据,并保存成元组 moves = [] def get_moves_from_csv(csv_file): with open(csv_file, 'rt') as csvfile: reader = csv.reader(csvfile, delimiter=',') for row in reader: moves.append(([int(x) for x in row[0:9]], int(row[9]))) return (moves) #写入文件 获取一种最优解 得到变形后的其余几种 都存入数据表中 def wrrite_moves_from_csv(csv_file,data): moves=get_moves_from_csv(csv_file) with open(csv_file,'a+',newline='') as csvfile: writer = csv.writer(csvfile,lineterminator=' ') allmoves=get_other_move(data) allmoves=[ x for x in allmoves if (x[0:-1],x[-1]) not in moves] writer.writerows(allmoves) def get_other_move(data): possible_transforms = ['rotate90', 'rotate180', 'rotate270', 'flip_v', 'flip_h'] otherMoves=[] for transform in possible_transforms: (board, response) = get_symmetry(data[0:-1], data[-1], transform) new=board+[response] new=list(map(lambda x:int(x),new)) otherMoves.append(new) return otherMoves #返回一个随机变换棋盘和落子点 def get_rand_move(moves): # This function performs random transformations on a board. #(board, response) = random.choice(moves) possible_transforms = ['rotate90', 'rotate180', 'rotate270', 'flip_v', 'flip_h'] fourBoards=[] #random_transform = random.choice(possible_transforms) for board,response in moves: for transform in possible_transforms: (board, response) = get_symmetry(board, response, transform) fourBoards.append((board, response)) return fourBoards sess = tf.Session() moves = get_moves_from_csv('base_tic_tac_toe_moves.csv') batch_size = 100 train_length = 100 train_set = [] train_set=moves*train_length #设置测试集 训练集 测试集最优为6 test_board = [0, 0, -1, 1, -1, -1, 0, 0, 1] train_set = [x for x in train_set if x[0] != test_board] #创建init_weights()函数和model()函数,分别实现初始化模型变量和模型操作 def init_weights(shape): return(tf.Variable(tf.random_normal(shape))) def model(X, A1, A2, bias1, bias2): layer1 = tf.nn.sigmoid(tf.add(tf.matmul(X, A1), bias1)) layer2 = tf.add(tf.matmul(layer1, A2), bias2) return(layer2) #声明占位符、变量和模型 X = tf.placeholder(dtype=tf.float32, shape=[None, 9]) Y = tf.placeholder(dtype=tf.int32, shape=[None]) A1 = init_weights([9, 81]) bias1 = init_weights([81]) A2 = init_weights([81, 9]) bias2 = init_weights([9]) model_output = model(X, A1, A2, bias1, bias2) #声明算法模型的损失函数,该函数是最后输出的逻辑变换的平均softmax值 #由之前的概率值转化为对应的预测label的索引 loss = tf.reduce_mean(tf.nn.sparse_softmax_cross_entropy_with_logits( logits=model_output,labels=Y)) train_step = tf.train.GradientDescentOptimizer(0.025).minimize(loss) prediction = tf.argmax(model_output, 1) # Initialize variables init = tf.initialize_all_variables() sess.run(init) loss_vec = [] for i in range(10000): # Select random indices for batch rand_indices = np.random.choice(range(len(train_set)), batch_size, replace=False) # Get batch batch_data = [train_set[i] for i in rand_indices] x_input = [x[0] for x in batch_data] y_target = np.array([y[1] for y in batch_data]) # Run training step sess.run(train_step, feed_dict={X: x_input, Y: y_target}) # Get training loss temp_loss = sess.run(loss, feed_dict={X: x_input, Y: y_target}) loss_vec.append(temp_loss) if i%1000==0: print('iteration ' + str(i) + ' Loss: ' + str(temp_loss)) test_boards = [test_board] feed_dict = {X: test_boards} logits = sess.run(model_output, feed_dict=feed_dict) #print(logits) predictions = sess.run(prediction, feed_dict=feed_dict) print_board(test_board) print(predictions) #人机对局监测 #检测函数 游戏是否结束 def check(board): wins = [[0, 1, 2], [3, 4, 5], [6, 7, 8], [0, 3, 6], [1, 4, 7], [2, 5, 8], [0, 4, 8], [2, 4, 6]] for i in range(len(wins)): if board[wins[i][0]] == board[wins[i][1]] == board[wins[i][2]] == 1.: return (1) elif board[wins[i][0]] == board[wins[i][1]] == board[wins[i][2]] == -1.: return (1) return (0) #初始化棋盘 game_tracker = [0, 0, 0, 0, 0, 0, 0, 0, 0] win_logical = False num_moves = 0 #实时面板登记 tempBoard=[] while not win_logical: player_index = input('Input index of your move (0-8): ') # 记录用户操作 tempBoard.append(game_tracker + [int(player_index)]) #步数 num_moves += 1 # Add player move to game try: game_tracker[int(player_index)] = 1. except: print('不合法的输入') continue # Get model's move by first getting all the logits for each index [potential_moves] = sess.run(model_output, feed_dict={X:[game_tracker]}) # Now find allowed moves (where game tracker values = 0.0) allowed_moves = [ix for ix,x in enumerate(game_tracker) if x==0] # Find best move by taking argmax of logits if they are in allowed moves model_move = np.argmax([x if ix in allowed_moves else -999 for ix,x in enumerate(potential_moves)]) # Add model move to game game_tracker[int(model_move)] = -1. print('Model has moved') print_board(game_tracker) # Now check for win or too many moves if check(game_tracker)==1 or num_moves>=5: print('Game Over!') if check(game_tracker)==1: wrrite_moves_from_csv('base_tic_tac_toe_moves.csv', tempBoard[-2]) wrrite_moves_from_csv('base_tic_tac_toe_moves.csv',tempBoard[-1]) conKey = input('Input 1 to end this game ') if conKey== "1": win_logical = True game_tracker = [0, 0, 0, 0, 0, 0, 0, 0, 0] tempBoard = [] num_moves=0