携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第 18 天,点击查看活动详情
井字游戏
原题地址
设计一个算法,判断玩家是否赢了井字游戏。输入是一个 N x N 的数组棋盘,由字符 " ","X" 和 "O" 组成,其中字符 " " 代表一个空位。
以下是井字游戏的规则:
- 玩家轮流将字符放入空位(
" ")中。 - 第一个玩家总是放字符
"O",且第二个玩家总是放字符"X"。 "X"和"O"只允许放置在空位中,不允许对已放有字符的位置进行填充。- 当有N个相同(且非空)的字符填充任何行、列或对角线时,游戏结束,对应该字符的玩家获胜。
- 当所有位置非空时,也算为游戏结束。
- 如果游戏结束,玩家不允许再放置字符。
- 如果游戏存在获胜者,就返回该游戏的获胜者使用的字符("X"或"O");如果游戏以平局结束,则返回 "Draw";如果仍会有行动(游戏未结束),则返回 "Pending"。
示例 1:
输入: board = ["O X"," XO","X O"]
输出: "X"
示例 2:
输入: board = ["OOX","XXO","OXO"]
输出: "Draw"
解释: 没有玩家获胜且不存在空位
示例 3:
输入: board = ["OOX","XXO","OX "]
输出: "Pending"
解释: 没有玩家获胜且仍存在空位
提示:
1 <= board.length == board[i].length <= 100- 输入一定遵循井字棋规则
思路分析
- 分析题目,可以得知,若 行、列或者对角线有相同的
X或者O,则说明一方胜利;否则若还有空格,则为Pending,若没有空格则为平局Draw; - 处理行:因为数组中是字符串,因此处理行的时候,只需要判断每一项是否与 全是X 或者 全是O 的字符串相同即可;
- 处理列:定义
xR和oR分别存储每一列中 X 和 O 出现的次数,统计完成后,判断次数中是否有跟棋盘长度相同的值,若有则返回对应的一方。另外在遍历过程中,判断是否有空位,赋值给havaSpace; - 处理对角线:首先循环处理正对角线,出现次数赋值给 xZD 和 oZD,然后再处理斜对角线,出现次数赋值给 xFD 和 oFD,最后出现次数判断是否跟棋盘长度相同,返回对应的一方;
- 上述情况都没有返回值,说明两方都未胜利,那么需要判断是否还有空位,即
havaSpace的值,若有,返回Pending,若无,返回Draw。
AC 代码
/**
* @param {string[]} board
* @return {string}
*/
var tictactoe = function(board) {
const m = board.length
// 行
const x = 'X'.repeat(m)
const o = 'O'.repeat(m)
for(let i = 0; i < m; i++) {
if(board[i] === x) {
return 'X'
}
if(board[i] === o) {
return 'O'
}
}
// 列
let haveSpace = false // 是否有空格
let xR = {}
let oR = {}
for(let i = 0; i < m; i++) {
for(let j = 0; j < m; j++) {
if(board[i][j] === 'X') {
if(xR[j]) {
xR[j] += 1
} else {
xR[j] = 1
}
}
if(board[i][j] === 'O') {
if(oR[j]) {
oR[j] += 1
} else {
oR[j] = 1
}
}
if(board[i][j] === ' ') haveSpace = true
}
}
if(Object.values(xR).some(item => item === m)) return 'X'
if(Object.values(oR).some(item => item === m)) return 'O'
// 对角线
let xZD = 0
let oZD = 0
for(let i = 0; i < m; i++) {
if(board[i][i] === 'X') xZD += 1
if(board[i][i] === 'O') oZD += 1
}
let xFD = 0
let oFD = 0
for(let i = 0; i < m; i++) {
if(board[i][m - i - 1] === 'X') xFD += 1
if(board[i][m - i - 1] === 'O') oFD += 1
}
if(xZD === m || xFD === m) return 'X'
if(oZD === m || oFD === m) return 'O'
return haveSpace ? 'Pending' : 'Draw'
};
结果:
- 执行结果: 通过
- 执行用时:76 ms, 在所有 JavaScript 提交中击败了25.00%的用户
- 内存消耗:43.1 MB, 在所有 JavaScript 提交中击败了60.00%的用户
- 通过测试用例:70 / 70