'array', 'moves_history' => 'array', 'invite_expires_at' => 'datetime', 'started_at' => 'datetime', 'finished_at' => 'datetime', ]; } // ─── 关联 ───────────────────────────────────────────────────────── /** * 黑棋玩家(发起方)。 */ public function playerBlack(): BelongsTo { return $this->belongsTo(User::class, 'player_black_id'); } /** * 白棋玩家(PvP 接受方)。 */ public function playerWhite(): BelongsTo { return $this->belongsTo(User::class, 'player_white_id'); } /** * 所属聊天室。 */ public function room(): BelongsTo { return $this->belongsTo(Room::class); } // ─── 棋盘操作 ───────────────────────────────────────────────────── /** * 生成空白 15×15 棋盘(全 0)。 */ public static function emptyBoard(): array { return array_fill(0, 15, array_fill(0, 15, 0)); } /** * 在指定坐标落子,返回新棋盘状态。 * * @param array $board 当前棋盘 * @param int $row 行(0-14) * @param int $col 列(0-14) * @param int $color 棋子颜色(1=黑 2=白) */ public static function placeStone(array $board, int $row, int $col, int $color): array { $board[$row][$col] = $color; return $board; } /** * 检查指定坐标是否已有棋子。 * * @param array $board 棋盘 * @param int $row 行 * @param int $col 列 */ public static function isOccupied(array $board, int $row, int $col): bool { return ($board[$row][$col] ?? 0) !== 0; } /** * 判断在指定坐标落子后,该颜色是否已连成五子。 * * @param array $board 落子后的棋盘 * @param int $row 最后落子行 * @param int $col 最后落子列 * @param int $color 棋子颜色(1=黑 2=白) */ public static function checkWin(array $board, int $row, int $col, int $color): bool { // 四个方向:横、竖、左斜、右斜 $directions = [[0, 1], [1, 0], [1, 1], [1, -1]]; foreach ($directions as [$dr, $dc]) { $count = 1; // 向正方向延伸 for ($i = 1; $i <= 4; $i++) { $r = $row + $dr * $i; $c = $col + $dc * $i; if ($r < 0 || $r >= 15 || $c < 0 || $c >= 15) { break; } if (($board[$r][$c] ?? 0) !== $color) { break; } $count++; } // 向反方向延伸 for ($i = 1; $i <= 4; $i++) { $r = $row - $dr * $i; $c = $col - $dc * $i; if ($r < 0 || $r >= 15 || $c < 0 || $c >= 15) { break; } if (($board[$r][$c] ?? 0) !== $color) { break; } $count++; } if ($count >= 5) { return true; } } return false; } /** * 判断棋盘是否已下满(平局)。 * * @param array $board 棋盘 */ public static function isBoardFull(array $board): bool { foreach ($board as $row) { foreach ($row as $cell) { if ($cell === 0) { return false; } } } return true; } // ─── 状态辅助 ───────────────────────────────────────────────────── /** * 判断对局是否属于某个用户。 * * @param int $userId 用户 ID */ public function belongsToUser(int $userId): bool { return $this->player_black_id === $userId || $this->player_white_id === $userId; } /** * 获取指定用户在此对局的棋子颜色。 * 返回 1(黑棋)或 2(白棋),不在局中返回 null。 * * @param int $userId 用户 ID */ public function colorOf(int $userId): ?int { if ($this->player_black_id === $userId) { return 1; } if ($this->player_white_id === $userId) { return 2; } return null; } /** * 判断当前是否轮到指定用户行棋(PvP 用)。 * * @param int $userId 用户 ID */ public function isUserTurn(int $userId): bool { return $this->colorOf($userId) === $this->current_turn; } }