Created
June 21, 2016 15:50
-
-
Save willkessler/84c47163c4789b32d00efd29a6621ee0 to your computer and use it in GitHub Desktop.
connect4 game
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
console.log('Welcome to connect4!', "\n"); | |
var connect4Obj = { | |
board: new Array(), // this will be a two dimensional array | |
boardWidth : 7, | |
boardHeight : 5, | |
player1Piece : 'X', | |
player2Piece : 'O', | |
requiredToWin: 4, | |
constructWinnerSubstr: function(piece) { | |
return new Array(this.requiredToWin + 1).join( piece ); | |
}, | |
// Build the player board | |
buildBoard: function(width,height) { | |
console.log('Building board.'); | |
for (var i = 0; i < height; ++i) { | |
var row = Array(); | |
for (var j = 0; j < width; ++j) { | |
row.push('*'); | |
} | |
this.board.push(row); | |
} | |
}, | |
printBoard: function() { | |
for (var i = 0; i < this.board.length; ++i) { | |
var rowStr = this.board[i].join(' '); | |
console.log(rowStr); | |
} | |
}, | |
// Place a piece in the top of the board. Have it "fall" downwards until it can no longer fall. This simply means | |
// find the first spot it will fit starting from the last row. Return true if piece placed successfully, false | |
// if there was no spot it could fit | |
placePiece: function(column, piece) { | |
for (var i = this.boardHeight - 1; i >= 0; --i) { | |
if (this.board[i][column] == '*') { | |
this.board[i][column] = piece; | |
return true; | |
} | |
} | |
return false; | |
}, | |
checkForWinnerInString: function(singleRow) { | |
var player1Winner = this.constructWinnerSubstr(this.player1Piece); | |
var player2Winner = this.constructWinnerSubstr(this.player2Piece); | |
if (singleRow.indexOf(player1Winner) > -1) { | |
console.log('Winner is player 1 using \'X\'!'); | |
this.printBoard(); | |
return true; // we have a winner | |
} else if (singleRow.indexOf(player2Winner) > -1) { | |
console.log('Winner is player 2 using \'O\'!'); | |
this.printBoard(); | |
return true; // we have a winner | |
} | |
//console.log('No winner yet!'); | |
return false; // no winner thus far | |
}, | |
constructDiagStrLLUR: function(startRow, startCol) { | |
//console.log('starting at row:', startRow, ' col:', startCol); | |
var diagStr = ''; | |
var rowCheck = startRow; | |
var colCheck = startCol; | |
while (rowCheck > -1 && colCheck < this.boardWidth) { | |
//console.log(rowCheck,colCheck); | |
diagStr += this.board[rowCheck][colCheck]; | |
rowCheck--; | |
colCheck++; | |
} | |
//console.log('diagstr from constructDiagStr=' + diagStr); | |
return diagStr; | |
}, | |
constructDiagStrULLR: function(startRow, startCol) { | |
//console.log('starting at row:', startRow, ' col:', startCol); | |
var diagStr = ''; | |
var rowCheck = startRow; | |
var colCheck = startCol; | |
while (rowCheck < this.boardHeight && colCheck < this.boardWidth) { | |
//console.log(rowCheck,colCheck); | |
diagStr += this.board[rowCheck][colCheck]; | |
rowCheck++; | |
colCheck++; | |
} | |
//console.log('diagstr from constructDiagStr=' + diagStr); | |
return diagStr; | |
}, | |
// Scan for horizontal 4 in a row, vertical 4 in a row, and diagonal 4 in a row of the same kind. | |
// To be cute, we can check using string concat (might be faster than generic iterative scanning since | |
// substr is a C func under the covers). Trickier for diagonal winners... | |
checkForWinner: function() { | |
// Construct string for horizontal check | |
for (var i = 0; i < this.boardHeight; ++i) { | |
var singleRow = ''; | |
for (var j = 0; j < this.boardWidth; ++j) { | |
singleRow += this.board[i][j]; | |
} | |
//console.log('Horizontal winner check:' , singleRow); | |
if (this.checkForWinnerInString(singleRow)) { | |
console.log('winner found in a row'); | |
return true; | |
} | |
} | |
// Construct string for vertical check | |
for (var i = 0; i < this.boardWidth; ++i) { | |
var singleRow = ''; | |
for (var j = 0; j < this.boardHeight; ++j) { | |
singleRow += this.board[j][i]; | |
} | |
//console.log('Vertical winner check:' , singleRow); | |
if (this.checkForWinnerInString(singleRow)) { | |
console.log('winner found in a column'); | |
return true; | |
} | |
} | |
// Now that I've written these two it could be refactored to one routine since rows and cols and the limits just reverse. | |
//console.log('check for LLUR'); | |
// Construct string for diagonal check for diagonals from lower left->upper right (LLUR) | |
var startRow = this.requiredToWin - 1; | |
var startCol = 0; | |
while (startCol < this.boardWidth - this.requiredToWin + 1) { | |
var diagStr = this.constructDiagStrLLUR(startRow,startCol); | |
if (this.checkForWinnerInString(diagStr)) { | |
console.log('winner found in a LLUR diagonal'); | |
return true; | |
} | |
var checkRow = startRow + 1; | |
startRow = Math.min(checkRow, this.boardHeight - 1); | |
if (checkRow > this.boardHeight - 1) { | |
startCol++; | |
} | |
} | |
//console.log('check for ULLR'); | |
// Construct string for diagonal check for diagonals from upper left -> lower right (ULLR) | |
var startRow = 0; | |
var startCol = this.requiredToWin - 1; | |
while (startRow < this.boardHeight - this.requiredToWin + 1) { | |
var diagStr = this.constructDiagStrULLR(startRow,startCol); | |
if (this.checkForWinnerInString(diagStr)) { | |
console.log('winner found in a ULLR diagonal'); | |
return true; | |
} | |
var checkCol = startCol - 1; | |
startCol = Math.max(0, checkCol); | |
if (startCol == 0) { | |
startRow++; | |
} | |
} | |
return false; | |
}, | |
pickRandomPlayerPiece: function() { | |
var playerId = Math.floor(Math.random() * 2); | |
return (playerId == 0 ? this.player1Piece : this.player2Piece); | |
}, | |
findFreeSpot: function() { | |
var startSpot = Math.floor(Math.random() * this.boardWidth); | |
var check = (startSpot + 1) % this.boardWidth ; | |
while (check != startSpot) { | |
if (this.board[0][check] == '*') { | |
//console.log('found free spot at check=',check); | |
return(check); | |
} | |
check = (check + 1) % this.boardWidth; | |
} | |
return -1; | |
}, | |
playGame: function() { | |
this.buildBoard(this.boardWidth,this.boardHeight); | |
// Fill in a vertical column of X's | |
//for (var i = 0; i < 4; ++i ) { | |
// this.placePiece(2, 'X'); | |
// } | |
// Fill in moves until the board is full (ie placePiece returns false), checking for winners along the way | |
var freeSpot; | |
while ((freeSpot = this.findFreeSpot()) > -1) { | |
this.placePiece(freeSpot, this.pickRandomPlayerPiece()); | |
this.printBoard(); | |
console.log("\n"); | |
if (this.checkForWinner()) { | |
break; | |
} | |
} | |
} | |
}; | |
connect4Obj.playGame(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment