Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Completed 2048 game #12

Open
wants to merge 58 commits into
base: jr/master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
58 commits
Select commit Hold shift + click to select a range
c80c1b9
function working for collision logic in both positive and negative di…
rileslovesyall Feb 2, 2016
ac5c1fb
some gameOver logic that isn't quite working yet
rileslovesyall Feb 2, 2016
d3c3208
removed extraneous code
rileslovesyall Feb 2, 2016
7de23b5
add gameover function
jbuechs Feb 2, 2016
6118a1a
create addTile method for adding and displaying new tile
jbuechs Feb 2, 2016
6ed7318
revamped for tile objects, addTiles working but not displaying
rileslovesyall Feb 2, 2016
138b6b2
comment w next step
rileslovesyall Feb 2, 2016
62944b6
addTile properly displaying initial tiles, like a boss
rileslovesyall Feb 2, 2016
71c0383
new Tile html includes tileId in class
rileslovesyall Feb 2, 2016
65e69ec
hard coded moving tiles working
rileslovesyall Feb 2, 2016
ff298d5
back end tile collision function for pressing up
jbuechs Feb 2, 2016
95c3bfe
removed extraneous files
rileslovesyall Feb 2, 2016
77ee506
html displaying and combining properly
rileslovesyall Feb 2, 2016
55b2205
bugfix remove deleted tiles from this.board
jbuechs Feb 3, 2016
863cfd3
Big fixed: addTile won't double up on tile spaces
rileslovesyall Feb 3, 2016
dde79c5
added catch for if a tile doesn't have pair
rileslovesyall Feb 3, 2016
aac9788
DRYed bug fix, still not working entirely
rileslovesyall Feb 3, 2016
adbaf5c
delete extraneous comments and consoles
jbuechs Feb 3, 2016
144644a
bugfix moveTile switching around
jbuechs Feb 3, 2016
9bcaa8c
bugfix update data-row attr for not combined tiles in moveTile
jbuechs Feb 3, 2016
df3f5fd
complete down arrow functionality in makeMove
jbuechs Feb 3, 2016
c322cd5
left arrow works
rileslovesyall Feb 3, 2016
68613c8
add right functionality to makeMove function
jbuechs Feb 3, 2016
3afa0cb
only add tile when move is made for up arrow
jbuechs Feb 3, 2016
7c1fe6e
removed extraneous code
rileslovesyall Feb 3, 2016
bc4c887
added moveCount functionality to right, left, and down
rileslovesyall Feb 3, 2016
39f31c8
delayed addTiles for each direction
rileslovesyall Feb 3, 2016
265ec5c
remove extra console logs
jbuechs Feb 3, 2016
fd0e582
refactored moveTile for DRYer code
rileslovesyall Feb 3, 2016
7a85cb5
add score functionality
jbuechs Feb 3, 2016
8293274
game reset functional, yussss
rileslovesyall Feb 3, 2016
ae99748
add game won functionality
jbuechs Feb 3, 2016
1597ec8
gameOver code in progress
rileslovesyall Feb 4, 2016
df6c339
fix checkGameOver logic
jbuechs Feb 4, 2016
4e288d5
add 4 value to new tiles
jbuechs Feb 4, 2016
079d383
awsd keys work to play game as well as arrows
rileslovesyall Feb 4, 2016
4059409
working on css
rileslovesyall Feb 4, 2016
b2e043c
Merge branch 'gameOver' into jr/master
rileslovesyall Feb 4, 2016
9be0a7c
minor merge issue fixed
rileslovesyall Feb 4, 2016
64055fe
stupid merge error fixed
rileslovesyall Feb 4, 2016
153895a
score looking a little better
rileslovesyall Feb 4, 2016
925b5bd
add high score
jbuechs Feb 4, 2016
7b9031d
New Game button visible
rileslovesyall Feb 4, 2016
5e3990b
fix merge conflicts
jbuechs Feb 4, 2016
78b9a66
Merge branch 'jr/master' of github.com:rileyrileyrose/2048 into jr/ma…
jbuechs Feb 4, 2016
a089931
display high score at beginning of game
jbuechs Feb 4, 2016
dab597b
some CSS is okay i guess ughh
rileslovesyall Feb 4, 2016
11f8e86
front board looks pretty okay i guess
rileslovesyall Feb 4, 2016
59f0af5
change css to display game over message
jbuechs Feb 4, 2016
75907fe
fix merge conflicts
jbuechs Feb 4, 2016
628947c
updated css for gameover screen
rileslovesyall Feb 4, 2016
d789e6f
add game won message
jbuechs Feb 5, 2016
b8e9720
slightly changed header size
rileslovesyall Feb 5, 2016
cdad9e5
added a delay, so two tiles combining over a long distance looks less…
rileslovesyall Feb 5, 2016
3efc945
format score boxes
jbuechs Feb 5, 2016
846ae93
Merge branch 'jr/master' of github.com:rileyrileyrose/2048 into jr/ma…
jbuechs Feb 5, 2016
d642eed
change animation timings for collisions
jbuechs Feb 5, 2016
14f5870
style new game button
jbuechs Feb 5, 2016
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
63 changes: 43 additions & 20 deletions index.html
Original file line number Diff line number Diff line change
Expand Up @@ -4,29 +4,52 @@
<title>2048</title>
<link rel="stylesheet" media="all" href="stylesheets/2048.css"/>
<script type="text/javascript" src="http://code.jquery.com/jquery-2.1.4.min.js"></script>
<script type="text/javascript" src="javascripts/underscore-min.js"></script>
<script type="text/javascript" src="javascripts/2048.js"></script>
</head>
<body>
<div id="gameboard">
<div class="cells">
<div class="cell"></div>
<div class="cell"></div>
<div class="cell"></div>
<div class="cell"></div>
<div class="cell"></div>
<div class="cell"></div>
<div class="cell"></div>
<div class="cell"></div>
<div class="cell"></div>
<div class="cell"></div>
<div class="cell"></div>
<div class="cell"></div>
<div class="cell"></div>
<div class="cell"></div>
<div class="cell"></div>
<div class="cell"></div>
<div id="container">
<div class="header">
<h1 class="2048">2048</h1>
<div class="score-container">
<h4 class="score-header">SCORE</h4>
<div id="score"></div>
</div>
<div class="high-score-container">
<h4 class="score-header">BEST</h4>
<div id="high_score"></div>
</div>
<a id="reset" class="reset">New Game</a>
</div>
<div id="gameboard">
<div id="game-message">
<p class="game-change">Game over!</p>
<button class="btn reset">New Game</button>
</div>
<div id="game-won">
<p class="game-change">Game won!</p>
<button class="btn reset">New Game</button>
<button class="btn resume">Keep Playing</button>
</div>
<div class="cells">
<div class="cell"></div>
<div class="cell"></div>
<div class="cell"></div>
<div class="cell"></div>
<div class="cell"></div>
<div class="cell"></div>
<div class="cell"></div>
<div class="cell"></div>
<div class="cell"></div>
<div class="cell"></div>
<div class="cell"></div>
<div class="cell"></div>
<div class="cell"></div>
<div class="cell"></div>
<div class="cell"></div>
<div class="cell"></div>
</div>
</div>
<div class="tile" data-row="r1", data-col="c1" data-val="2">2</div>
</div>
</div>
</body>
</html>
283 changes: 269 additions & 14 deletions javascripts/2048.js
Original file line number Diff line number Diff line change
@@ -1,36 +1,291 @@
var Game = function() {
// Game logic and initialization here
this.highScore = 0;
};

var tileCount = 0;

var Tile = function (row, col, val) {
// make new Tiles
this.row = row;
this.col = col;
this.val = val;
this.moveCount = 0;
this.tileId = String(tileCount++);
};

Game.prototype.startGame = function () {
$('#game-message').fadeOut();
$('.tile').remove();
this.gameOver = false;
this.gameWon = false;
this.board = [];
this.score = 0;
$('#score').html(this.score);
$('#high_score').html(this.highScore);
this.addTile();
this.addTile();
};

Game.prototype.updateGameWon = function(){
var values = this.board.map(function(tile){ return tile.val; });
if (values.includes(2048)) { this.gameWon = true; }
};

Game.prototype.checkGameOver = function () {
if (this.board.length !== 16) {
return;
} else {
var groupedTiles = _.groupBy(this.board, function(tile) {
return tile.val;
});
for (var val in groupedTiles) {
var tiles = groupedTiles[val];
for (var i=0; i < tiles.length; i++) {
var match = _.find(tiles, function(tile) {
return (tiles[i].row === tile.row &&
(tiles[i].col == tile.col + 1 || tiles[i].col == tile.col - 1)) ||
(tiles[i].col === tile.col &&
(tiles[i].row == tile.row + 1 || tiles[i].row == tile.row - 1));
});
if (match) { return; }
}
}
this.gameOver = true;
$('#game-message').fadeIn();
}
};


Game.prototype.addTile = function () {
var valArray = [2, 2, 2, 2, 2, 2, 2, 2, 2, 4];
if (this.board.length < 16) {
var tilePlaced = false,
val = valArray[Math.floor(Math.random() * 10)],
currentTiles = [];
this.board.forEach(function (tile) {
currentTiles.push([tile.row, tile.col]);
});
while (!tilePlaced) {
var col = Math.floor(Math.random() * (4 - 0)),
row = Math.floor(Math.random() * (4 - 0));
var sameTile = _.find(this.board, function(tile) { return tile.col === col && tile.row === row; });
if (!sameTile) {
tilePlaced = true;
newTile = new Tile(row, col, val);
this.board.push(newTile);
var $tileHTML = $('<div class="tile" id="' + newTile.tileId + '" data-row="r'+ row +'", data-col="c'+ col +'" data-val="'+val+'">'+val+'</div>');
$('#gameboard').append($tileHTML);
}
}
}
};

Game.prototype.moveTile = function(tile, direction) {
var addTileCallback = function () { this.addTile(); }.bind(this) ;
// Game method here
var initMoves = this.board.map(function(tile) {return tile.moveCount;});
switch(direction) {
case 87:
case 38: //up
console.log('up');
var groupedTiles = _.groupBy(this.board, function(tile) {
return tile.col;
});
// iterate through each column
var func = function(key){
var colArray = groupedTiles[key];
colArray = _.sortBy(colArray, function(tile){ return tile.row; });
for (var row = 0; row < colArray.length; row++) {
// if combining
if (colArray[row] && colArray[row+1] && colArray[row].val === colArray[row+1].val) {
colArray[row+1].val *= 2;
this.score += colArray[row+1].val;
colArray[row+1].row = row;
colArray[row+1].moveCount++;
// change HTML of tile
$("#" + colArray[row+1].tileId).attr("data-row", "r" + row);
$("#" + colArray[row+1].tileId).attr("data-val", colArray[row+1].val);
$("#" + colArray[row+1].tileId).html(colArray[row+1].val);
// delete from board

var deleteTileIndex = _.indexOf(this.board, colArray[row]);
this.board.splice(deleteTileIndex, 1);
// delete current html object
$("#" + colArray[row].tileId).delay(75).fadeOut(50, function(){$(this).remove();});
// delete current value (tile object)
colArray.splice(row, 1);
// if not combining
} else if (colArray[row].row !== row){
colArray[row].row = row;
$("#" + colArray[row].tileId).attr("data-row", "r" + row);
colArray[row].moveCount++;
}
}
};
break;

case 83:
case 40: //down
console.log('down');
groupedTiles = _.groupBy(this.board, function(tile) {
return tile.col;
});
// iterate through each column
func = function(key){
var colArray = groupedTiles[key];
colArray = _.sortBy(colArray, function(tile){ return tile.row; });
for (var i = 0; i < colArray.length; i++) {
// if combining
var arrayIndex = colArray.length - i - 1,
row = 3 - i;
if (colArray[arrayIndex] && colArray[arrayIndex-1] && colArray[arrayIndex].val === colArray[arrayIndex-1].val) {
colArray[arrayIndex-1].val *= 2;
this.score += colArray[arrayIndex-1].val;
colArray[arrayIndex-1].row = row;
colArray[arrayIndex-1].moveCount++;
// change HTML of tile
$("#" + colArray[arrayIndex-1].tileId).attr("data-row", "r" + row);
$("#" + colArray[arrayIndex-1].tileId).attr("data-val", colArray[arrayIndex-1].val);
$("#" + colArray[arrayIndex-1].tileId).html(colArray[arrayIndex-1].val);
// delete from board
var deleteTileIndex = _.indexOf(this.board, colArray[arrayIndex]);
this.board.splice(deleteTileIndex, 1);
// delete current html object
$("#" + colArray[arrayIndex].tileId).delay(75).fadeOut(50, function(){$(this).remove();});
// delete current value (tile object)
colArray.splice(arrayIndex, 1);
// if not combining
} else {
colArray[arrayIndex].row = row;
colArray[arrayIndex].moveCount++;
$("#" + colArray[arrayIndex].tileId).attr("data-row", "r" + row);
}
}
};
break;

case 65:
case 37: //left
console.log('left');
break;
groupedTiles = _.groupBy(this.board, function(tile) {
return tile.row;
});
// iterate through each row
func = function(key){
var rowArray = groupedTiles[key];
rowArray = _.sortBy(rowArray, function(tile){ return tile.col; });
for (var col = 0; col < rowArray.length; col++) {
// if combining
if (rowArray[col] && rowArray[col+1] && rowArray[col].val === rowArray[col+1].val) {
rowArray[col+1].val *= 2;
this.score += rowArray[col+1].val;
rowArray[col+1].col = col;
rowArray[col+1].moveCount++;
// change HTML of tile
$("#" + rowArray[col+1].tileId).attr("data-col", "c" + col);
$("#" + rowArray[col+1].tileId).attr("data-val", rowArray[col+1].val);
$("#" + rowArray[col+1].tileId).html(rowArray[col+1].val);
// delete from board
var deleteTileIndex = _.indexOf(this.board, rowArray[col]);
this.board.splice(deleteTileIndex, 1);
// delete current html object
$("#" + rowArray[col].tileId).delay(75).fadeOut(50, function(){$(this).remove();});
// delete current tile object)
rowArray.splice(col, 1);
// if not combining
} else {
rowArray[col].col = col;
rowArray[col].moveCount++;
$("#" + rowArray[col].tileId).attr("data-col", "c" + col);
}
}
};
break;

case 68:
case 39: //right
console.log('right');
groupedTiles = _.groupBy(this.board, function(tile) {
return tile.row;
});
// iterate through each column
func = function(key){
var rowArray = groupedTiles[key];
rowArray = _.sortBy(rowArray, function(tile){ return tile.col; });
for (var i = 0; i < rowArray.length; i++) {
// if combining
var arrayIndex = rowArray.length - i - 1,
col = 3 - i;
if (rowArray[arrayIndex] && rowArray[arrayIndex-1] && rowArray[arrayIndex].val === rowArray[arrayIndex-1].val) {
rowArray[arrayIndex-1].val *= 2;
this.score += rowArray[arrayIndex-1].val;
rowArray[arrayIndex-1].col = col;
rowArray[arrayIndex-1].moveCount++;
// change HTML of tile
$("#" + rowArray[arrayIndex-1].tileId).attr("data-col", "c" + col);
$("#" + rowArray[arrayIndex-1].tileId).attr("data-val", rowArray[arrayIndex-1].val);
$("#" + rowArray[arrayIndex-1].tileId).html(rowArray[arrayIndex-1].val);
// delete from board
var deleteTileIndex = _.indexOf(this.board, rowArray[arrayIndex]);
this.board.splice(deleteTileIndex, 1);
// delete current html object
$("#" + rowArray[arrayIndex].tileId).delay(75).fadeOut(50, function(){$(this).remove();});
// delete current value (tile object)
rowArray.splice(arrayIndex, 1);
// if not combining
} else {
rowArray[arrayIndex].col = col;
rowArray[arrayIndex].moveCount++;
$("#" + rowArray[arrayIndex].tileId).attr("data-col", "c" + col);
}
}
};
break;
}

func = _.bind(func, this);
Object.keys(groupedTiles).forEach(function(key) { return func(key); });
afterMoves = this.board.map(function(tile) {return tile.moveCount;});
matching = afterMoves.every(function(element, index) { return initMoves[index] === element; });

if (!matching) {
setTimeout(addTileCallback, 200);
}
if (this.gameWon === false) {
this.updateGameWon();
if (this.gameWon) {
$('#game-won').fadeIn();
}
}
this.checkGameOver();
if (this.score > this.highScore) {
this.highScore = this.score;
}
};

Game.prototype.updateGameOver = function(){
};

$(document).ready(function() {
console.log("ready to go!");
// Any interactive jQuery functionality
var game = new Game();

var tile,
game = new Game();
game.startGame();
$('body').keydown(function(event){
var arrows = [37, 38, 39, 40];
if (arrows.indexOf(event.which) > -1) {
var tile = $('.tile');

game.moveTile(tile, event.which);
}
if (!game.gameOver) {
var directions = [37, 38, 39, 40, 87, 65, 83, 68];
if (directions.indexOf(event.which) > -1) {
tile = $('.tile');
game.moveTile(tile, event.which);
$('#score').html(game.score);
$('#high_score').html(game.highScore);
}
}
});
$('.reset').click(function () {
game.startGame();
$('#game-won').fadeOut();
});

$('.resume').click(function() {
$('#game-won').fadeOut();
});

});
Loading