蓝桥与力扣刷题(1275 找出井字棋的获胜者)
题目:
井字棋 是由两个玩家 A
和 B
在 3 x 3
的棋盘上进行的游戏。井字棋游戏的规则如下:
- 玩家轮流将棋子放在空方格 (
' '
) 上。 - 第一个玩家
A
总是用'X'
作为棋子,而第二个玩家B
总是用'O'
作为棋子。 'X'
和'O'
只能放在空方格中,而不能放在已经被占用的方格上。- 只要有 3 个相同的(非空)棋子排成一条直线(行、列、对角线)时,游戏结束。
- 如果所有方块都放满棋子(不为空),游戏也会结束。
- 游戏结束后,棋子无法再进行任何移动。
给你一个数组 moves
,其中 moves[i] = [rowi, coli]
表示第 i
次移动在 grid[rowi][coli]
。如果游戏存在获胜者(A
或 B
),就返回该游戏的获胜者;如果游戏以平局结束,则返回 "Draw"
;如果仍会有行动(游戏未结束),则返回 "Pending"
。
你可以假设 moves
都 有效(遵循 井字棋 规则),网格最初是空的,A
将先行动。
示例 1:
输入:moves = [[0,0],[2,0],[1,1],[2,1],[2,2]] 输出:"A" 解释:"A" 获胜,他总是先走。
示例 2:
输入:moves = [[0,0],[1,1],[0,1],[0,2],[1,0],[2,0]] 输出:"B" 解释:"B" 获胜。
示例 3:
输入:moves = [[0,0],[1,1],[2,0],[1,0],[1,2],[2,1],[0,1],[0,2],[2,2]] 输出:"Draw" 解释:由于没有办法再行动,游戏以平局结束。
解题思路+代码:
代码:
class Solution {
public String tictactoe(int[][] moves) {
/*
思路:
1.判断回合数
2.确定最后下棋的玩家(根据回合数的奇偶性确定最后下棋的玩家,奇A偶B)
3.初始3✖3的棋盘
4.模拟落子(只模拟最后下棋的玩家的落子)
5.判断胜负:从第5或第6回合开始,每次落子后判断当前回合的棋子所在行、列以及两条对角线是否满足三子连线的条件。
6.平局判断:如果所有位置都已填满(即回合数为9)
7.回合少于9,也没有玩家获胜,提醒游戏未结束返回pending
*/
int len = moves.length; // 数组长度(回合数)
// 小于5回合无法分出胜负
if (len < 5) {
return "Pending";
}
/**
* 赢家一定是最后一回合下棋的玩家
* 所以我们只需要分析一名玩家的棋
* A先手,B后手
* A的回合数组下标是:0, 2, 4, 6, 8 (偶数)
* B的回合数组下标是:1, 3, 5, 7 (奇数)
*/
// 先默认是A
int index = 0; // 从0开始
String winner = "A";
if ((len & 1) == 0){ // (偶数)最后下棋的是B,注意:B的回合下标是奇数,对应的数组长度是偶数
index = 1; // 从1开始
winner = "B";
}
int[][] map = new int[3][3];
for (int i=index; i<len; i+=2) { // 只模拟一名玩家棋
map[moves[i][0]][moves[i][1]] = 1;
}
/**
* 玩家A只需要判断5,7,9回合
* 玩家B只需要判断6,8回合
* 每次落子判断当前回合棋子所在行,列以及两条对接线是否满足条件
* (0,1), (1,0), (1, 2), (2,1) 这四个点不用判断对角线
* 用 row + col == 1 和 row + col == 3 来判断是不是这四个点
*/
int row, col;
for (int i=4+index; i<len; i+=2) { // 从5/6回合开始判断
row = moves[i][0]; // 获取行
col = moves[i][1]; // 获取列
// 判断行,列
if (map[row][0] + map[row][1] + map[row][2] == 3 || // 行
map[0][col] + map[1][col] + map[2][col] == 3) { // 列
return winner;
}
// 当前点不用判断对角线
if (row + col == 1 || row + col == 3){
continue;
}
// 判断两条对角线
if (map[0][0] + map[1][1] + map[2][2] == 3 ||
map[0][2] + map[1][1] + map[2][0] == 3) {
return winner;
}
}
if (len == 9) { // 下满未分胜负平局
return "Draw";
}
return "Pending"; // 未下满,未分胜负
}
}
总结:个人认为这题比较偏重逻辑思路,怎么判断谁是获胜者?怎么判断三子连线?获胜者我们可以通过奇A偶B来判断,三子连线我们也可以划分出情况逐一分析,垂直、水平、对角线三种情况,分别列举出来进行判断。