Files
chatroom/app/Models/GomokuGame.php

225 lines
5.8 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<?php
/**
* 文件功能:五子棋对局模型
*
* 管理 PvP玩家对战和 PvE人机对战两种模式的对局记录。
* 提供棋盘操作、胜负判断及状态管理方法。
*
* @author ChatRoom Laravel
*
* @version 1.0.0
*/
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
class GomokuGame extends Model
{
protected $fillable = [
'mode',
'room_id',
'player_black_id',
'player_white_id',
'ai_level',
'status',
'board',
'current_turn',
'winner',
'moves_history',
'reward_gold',
'entry_fee',
'invite_expires_at',
'started_at',
'finished_at',
];
/**
* 属性类型转换。
*/
protected function casts(): array
{
return [
'board' => '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;
}
}