import java.util.Scanner;

public class TicTacToe_005 {
	public static void main(String[] arg) {
		char[][] board = {{'#','#','#'},
				{'#','#','#'},
				{'#','#','#'}};

		Scanner in = new Scanner(System.in);

		boolean turn = false; // If turn = true here the computer will move first; otherwise it will move second.
		boolean draw = false;
		boolean win = false;

		printBoard(board);
		Move m = null;
		while(true) {
			
			if (turn) {
				m = computer_move2(board, m);
			}
			else {
				m = new Move(in.nextInt(), in.nextInt());
				while (!isValidMove(board, m)) {
					m.row = in.nextInt();
					m.col = in.nextInt();
				}
			}
			board[m.row][m.col] = (turn ? 'x' : 'o');

			printBoard(board);

			if (win(board, m)) {
				win = true;
				break;
			}
			if (draw(board)) {
				draw = true;
				break;
			}
			turn = !turn;
		}
		if (draw) System.out.println("draw");
		if (win) System.out.println((turn ? "x" : "o") + " wins!");
	}

	public static void resetBoard(char[][] board) {
		for (int row = 0; row < 3; row++) {
			for (int col = 0; col < 3; col++) {
				board[row][col] = '#';
			}
		}
	}

	public static void printArray(char[][] a) {
		for (int row = 0; row < 3; row++) {
			for (int col = 0; col < 3; col++) {
				System.out.print(a[row][col] + " ");
			}
			System.out.println();
		}
	}

	public static void printBoard(char[][] board) {
		System.out.println();
		printArray(board);
		System.out.println();
	}

	public static Move computer_move(char[][] board) {
		Move m = new Move(1,1);
		while (!isValidMove(board, m)) {
			m.row = (int)(Math.random() * 3);
			m.col = (int)(Math.random() * 3);
		}
		return m;
	}

	public static Move computer_move2(char[][] board, Move pm) {
		char[][] boardCopy = copyBoard(board);
		Move m = new Move(1,1);

		if (pm == null) return m;  // Save some time, if we are the first player.

		char otherPlayer = board[pm.row][pm.col];
		char player = (otherPlayer == 'x' ? 'o' : 'x');
		
		// 1. Do I have 2 in a row?
		for (int row = 0; row < 3; row++) {
			for (int col = 0; col < 3; col++) {
				if (boardCopy[row][col] == '#') {
					boardCopy[row][col] = player;
					m.row = row;
					m.col = col;
					if (win(boardCopy, m)) {
						return m;
					}
					else {
						boardCopy[row][col] = '#';
					}
				}
				else {
					continue;
				}
			}
		}
		// 2. Does my opponent have 2 in a row?
		for (int row = 0; row < 3; row++) {
			for (int col = 0; col < 3; col++) {
				if (boardCopy[row][col] == '#') {
					boardCopy[row][col] = otherPlayer;
					m.row = row;
					m.col = col;
					if (win(boardCopy, m)) {
						return m;
					}
					else {
						boardCopy[row][col] = '#';
					}
				}
				else {
					continue;
				}
			}
		}
		// 3. Can I fork my opponent?
		for (int row = 0; row < 3; row++) {
			for (int col = 0; col < 3; col++) {
				if (boardCopy[row][col] == '#') {
					boardCopy[row][col] = player;
					if (twoInARows(boardCopy, player) > 1) {
						m.row = row;
						m.col = col;
						return m;
					}
					else {
						boardCopy[row][col] = '#';
					}
				}
				else {
					continue;
				}
			}
		}
		// 4. Can my opponent fork me?
		int n_forks = 0;
		for (int row = 0; row < 3; row++) {
			for (int col = 0; col < 3; col++) {
				if (boardCopy[row][col] == '#') {
					boardCopy[row][col] = otherPlayer;
					if (twoInARows(boardCopy, otherPlayer) > 1) {
						n_forks++;
						m.row = row;
						m.col = col;
					}
					boardCopy[row][col] = '#';
				}
				else {
					continue;
				}
			}
		}
		if (n_forks == 1) {
			// There is only one possible fork for the opponent, so block it directly.
			return m;
		}
		else if (n_forks == 2) {
			// Force the opponent to block and not create a fork.
			if (board[0][1] == '#') {
				m.row = 0;
				m.col = 1;
			}
			else if (board[1][0] == '#') {
				m.row = 1;
				m.col = 0;
			}
			else if (board[1][2] == '#') {
				m.row = 1;
				m.col = 2;
			}
			return m;
		}
		else if (n_forks > 2) {
			// Force the opponent to block and not create a fork.
			// *** Remember to search for an open corner if you modify the algorithm to possibly choose 0,2 on its first move. ***
			m.row = 0;
			m.col = 2;  
			return m;
		}

		// 5. Is the center open?

		// 6. Did my opponent move in a corner?  If so, move in the opposite corner.
		
		// 7. Is there an empty corner?

		// 8. Otherwise, move on a side middle.

		return computer_move(board);  // Once all 8 rules are implemented, this won't happen.
	}

	public static boolean isValidMove(char[][] board, Move m) {
		boolean valid = true;
		if (m.row > 2 || m.row < 0) valid = false;
		if (m.col > 2 || m.col < 0) valid = false;
		if (board[m.row][m.col] != '#') valid = false;
		return valid;
	}

	public static boolean draw(char[][] board) {
		boolean draw = true;
		for (char[] row : board) {
			for (char c : row) {
				if (c == '#') draw = false;
			}
		}
		return draw;
	}

	public static boolean win(char[][] board, Move m) {
		boolean win = false;

		// Check for a vertical win
		if (board[m.row][m.col] == board[(m.row + 1) % 3][m.col] && 
				board[m.row][m.col] == board[(m.row + 2) % 3][m.col]) 
			return true;

		// Check for a horizontal win
		if (board[m.row][m.col] == board[m.row][(m.col + 1) % 3] && 
				board[m.row][m.col] == board[m.row][(m.col + 2) %3 ]) 
			return true;

		// Check for a main diagonal win
		if (m.row == m.col) {
			if (board[m.row][m.col] == board[(m.row + 1) % 3][(m.col + 1) % 3] && 
					board[m.row][m.col] == board[(m.row + 2) % 3][(m.col + 2) % 3])
				return true;
		}

		// Check for other diagonal win
		if (m.col == 2 - m.row) {
			if (board[m.row][m.col] == board[(m.row + 1) % 3][(m.col + 2) % 3] && 
					board[m.row][m.col] == board[(m.row + 2) % 3][(m.col + 4) % 3])
				return true;
		}
		return win;
	}

	public static int twoInARows(char[][] board, char player) {
		char[][] boardCopy = copyBoard(board);
		Move m = new Move(1,1);

		int twoInARows = 0;

		for (int row = 0; row < 3; row++) {
			for (int col = 0; col < 3; col++) {
				if (boardCopy[row][col] == '#') {
					boardCopy[row][col] = player;
					m.row = row;
					m.col = col;
					if (win(boardCopy, m)) {
						twoInARows++;
					}
					boardCopy[row][col] = '#';
				}
				else {
					continue;
				}
			}
		}

		return twoInARows;
	}
	
	public static char[][] copyBoard(char[][] b) {
		char[][] a = new char[3][3];
		for (int row = 0; row < 3; row++) {
			for (int col = 0; col < 3; col++) {
				a[row][col] = b[row][col];
			}
		}
		return a;
	}
}