Files
xzmaster/backend/src/main/java/com/xuezhanmaster/game/service/SettlementService.java
hujun 36dcfb7d31 feat: 实现麻将游戏结算系统与自摸胡功能
新增结算类型枚举和分数变更记录模型
补全响应裁决器与结算服务,支持点炮胡、自摸胡和明杠结算
扩展座位模型,增加已胡状态和分数字段
完善胡牌评估器,支持自摸胡判断
前端原型页增加分数显示和已胡状态
更新SPRINT文档记录当前进度
2026-03-20 13:58:16 +08:00

119 lines
3.7 KiB
Java

package com.xuezhanmaster.game.service;
import com.xuezhanmaster.game.domain.ActionType;
import com.xuezhanmaster.game.domain.GameSeat;
import com.xuezhanmaster.game.domain.GameTable;
import com.xuezhanmaster.game.domain.ScoreChange;
import com.xuezhanmaster.game.domain.SettlementResult;
import com.xuezhanmaster.game.domain.SettlementType;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
@Service
public class SettlementService {
private static final int DIAN_PAO_HU_SCORE = 1;
private static final int ZI_MO_HU_SCORE = 1;
private static final int MING_GANG_SCORE = 1;
public SettlementResult settleDiscardHu(
GameTable table,
int winnerSeatNo,
int sourceSeatNo,
String triggerTile
) {
return applySettlement(
table,
SettlementType.DIAN_PAO_HU,
ActionType.HU,
winnerSeatNo,
sourceSeatNo,
triggerTile,
orderedDeltas(winnerSeatNo, DIAN_PAO_HU_SCORE, sourceSeatNo, -DIAN_PAO_HU_SCORE)
);
}
public SettlementResult settleExposedGang(
GameTable table,
int winnerSeatNo,
int sourceSeatNo,
String triggerTile
) {
return applySettlement(
table,
SettlementType.MING_GANG,
ActionType.GANG,
winnerSeatNo,
sourceSeatNo,
triggerTile,
orderedDeltas(winnerSeatNo, MING_GANG_SCORE, sourceSeatNo, -MING_GANG_SCORE)
);
}
public SettlementResult settleSelfDrawHu(
GameTable table,
int winnerSeatNo,
String triggerTile
) {
Map<Integer, Integer> scoreDeltas = new LinkedHashMap<>();
int totalWinScore = 0;
for (GameSeat seat : table.getSeats()) {
if (seat.getSeatNo() == winnerSeatNo || seat.isWon()) {
continue;
}
scoreDeltas.put(seat.getSeatNo(), -ZI_MO_HU_SCORE);
totalWinScore += ZI_MO_HU_SCORE;
}
scoreDeltas.put(winnerSeatNo, totalWinScore);
return applySettlement(
table,
SettlementType.ZI_MO_HU,
ActionType.HU,
winnerSeatNo,
winnerSeatNo,
triggerTile,
scoreDeltas
);
}
private SettlementResult applySettlement(
GameTable table,
SettlementType settlementType,
ActionType actionType,
int actorSeatNo,
int sourceSeatNo,
String triggerTile,
Map<Integer, Integer> scoreDeltas
) {
List<ScoreChange> scoreChanges = new ArrayList<>();
for (Map.Entry<Integer, Integer> entry : scoreDeltas.entrySet()) {
GameSeat seat = table.getSeats().get(entry.getKey());
seat.addScore(entry.getValue());
scoreChanges.add(new ScoreChange(
seat.getSeatNo(),
entry.getValue(),
seat.getScore()
));
}
return new SettlementResult(
settlementType,
actionType,
actorSeatNo,
sourceSeatNo,
triggerTile,
List.copyOf(scoreChanges)
);
}
private Map<Integer, Integer> orderedDeltas(int winnerSeatNo, int winnerDelta, int sourceSeatNo, int sourceDelta) {
Map<Integer, Integer> deltas = new LinkedHashMap<>();
deltas.put(winnerSeatNo, winnerDelta);
deltas.put(sourceSeatNo, sourceDelta);
return deltas;
}
}