SirRmelTheThird/HyperJump
GitHub: SirRmelTheThird/HyperJump
HyperJump 是一款基于 Java 的回合制棋盘游戏,支持多种游戏玩法变体。
Stars: 0 | Forks: 0
# 超跃
## 简介
HyperJump 是一款基于 Java 的回合制棋盘游戏,允许玩家通过掷骰子来在棋盘上移动。游戏支持多种游戏玩法变体,例如单骰子移动、精确终点规则、击中检测、通过虫洞传送,以及适合四名玩家的更大棋盘。
游戏采用清洁架构原则设计,特别是 **端口和适配器架构**,以便将核心游戏逻辑与基础设施代码(如控制台输出、持久性、回放存储和骰子适配器)分离。
要运行游戏,请确保在运行配置中输入“test, memory”到活动配置文件类别,以进行固定的单骰子模拟,而“real, memory”则是用于所有变体的随机双/单骰子模拟。
实现还使用了几个设计模式,包括:
- 工厂模式
- 策略模式
- 装饰器模式
- 状态模式
- 观察者模式
- 存储库模式
# 架构
## 游戏
`GameConsoleRunner` 从控制台接收用户交互,并调用 `StartGameUseCase` 的输入端口。
这些接口由外部适配器用于与应用程序核心交互。
UML 图
```
classDiagram
direction LR
class GameConsoleRunner {
}
class CommandLineRunner {
<>
+run(String... args)
}
class StartGameUseCase {
<>
+play()
}
class GameSessionUseCase {
+play()
}
class SavedGameRepository {
<>
+nextId()
+save(SavedGame)
+findById(id)
+findAll()
+clearAll()
}
GameConsoleRunner ..|> CommandLineRunner
GameConsoleRunner ..> StartGameUseCase : << use >>
GameSessionUseCase ..|> StartGameUseCase
GameSessionUseCase ..> SavedGameRepository : << use >>
```
应用程序服务实现输入端口并协调游戏流程。
文件:
- `StartGameService`
- `GameSessionUseCase`
- `InitialisePlayerUseCase`
- `InitialiseRulesUseCase`
这些类控制用例,但并不直接依赖于基础设施细节。
## 回放
`GameConsoleRunner` 从控制台接收用户回放交互,并调用 `ReplayGameUseCase` 的输入端口。
这些接口由外部适配器用于与应用程序核心交互。
UML 图
```
classDiagram
direction LR
class GameConsoleRunner {
}
class CommandLineRunner {
<>
+run(String... args)
}
class ReplayGameUseCase {
<>
+replay(int gameId)
}
class ReplaySessionUseCase {
+replay(int gameId)
}
class SavedGameRepository {
<>
+nextId()
+save(SavedGame)
+findById(id)
+findAll()
+clearAll()
}
GameConsoleRunner ..|> CommandLineRunner
GameConsoleRunner ..> ReplayGameUseCase : << use >>
ReplaySessionUseCase ..|> ReplayGameUseCase
ReplaySessionUseCase ..> SavedGameRepository : << use >>
```
应用程序服务实现输入端口并协调游戏流程。
文件:
- `ReplayGameService`
- `ReplaySessionUseCase`
- `InitialisePlayerUseCase`
- `InitialiseRulesUseCase`
- `InitialiseReplayUseCase`
这些类控制用例,但并不直接依赖于基础设施细节。
# 端口和适配器
该项目使用 **端口和适配器**,也称为 **六边形架构**。
主要思想是核心应用程序不应直接依赖于外部系统。相反,应用程序依赖于称为 **端口** 的接口,而基础设施类实现这些端口作为 **适配器**。
## 棋盘端口
输出端口定义了应用程序需要从外部系统获取的内容。
UML 图
```
classDiagram
direction BT
class GameSessionUseCase {
+play()
}
class Board {
<>
+createBoard(playerCount)
}
class BoardFactoryAdapter {
}
GameSessionUseCase --> Board : << output port >>
BoardFactoryAdapter ..|> Board
```
- `Board`
此端口需要通知游戏已创建棋盘并与相关适配器交互。
## 骰子摇动端口
输出端口定义了应用程序需要从外部系统获取的内容。
UML 图
```
classDiagram
direction BT
class GameSessionUseCase {
+play()
}
class DiceShaker {
<>
+roll()
}
class RandomDiceShakerAdapter {
}
class FixedDiceShakerAdapter {
}
class ReplayDiceShakerAdapter {
}
GameSessionUseCase --> DiceShaker : << output port >>
RandomDiceShakerAdapter ..|> DiceShaker
FixedDiceShakerAdapter ..|> DiceShaker
ReplayDiceShakerAdapter ..|> DiceShaker
```
- `DiceShaker`
此端口需要通知骰子摇动序列类型并与相关适配器交互。
## 游戏已保存端口
输出端口定义了应用程序需要从外部系统获取的内容。
UML 图
```
classDiagram
direction BT
class GameSessionUseCase {
+play()
}
class SavedGameRepository {
<>
+save(SavedGame)
+findById(id)
}
class JsonFileSavedGameRepositoryAdapter {
}
class InMemorySavedGameRepositoryAdapter {
}
GameSessionUseCase --> SavedGameRepository : << output port >>
JsonFileSavedGameRepositoryAdapter ..|> SavedGameRepository
InMemorySavedGameRepositoryAdapter ..|> SavedGameRepository
```
- `SavedGameRepository`
此端口需要通知游戏存储库已保存并与相关适配器交互。
这些适配器将应用程序连接到外部关注点
## 依赖关系
依赖关系指向应用程序核心。
```
Console / Infrastructure
↓
Adapters
↓
Ports / Interfaces
↓
Application Use Cases
↓
Domain Model
```
这意味着核心游戏逻辑不依赖于控制台输出、文件、JSON 存储,或基础设施类。
## SOLID原则
### 依赖倒置
应用程序依赖于端口接口,如 `Board`、`DiceShaker` 和 `SavedGameRepository`。
### 单一职责
每个适配器只有一个任务。例如,`JsonFileSavedGameRepositoryAdapter` 处理文件持久性,尽管适配器尚未完全实现,但该类已存在以供进一步开发,而控制台适配器处理控制台输出,例如 `ConsoleTurnAdapter` 处理每个玩家的回合输出。
### 开放/关闭
可以添加新的适配器,而无需更改核心游戏逻辑。
## 变体/高级功能
## 单骰子变体
游戏支持使用单个六面骰子进行测试,固定单骰子序列将作为标准随机双骰子设置的替代方案。
骰子系统通过骰子接口和实现进行抽象。这允许游戏使用随机双骰子/单骰子,或者在这个例子中,使用固定单骰子进行回放和测试。
### UML 图
```
classDiagram
DiceShakerFactory <|.. AbstractDiceShaker
DiceShakerFactory <|.. FixedSingleDiceShaker
AbstractDiceShaker <|-- RandomSingleDiceShaker
AbstractDiceShaker <|-- RandomDoubleDiceShaker
class DiceShakerFactory {
<>
+roll(): DiceRoll
}
class AbstractDiceShaker {
+roll(): DiceRoll
}
class RandomSingleDiceShaker {
+roll(): DiceRoll
}
class RandomDoubleDiceShaker {
+roll(): DiceRoll
}
class FixedSingleDiceShaker {
+roll(): DiceRoll
}
```
### SOLID 原则
#### 单一职责
每个骰子类只负责生成骰子滚动。
#### 开放/关闭
可以添加新的骰子类型,而无需更改主游戏会话逻辑。
#### 依赖倒置
游戏依赖于骰子抽象,而不是具体的骰子类。
## 精确终点变体
精确终点变体通过移动装饰器实现。`ExactEndVariationDecorator` 包装正常的移动行为并添加回弹逻辑。
### UML 图
```
classDiagram
Movement <|.. BasicMovement
Movement <|.. MovementDecorator
MovementDecorator <|-- ExactEndVariationDecorator
ExactEndVariationDecorator --> ExactEndRule : uses
ExactEndRule ..|> GameRule
class Movement {
<>
+move(Player, DiceRoll): TurnOutcome
}
class BasicMovement {
+move(Player, DiceRoll): TurnOutcome
}
class MovementDecorator {
-Movement wrapped
+move(Player, DiceRoll): TurnOutcome
}
class ExactEndVariationDecorator {
+move(Player, DiceRoll): TurnOutcome
}
class ExactEndRule {
+getBounceIndex(Player, int)
+decorate(Movement): Movement
}
class GameRule {
<>
+decorate(Movement): Movement
}
```
### SOLID 原则
#### 开放/关闭
精确终点行为添加而不修改 `BasicMovement`。
#### 单一职责
`ExactEndVariationDecorator` 只处理精确终点移动行为。
#### 李斯克代换
装饰器可以在期望 `Movement` 对象的地方使用。
## 击中变体
击中变体使用 **装饰器模式** 和 **策略模式**。装饰器向移动添加击中行为,而 `HitStrategy` 允许击中检测算法与规则本身分离。
### UML 图
```
classDiagram
Movement <|.. BasicMovement
Movement <|.. MovementDecorator
MovementDecorator <|-- HitVariationDecorator
HitVariationDecorator --> HitRule : uses
HitRule --> HitStrategy : uses
HitStrategy <|.. SamePositionHit
HitRule ..|> GameRule
class Movement {
<>
+move(Player, DiceRoll): TurnOutcome
}
class BasicMovement {
+move(Player, DiceRoll): TurnOutcome
}
class MovementDecorator {
-Movement wrapped
}
class HitVariationDecorator {
+move(Player, DiceRoll): TurnOutcome
}
class HitRule {
+getHitPlayer(Player, Position): Player
+decorate(Movement): Movement
}
class HitStrategy {
<>
+getHitPlayer(Player, Position): Player
}
class SamePositionHit {
+getHitPlayer(Player, Position): Player
}
class GameRule {
<>
}
```
### SOLID 原则
#### 单一职责原则
`HitVariationDecorator` 处理移动行为,而 `SamePositionHit` 处理击中检测逻辑。
#### 开放/关闭原则
可以添加新的击中策略,而无需更改 `HitRule`。
#### 依赖倒置原则
`HitRule` 依赖于 `HitStrategy` 接口,而不是具体实现。
## 传送变体
传送变体使用 **装饰器模式** 向移动添加传送行为。它还使用 **策略模式** 允许以不同的方式生成虫洞,例如固定传送位置、随机传送位置或无传送位置。
### UML 图
```
classDiagram
Movement <|.. BasicMovement
Movement <|.. MovementDecorator
MovementDecorator <|-- TeleportVariationDecorator
TeleportVariationDecorator --> TeleportRule : uses
TeleportRule --> TeleportGenerationStrategy : uses
TeleportGenerationStrategy <|.. FixedTeleportGeneration
TeleportGenerationStrategy <|.. RandomTeleportGeneration
TeleportGenerationStrategy <|.. NoOpTeleportGeneration
TeleportRule ..|> GameRule
class Movement {
<>
+move(Player, DiceRoll): TurnOutcome
}
class BasicMovement
class MovementDecorator {
-Movement wrapped
}
class TeleportVariationDecorator {
+move(Player, DiceRoll): TurnOutcome
}
class TeleportRule {
+getDestination(Position): Position
+decorate(Movement): Movement
}
class TeleportGenerationStrategy {
<>
+generate(boardSize, players): Map~Position, Position~
}
class FixedTeleportGeneration
class RandomTeleportGeneration
class NoOpTeleportGeneration
class GameRule {
<>
}
```
### SOLID 原则
#### 开放/关闭
传送行为和传送生成可以更改而不修改主移动逻辑。
#### 单一职责
`TeleportVariationDecorator` 处理传送移动,而传送生成类处理虫洞创建。
#### 依赖倒置原则
`TeleportRule` 依赖于 `TeleportGenerationStrategy`,而不是具体生成器。
## 大棋盘变体
游戏使用棋盘工厂适配器根据玩家数量创建正确的棋盘。这将棋盘创建与主游戏逻辑分离。
游戏支持两种棋盘/玩家配置:
- 小型 5x5 棋盘,2 名玩家
- 大型 6x6 棋盘,4 名玩家
### UML 图
```
classDiagram
Board <|.. BoardFactoryAdapter
BoardFactoryAdapter --> SmallBoard : instantiate
BoardFactoryAdapter --> LargeBoard : instantiate
SmallBoard --|> AbstractBoard
LargeBoard --|> AbstractBoard
AbstractBoard --|> BoardFactory
class Board {
<>
+createBoard(playerCount): BoardFactory
}
class BoardFactoryAdapter {
+createBoard(playerCount): BoardFactory
}
class BoardFactory {
<>
}
class AbstractBoard {
+getPositions(): List~Position~
+getRows(): int
+getPosition(index): Position
}
class SmallBoard
class LargeBoard
```
### SOLID 原则
#### 开放/关闭
可以添加新的棋盘类型,而无需更改主游戏流程。
#### 李斯克代换
`SmallBoard` 和 `LargeBoard` 都可以作为 `BoardFactory` 实现使用。
#### 依赖倒置
应用程序使用 `Board` 端口,而不是直接依赖于棋盘实现。
# 高级功能
## 游戏状态机
游戏状态机使用 **状态模式** 实现。每个状态控制其自己的行为,而不是使用大型条件语句。
- 准备状态
- 游戏进行状态
- 游戏结束状态
### 状态 UML 图
```
stateDiagram-v2
[*] --> Ready
Ready --> InPlay : start game / first turn
InPlay --> InPlay : next turn
InPlay --> GameOver : winning condition met
GameOver --> [*]
```
### SOLID 原则
#### 单一职责
每个状态类只处理一个游戏状态的行为。
#### 开放/关闭
可以添加新状态,而无需重写状态机。
#### 李斯克代换
所有状态实现 `GameState` 并可以互换使用。
## 游戏保存和回放
保存和回放系统使用端口和适配器将持久性和回放骰子与核心游戏逻辑分离。
游戏可以将完成的游戏保存在内存中,稍后使用保存的配置和骰子滚动进行回放。
### UML 图
```
classDiagram
ReplayGameUseCase <|.. ReplayGameService
ReplayGameService --> SavedGameRepository : loads
ReplayGameService --> ReplayDiceShaker : creates replay dice
ReplayGameService --> ReplayObserverPort : notifies
ReplayGameService --> ReplaySessionUseCase : uses
SavedGameRepository <|.. InMemorySavedGameRepositoryAdapter
SavedGameRepository <|.. JsonFileSavedGameRepositoryAdapter
ReplayDiceShaker <|.. ReplayDiceShakerAdapter
DiceShaker <|.. ReplayDiceShakerAdapter
class ReplayGameUseCase {
<>
+replay(gameId)
}
class ReplayGameService {
+replay(gameId)
}
class SavedGameRepository {
<>
+save(SavedGame)
+findById(id)
+findAll()
}
class ReplayDiceShaker {
<>
+createReplayDiceShaker(rolls): DiceShaker
}
class DiceShaker {
<>
+roll(): DiceRoll
}
class ReplayObserverPort {
<>
}
class ReplaySessionUseCase
class InMemorySavedGameRepositoryAdapter
class JsonFileSavedGameRepositoryAdapter
class ReplayDiceShakerAdapter
```
### SOLID 原则
#### 单一职责
`ReplayGameService` 处理回放,存储库处理保存/加载,回放骰子适配器重现保存的骰子滚动。
#### 依赖倒置
回放逻辑依赖于 `SavedGameRepository` 和 `ReplayDiceShaker` 接口。
#### 开放/关闭
可以添加不同的存储实现,而无需更改回放逻辑。
# 设计模式
## 工厂模式
工厂模式用于将对象创建与游戏逻辑分离。例如,`BoardFactoryAdapter` 决定是否创建 `SmallBoard` 或 `LargeBoard`。
模式用于:
- `BoardFactory`
- `SmallBoard`
- `LargeBoard`
### UML 图
```
classDiagram
class BoardFactory {
<>
}
class AbstractBoard {
+getPositions(): List~Position~
}
class SmallBoard
class LargeBoard
BoardFactory <|.. AbstractBoard
AbstractBoard <|-- SmallBoard
AbstractBoard <|-- LargeBoard
```
### SOLID 原则
#### 开放/关闭
可以添加新的棋盘类型,而无需更改游戏会话逻辑。
#### 单一职责
工厂只负责对象创建。
#### 依赖倒置
游戏使用 `Board` 抽象,而不是直接创建具体的棋盘对象。
## 策略模式
规则选择可以根据游戏是否使用固定规则、随机规则或保存的规则进行回放而更改。策略模式允许这种行为更改而不修改 `InitialiseRulesUseCase`。
模式用于:
- `RuleSelectionStrategy`
- `FixedRuleSelection`
- `RandomRuleSelection`
- `SavedRuleSelection`
- `InitialiseRulesUseCase`
### UML 图
```
classDiagram
RuleSelectionStrategy <|.. FixedRuleSelection
RuleSelectionStrategy <|.. RandomRuleSelection
RuleSelectionStrategy <|.. SavedRuleSelection
InitialiseRulesUseCase --> RuleSelectionStrategy : uses
class InitialiseRulesUseCase {
+setupRules(boardSize, players): List~GameRule~
}
class RuleSelectionStrategy {
<>
+select(availableRules): List~GameRule~
}
class FixedRuleSelection
class RandomRuleSelection
class SavedRuleSelection
```
### SOLID 原则
#### 开放/关闭
可以添加新的规则选择策略,而无需更改规则设置用例。
#### 依赖倒置
`InitialiseRulesUseCase` 依赖于 `RuleSelectionStrategy`,而不是具体的规则选择类。
## 策略模式
游戏可以以不同的方式生成传送虫洞。这允许传送可以固定、随机或禁用,而无需更改传送规则本身。
- `TeleportGenerationStrategy`
- `FixedTeleportGeneration`
- `RandomTeleportGeneration`
- `NoOpTeleportGeneration`
- `TeleportRule`
### UML 图
```
classDiagram
TeleportGenerationStrategy <|.. FixedTeleportGeneration
TeleportGenerationStrategy <|.. RandomTeleportGeneration
TeleportGenerationStrategy <|.. NoOpTeleportGeneration
TeleportRule --> TeleportGenerationStrategy : uses
class TeleportRule {
+getDestination(Position): Position
+decorate(Movement): Movement
}
class TeleportGenerationStrategy {
<>
+generate(boardSize, players): Map~Position, Position~
}
class FixedTeleportGeneration
class RandomTeleportGeneration
class NoOpTeleportGeneration
```
### SOLID 原则
#### 开放/关闭
可以添加新的传送生成方法作为新的策略。
#### 单一职责
传送生成与传送移动行为分离。
#### 依赖倒置
`TeleportRule` 依赖于 `TeleportGenerationStrategy` 抽象。
## 策略模式
击中检测被分离到策略中,以便规则可以支持未来支持不同碰撞检查方式。
模式用于:
- `HitStrategy`
- `SamePositionHit`
- `HitRule`
### UML 图
```
classDiagram
HitStrategy <|.. SamePositionHit
HitRule --> HitStrategy : uses
class HitRule {
+getHitPlayer(Player, Position): Player
+decorate(Movement): Movement
}
class HitStrategy {
<>
+getHitPlayer(Player, Position): Player
}
class SamePositionHit
```
### SOLID 原则
#### 单一职责
`SamePositionHit` 只检查玩家是否落在另一个玩家上。
#### 开放/关闭
可以添加新的击中检测算法,而无需更改 `HitRule`。
## 策略模式
不同的玩家需要根据他们的起始和结束位置不同的棋盘路径。策略模式允许路径计算更改而不更改棋盘类。
模式用于:
- `PathCalculationStrategy`
- `ForwardPathCalculation`
- `BackwardPathCalculation`
- `RotatedPathCalculation`
- `ReversedRotatedPathCalculation`
- `AbstractBoard`
### UML 图
```
classDiagram
PathCalculationStrategy <|.. ForwardPathCalculation
PathCalculationStrategy <|.. BackwardPathCalculation
PathCalculationStrategy <|.. RotatedPathCalculation
PathCalculationStrategy <|.. ReversedRotatedPathCalculation
AbstractBoard --> PathCalculationStrategy : uses
class AbstractBoard {
+calculatePath(startPos, endPos): List~Position~
}
class PathCalculationStrategy {
<>
+calculate(fullBoard, cols, startPos): List~Position~
}
class ForwardPathCalculation
class BackwardPathCalculation
class RotatedPathCalculation
class ReversedRotatedPathCalculation
```
### SOLID 原则
#### 开放/关闭
可以添加新的路径计算作为单独的类。
#### 单一职责
每个路径计算类处理一个路径算法。
## 策略模式
游戏需要为两名玩家游戏和四名玩家游戏不同的玩家起始和结束位置。策略模式避免了在玩家设置类中硬编码所有定位逻辑。
模式用于:
- `PlayerPositionStrategy`
- `TwoPlayerPosition`
- `FourPlayerPosition`
- `InitialisePlayerUseCase`
### UML 图
```
classDiagram
PlayerPositionStrategy <|.. TwoPlayerPosition
PlayerPositionStrategy <|.. FourPlayerPosition
InitialisePlayerUseCase --> PlayerPositionStrategy : uses
class InitialisePlayerUseCase {
+setupPlayers(playerCount, boardFactory)
}
class PlayerPositionStrategy {
<>
+supports(playerCount): boolean
+startPositions(start, end, cols): List~Position~
+endPositions(start, end, cols): List~Position~
}
class TwoPlayerPosition
class FourPlayerPosition
```
### SOLID 原则
#### 单一职责
每个定位策略处理一个玩家布局。
#### 开放/关闭
可以添加新的玩家数量配置作为新的策略。
## 装饰器模式
装饰器模式允许在基本移动之上分层游戏玩法变体。例如,游戏可以使用仅基本移动,或组合精确终点、击中和传送变体。
模式用于:
- `Movement`
- `BasicMovement`
- `MovementDecorator`
- `ExactEndVariationDecorator`
- `HitVariationDecorator`
- `TeleportVariationDecorator`
### UML 图
```
classDiagram
Movement <|.. BasicMovement
Movement <|.. MovementDecorator
MovementDecorator --> Movement : wraps
MovementDecorator <|-- ExactEndVariationDecorator
MovementDecorator <|-- HitVariationDecorator
MovementDecorator <|-- TeleportVariationDecorator
class Movement {
<>
+move(Player, DiceRoll): TurnOutcome
}
class BasicMovement {
+move(Player, DiceRoll): TurnOutcome
}
class MovementDecorator {
-Movement wrapped
+move(Player, DiceRoll): TurnOutcome
}
class ExactEndVariationDecorator
class HitVariationDecorator
class TeleportVariationDecorator
```
### SOLID 原则
#### 单一职责
每个装饰器处理一个规则。
#### 开放/关闭
可以添加新的移动规则,而无需编辑 `BasicMovement`。
#### 李斯克代换
每个装饰器实现 `Movement`,因此它可以替换任何其他移动对象。
## 观察者模式
观察者模式将游戏事件与控制台输出解耦。游戏不需要知道事件如何显示。
模式用于:
- `TurnObserverPort`
- `GameStartedObserverPort`
- `GameEndedObserverPort`
- `GameSavedObserverPort`
- `GamERunnerObserverPort`
- `ConsoleTurnAdapter`
- `ConsoleGameStartedAdapter`
- `ConsoleGameEndedAdapter`
- `ConsoleGameSavedAdapter`
- `ConsoleGameRunnerDisplayAdapter`
### UML 图
```
classDiagram
direction TB
TurnObserverPort <|.. ConsoleTurnAdapter
GameStartedObserverPort <|.. ConsoleGameStartedAdapter
GameEndedObserverPort <|.. ConsoleGameEndedAdapter
GameSavedObserverPort <|.. ConsoleGameSavedAdapter
GameRunnerObserverPort <|.. ConsoleGameRunnerDisplayAdapter
class TurnObserverPort {
<>
+onTurnPlayed(PlayerTurn playerTurn): void
}
class GameStartedObserverPort {
<>
+onGameStarted(GameStartInfo gameStartInfo): void
}
class GameEndedObserverPort {
<>
+onGameEnded(GameEndInfo info): void
}
class GameSavedObserverPort {
<>
+onGameSaved(SavedGame savedGame): void
}
class GameRunnerObserverPort {
<>
+onGameRunStarted(int gameNumber): void
+onReplayRunStarted(): void
+onReplaySelected(SavedGame savedGame): void
+onReplayNotFound(int gameId): void
}
class ConsoleTurnAdapter
class ConsoleGameStartedAdapter
class ConsoleGameEndedAdapter
class ConsoleGameSavedAdapter
class ConsoleGameRunnerDisplayAdapter
```
### SOLID 原则
#### 单一职责
游戏逻辑产生事件,而控制台适配器显示它们。
#### 开放/关闭
可以添加新的观察者,而无需更改游戏会话逻辑。
#### 依赖倒置
游戏依赖于观察者接口,而不是控制台类。
## 存储库模式
存储库模式将游戏保存和加载与主游戏逻辑分离。
模式用于:
- `SavedGameRepository`
- `InMemorySavedGameRepositoryAdapter`
- `JsonFileSavedGameRepositoryAdapter`
- `SavedGame`
### UML 图
```
classDiagram
SavedGameRepository <|.. InMemorySavedGameRepositoryAdapter
SavedGameRepository <|.. JsonFileSavedGameRepositoryAdapter
InMemorySavedGameRepositoryAdapter --> SavedGame : stores
JsonFileSavedGameRepositoryAdapter --> SavedGame : stores
class SavedGameRepository {
<>
+nextId()
+save(SavedGame)
+findById(id): SavedGame
+findAll(): List~SavedGame~
}
class InMemorySavedGameRepositoryAdapter
class JsonFileSavedGameRepositoryAdapter
class SavedGame {
+recordRoll(DiceRoll)
+getConfiguration()
+getDiceRolls()
}
```
### SOLID 原则
#### 单一职责
存储库类只处理持久性。
#### 开放/关闭
可以添加新的存储方法,而无需更改游戏或回放服务。
#### 依赖倒置
用例依赖于 `SavedGameRepository`,而不是文件或内存存储直接。
# 综合评估
实现成功地将面向对象设计、清洁架构和多个设计模式应用于解决棋盘游戏模拟的需求。
## 优点
### 可维护性
代码被拆分为清晰的职责,例如领域模型、用例、端口和基础设施适配器。
### 可扩展性
项目可以以最小的现有代码更改支持新的规则、骰子类型、棋盘、存储系统和显示系统。
### 可测试性
由于应用程序依赖于接口,因此可以将依赖关系替换为模拟或测试双倍。
### 设计模式的好用
游戏使用模式来解决真实的设计问题:
- 工厂用于棋盘和骰子创建
- 策略用于可互换算法
- 装饰器用于组合移动规则
- 状态用于生命周期管理
- 观察者用于事件通知
- 存储库用于保存/回放性
- 适配器用于基础设施分离
## 局限性
### 类和复杂性更多
使用多个模式增加了类的数量,这可能会使项目在最初难以理解。
### 仅控制台界面
当前实现使用控制台适配器。然而,由于架构,可以稍后添加 GUI 或 Web 界面。
### 一些行为取决于配置
游戏依赖于策略、装饰器、观察器和适配器的正确连接。这很灵活,但也意味着必须仔细管理配置。
## 结论
游戏展示了清洁架构和面向对象设计的强大实现。端口和适配器的使用使领域独立于基础设施,而设计模式使游戏足够灵活,以支持所需变体和高级功能。
## 示例输出
```
=== GAME 1 ===
Players: 2
Board Size: 25
Game Rules: None
Fixed sequence of dice rolls [1, 2, 3, 4, 5, 6]
Board: rows = 5 columns = 5
RED Home (Position 1), 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, End (Position 25)
BLUE Home (Position 25), 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, End (Position 1)
RED's turn 1 rolls Single Dice 1
RED moves from Home (Position 1) to 2
BLUE's turn 1 rolls Single Dice 2
BLUE moves from Home (Position 25) to 23
...
BLUE wins! in 12 turns
Total turns: 12
Game State: InPlay → GameOver
Dice rolls: {1, 2, 3, 4, 5, 6, 1, 2, 3, 4, 5, 6}
Game Id: 1 saved.
```
## 许可证
本项目采用 MIT 许可证。
有关更多信息,请参阅 `LICENSE` 文件。
标签:JS文件枚举, wormhole, 仓储模式, 内存模拟, 回合制游戏, 域名枚举, 多人游戏, 工厂模式, 架构设计, 棋盘游戏, 游戏存储, 游戏开发, 游戏引擎, 游戏玩法, 游戏规则, 游戏运行, 游戏逻辑, 游戏配置, 状态模式, 用户交互, 端口适配器架构, 策略模式, 装饰者模式, 观察者模式, 设计模式, 随机数生成