add board
This commit is contained in:
parent
20885474db
commit
39138354b7
143
src/core/Board.ts
Normal file
143
src/core/Board.ts
Normal file
@ -0,0 +1,143 @@
|
|||||||
|
import { Bank, Pit } from './Pit';
|
||||||
|
|
||||||
|
const bankCount = 2;
|
||||||
|
|
||||||
|
export type PitType =
|
||||||
|
| 'player1Pit'
|
||||||
|
| 'player1Bank'
|
||||||
|
| 'player2Pit'
|
||||||
|
| 'player2Bank';
|
||||||
|
|
||||||
|
export class Board {
|
||||||
|
pits: Pit[];
|
||||||
|
playerPitCount: number;
|
||||||
|
initialStoneCountInPits: number;
|
||||||
|
|
||||||
|
onGameMoveStart: (index: number) => void = () => {};
|
||||||
|
onGameMove: (index: number) => void = () => {};
|
||||||
|
onGameMoveEnd: (index: number) => void = () => {};
|
||||||
|
|
||||||
|
constructor(playerPitCount: number, initialStoneCountInPits: number) {
|
||||||
|
this.playerPitCount = playerPitCount;
|
||||||
|
this.initialStoneCountInPits = initialStoneCountInPits;
|
||||||
|
this.pits = this.createPits(playerPitCount, initialStoneCountInPits);
|
||||||
|
}
|
||||||
|
|
||||||
|
createPits(playerPitCount: number, initialStoneCountInPits: number): Pit[] {
|
||||||
|
const totalPitCount = playerPitCount + playerPitCount + bankCount;
|
||||||
|
const pitArray = new Array<Pit>(totalPitCount);
|
||||||
|
for (let index = 0; index < this.totalPitCount(); index++) {
|
||||||
|
const pitType = this.getPitTypeByIndex(index);
|
||||||
|
if (pitType === 'player1Pit' || pitType === 'player2Pit') {
|
||||||
|
pitArray[index] = new Pit(initialStoneCountInPits);
|
||||||
|
} else if (pitType === 'player1Bank' || pitType === 'player2Bank') {
|
||||||
|
pitArray[index] = new Bank(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return pitArray;
|
||||||
|
}
|
||||||
|
|
||||||
|
public player1PitStartIndex = () => 0;
|
||||||
|
public player1PitStopIndex = () =>
|
||||||
|
this.player1PitStartIndex() + this.playerPitCount - 1;
|
||||||
|
public player1BankIndex = () => this.player1PitStopIndex() + 1;
|
||||||
|
public player2PitStartIndex = () => this.player1BankIndex() + 1;
|
||||||
|
public player2PitStopIndex = () =>
|
||||||
|
this.player2PitStartIndex() + this.playerPitCount - 1;
|
||||||
|
public player2BankIndex = () => this.player2PitStopIndex() + 1;
|
||||||
|
public totalPitCount = () => this.player2BankIndex() + 1;
|
||||||
|
|
||||||
|
public checkIndex(index: number): boolean {
|
||||||
|
return (
|
||||||
|
index >= this.player1PitStartIndex() && index <= this.player2BankIndex()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
checkIndeAndMaybeThrowError(index: number): void {
|
||||||
|
if (!this.checkIndex(index)) {
|
||||||
|
throw new Error(
|
||||||
|
`IndexOutOfRange => index : ${index} [start, stop] = [${this.player1PitStartIndex()}, ${this.player2BankIndex()}]`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public getPitTypeByIndex(index: number): PitType {
|
||||||
|
this.checkIndeAndMaybeThrowError(index);
|
||||||
|
if (
|
||||||
|
index >= this.player1PitStartIndex() &&
|
||||||
|
index <= this.player1PitStopIndex()
|
||||||
|
) {
|
||||||
|
return 'player1Pit';
|
||||||
|
} else if (index === this.player1BankIndex()) {
|
||||||
|
return 'player1Bank';
|
||||||
|
} else if (index <= this.player2PitStopIndex()) {
|
||||||
|
return 'player2Pit';
|
||||||
|
} else {
|
||||||
|
return 'player2Bank';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public move(index: number) {
|
||||||
|
this.checkIndeAndMaybeThrowError(index);
|
||||||
|
const pitType = this.getPitTypeByIndex(index);
|
||||||
|
if (pitType === 'player1Bank' || pitType === 'player2Bank') {
|
||||||
|
throw new Error(`InCorrectPit => index : ${index} pitType = ${pitType}`);
|
||||||
|
}
|
||||||
|
const pit = this.pits[index];
|
||||||
|
if (pit.stoneCount <= 0) {
|
||||||
|
throw new Error(
|
||||||
|
`StoneNotFound => index : ${index} stoneCount = ${pit.stoneCount}`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
const stepCount = pit.stoneCount;
|
||||||
|
this.pits[index].stoneCount = 0;
|
||||||
|
this.fireOnGameMoveStart(index);
|
||||||
|
if (stepCount === 1) {
|
||||||
|
this.fireOnGameMove(index);
|
||||||
|
this.getNextPitCircularly(index).increaseStone();
|
||||||
|
const nextPitIndex = this.getNextPitIndexCircularly(index);
|
||||||
|
this.fireOnGameMove(nextPitIndex);
|
||||||
|
this.fireOnGameMoveEnd(nextPitIndex);
|
||||||
|
} else {
|
||||||
|
for (let i = 0; i < stepCount; i++) {
|
||||||
|
const pit = this.getPitCircularly(index + i);
|
||||||
|
pit.increaseStone();
|
||||||
|
this.fireOnGameMove(index + i);
|
||||||
|
}
|
||||||
|
this.fireOnGameMoveEnd(index + stepCount - 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public getNextPitCircularly(currentPitIndex: number) {
|
||||||
|
return this.pits[this.getNextPitIndexCircularly(currentPitIndex)];
|
||||||
|
}
|
||||||
|
|
||||||
|
public getNextPitIndexCircularly(currentPitIndex: number) {
|
||||||
|
this.checkIndeAndMaybeThrowError(currentPitIndex);
|
||||||
|
return this.getPitIndexCircularly(currentPitIndex + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
public getPitCircularly(currentPitIndex: number) {
|
||||||
|
return this.pits[this.getPitIndexCircularly(currentPitIndex)];
|
||||||
|
}
|
||||||
|
|
||||||
|
public getPitIndexCircularly(currentPitIndex: number) {
|
||||||
|
return currentPitIndex % this.totalPitCount();
|
||||||
|
}
|
||||||
|
|
||||||
|
fireOnGameMoveStart(index: number): void {
|
||||||
|
this.onGameMoveStart(index);
|
||||||
|
}
|
||||||
|
|
||||||
|
fireOnGameMove(index: number): void {
|
||||||
|
this.onGameMove(index);
|
||||||
|
}
|
||||||
|
|
||||||
|
fireOnGameMoveEnd(index: number): void {
|
||||||
|
this.onGameMoveEnd(index);
|
||||||
|
}
|
||||||
|
|
||||||
|
public getStoneArray(): number[] {
|
||||||
|
return [...this.pits.map((pit) => pit.stoneCount)];
|
||||||
|
}
|
||||||
|
}
|
||||||
92
tests/Board.test.ts
Normal file
92
tests/Board.test.ts
Normal file
@ -0,0 +1,92 @@
|
|||||||
|
import { Board } from '../src/core/Board';
|
||||||
|
|
||||||
|
describe('Board Test', () => {
|
||||||
|
test('test getPitTypeByIndex', () => {
|
||||||
|
const board = new Board(6, 4);
|
||||||
|
expect(board.getPitTypeByIndex(0)).toBe('player1Pit');
|
||||||
|
expect(board.getPitTypeByIndex(1)).toBe('player1Pit');
|
||||||
|
expect(board.getPitTypeByIndex(2)).toBe('player1Pit');
|
||||||
|
expect(board.getPitTypeByIndex(3)).toBe('player1Pit');
|
||||||
|
expect(board.getPitTypeByIndex(4)).toBe('player1Pit');
|
||||||
|
expect(board.getPitTypeByIndex(5)).toBe('player1Pit');
|
||||||
|
expect(board.getPitTypeByIndex(6)).toBe('player1Bank');
|
||||||
|
expect(board.getPitTypeByIndex(7)).toBe('player2Pit');
|
||||||
|
expect(board.getPitTypeByIndex(8)).toBe('player2Pit');
|
||||||
|
expect(board.getPitTypeByIndex(9)).toBe('player2Pit');
|
||||||
|
expect(board.getPitTypeByIndex(10)).toBe('player2Pit');
|
||||||
|
expect(board.getPitTypeByIndex(11)).toBe('player2Pit');
|
||||||
|
expect(board.getPitTypeByIndex(12)).toBe('player2Pit');
|
||||||
|
expect(board.getPitTypeByIndex(13)).toBe('player2Bank');
|
||||||
|
expect(() => board.getPitTypeByIndex(-1)).toThrowError();
|
||||||
|
expect(() => board.getPitTypeByIndex(14)).toThrowError();
|
||||||
|
});
|
||||||
|
test('test checkIndex', () => {
|
||||||
|
const board = new Board(6, 4);
|
||||||
|
expect(board.checkIndex(0)).toBe(true);
|
||||||
|
expect(board.checkIndex(1)).toBe(true);
|
||||||
|
expect(board.checkIndex(2)).toBe(true);
|
||||||
|
expect(board.checkIndex(4)).toBe(true);
|
||||||
|
expect(board.checkIndex(5)).toBe(true);
|
||||||
|
expect(board.checkIndex(6)).toBe(true);
|
||||||
|
expect(board.checkIndex(7)).toBe(true);
|
||||||
|
expect(board.checkIndex(8)).toBe(true);
|
||||||
|
expect(board.checkIndex(9)).toBe(true);
|
||||||
|
expect(board.checkIndex(10)).toBe(true);
|
||||||
|
expect(board.checkIndex(11)).toBe(true);
|
||||||
|
expect(board.checkIndex(12)).toBe(true);
|
||||||
|
expect(board.checkIndex(13)).toBe(true);
|
||||||
|
expect(board.checkIndex(14)).toBe(false);
|
||||||
|
expect(board.checkIndex(-1)).toBe(false);
|
||||||
|
});
|
||||||
|
test('test getPitIndexCircularly', () => {
|
||||||
|
const board = new Board(6, 4);
|
||||||
|
expect(board.getPitIndexCircularly(0)).toBe(0);
|
||||||
|
expect(board.getPitIndexCircularly(1)).toBe(1);
|
||||||
|
expect(board.getPitIndexCircularly(2)).toBe(2);
|
||||||
|
expect(board.getPitIndexCircularly(3)).toBe(3);
|
||||||
|
expect(board.getPitIndexCircularly(4)).toBe(4);
|
||||||
|
expect(board.getPitIndexCircularly(5)).toBe(5);
|
||||||
|
expect(board.getPitIndexCircularly(6)).toBe(6);
|
||||||
|
expect(board.getPitIndexCircularly(7)).toBe(7);
|
||||||
|
expect(board.getPitIndexCircularly(8)).toBe(8);
|
||||||
|
expect(board.getPitIndexCircularly(9)).toBe(9);
|
||||||
|
expect(board.getPitIndexCircularly(10)).toBe(10);
|
||||||
|
expect(board.getPitIndexCircularly(11)).toBe(11);
|
||||||
|
expect(board.getPitIndexCircularly(12)).toBe(12);
|
||||||
|
expect(board.getPitIndexCircularly(13)).toBe(13);
|
||||||
|
expect(board.getPitIndexCircularly(14)).toBe(0);
|
||||||
|
expect(board.getPitIndexCircularly(15)).toBe(1);
|
||||||
|
expect(board.getPitIndexCircularly(16)).toBe(2);
|
||||||
|
});
|
||||||
|
test('test move', () => {
|
||||||
|
const board = new Board(6, 4);
|
||||||
|
const initialBoard = [4, 4, 4, 4, 4, 4, 0, 4, 4, 4, 4, 4, 4, 0];
|
||||||
|
expect(board.getStoneArray()).toStrictEqual(initialBoard);
|
||||||
|
board.move(0);
|
||||||
|
expect(board.getStoneArray()).toStrictEqual([
|
||||||
|
1, 5, 5, 5, 4, 4, 0, 4, 4, 4, 4, 4, 4, 0
|
||||||
|
]);
|
||||||
|
board.move(0);
|
||||||
|
expect(board.getStoneArray()).toStrictEqual([
|
||||||
|
0, 6, 5, 5, 4, 4, 0, 4, 4, 4, 4, 4, 4, 0
|
||||||
|
]);
|
||||||
|
board.move(1);
|
||||||
|
expect(board.getStoneArray()).toStrictEqual([
|
||||||
|
0, 1, 6, 6, 5, 5, 1, 4, 4, 4, 4, 4, 4, 0
|
||||||
|
]);
|
||||||
|
board.move(5);
|
||||||
|
expect(board.getStoneArray()).toStrictEqual([
|
||||||
|
0, 1, 6, 6, 5, 1, 2, 5, 5, 5, 4, 4, 4, 0
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
test('test move 2', () => {
|
||||||
|
const board = new Board(6, 4);
|
||||||
|
board.pits[5].stoneCount = 15;
|
||||||
|
const initialBoard = [4, 4, 4, 4, 4, 15, 0, 4, 4, 4, 4, 4, 4, 0];
|
||||||
|
expect(board.getStoneArray()).toStrictEqual(initialBoard);
|
||||||
|
board.move(5);
|
||||||
|
expect(board.getStoneArray()).toStrictEqual([
|
||||||
|
5, 5, 5, 5, 5, 2, 1, 5, 5, 5, 5, 5, 5, 1
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
});
|
||||||
Loading…
Reference in New Issue
Block a user