-
Notifications
You must be signed in to change notification settings - Fork 0
/
four-in-a-row.min.js
1 lines (1 loc) · 3.15 KB
/
four-in-a-row.min.js
1
const t={IN_PROGRESS:"in-progress",START:"start",WIN:"win",DRAW:"draw"},r={INVALID:"invalid",WIN:"win",SUCCESS:"success",DRAW:"draw"},e={NONE:"none",YELLOW:"yellow",RED:"red"},n={ROWS:6,COLUMNS:7,WIN_LINE_LENGTH:4},o={NONE:0,YELLOW:1,RED:2};class i{startingColor;currentTurn;status;currentBoard;constructor(){this.reset()}static createBoard(){let t=new Array(n.ROWS);for(let r=0;r<n.ROWS;r++)t[r]=new Uint8Array(n.COLUMNS),t[r].fill(o.NONE);return t}static deepBoardCopy(t){let r=new Array(n.ROWS);for(let e=0;e<n.ROWS;e++){r[e]=new Uint8Array(n.COLUMNS);for(let o=0;o<n.COLUMNS;o++)r[e][o]=t[e][o]}return r}static playerColorToBoardToken(t){switch(t){case e.YELLOW:return o.YELLOW;case e.RED:return o.RED;default:return o.NONE}}static tryFindWinLine(t,r){let e=(r=r||{}).startRowIndex||0,a=r.startColumnIndex||0,s=r.rowCountStep||0,u=r.columnCountStep||0,l=0,N=o.NONE,c=[];for(let r=0;r<n.WIN_LINE_LENGTH;r++){let n=e+s*r,d=a+u*r;if(i.checkIfOutOfBounds(n,d))break;let L=t[n][d];if(L===o.NONE)break;N===o.NONE&&(N=L),L===N&&l++,c.push({row:n,column:d})}return l===n.WIN_LINE_LENGTH?{winLine:c,winner:i.boardTokenToPlayerColor(N)}:{winLine:[]}}static checkIfOutOfBounds(t,r){return t<0||t>n.ROWS||r<0||r>n.COLUMNS}static boardTokenToPlayerColor(t){switch(t){case o.YELLOW:return e.YELLOW;case o.RED:return e.RED;default:return e.NONE}}static checkForWin(t){for(let r=0;r<n.COLUMNS;r++)for(let e=n.ROWS-1;e>-1;e--){let n=i.tryFindWinLine(t,{startRowIndex:e,startColumnIndex:r,rowCountStep:-1});if(n.winner)return n;let o=i.tryFindWinLine(t,{startRowIndex:e,startColumnIndex:r,columnCountStep:-1});if(o.winner)return o;let a=i.tryFindWinLine(t,{startRowIndex:e,startColumnIndex:r,rowCountStep:-1,columnCountStep:-1});if(a.winner)return a;let s=i.tryFindWinLine(t,{startRowIndex:e,startColumnIndex:r,rowCountStep:-1,columnCountStep:1});if(s.winner)return s}return{winLine:[],winner:e.NONE}}static checkForFilledBoard(t){for(let r=0;r<t.length;r++){let e=t[r];for(let t=0;t<e.length;t++){if(e[t]===o.NONE)return!1}}return!0}reset(){this.startingColor=e.YELLOW,this.currentTurn=this.startingColor,this.status=t.START,this.currentBoard=i.createBoard()}playMove(n){switch(this.status){case t.START:this.status=t.IN_PROGRESS;break;case t.DRAW:case t.WIN:return this.evaluateGame(this.currentBoard)}let o=this.performMove(n);return o.status===r.SUCCESS&&(this.currentTurn=this.currentTurn===e.YELLOW?e.RED:e.YELLOW),o}performMove(t){let n=i.deepBoardCopy(this.currentBoard),o=this.tryPerformMove(t,n);return o.status===r.INVALID?{board:n,winner:e.NONE,status:r.INVALID,winLine:[]}:(this.currentBoard=o.board,this.evaluateGame(o.board))}tryPerformMove(t,e){let n=!1;for(let r=e.length-1;r>-1;r--){let a=e[r];if(a[t]===o.NONE){a[t]=i.playerColorToBoardToken(this.currentTurn),n=!0;break}}return n?{status:r.SUCCESS,board:e}:{status:r.INVALID}}evaluateGame(n){let o=i.checkForWin(n);return o.winner!==e.NONE?(this.status=t.WIN,{board:n,winner:o.winner,status:r.WIN,winLine:o.winLine}):i.checkForFilledBoard(n)?(this.status=t.DRAW,{board:n,winner:e.NONE,status:r.DRAW,winLine:[]}):{board:n,winner:e.NONE,status:r.SUCCESS,winLine:[]}}}export{n as BoardDimensions,o as BoardToken,i as Game,t as GameStatus,r as MoveStatus,e as PlayerColor};