博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
348. Design Tic-Tac-Toe
阅读量:6941 次
发布时间:2019-06-27

本文共 4527 字,大约阅读时间需要 15 分钟。

题目:

Design a Tic-tac-toe game that is played between two players on a n x n grid.

You may assume the following rules:

A move is guaranteed to be valid and is placed on an empty block.

Once a winning condition is reached, no more moves is allowed.
A player who succeeds in placing n of their marks in a horizontal, vertical, or diagonal row wins the game.
Example:

Given n = 3, assume that player 1 is "X" and player 2 is "O" in the board.TicTacToe toe = new TicTacToe(3);toe.move(0, 0, 1); -> Returns 0 (no one wins)|X| | || | | |    // Player 1 makes a move at (0, 0).| | | |toe.move(0, 2, 2); -> Returns 0 (no one wins)|X| |O|| | | |    // Player 2 makes a move at (0, 2).| | | |toe.move(2, 2, 1); -> Returns 0 (no one wins)|X| |O|| | | |    // Player 1 makes a move at (2, 2).| | |X|toe.move(1, 1, 2); -> Returns 0 (no one wins)|X| |O|| |O| |    // Player 2 makes a move at (1, 1).| | |X|toe.move(2, 0, 1); -> Returns 0 (no one wins)|X| |O|| |O| |    // Player 1 makes a move at (2, 0).|X| |X|toe.move(1, 0, 2); -> Returns 0 (no one wins)|X| |O||O|O| |    // Player 2 makes a move at (1, 0).|X| |X|toe.move(2, 1, 1); -> Returns 1 (player 1 wins)|X| |O||O|O| |    // Player 1 makes a move at (2, 1).|X|X|X|

Follow up:

Could you do better than O(n2) per move() operation?

Hint:

Could you trade extra space such that move() operation can be done in O(1)?

You need two arrays: int rows[n], int cols[n], plus two variables: diagonal, anti_diagonal.

解答:

一开始其实就想到了hint, 作出了下面的解法:

public class TicTacToe {    int[][] grid;    int n;    /** Initialize your data structure here. */    public TicTacToe(int n) {        grid = new int[n][n];        this.n = n;    }        public boolean check(int row, int col, int len) {        boolean hori = true, verti = true, diag1 = true, diag2 = true;        //check horizontal        for (int i = 0; i < len - 1; i++) {            if (grid[row][i] != grid[row][i + 1]) {                hori = false;            }        }        //check vertical        for (int j = 0; j < len - 1; j++) {            if (grid[j][col] != grid[j + 1][col]) {                verti = false;            }        }        //check diagonals        if (row == col) {            for (int i = 0; i < len - 1; i++) {                if (grid[i][i] != grid[i + 1][i + 1]) {                    diag1 = false;                }            }        } else {            diag1 = false;        }                if (row + col == len - 1) {            for (int i = 0; i < len - 1; i++) {                if (grid[i][len - 1 - i] != grid[i + 1][len - 2 - i]) {                    diag2 = false;                }            }        } else {            diag2 = false;        }        return hori || verti || diag1 || diag2;    }        /** Player {player} makes a move at ({row}, {col}).        @param row The row of the board.        @param col The column of the board.        @param player The player, can be either 1 or 2.        @return The current winning condition, can be either:                0: No one wins.                1: Player 1 wins.                2: Player 2 wins. */    public int move(int row, int col, int player) {        grid[row][col] = player;        if (check(row, col, n)) return player;        return 0;    }}

这个解法冗余在check行个列的时候,每一次都要再扫一遍这一行这一列,所以如果只有两个player,可以把这两个player记作1, -1。当有一行完全只有这两个player中的其中一个人时,sum的绝对值应该等于这个数列的长度,这样就不需要每次再扫一遍数组。代码如下:

public class TicTacToe {    int[] rows, cols;    int diagonal, antiDiagonal;    int len;    /** Initialize your data structure here. */    public TicTacToe(int n) {        rows = new int[n];        cols = new int[n];        this.len = n;    }        /** Player {player} makes a move at ({row}, {col}).        @param row The row of the board.        @param col The column of the board.        @param player The player, can be either 1 or 2.        @return The current winning condition, can be either:                0: No one wins.                1: Player 1 wins.                2: Player 2 wins. */    public int move(int row, int col, int player) {        //Take player 1 and 2 as value of 1 and -1;        //Every time we only do adding, dont need to re-scan the whole line        int toAdd = player == 1 ? 1 : -1;        rows[row] += toAdd;        cols[col] += toAdd;        if (row == col) diagonal += toAdd;        if (row == len - 1 - col) antiDiagonal += toAdd;        if (Math.abs(rows[row]) == len || Math.abs(cols[col]) == len || Math.abs(diagonal) == len || Math.abs(antiDiagonal) == len) {            return player;        }        return 0;    }}

转载地址:http://otwnl.baihongyu.com/

你可能感兴趣的文章
VRRP协议介绍
查看>>
Android 监听wifi广播的两种方式
查看>>
我的友情链接
查看>>
Linux samba 只有访问权限,没有修改权限
查看>>
RAC Archive log写入错误的节点
查看>>
我的友情链接
查看>>
查询linux发行版本号方法总结
查看>>
4.入门第四课:javascript日期对象
查看>>
python 批量生产10万接入用户
查看>>
我的友情链接
查看>>
类和对象之分号推断
查看>>
jdbc详解:2、DriverManager管理多个数据库驱动
查看>>
Hibernate-annotation3.30 创建自定义注解,向oracle数据库写列注释
查看>>
同步助手让你的骑行生活“嗨”起来
查看>>
数据库
查看>>
centos下的php编译安装
查看>>
SQL注入语法类型
查看>>
mysql 单表备份脚本
查看>>
mongodb——安装mongodb监控管理工具使用*
查看>>
我的友情链接
查看>>