diff --git a/README ETUDIANTS.md b/README ETUDIANTS.md new file mode 100644 index 0000000..16d11b0 --- /dev/null +++ b/README ETUDIANTS.md @@ -0,0 +1,6 @@ +# Nom Prénom + +- Pesant Fantin +- Chlabi Aymen +- Pouget--Péjoan Elfin +- Hoarau Allan diff --git a/src/12_RefactoringGolf/exo5/README.md b/src/12_RefactoringGolf/exo5/README.md index 2168b16..311f775 100644 --- a/src/12_RefactoringGolf/exo5/README.md +++ b/src/12_RefactoringGolf/exo5/README.md @@ -1,17 +1,17 @@ # Exo 5 to Exo 6 - ## Refactorings + - PROBLEME: la loi de Demeter n'est pas respectée ("Tell, Don't Ask" ou "principle of least knowledge") - - https://martinfowler.com/bliki/TellDontAsk.html - - https://savoiragile.com/2012/05/04/connaissez-vous-la-loi-de-demeter/ - - https://tech-fr.netlify.app/articles/fr512716/index.html - - https://www.arolla.fr/blog/2017/02/principes-solid-vie-de-jours/#Loi_de_Demeter + - + - + - + - - -- REVUE DE CODE: repérez les endroits où, pour obtenir une condition dans un IF, on fait appel (ASK) à des propriétés +- REVUE DE CODE: repérez les endroits où, pour obtenir une condition dans un IF, on fait appel (ASK) à des propriétés qui ne sont pas dans l'objet courant Example: + ```javascript if ( this._board.TileAt(row, firstColumn)!.Symbol == diff --git a/src/12_RefactoringGolf/exo5/kata.ts b/src/12_RefactoringGolf/exo5/kata.ts index 22d3cae..b2beeb1 100644 --- a/src/12_RefactoringGolf/exo5/kata.ts +++ b/src/12_RefactoringGolf/exo5/kata.ts @@ -10,106 +10,125 @@ const thirdColumn = 2; const playerO = 'O'; const emptyPlay = ' '; -export class Game { -private _lastSymbol = emptyPlay; -private _board: Board = new Board(); +interface TileInterface { + X: number; + Y: number; + Symbol: string; +} -public Play(symbol: string, x: number, y: number): void { -this.validateFirstMove(symbol); -this.validatePlayer(symbol); -this.validatePositionIsEmpty(x, y); +class Tile implements TileInterface { + X: number; + Y: number; + Symbol: string; -this.updateLastPlayer(symbol); -this.updateBoard(symbol, x, y); -} + constructor(x: number, y: number, symbol: string) { + this.X = x; + this.Y = y; + this.Symbol = symbol; + } -private validateFirstMove(player: string) { -if (this._lastSymbol == emptyPlay) { - if (player == playerO) { - throw new Error('Invalid first player'); + isEmpty(): boolean { + return this.Symbol === emptyPlay; } -} -} -private validatePlayer(player: string) { -if (player == this._lastSymbol) { - throw new Error('Invalid next player'); -} + hasSameSymbolAs(other: Tile): boolean { + return this.Symbol === other.Symbol; + } } -private validatePositionIsEmpty(x: number, y: number) { -if (this._board.TileAt(x, y).Symbol != emptyPlay) { - throw new Error('Invalid position'); -} -} +export class Game { + private _lastSymbol = emptyPlay; + private _board: Board = new Board(); -private updateLastPlayer(player: string) { -this._lastSymbol = player; -} + public Play(symbol: string, x: number, y: number): void { + this.validateFirstMove(symbol); + this.validatePlayer(symbol); + this.validatePositionIsEmpty(x, y); -private updateBoard(player: string, x: number, y: number) { -this._board.AddTileAt(player, x, y); -} + this.updateLastPlayer(symbol); + this.updateBoard(symbol, x, y); + } -public Winner(): string { -return this._board.findRowFullWithSamePlayer(); -} -} + private validateFirstMove(player: string) { + if (this._lastSymbol == emptyPlay) { + if (player == playerO) { + throw new Error('Invalid first player'); + } + } + } -interface Tile { -X: number; -Y: number; -Symbol: string; -} + private validatePlayer(player: string) { + if (player == this._lastSymbol) { + throw new Error('Invalid next player'); + } + } -class Board { -private _plays: Tile[] = []; + private validatePositionIsEmpty(x: number, y: number) { + if (!this._board.TileAt(x, y).isEmpty()) { + throw new Error('Invalid position'); + } + } -constructor() { -for (let i = firstRow; i <= thirdRow; i++) { - for (let j = firstColumn; j <= thirdColumn; j++) { - const tile: Tile = { X: i, Y: j, Symbol: emptyPlay }; - this._plays.push(tile); + private updateLastPlayer(player: string) { + this._lastSymbol = player; } -} -} -public TileAt(x: number, y: number): Tile { -return this._plays.find((t: Tile) => t.X == x && t.Y == y)!; -} + private updateBoard(player: string, x: number, y: number) { + this._board.AddTileAt(player, x, y); + } -public AddTileAt(symbol: string, x: number, y: number): void { -this._plays.find((t: Tile) => t.X == x && t.Y == y)!.Symbol = symbol; + public Winner(): string { + return this._board.findRowFullWithSamePlayer(); + } } -public findRowFullWithSamePlayer(): string { -if (this.isRowFull(firstRow) && this.isRowFullWithSameSymbol(firstRow)) { - return this.TileAt(firstRow, firstColumn)!.Symbol; -} +class Board { + private _plays: Tile[] = []; + + constructor() { + for (let i = firstRow; i <= thirdRow; i++) { + for (let j = firstColumn; j <= thirdColumn; j++) { + this._plays.push(new Tile(i, j, emptyPlay)); + } + } + } -if (this.isRowFull(secondRow) && this.isRowFullWithSameSymbol(secondRow)) { - return this.TileAt(secondRow, firstColumn)!.Symbol; -} + public TileAt(x: number, y: number): Tile { + return this._plays.find((t: Tile) => t.X == x && t.Y == y)!; + } -if (this.isRowFull(thirdRow) && this.isRowFullWithSameSymbol(thirdRow)) { - return this.TileAt(thirdRow, firstColumn)!.Symbol; -} + public AddTileAt(symbol: string, x: number, y: number): void { + this.TileAt(x, y).Symbol = symbol; + } -return emptyPlay; -} + public findRowFullWithSamePlayer(): string { + if (this.isRowFull(firstRow) && this.isRowFullWithSameSymbol(firstRow)) { + return this.TileAt(firstRow, firstColumn)!.Symbol; + } -private isRowFull(row: number) { -return ( - this.TileAt(row, firstColumn)!.Symbol != emptyPlay && - this.TileAt(row, secondColumn)!.Symbol != emptyPlay && - this.TileAt(row, thirdColumn)!.Symbol != emptyPlay -); -} + if (this.isRowFull(secondRow) && this.isRowFullWithSameSymbol(secondRow)) { + return this.TileAt(secondRow, firstColumn)!.Symbol; + } -private isRowFullWithSameSymbol(row: number) { -return ( - this.TileAt(row, firstColumn)!.Symbol == this.TileAt(row, secondColumn)!.Symbol && - this.TileAt(row, thirdColumn)!.Symbol == this.TileAt(row, secondColumn)!.Symbol -); -} + if (this.isRowFull(thirdRow) && this.isRowFullWithSameSymbol(thirdRow)) { + return this.TileAt(thirdRow, firstColumn)!.Symbol; + } + + return emptyPlay; + } + + private isRowFull(row: number) { + return ( + !this.TileAt(row, firstColumn).isEmpty() && + !this.TileAt(row, secondColumn).isEmpty() && + !this.TileAt(row, thirdColumn).isEmpty() + ); + } + + private isRowFullWithSameSymbol(row: number) { + return ( + this.TileAt(row, firstColumn).hasSameSymbolAs(this.TileAt(row, secondColumn)) && + this.TileAt(row, thirdColumn).hasSameSymbolAs(this.TileAt(row, secondColumn)) + ); + } } \ No newline at end of file diff --git a/src/12_RefactoringGolf/exo5/test.ts b/src/12_RefactoringGolf/exo5/test.ts index 9aa2e2e..a533194 100644 --- a/src/12_RefactoringGolf/exo5/test.ts +++ b/src/12_RefactoringGolf/exo5/test.ts @@ -109,4 +109,10 @@ describe('TicTacToe game', () => { expect(winner).toBe('O'); }); + + it('should declare empty string as winner if nothing is played', () => { + const winner = game.Winner(); + + expect(winner).toBe(' '); + }); });