Создан пул для фишек
This commit is contained in:
parent
fbb3bca0a9
commit
473fb279bf
@ -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()
|
||||
{
|
||||
|
||||
68
Assets/Scripts/ChipPool.cs
Normal file
68
Assets/Scripts/ChipPool.cs
Normal file
@ -0,0 +1,68 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
public class ChipPool : MonoBehaviour
|
||||
{
|
||||
private Chip _prefab;
|
||||
private Queue<Chip> _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<Chip>(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;
|
||||
}
|
||||
}
|
||||
2
Assets/Scripts/ChipPool.cs.meta
Normal file
2
Assets/Scripts/ChipPool.cs.meta
Normal file
@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 6f304a4db5b21a3438c74970b41a0db7
|
||||
@ -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();
|
||||
}
|
||||
|
||||
@ -88,7 +88,7 @@ public class ShowWinnerState : IState
|
||||
winningChips = new List<SpriteRenderer>();
|
||||
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://чистим поле и переходим в меню с параметром чтобы панельки съехались обратно
|
||||
|
||||
@ -121,7 +121,7 @@ public static class StateRouter
|
||||
}
|
||||
|
||||
|
||||
private static IState PlayerWinPvpHandler(CellState winner)
|
||||
private static IState PlayerWinPvpHandler(Team winner)
|
||||
{
|
||||
gm.IncreaseScore(winner);
|
||||
|
||||
|
||||
@ -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<SpriteRenderer>().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());
|
||||
}
|
||||
|
||||
@ -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;//я получаю кто сейчас ходит через этого менеджера. Если у вас другое, допишите.
|
||||
|
||||
|
||||
|
||||
@ -13,7 +13,7 @@
|
||||
/// </remarks>
|
||||
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;//я получаю кто сейчас ходит через этого менеджера. Если у вас другое, допишите.
|
||||
|
||||
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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();
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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);
|
||||
}
|
||||
@ -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
|
||||
{
|
||||
|
||||
@ -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)
|
||||
{
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -7,12 +7,12 @@ public class AvatarEventBus : MonoBehaviour
|
||||
|
||||
//Список событий переделать
|
||||
public UnityEvent OnAvatarsAppeared; //когда уже выехали на экран
|
||||
public UnityEvent<CellState> OnTurnStart; //Начало хода конкретного игрока
|
||||
public UnityEvent<CellState> OnTurnEnd; //Конец хода конкретного игрока (перед падением фишки)
|
||||
public UnityEvent<CellState> OnEndRound; //Конец раунда (передаем победителя)
|
||||
public UnityEvent<Team> OnTurnStart; //Начало хода конкретного игрока
|
||||
public UnityEvent<Team> OnTurnEnd; //Конец хода конкретного игрока (перед падением фишки)
|
||||
public UnityEvent<Team> OnEndRound; //Конец раунда (передаем победителя)
|
||||
public UnityEvent OnDraw; //Ничья
|
||||
public UnityEvent<CellState> OnNewRoundStarted; //Новый раунд (передаем кто прошлый победитель)
|
||||
public UnityEvent<CellState> OnEndGame; //Конец игры (победителя передаем)
|
||||
public UnityEvent<Team> OnNewRoundStarted; //Новый раунд (передаем кто прошлый победитель)
|
||||
public UnityEvent<Team> OnEndGame; //Конец игры (победителя передаем)
|
||||
|
||||
public void Initialize() => Instance = this;
|
||||
}
|
||||
|
||||
@ -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<GameObject> characterPrefabs;
|
||||
Dictionary<CellState, Avatar> avatars = new();
|
||||
Dictionary<Team, Avatar> 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");
|
||||
}
|
||||
|
||||
@ -8,7 +8,7 @@ public class PvpPointer : MonoBehaviour
|
||||
[SerializeField] List<Sprite> 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;
|
||||
|
||||
|
||||
@ -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<int> GetValidLocations(CellState[,] board)
|
||||
private static List<int> GetValidLocations(Team[,] board)
|
||||
{
|
||||
var res = new List<int>(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;
|
||||
|
||||
|
||||
@ -82,7 +82,7 @@ public static class SolverV2
|
||||
/// <summary>
|
||||
/// Главный метод: верни индекс колонки 0..6, куда бросать фишку.
|
||||
/// </summary>
|
||||
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);
|
||||
|
||||
|
||||
@ -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();
|
||||
}
|
||||
}
|
||||
@ -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;
|
||||
}
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user