From 473fb279bf158a149b540f3eeeee5b28c7b6c270 Mon Sep 17 00:00:00 2001 From: sega Date: Mon, 3 Aug 2026 11:20:01 +0300 Subject: [PATCH] =?UTF-8?q?=D0=A1=D0=BE=D0=B7=D0=B4=D0=B0=D0=BD=20=D0=BF?= =?UTF-8?q?=D1=83=D0=BB=20=D0=B4=D0=BB=D1=8F=20=D1=84=D0=B8=D1=88=D0=B5?= =?UTF-8?q?=D0=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Assets/Scripts/ChipPointer.cs | 2 +- Assets/Scripts/ChipPool.cs | 68 +++++++++++++++++++ Assets/Scripts/ChipPool.cs.meta | 2 + .../Common/GameFSM/ChipFallingState.cs | 2 +- .../Scripts/Common/GameFSM/ShowWinnerState.cs | 8 +-- Assets/Scripts/Common/GameFSM/StateRouter.cs | 2 +- Assets/Scripts/Common/GameManager.cs | 22 +++--- Assets/Scripts/Common/Inputs/COMinput.cs | 2 +- Assets/Scripts/Common/Inputs/KeyboardInput.cs | 2 +- Assets/Scripts/Common/LightUtility.cs | 4 +- Assets/Scripts/Common/SoundManager.cs | 4 +- Assets/Scripts/Gameplay/Board.cs | 8 +-- Assets/Scripts/Gameplay/Chip.cs | 15 +++- Assets/Scripts/Gameplay/EndOfTurnHandler.cs | 6 +- Assets/Scripts/Gameplay/FieldChecker.cs | 26 +++---- .../Scripts/Gameplay/PVP Characters/Avatar.cs | 4 +- .../Gameplay/PVP Characters/AvatarEventBus.cs | 10 +-- .../PVP Characters/DualAvatarController.cs | 26 +++---- Assets/Scripts/Gameplay/PvpPointer.cs | 2 +- Assets/Scripts/Gameplay/Solver.cs | 52 +++++++------- Assets/Scripts/Gameplay/SolverV2.cs | 10 +-- Assets/Scripts/Gameplay/TimerManager.cs | 6 +- Assets/Scripts/Gameplay/WinPanel.cs | 8 +-- 23 files changed, 186 insertions(+), 105 deletions(-) create mode 100644 Assets/Scripts/ChipPool.cs create mode 100644 Assets/Scripts/ChipPool.cs.meta diff --git a/Assets/Scripts/ChipPointer.cs b/Assets/Scripts/ChipPointer.cs index 73dbbfc..fd518f3 100644 --- a/Assets/Scripts/ChipPointer.cs +++ b/Assets/Scripts/ChipPointer.cs @@ -11,7 +11,7 @@ public class ChipPointer : MonoBehaviour public void SetPosition(Vector2 position) => transform.position = position; - public void SetColorByPlayer(CellState player) => spriteRenderer.color = player == CellState.Player1 ? player1Color : player2Color; + public void SetColorByPlayer(Team player) => spriteRenderer.color = player == Team.Player1 ? player1Color : player2Color; public void SinAlphaAnimation() { diff --git a/Assets/Scripts/ChipPool.cs b/Assets/Scripts/ChipPool.cs new file mode 100644 index 0000000..e941d86 --- /dev/null +++ b/Assets/Scripts/ChipPool.cs @@ -0,0 +1,68 @@ +using System; +using System.Collections.Generic; +using UnityEngine; + +public class ChipPool : MonoBehaviour +{ + private Chip _prefab; + private Queue _availableChips; + private bool _isInit; + + public static ChipPool Instance { get; private set; } + + public void Init(Chip prefab, int amount) + { + if (_isInit) + return; + + _prefab = prefab; + _availableChips = new Queue(amount); + + for (int i = 0; i < amount; i++) + Create(); + + Instance = this; + _isInit = true; + } + + public Chip Get() + { + if (_isInit == false) + throw new InvalidOperationException("Пул фишек не инициализирован"); + + if (_availableChips.Count == 0) + Create(); + + Chip chip = _availableChips.Dequeue(); + chip.gameObject.SetActive(true); + return chip; + } + + public Chip GetConfigured(Sprite sprite, Team team) + { + if (_isInit == false) + throw new InvalidOperationException("Пул фишек не инициализирован"); + + Chip chip = Get(); + chip.Configure(sprite, team); + return chip; + } + + public void Release(Chip chip) + { + if (_isInit == false) + throw new InvalidOperationException("Пул фишек не инициализирован"); + + chip.gameObject.SetActive(false); + _availableChips.Enqueue(chip); + } + + private Chip Create() + { + Chip chip = Instantiate(_prefab); + chip.gameObject.SetActive(false); + _availableChips.Enqueue(chip); + + return chip; + } +} \ No newline at end of file diff --git a/Assets/Scripts/ChipPool.cs.meta b/Assets/Scripts/ChipPool.cs.meta new file mode 100644 index 0000000..350b6d9 --- /dev/null +++ b/Assets/Scripts/ChipPool.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: 6f304a4db5b21a3438c74970b41a0db7 \ No newline at end of file diff --git a/Assets/Scripts/Common/GameFSM/ChipFallingState.cs b/Assets/Scripts/Common/GameFSM/ChipFallingState.cs index 1547809..8394cd6 100644 --- a/Assets/Scripts/Common/GameFSM/ChipFallingState.cs +++ b/Assets/Scripts/Common/GameFSM/ChipFallingState.cs @@ -63,7 +63,7 @@ public class ChipFallingState : IState private void AnnouncePlayerTurn() { - if (GameManager.instance.currentPlayer == CellState.Player1) + if (GameManager.instance.currentPlayer == Team.Player1) { CharacterEventBus.Instance.OnPlayerTurn?.Invoke(); } diff --git a/Assets/Scripts/Common/GameFSM/ShowWinnerState.cs b/Assets/Scripts/Common/GameFSM/ShowWinnerState.cs index e46db4f..961e98f 100644 --- a/Assets/Scripts/Common/GameFSM/ShowWinnerState.cs +++ b/Assets/Scripts/Common/GameFSM/ShowWinnerState.cs @@ -88,7 +88,7 @@ public class ShowWinnerState : IState winningChips = new List(); CollectChipsList(result); - if (gm.currentPlayer == CellState.Player1)//Последный держал фишку игрок + if (gm.currentPlayer == Team.Player1)//Последный держал фишку игрок { if (gm.vsBotScore == 5)//5 побед над ботом @@ -164,13 +164,13 @@ public class ShowWinnerState : IState //Вопрос к логике тут. //bool bossUpgraded = GameManager.instance.BossUpgraded; bool bossFirst = SettingsManager.GetString(SettingKey.DIFFICULTY_MODE) != "Прохождение"; - CellState firstRoundPlayer = bossFirst ? CellState.Player2 : CellState.Player1; + Team firstRoundPlayer = bossFirst ? Team.Player2 : Team.Player1; gm.PrepareRound(firstRoundPlayer); return; } else { - CellState nextPlayer = GameManager.instance.currentPlayer == CellState.Player1 ? CellState.Player2 : CellState.Player2; + Team nextPlayer = GameManager.instance.currentPlayer == Team.Player1 ? Team.Player2 : Team.Player2; gm.PrepareRound(nextPlayer); } } @@ -209,7 +209,7 @@ public class ShowWinnerState : IState AvatarEventBus.Instance.OnNewRoundStarted?.Invoke(gm.currentPlayer); Board.Instance.MakeClearField(); - CellState nextPlayer = gm.currentPlayer == CellState.Player1 ? CellState.Player2 : CellState.Player1; + Team nextPlayer = gm.currentPlayer == Team.Player1 ? Team.Player2 : Team.Player1; gm.PrepareRound(nextPlayer); break; case EndOption.Menu://чистим поле и переходим в меню с параметром чтобы панельки съехались обратно diff --git a/Assets/Scripts/Common/GameFSM/StateRouter.cs b/Assets/Scripts/Common/GameFSM/StateRouter.cs index 3086610..899b8b3 100644 --- a/Assets/Scripts/Common/GameFSM/StateRouter.cs +++ b/Assets/Scripts/Common/GameFSM/StateRouter.cs @@ -121,7 +121,7 @@ public static class StateRouter } - private static IState PlayerWinPvpHandler(CellState winner) + private static IState PlayerWinPvpHandler(Team winner) { gm.IncreaseScore(winner); diff --git a/Assets/Scripts/Common/GameManager.cs b/Assets/Scripts/Common/GameManager.cs index 5309800..4359505 100644 --- a/Assets/Scripts/Common/GameManager.cs +++ b/Assets/Scripts/Common/GameManager.cs @@ -26,7 +26,7 @@ public class GameManager : MonoBehaviour [Header("Menu")] public GameMode gameMode; - [HideInInspector] public CellState currentPlayer = CellState.Player2; + [HideInInspector] public Team currentPlayer = Team.Player2; @@ -131,28 +131,28 @@ public class GameManager : MonoBehaviour { GameObject chipToSpawn; if (gameMode == GameMode.pvp) - chipToSpawn = currentPlayer == CellState.Player1 ? player1Chip : player2Chip; + chipToSpawn = currentPlayer == Team.Player1 ? player1Chip : player2Chip; else - chipToSpawn = currentPlayer == CellState.Player1 ? player1Chip : botChip; + chipToSpawn = currentPlayer == Team.Player1 ? player1Chip : botChip; currentChip = Instantiate(chipPrefab, new Vector2(0, 20), Quaternion.identity); - currentChip.Team = currentPlayer; - if (currentPlayer == CellState.Player2) + currentChip.team = currentPlayer; + if (currentPlayer == Team.Player2) currentChip.GetComponentInChildren().sprite = CharactersController.CurrentCharacter.chipImage; } public void SwitchPlayer() { - currentPlayer = currentPlayer == CellState.Player1 ? CellState.Player2 : CellState.Player1; + currentPlayer = currentPlayer == Team.Player1 ? Team.Player2 : Team.Player1; } public void SetMode(GameMode mode) => gameMode = mode; - public void IncreaseScore(CellState player) + public void IncreaseScore(Team player) { - if (player == CellState.Player1) + if (player == Team.Player1) player1score += 1; else player2score += 1; @@ -194,14 +194,14 @@ public class GameManager : MonoBehaviour } } - public void PrepareRound(CellState firstPlayer) + public void PrepareRound(Team firstPlayer) { currentPlayer = firstPlayer; timerManager.SetupTimers(gameMode); if (gameMode == GameMode.pve) { - timerManager.SetActiveTimer(CellState.Player1); + timerManager.SetActiveTimer(Team.Player1); int difficultyIndex = DifficultyManager.Instance.currentOpponent; CharactersController.SwitchToCharacter(difficultyIndex); } @@ -223,7 +223,7 @@ public class GameManager : MonoBehaviour LightUtility.Player(currentPlayer); } - if (currentPlayer == CellState.Player1) + if (currentPlayer == Team.Player1) { stateMachine.ChangeState(new PositioningState()); } diff --git a/Assets/Scripts/Common/Inputs/COMinput.cs b/Assets/Scripts/Common/Inputs/COMinput.cs index 450031e..585d295 100644 --- a/Assets/Scripts/Common/Inputs/COMinput.cs +++ b/Assets/Scripts/Common/Inputs/COMinput.cs @@ -25,7 +25,7 @@ public class COMinput : InputSource //Свойство для определения текущего игрока //Должно возвращать 1 или 2 //Используется для получения состояния кнопок с пометкой ...CurrentPlayer - private int currentPlayer => gm.currentPlayer == CellState.Player1 ? 1 : 2;//ПЕРЕОПРЕДЕЛИТЕ ОПРЕДЕЛЕНИЕ ТЕКУЩЕГО ИГРОКА ПОД СВОЮ СИСТЕМУ. + private int currentPlayer => gm.currentPlayer == Team.Player1 ? 1 : 2;//ПЕРЕОПРЕДЕЛИТЕ ОПРЕДЕЛЕНИЕ ТЕКУЩЕГО ИГРОКА ПОД СВОЮ СИСТЕМУ. private GameManager gm;//я получаю кто сейчас ходит через этого менеджера. Если у вас другое, допишите. diff --git a/Assets/Scripts/Common/Inputs/KeyboardInput.cs b/Assets/Scripts/Common/Inputs/KeyboardInput.cs index 4f655fe..6a58b7c 100644 --- a/Assets/Scripts/Common/Inputs/KeyboardInput.cs +++ b/Assets/Scripts/Common/Inputs/KeyboardInput.cs @@ -13,7 +13,7 @@ /// public class KeyboardInput : InputSource { - private int currentPlayer => gm.currentPlayer == CellState.Player1 ? 1 : 2;//ПЕРЕОПРЕДЕЛИТЕ ОПРЕДЕЛЕНИЕ ТЕКУЩЕГО ИГРОКА ПОД СВОЮ СИСТЕМУ. + private int currentPlayer => gm.currentPlayer == Team.Player1 ? 1 : 2;//ПЕРЕОПРЕДЕЛИТЕ ОПРЕДЕЛЕНИЕ ТЕКУЩЕГО ИГРОКА ПОД СВОЮ СИСТЕМУ. private GameManager gm;//я получаю кто сейчас ходит через этого менеджера. Если у вас другое, допишите. diff --git a/Assets/Scripts/Common/LightUtility.cs b/Assets/Scripts/Common/LightUtility.cs index c1091fb..63ad48d 100644 --- a/Assets/Scripts/Common/LightUtility.cs +++ b/Assets/Scripts/Common/LightUtility.cs @@ -22,9 +22,9 @@ public static class LightUtility SendLightCommandToCom(LightMode.Lose); } - public static void Player(CellState currentPlayer) + public static void Player(Team currentPlayer) { - if (currentPlayer == CellState.Player1) + if (currentPlayer == Team.Player1) SendLightCommandToCom(LightMode.Orange); else SendLightCommandToCom(LightMode.Blue); diff --git a/Assets/Scripts/Common/SoundManager.cs b/Assets/Scripts/Common/SoundManager.cs index 6158428..ab6e7d7 100644 --- a/Assets/Scripts/Common/SoundManager.cs +++ b/Assets/Scripts/Common/SoundManager.cs @@ -163,7 +163,7 @@ public class SoundManager : MonoBehaviour audioSource.clip = clipToPlay; //audioSource.pitch = 1 + Random.Range(0, 2) * 0.6f; - audioSource.pitch = GameManager.instance.currentPlayer == CellState.Player1 ? 1 : 1.3f; + audioSource.pitch = GameManager.instance.currentPlayer == Team.Player1 ? 1 : 1.3f; audioSource.volume = effectsVolume; @@ -186,7 +186,7 @@ public class SoundManager : MonoBehaviour audioSource.clip = clipToPlay; audioSource.volume = effectsVolume; - audioSource.pitch = GameManager.instance.currentPlayer == CellState.Player1 ? 0.8f : 0.85f; + audioSource.pitch = GameManager.instance.currentPlayer == Team.Player1 ? 0.8f : 0.85f; effect.SetActive(true); audioSource.Play(); diff --git a/Assets/Scripts/Gameplay/Board.cs b/Assets/Scripts/Gameplay/Board.cs index 4569966..dd5d2be 100644 --- a/Assets/Scripts/Gameplay/Board.cs +++ b/Assets/Scripts/Gameplay/Board.cs @@ -81,16 +81,16 @@ public class Board : MonoBehaviour return -1; } - public CellState[,] GridToTeam() + public Team[,] GridToTeam() { - CellState[,] res = new CellState[Columns, Rows]; + Team[,] res = new Team[Columns, Rows]; for (int col = 0; col < Columns; col++) { for (int row = 0; row < Rows; row++) { var chip = Grid[col, row]; - if (chip == null) res[col, row] = CellState.Empty; - else res[col, row] = chip.Team; + if (chip == null) res[col, row] = Team.None; + else res[col, row] = chip.team; } } return res; diff --git a/Assets/Scripts/Gameplay/Chip.cs b/Assets/Scripts/Gameplay/Chip.cs index dbfb817..49d09fd 100644 --- a/Assets/Scripts/Gameplay/Chip.cs +++ b/Assets/Scripts/Gameplay/Chip.cs @@ -2,13 +2,21 @@ public class Chip : MonoBehaviour { - public CellState Team; + public Team team; [SerializeField] float acceleration = 200f; [SerializeField] float maxFallingRotationSpeed = 500; + [SerializeField] private SpriteRenderer spriteRenderer; + private float chipVelocity = 0; private float rotationSpeed = 0; + public void Configure(Sprite sprite, Team team) + { + spriteRenderer.sprite = sprite; + this.team = team; + } + public virtual void RemoveFromField() { Destroy(gameObject); @@ -17,8 +25,10 @@ public class Chip : MonoBehaviour public bool MoveToLinear(Vector2 target, float speed) { transform.position = Vector2.MoveTowards(transform.position, target, speed * Time.deltaTime); + if ((Vector2)transform.position == target) return true; + return false; } @@ -32,10 +42,11 @@ public class Chip : MonoBehaviour acceleration = 0; return true; } + return false; } - public void SetRandomRotationSpeed() => rotationSpeed = Random.Range(-maxFallingRotationSpeed, maxFallingRotationSpeed); + public void Rotate() => transform.Rotate(Vector3.forward * rotationSpeed * Time.deltaTime); } \ No newline at end of file diff --git a/Assets/Scripts/Gameplay/EndOfTurnHandler.cs b/Assets/Scripts/Gameplay/EndOfTurnHandler.cs index a4e4cb0..133099d 100644 --- a/Assets/Scripts/Gameplay/EndOfTurnHandler.cs +++ b/Assets/Scripts/Gameplay/EndOfTurnHandler.cs @@ -27,7 +27,7 @@ public static class EndOfTurnHandler if (gm.gameMode == GameMode.pvp) { //p2 не успел - if (gm.currentPlayer == CellState.Player2) + if (gm.currentPlayer == Team.Player2) { gm.player1score += 1; //gm.Player1Scale.SetMedalsCount(gm.player1score); @@ -65,7 +65,7 @@ public static class EndOfTurnHandler } - public static TurnEndingResult Evaluate(CheckResult result, GameMode gameMode, CellState lastPlayer) + public static TurnEndingResult Evaluate(CheckResult result, GameMode gameMode, Team lastPlayer) { if (!result.End) return TurnEndingResult.GameContinues; if (result.Draw) return TurnEndingResult.Draw; @@ -73,7 +73,7 @@ public static class EndOfTurnHandler if (gameMode == GameMode.pve) { - return lastPlayer == CellState.Player1 ? TurnEndingResult.PlayerWinPve : TurnEndingResult.BotWin; + return lastPlayer == Team.Player1 ? TurnEndingResult.PlayerWinPve : TurnEndingResult.BotWin; } else //pvp { diff --git a/Assets/Scripts/Gameplay/FieldChecker.cs b/Assets/Scripts/Gameplay/FieldChecker.cs index 423e9ad..0f8fc1f 100644 --- a/Assets/Scripts/Gameplay/FieldChecker.cs +++ b/Assets/Scripts/Gameplay/FieldChecker.cs @@ -1,19 +1,19 @@ -using System; -using System.Collections.Generic; +using System.Collections.Generic; -public enum CellState +public enum Team { - Empty, Player1, Player2 + None, + Player1, + Player2 } public static class FieldChecker { - static GameManager gm => GameManager.instance; public static Chip[,] FieldArray => Board.Instance.Grid; public static int Height => Board.Instance.Rows; public static int Width => Board.Instance.Columns; public static int TargetLineLength = 4; - public static CheckResult Check(CellState lastPlayer) + public static CheckResult Check(Team lastPlayer) { HashSet<(int row, int col)> WinningIndexes = new(); @@ -51,7 +51,7 @@ public static class FieldChecker } - private static (bool hasWin, HashSet<(int row, int col)> winningIndexes) checkAllRows(CellState targetTeam) + private static (bool hasWin, HashSet<(int row, int col)> winningIndexes) checkAllRows(Team targetTeam) { var winningCells = new HashSet<(int row, int col)>(); @@ -63,7 +63,7 @@ public static class FieldChecker { // Проверяем, не вышли ли за границы массива var chip = FieldArray[col, row]; - bool isMatch = col < Width && chip != null && chip.Team == targetTeam; + bool isMatch = col < Width && chip != null && chip.team == targetTeam; if (isMatch && start == -1) start = col; @@ -83,7 +83,7 @@ public static class FieldChecker return (winningCells.Count > 0, winningCells); } - private static (bool hasWin, HashSet<(int row, int col)> winningIndexes) checkAllColumns(CellState targetTeam) + private static (bool hasWin, HashSet<(int row, int col)> winningIndexes) checkAllColumns(Team targetTeam) { var winningCells = new HashSet<(int row, int col)>(); @@ -94,7 +94,7 @@ public static class FieldChecker for (int row = 0; row <= Height; row++) { var chip = FieldArray[col, row]; - bool isMatch = row < Height && chip != null && chip.Team == targetTeam; + bool isMatch = row < Height && chip != null && chip.team == targetTeam; if (isMatch && start == -1) start = row; @@ -115,7 +115,7 @@ public static class FieldChecker return (winningCells.Count > 0, winningCells); } - private static (bool hasWin, HashSet<(int row, int col)> winningIndexes) checkAllDiagonals(CellState targetCellState) + private static (bool hasWin, HashSet<(int row, int col)> winningIndexes) checkAllDiagonals(Team targetCellState) { var winningCells = new HashSet<(int row, int col)>(); @@ -143,7 +143,7 @@ public static class FieldChecker } private static void CheckDiagonalStartingAt(int startRow, int startCol, int rowStep, int colStep, - CellState targetCellState, HashSet<(int, int)> winningCells) + Team targetCellState, HashSet<(int, int)> winningCells) { int rows = Height; int cols = Width; @@ -157,7 +157,7 @@ public static class FieldChecker currentCol >= 0 && currentCol < cols) { var chip = FieldArray[currentCol, currentRow]; - bool isMatch = chip != null && chip.Team == targetCellState; + bool isMatch = chip != null && chip.team == targetCellState; if (isMatch) { diff --git a/Assets/Scripts/Gameplay/PVP Characters/Avatar.cs b/Assets/Scripts/Gameplay/PVP Characters/Avatar.cs index 86b2758..c994816 100644 --- a/Assets/Scripts/Gameplay/PVP Characters/Avatar.cs +++ b/Assets/Scripts/Gameplay/PVP Characters/Avatar.cs @@ -23,7 +23,7 @@ public class Avatar : MonoBehaviour private GameObject currentMessageBox; private bool nowTyping = false; - private CellState team; + private Team team; #region REPLICAS_LISTS [Header("Появление")] @@ -80,7 +80,7 @@ public class Avatar : MonoBehaviour - public void Initialize(CellState team) + public void Initialize(Team team) { this.team = team; SettingsManager.OnSettingsChanged += pullSettings; diff --git a/Assets/Scripts/Gameplay/PVP Characters/AvatarEventBus.cs b/Assets/Scripts/Gameplay/PVP Characters/AvatarEventBus.cs index 6adb9b5..548b2f1 100644 --- a/Assets/Scripts/Gameplay/PVP Characters/AvatarEventBus.cs +++ b/Assets/Scripts/Gameplay/PVP Characters/AvatarEventBus.cs @@ -7,12 +7,12 @@ public class AvatarEventBus : MonoBehaviour //Список событий переделать public UnityEvent OnAvatarsAppeared; //когда уже выехали на экран - public UnityEvent OnTurnStart; //Начало хода конкретного игрока - public UnityEvent OnTurnEnd; //Конец хода конкретного игрока (перед падением фишки) - public UnityEvent OnEndRound; //Конец раунда (передаем победителя) + public UnityEvent OnTurnStart; //Начало хода конкретного игрока + public UnityEvent OnTurnEnd; //Конец хода конкретного игрока (перед падением фишки) + public UnityEvent OnEndRound; //Конец раунда (передаем победителя) public UnityEvent OnDraw; //Ничья - public UnityEvent OnNewRoundStarted; //Новый раунд (передаем кто прошлый победитель) - public UnityEvent OnEndGame; //Конец игры (победителя передаем) + public UnityEvent OnNewRoundStarted; //Новый раунд (передаем кто прошлый победитель) + public UnityEvent OnEndGame; //Конец игры (победителя передаем) public void Initialize() => Instance = this; } diff --git a/Assets/Scripts/Gameplay/PVP Characters/DualAvatarController.cs b/Assets/Scripts/Gameplay/PVP Characters/DualAvatarController.cs index 97ef882..e894073 100644 --- a/Assets/Scripts/Gameplay/PVP Characters/DualAvatarController.cs +++ b/Assets/Scripts/Gameplay/PVP Characters/DualAvatarController.cs @@ -13,12 +13,12 @@ public class DualAvatarController : MonoBehaviour - const CellState PLAYER1 = CellState.Player1; - const CellState PLAYER2 = CellState.Player2; + const Team PLAYER1 = Team.Player1; + const Team PLAYER2 = Team.Player2; [SerializeField] private List characterPrefabs; - Dictionary avatars = new(); + Dictionary avatars = new(); [SerializeField] Transform AvatarsParent; private AvatarEventBus bus; @@ -73,7 +73,7 @@ public class DualAvatarController : MonoBehaviour StartCoroutine(MoveLocal(avatars[PLAYER2], GetHiddenPosition(PLAYER2), CharacterMovementSpeed, OnComplete: () => { })); } - Avatar CreateAvatar(GameObject prefab, Transform parent, CellState team) + Avatar CreateAvatar(GameObject prefab, Transform parent, Team team) { GameObject go = Instantiate(prefab, parent); @@ -86,9 +86,9 @@ public class DualAvatarController : MonoBehaviour return avatar; } - Vector2 GetHiddenPosition(CellState team) + Vector2 GetHiddenPosition(Team team) => team == PLAYER1 ? baseHiddenLocalPosition : new Vector2(-baseHiddenLocalPosition.x, baseHiddenLocalPosition.y); - Vector2 GetShownPosition(CellState team) + Vector2 GetShownPosition(Team team) => team == PLAYER1 ? baseShownLocalPosition : new Vector2(-baseShownLocalPosition.x, baseShownLocalPosition.y); @@ -129,21 +129,21 @@ public class DualAvatarController : MonoBehaviour { avatars[PLAYER1].Animator.SetTrigger(APPEAR_TRIGGER); } - private void TurnStart(CellState player) { } - private void TurnEnd(CellState player) + private void TurnStart(Team player) { } + private void TurnEnd(Team player) { avatars[player].Animator.SetTrigger(CHIPSPAWN_TRIGGER); } - private void EndRound(CellState winner) + private void EndRound(Team winner) { //Обозначние для ничьей - if (winner == CellState.Empty) + if (winner == Team.None) { Draw(); return; } - CellState loser = winner == CellState.Player1 ? CellState.Player2 : CellState.Player1; + Team loser = winner == Team.Player1 ? Team.Player2 : Team.Player1; avatars[winner].Animator.SetTrigger(WIN_TRIGGER); avatars[loser].Animator.SetTrigger(LOSE_TRIGGER); } @@ -151,11 +151,11 @@ public class DualAvatarController : MonoBehaviour { Debug.Log("DRAW"); } - private void NewRound(CellState lastRoundWinner) + private void NewRound(Team lastRoundWinner) { //Debug.Log("NEW ROUND LAST WINNER " + lastRoundWinner); } - private void EndGame(CellState gameWinner) + private void EndGame(Team gameWinner) { //Debug.Log("ENDGAME"); } diff --git a/Assets/Scripts/Gameplay/PvpPointer.cs b/Assets/Scripts/Gameplay/PvpPointer.cs index 0dbb7f5..0308292 100644 --- a/Assets/Scripts/Gameplay/PvpPointer.cs +++ b/Assets/Scripts/Gameplay/PvpPointer.cs @@ -8,7 +8,7 @@ public class PvpPointer : MonoBehaviour [SerializeField] List sprites;//0 - первый, 1 - второй игрок. [SerializeField] Vector3 offset; - public void SetColor(CellState player) => _renderer.sprite = player == CellState.Player1 ? sprites[0] : sprites[1]; + public void SetColor(Team player) => _renderer.sprite = player == Team.Player1 ? sprites[0] : sprites[1]; public void SetVisibility(bool visible) => _renderer.enabled = visible; public void MoveTo(Vector3 targetPosition) => _renderer.transform.position = targetPosition + offset; diff --git a/Assets/Scripts/Gameplay/Solver.cs b/Assets/Scripts/Gameplay/Solver.cs index 6c29fe1..020bebf 100644 --- a/Assets/Scripts/Gameplay/Solver.cs +++ b/Assets/Scripts/Gameplay/Solver.cs @@ -16,8 +16,8 @@ public class Solver private static System.Random rand = new System.Random(); // текущие фигуры бота и оппонента — задаём при вызове FindBestMove - private static CellState BotPiece; - private static CellState HumanPiece; + private static Team BotPiece; + private static Team HumanPiece; private static int DEPTH = 8; private static int WIN_SCORE = 1_000_000; @@ -58,14 +58,14 @@ public class Solver } // -------- Публичный API -------- - public static int FindBestMove(CellState[,] board, CellState currentPlayer) + public static int FindBestMove(Team[,] board, Team currentPlayer) { ROWS = board.GetLength(0); COLS = board.GetLength(1); // сохраняем, за кого сейчас считаем BotPiece = currentPlayer; - HumanPiece = (currentPlayer == CellState.Player1) ? CellState.Player2 : CellState.Player1; + HumanPiece = (currentPlayer == Team.Player1) ? Team.Player2 : Team.Player1; var root = EvaluateRootMoves(board, DEPTH); @@ -105,7 +105,7 @@ public class Solver } // -------- Корневые ходы -------- - private static List<(int col, int score)> EvaluateRootMoves(CellState[,] board, int depth) + private static List<(int col, int score)> EvaluateRootMoves(Team[,] board, int depth) { var result = new List<(int col, int score)>(); var valid = GetValidLocations(board); @@ -123,20 +123,20 @@ public class Solver // если сразу победа — отлично if (WinningMoveAt(board, row, col, BotPiece)) { - board[row, col] = CellState.Empty; + board[row, col] = Team.None; result.Add((col, WIN_SCORE * depth)); continue; } int score = Minimax(board, depth - 1, int.MinValue, int.MaxValue, false, row, col, BotPiece).score; - board[row, col] = CellState.Empty; + board[row, col] = Team.None; result.Add((col, score)); } return result; } - private static bool LeadsToImmediateLoss(CellState[,] board, int botCol) + private static bool LeadsToImmediateLoss(Team[,] board, int botCol) { int row = GetNextOpenRow(board, botCol); if (row < 0) return false; @@ -148,7 +148,7 @@ public class Solver // соперник просто не получит ход if (WinningMoveAt(board, row, botCol, BotPiece)) { - board[row, botCol] = CellState.Empty; + board[row, botCol] = Team.None; return false; } @@ -156,7 +156,7 @@ public class Solver bool res = HasImmediateWin(board, HumanPiece); // откат - board[row, botCol] = CellState.Empty; + board[row, botCol] = Team.None; return res; } @@ -187,8 +187,8 @@ public class Solver // maximizingPlayer == true → ход бота (BOT) // maximizingPlayer == false → ход человека (HUMAN) private static (int column, int score) Minimax( - CellState[,] board, int depth, int alpha, int beta, - bool maximizingPlayer, int lastRow, int lastCol, CellState lastPlayer) + Team[,] board, int depth, int alpha, int beta, + bool maximizingPlayer, int lastRow, int lastCol, Team lastPlayer) { if (lastRow >= 0 && WinningMoveAt(board, lastRow, lastCol, lastPlayer)) { @@ -213,7 +213,7 @@ public class Solver board[r, col] = BotPiece; var child = Minimax(board, depth - 1, alpha, beta, false, r, col, BotPiece); - board[r, col] = CellState.Empty; + board[r, col] = Team.None; if (child.score > best) { best = child.score; bestCol = col; } alpha = Math.Max(alpha, best); @@ -234,7 +234,7 @@ public class Solver board[r, col] = HumanPiece; var child = Minimax(board, depth - 1, alpha, beta, true, r, col, HumanPiece); - board[r, col] = CellState.Empty; + board[r, col] = Team.None; if (child.score < best) { best = child.score; bestCol = col; } beta = Math.Min(beta, best); @@ -245,10 +245,10 @@ public class Solver } // -------- Эвристика -------- - private static int EvaluatePosition(CellState[,] board, CellState perspective /* всегда BOTpiece */) + private static int EvaluatePosition(Team[,] board, Team perspective /* всегда BOTpiece */) { int score = 0; - var opp = (perspective == CellState.Player1) ? CellState.Player2 : CellState.Player1; + var opp = (perspective == Team.Player1) ? Team.Player2 : Team.Player1; // 1) Центр (весим 3-4-5-7-5-4-3), не масштабируем на DEPTH for (int r = 0; r < ROWS; r++) @@ -273,12 +273,12 @@ public class Solver // Счёт «окон» длины 4, где pieceCount==length и остальные пусты, причём // хотя бы одна из пустых клеток «играбельна» (подперта снизу или нижняя граница). - private static int CountPotentialLinesPlayable(CellState[,] b, CellState piece, int length) + private static int CountPotentialLinesPlayable(Team[,] b, Team piece, int length) { int total = 0; bool In(int r, int c) => r >= 0 && r < ROWS && c >= 0 && c < COLS; - bool PlayableEmpty(int r, int c) => r == ROWS - 1 || b[r + 1, c] != CellState.Empty; + bool PlayableEmpty(int r, int c) => r == ROWS - 1 || b[r + 1, c] != Team.None; int ScanDir(int dr, int dc) { @@ -300,7 +300,7 @@ public class Solver int rr = r0 + dr * k, cc = c0 + dc * k; var v = b[rr, cc]; if (v == piece) p++; - else if (v == CellState.Empty) + else if (v == Team.None) { e++; if (PlayableEmpty(rr, cc)) hasPlayableEmpty = true; @@ -327,23 +327,23 @@ public class Solver } // -------- Хелперы по ходам/победам -------- - private static List GetValidLocations(CellState[,] board) + private static List GetValidLocations(Team[,] board) { var res = new List(COLS); for (int c = 0; c < COLS; c++) - if (board[0, c] == CellState.Empty) + if (board[0, c] == Team.None) res.Add(c); return res; } - private static int GetNextOpenRow(CellState[,] board, int col) + private static int GetNextOpenRow(Team[,] board, int col) { for (int r = ROWS - 1; r >= 0; r--) - if (board[r, col] == CellState.Empty) return r; + if (board[r, col] == Team.None) return r; return -1; } - private static bool HasImmediateWin(CellState[,] board, CellState player) + private static bool HasImmediateWin(Team[,] board, Team player) { var valid = GetValidLocations(board); foreach (int c in valid) @@ -352,13 +352,13 @@ public class Solver if (r < 0) continue; board[r, c] = player; bool win = WinningMoveAt(board, r, c, player); - board[r, c] = CellState.Empty; + board[r, c] = Team.None; if (win) return true; } return false; } - private static bool WinningMoveAt(CellState[,] b, int r, int c, CellState p) + private static bool WinningMoveAt(Team[,] b, int r, int c, Team p) { bool In(int rr, int cc) => rr >= 0 && rr < ROWS && cc >= 0 && cc < COLS; diff --git a/Assets/Scripts/Gameplay/SolverV2.cs b/Assets/Scripts/Gameplay/SolverV2.cs index aade191..263ec2e 100644 --- a/Assets/Scripts/Gameplay/SolverV2.cs +++ b/Assets/Scripts/Gameplay/SolverV2.cs @@ -82,7 +82,7 @@ public static class SolverV2 /// /// Главный метод: верни индекс колонки 0..6, куда бросать фишку. /// - public static int FindBestMove(CellState[,] board, CellState currentPlayer) + public static int FindBestMove(Team[,] board, Team currentPlayer) { if (board == null) throw new ArgumentNullException(nameof(board)); if (board.GetLength(0) != HEIGHT || board.GetLength(1) != WIDTH) @@ -95,14 +95,14 @@ public static class SolverV2 for (int c = 0; c < WIDTH; c++) { var cs = board[r, c]; - if (cs == CellState.Empty) continue; + if (cs == Team.None) continue; // В битбордах row=0 снизу. В массиве чаще row=0 сверху => инвертируем int br = (HEIGHT - 1) - r; // bottom=0 ulong bit = 1UL << (c * H1 + br); - if (cs == CellState.Player1) p1 |= bit; - else if (cs == CellState.Player2) p2 |= bit; + if (cs == Team.Player1) p1 |= bit; + else if (cs == Team.Player2) p2 |= bit; } } @@ -114,7 +114,7 @@ public static class SolverV2 } // Камень текущего игрока - ulong currentBits = (currentPlayer == CellState.Player1) ? p1 : p2; + ulong currentBits = (currentPlayer == Team.Player1) ? p1 : p2; var pos = new Position(currentBits, mask); diff --git a/Assets/Scripts/Gameplay/TimerManager.cs b/Assets/Scripts/Gameplay/TimerManager.cs index aa7e680..9f1706a 100644 --- a/Assets/Scripts/Gameplay/TimerManager.cs +++ b/Assets/Scripts/Gameplay/TimerManager.cs @@ -34,9 +34,9 @@ public class TimerManager : MonoBehaviour player2Timer.StopTimer(); } - public void SetActiveTimer(CellState currentPlayer) + public void SetActiveTimer(Team currentPlayer) { - (currentPlayer == CellState.Player1 ? player1Timer : player2Timer).StartTimer(); - (currentPlayer == CellState.Player1 ? player2Timer : player1Timer).StopTimer(); + (currentPlayer == Team.Player1 ? player1Timer : player2Timer).StartTimer(); + (currentPlayer == Team.Player1 ? player2Timer : player1Timer).StopTimer(); } } \ No newline at end of file diff --git a/Assets/Scripts/Gameplay/WinPanel.cs b/Assets/Scripts/Gameplay/WinPanel.cs index 45508af..3e0768f 100644 --- a/Assets/Scripts/Gameplay/WinPanel.cs +++ b/Assets/Scripts/Gameplay/WinPanel.cs @@ -5,7 +5,7 @@ public class WinPanel : MonoBehaviour { public GameObject win1, win2, winBot; public AudioSource sound; - public void ShowWin(CellState winner) + public void ShowWin(Team winner) { win1.SetActive(false); win2.SetActive(false); @@ -13,11 +13,11 @@ public class WinPanel : MonoBehaviour switch (winner) { - case CellState.Player1: + case Team.Player1: win1.SetActive(true); break; - case CellState.Player2: + case Team.Player2: win2.SetActive(true); break; - case CellState.Empty: + case Team.None: winBot.SetActive(true); break; }