Created
June 23, 2018 13:24
-
-
Save roehrdor/30ce5c61c4e11e48a7c47ac655be04e0 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(function (window) { | |
'use strict'; | |
var App = window.App || {}; | |
class ConnectFour { | |
constructor() { | |
this.settings = { | |
displayDump: false | |
}; | |
this.gameOver = false; | |
this.current = 0; | |
this.colHeight = [0, 0, 0, 0, 0, 0, 0]; | |
this.field = [ | |
[0, 0, 0, 0, 0, 0, 0], | |
[0, 0, 0, 0, 0, 0, 0], | |
[0, 0, 0, 0, 0, 0, 0], | |
[0, 0, 0, 0, 0, 0, 0], | |
[0, 0, 0, 0, 0, 0, 0], | |
[0, 0, 0, 0, 0, 0, 0] | |
]; | |
this.tokens = { 0: '.', 1: '1', 2: '2' }; | |
this.color = { 0: "lightgrey", 1: "green", 2: "yellow"}; | |
this.winmsg = { | |
2: ["Server wins!", "THe Server has won the game!"], | |
1: ["You win!", "You have won the game!"] | |
}; | |
this.generateBoard(); | |
} | |
// Reset the field to play again without reloading the tab | |
reset() { | |
this.field.forEach(row => row.fill(0)); | |
this.colHeight.fill(0); | |
this.current = 0; | |
this.gameOver = false; | |
this.updateBoard(); | |
} | |
// Start a new Game by calling the restful endpoint | |
startNewGame() { | |
this.reset(); | |
$.get('https://www2.hs-esslingen.de/~dbenin/connectfour/', {"command":"start"}, (data) => { | |
$('#statusline').append(JSON.parse(data).statusmsg + "<br/>"); | |
}); | |
} | |
// Generate the output for a cell in the debug field | |
genFieldText(cell) { | |
return ` <span style=color:${this.color[cell]}>${this.tokens[cell]}</span> `; | |
} | |
// Dump the field to the debug div by calling `genFieldText` per cell | |
dumpField() { | |
if (!this.settings.displayDump) return; | |
const textField = document.getElementById('debug'); | |
textField.innerHTML = "<p id=\"debug-title\">Debug Environment</p>"; | |
this.field.forEach(row => { | |
row.forEach(cell => textField.innerHTML += this.genFieldText(cell)); | |
textField.innerHTML += '<br/>'; | |
}); | |
} | |
// Return true if the field is completely filled | |
isFieldFull() { | |
return this.colHeight.find(e => e < 6) === undefined; | |
} | |
// Return the row a token in the `col` column would be placed at | |
freePosForCol(col) { | |
return this.colHeight[col]; | |
} | |
// Update the board by drawing the tokens | |
updateBoard() { | |
const board = $("#board"); | |
this.dumpField(); | |
this.field.forEach((row, ri) => { | |
row.forEach((_, ci) => { | |
const cell = board.find(`[data-row="${ri}"][data-column="${ci}"]`); | |
cell.css("background-color", this.color[this.field[ri][ci]]); | |
}); | |
}); | |
} | |
// Return true if any player has won | |
hasLineOfFour() { | |
return this.gameOver; | |
} | |
// Return true if its the turn of `tok`'s player | |
playerMove(tok) { | |
return this.current !== tok && !this.hasLineOfFour(); | |
} | |
// Display the winning message | |
displayIfWon() { | |
if(this.hasLineOfFour()){ | |
setTimeout(() => { | |
alert(this.winmsg[this.current][0]); | |
}, 10); | |
$('#statusline').append(this.winmsg[this.current][1]); | |
return true; | |
} | |
return false; | |
} | |
// Request the move from the server | |
requestServerMove(col) { | |
return new Promise((resolve, reject) => { | |
$.get("https://www2.hs-esslingen.de/~dbenin/connectfour/", | |
{ "command":"move", "x": col, "matrnr": 123456 }, | |
(data) => resolve(JSON.parse(data).x)); | |
}); | |
} | |
// Request the server to move in response to selecting the column `col` | |
async serverMove(col) { | |
while(!this.insertTokenInCol(await this.requestServerMove(col), 2)); | |
} | |
// Return true if the last move won the game | |
checkWinAfterInsert(col, row) { | |
var cols = 1; | |
var rows = 1; | |
var diag1 = 1; | |
var diag2 = 1; | |
const token = this.field[5 - row][col]; | |
row = 5 - row; | |
for (var c = col; cols < 4 && --c >= 0 && this.field[row][c] === token; ++cols); | |
for (var c = col; cols < 4 && ++c < 7 && this.field[row][c] === token; ++cols); | |
if (cols > 3) { this.gameOver = true; return; } | |
for (var r = row; rows < 4 && ++r < 6 && this.field[r][col] === token; ++rows); | |
if (rows > 3) { this.gameOver = true; return; } | |
for (var r = row, c = col; diag1 < 4 && --c >= 0 && --r >= 0 && this.field[r][c] === token; ++diag1); | |
for (var r = row, c = col; diag1 < 4 && ++c < 7 && ++r < 6 && this.field[r][c] === token; ++diag1); | |
if (diag1 > 3) { this.gameOver = true; return; } | |
for (var r = row, c = col; diag2 < 4 && ++c < 7 && --r >= 0 && this.field[r][c] === token; ++diag2); | |
for (var r = row, c = col; diag2 < 5 && --c >= 0 && ++r < 6 && this.field[r][c] === token; ++diag2); | |
if (diag2 > 3) { this.gameOver = true; return; } | |
} | |
// Inser the `token` into the column | |
// Return true if inserted or not the players turn | |
// Return false if the column is already filled | |
insertTokenInCol(col, token) { | |
if (!this.playerMove(token)) | |
return true; | |
const row = this.freePosForCol(col); | |
if (this.colHeight[col] > 5) | |
return false; | |
this.current = token; | |
this.field[5 - row][col] = token; | |
this.updateBoard(); | |
this.checkWinAfterInsert(col, this.colHeight[col]++); | |
this.displayIfWon(); | |
return true; | |
} | |
// Generate the board | |
generateBoard() { | |
for(var i = 0; i < 7; ++i) { | |
let column = $('<div class="column"></div>').appendTo('#board'); | |
column.attr('data-column', i); | |
column.on('click', (event) => { | |
const col = parseInt($(event.currentTarget).attr('data-column')); | |
this.insertTokenInCol(col, 1); | |
this.serverMove(col); | |
}); | |
for (var j = 0; j < 6; ++j) { | |
let cell = $('<div class="cell"></div>').appendTo(column); | |
cell.attr('data-row', j); | |
cell.attr('data-column', i); | |
} | |
} | |
} | |
} | |
App.ConnectFour = ConnectFour; | |
window.App = App; | |
})(window); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment