diff --git a/src/game/Game.test.ts b/src/game/Game.test.ts index 8a0c7fb..3b7530a 100644 --- a/src/game/Game.test.ts +++ b/src/game/Game.test.ts @@ -21,7 +21,7 @@ describe("GameState", () => { test("getting cell works", () => { const game = new Game(threeByThreeMatrix, [["AA"]], unrestrictedBuffer, unlimitedTime); - expect(game.getCell(0, 2)).toEqual("02") + expect(game.getCell(0, 2)).toEqual({ value: "02", isUsed: false }) }); describe("picking", () => { @@ -34,11 +34,18 @@ describe("GameState", () => { const game = new Game(threeByThreeMatrix, [["AA"]], unrestrictedBuffer, unlimitedTime); game.pick(0, 0); expect(game.state).toEqual({selectionMode: SelectionMode.RowPick, column: 0}); + expect(game.getCell(0, 0).isUsed).toEqual(true); expect(() => game.pick(0, 2)).toThrow(); game.pick(2, 0); expect(game.state).toEqual({selectionMode: SelectionMode.ColumnPick, row: 2}); }); + test("cannot pick cell twice", () => { + const game = new Game(threeByThreeMatrix, [["AA"]], unrestrictedBuffer, unlimitedTime); + game.pick(0, 0); + expect(() => game.pick(0, 0)).toThrow(); + }); + test("picking outside of range fails", () => { const game = new Game(threeByThreeMatrix, [], unrestrictedBuffer, unlimitedTime); expect(() => game.pick(-1, 0)).toThrow(); @@ -52,7 +59,11 @@ describe("GameState", () => { const game = new Game(threeByThreeMatrix, [simpleSequence], unrestrictedBuffer, unlimitedTime); expect(game.getSequences()).toEqual([{sequence: simpleSequence, numberOfFulfilled: 0}]) game.pick(0, 0); - expect(game.buffer).toEqual(["00"]); + expect(game.buffer).toEqual([{ + positionInMatrixRow: 0, + positionInMatrixColumn: 0, + value: "00" + }]); expect(game.getSequences()).toEqual([{sequence: simpleSequence, numberOfFulfilled: 1}]) }); diff --git a/src/game/Game.ts b/src/game/Game.ts index f6fda32..493f3ce 100644 --- a/src/game/Game.ts +++ b/src/game/Game.ts @@ -76,10 +76,21 @@ interface Sequence { numberOfFulfilled: number } +interface Buffer { + value: string + positionInMatrixRow: number + positionInMatrixColumn: number +} + +interface Cell { + value: string + isUsed: boolean +} + export class Game { state: State = {selectionMode: SelectionMode.FreePick} public readonly size: number - public readonly buffer: string[] = [] + public readonly buffer: Buffer[] = [] private readonly timeoutInterval: ReturnType private readonly startTimeTimeStamp: number private endTimestamp: number | null = null @@ -106,8 +117,14 @@ export class Game { return this.timeout - (Date.now() - this.startTimeTimeStamp) } - getCell(row: number, column: number): string { - return this.matrix[row + column * this.size] + getCell(row: number, column: number): Cell { + return { + value: this.matrix[row + column * this.size], + isUsed: this.buffer.some(x => + x.positionInMatrixRow == row && + x.positionInMatrixColumn == column + ), + } } getSequences(): Sequence[] { @@ -116,7 +133,7 @@ export class Game { for (let i = 0; i < this.buffer.length; ++i) { let prefixLength = 0; for (let j = 0; j < Math.min(sequence.length, this.buffer.length - i); ++j) { - if (this.buffer[i + j] != sequence[j]) { + if (this.buffer[i + j].value != sequence[j]) { // abort sequence prefixLength = 0 break; @@ -160,7 +177,16 @@ export class Game { Won: () => {throw new IllegalMoveError()}, Lost: () => {throw new IllegalMoveError()}, InProgress: (selectionMode) => { - this.buffer.push(this.getCell(row, column)) + const cell = this.getCell(row, column) + if (cell.isUsed) { + throw new IllegalMoveError() + } + + this.buffer.push({ + value: cell.value, + positionInMatrixRow: row, + positionInMatrixColumn: column, + }) matchSelectionState({ Free: () => {