update MancalaGame and Board

This commit is contained in:
Halit Aksoy 2022-05-04 15:04:41 +03:00
parent 81a74a416e
commit ed6787f2e6
2 changed files with 134 additions and 44 deletions

View File

@ -17,10 +17,16 @@ export class Board {
onGameMove: (index: number) => void = () => {}; onGameMove: (index: number) => void = () => {};
onGameMoveEnd: (index: number) => void = () => {}; onGameMoveEnd: (index: number) => void = () => {};
constructor(playerPitCount: number, initialStoneCountInPits: number) { constructor(
playerPitCount: number,
initialStoneCountInPits: number,
pits: Pit[] | null = null
) {
this.playerPitCount = playerPitCount; this.playerPitCount = playerPitCount;
this.initialStoneCountInPits = initialStoneCountInPits; this.initialStoneCountInPits = initialStoneCountInPits;
this.pits = this.createPits(playerPitCount, initialStoneCountInPits); this.pits = pits
? pits
: this.createPits(playerPitCount, initialStoneCountInPits);
} }
createPits(playerPitCount: number, initialStoneCountInPits: number): Pit[] { createPits(playerPitCount: number, initialStoneCountInPits: number): Pit[] {
@ -140,4 +146,57 @@ export class Board {
public getStoneArray(): number[] { public getStoneArray(): number[] {
return [...this.pits.map((pit) => pit.stoneCount)]; return [...this.pits.map((pit) => pit.stoneCount)];
} }
public get player1Pits(): Pit[] {
return this.pits.slice(
this.player1PitStartIndex(),
this.player1BankIndex()
);
}
get player2Pits(): Pit[] {
return this.pits.slice(
this.player2PitStartIndex(),
this.player2BankIndex()
);
}
get player1Bank(): Bank {
return this.pits[this.player1BankIndex()];
}
get player2Bank(): Bank {
return this.pits[this.player2BankIndex()];
}
public getOppositePitIndex(index: number) {
if (index > this.player1BankIndex()) {
return this.player2PitStopIndex() - index;
} else {
return this.player1BankIndex() + this.playerPitCount - index;
}
}
public clear() {
this.player1Bank.stoneCount = 0;
this.player2Bank.stoneCount = 0;
this.clearPlayer1Pits();
this.clearPlayer2Pits();
}
public clearPlayer1Pits() {
this.fillPlayer1Pits(0);
}
public clearPlayer2Pits() {
this.fillPlayer2Pits(0);
}
public fillPlayer1Pits(stoneCount: number) {
this.player1Pits.forEach((pit) => (pit.stoneCount = stoneCount));
}
public fillPlayer2Pits(stoneCount: number) {
this.player2Pits.forEach((pit) => (pit.stoneCount = stoneCount));
}
} }

View File

@ -1,29 +1,29 @@
import { Board, PitType } from './Board'; import { Board, PitType } from './Board';
import { GameRule } from './GameRule'; import { GameRule } from './GameRule';
import { Player } from './Player';
export type GameState = 'initial' | 'playing' | 'ended'; export type GameState = 'initial' | 'playing' | 'ended';
export class MancalaGame { export class MancalaGame {
board: Board; board: Board;
player1: Player; player1Id: string;
player2: Player; player2Id: string;
turnPlayerId: string; turnPlayerId: string;
state: GameState; state: GameState;
gameRules: GameRule[]; gameRules: GameRule[];
constructor( constructor(
board: Board, board: Board,
player1: Player, player1Id: string,
player2: Player, player2Id: string,
turnPlayerId: string, turnPlayerId: string,
gameRules: GameRule[] gameRules: GameRule[],
state: GameState = 'initial'
) { ) {
this.board = board; this.board = board;
this.player1 = player1; this.player1Id = player1Id;
this.player2 = player2; this.player2Id = player2Id;
this.turnPlayerId = turnPlayerId; this.turnPlayerId = turnPlayerId;
this.state = 'initial'; this.state = state;
this.gameRules = gameRules; this.gameRules = gameRules;
this.listenBoardMoveEvents(); this.listenBoardMoveEvents();
} }
@ -47,89 +47,92 @@ export class MancalaGame {
} }
changePlayerTurn() { changePlayerTurn() {
if (this.turnPlayerId === this.player1.id) { if (this.turnPlayerId === this.player1Id) {
this.turnPlayerId = this.player2.id; this.turnPlayerId = this.player2Id;
} else { } else {
this.turnPlayerId = this.player1.id; this.turnPlayerId = this.player1Id;
} }
} }
isTurnPlayer1() { isTurnPlayer1() {
return this.player1.id === this.turnPlayerId; return this.player1Id === this.turnPlayerId;
} }
isTurnPlayer2() { isTurnPlayer2() {
return this.player2.id === this.turnPlayerId; return this.player2Id === this.turnPlayerId;
} }
getPlayerByPitType(pitType: PitType): Player { getPlayerIdByPitType(pitType: PitType): string {
if (pitType === 'player1Pit' || pitType === 'player1Bank') { if (pitType === 'player1Pit' || pitType === 'player1Bank') {
return this.player1; return this.player1Id;
} else if (pitType === 'player2Pit' || pitType === 'player2Bank') { } else if (pitType === 'player2Pit' || pitType === 'player2Bank') {
return this.player2; return this.player2Id;
} else { } else {
throw new Error('Unknown pit type : ' + pitType); throw new Error('Unknown pit type : ' + pitType);
} }
} }
getPlayerByIndex(index: number): Player { getPlayerIdByIndex(index: number): string {
const pitType = this.board.getPitTypeByIndex(index); const pitType = this.board.getPitTypeByIndex(index);
return this.getPlayerByPitType(pitType); return this.getPlayerIdByPitType(pitType);
} }
checkIsPlayerTurnByIndex(index: number): boolean { checkIsPlayerTurnByIndex(index: number): boolean {
const player = this.getPlayerByIndex(index); const playerId = this.getPlayerIdByIndex(index);
return this.checkIsPlayerTurn(player); return this.checkIsPlayerTurn(playerId);
} }
getBoardIndexByPlayer(player: Player, pitIndex: number) { getBoardIndexByPlayerId(playerId: string, pitIndex: number) {
if (this.player1.id === player.id) { if (this.player1Id === playerId) {
return this.board.player1PitStartIndex() + pitIndex; return this.board.player1PitStartIndex() + pitIndex;
} else if (this.player2.id === player.id) { } else if (this.player2Id === playerId) {
return this.board.player2PitStartIndex() + pitIndex; return this.board.player2PitStartIndex() + pitIndex;
} else { } else {
return -1; // throwing an error might be better return -1; // throwing an error might be better
} }
} }
public checkIsPlayerTurn(player: Player) { public checkIsPlayerTurn(playerId: string) {
return player.id === this.turnPlayerId; return playerId === this.turnPlayerId;
} }
public checkPitIndexForPlayer(player: Player, pitIndex: number) { public checkPitIndexForPlayerId(playerId: string, pitIndex: number) {
const foundPlayer = this.getPlayerByIndex( const foundPlayerId = this.getPlayerIdByIndex(
this.getBoardIndexByPlayer(player, pitIndex) this.getBoardIndexByPlayerId(playerId, pitIndex)
); );
return player.id === foundPlayer.id; return playerId === foundPlayerId;
} }
public checkIsPitIndexBank(player: Player, pitIndex: number) { public checkIsPitIndexBank(playerId: string, pitIndex: number) {
const pitType = this.board.getPitTypeByIndex( const pitType = this.board.getPitTypeByIndex(
this.getBoardIndexByPlayer(player, pitIndex) this.getBoardIndexByPlayerId(playerId, pitIndex)
); );
return pitType === 'player1Bank' || pitType === 'player2Bank'; return pitType === 'player1Bank' || pitType === 'player2Bank';
} }
public canPlayerMove(player: Player, pitIndex: number) { public canPlayerMove(playerId: string, pitIndex: number) {
const isPitIndexCorrect = this.checkPitIndexForPlayer(player, pitIndex); const isPitIndexCorrect = this.checkPitIndexForPlayerId(playerId, pitIndex);
const isPitIndexBank = this.checkIsPitIndexBank(player, pitIndex); const isPitIndexBank = this.checkIsPitIndexBank(playerId, pitIndex);
const isPlayerTurn = this.checkIsPlayerTurn(player); const isPlayerTurn = this.checkIsPlayerTurn(playerId);
return isPitIndexCorrect && !isPitIndexBank && isPlayerTurn; return isPitIndexCorrect && !isPitIndexBank && isPlayerTurn;
} }
public moveByPlayerPit(player: Player, pitIndex: number) { public moveByPlayerPit(playerId: string, pitIndex: number) {
if (this.state === 'ended') return; if (this.state === 'ended') return;
if (this.state === 'initial') { if (this.state === 'initial') {
this.state = 'playing'; this.state = 'playing';
} }
if (this.canPlayerMove(player, pitIndex)) { if (this.canPlayerMove(playerId, pitIndex)) {
this.board.move(this.getBoardIndexByPlayer(player, pitIndex)); this.board.move(this.getBoardIndexByPlayerId(playerId, pitIndex));
if (this.checkGameIsEnded()) { if (this.checkGameIsEnded()) {
this.state = 'ended'; this.state = 'ended';
} }
} else { } else {
const isPitIndexCorrect = this.checkPitIndexForPlayer(player, pitIndex); const isPitIndexCorrect = this.checkPitIndexForPlayerId(
const isPlayerTurn = this.checkIsPlayerTurn(player); playerId,
pitIndex
);
const isPlayerTurn = this.checkIsPlayerTurn(playerId);
throw new Error( throw new Error(
`Player cannot move reason : isPitIndexCorrect = ${isPitIndexCorrect} isPlayerTurn = ${isPlayerTurn}` `Player cannot move reason : isPitIndexCorrect = ${isPitIndexCorrect} isPlayerTurn = ${isPlayerTurn}`
); );
@ -165,7 +168,7 @@ export class MancalaGame {
); );
} }
checkGameIsEnded(): boolean { public checkGameIsEnded(): boolean {
if ( if (
this.getPlayer1StoneCountInPits() === 0 || this.getPlayer1StoneCountInPits() === 0 ||
this.getPlayer2StoneCountInPits() === 0 this.getPlayer2StoneCountInPits() === 0
@ -174,4 +177,32 @@ export class MancalaGame {
} }
return false; return false;
} }
public getWonPlayerId(): string | null {
if (this.checkGameIsEnded()) {
if (
this.board.player1Bank.stoneCount > this.board.player2Bank.stoneCount
) {
return this.player1Id;
} else {
return this.player2Id;
}
}
return null;
}
public static createFromMancalaGame(mancalaGame: MancalaGame): MancalaGame {
return new MancalaGame(
new Board(
mancalaGame.board.playerPitCount,
mancalaGame.board.initialStoneCountInPits,
mancalaGame.board.pits
),
mancalaGame.player1Id,
mancalaGame.player2Id,
mancalaGame.turnPlayerId,
mancalaGame.gameRules,
mancalaGame.state
);
}
} }