拖了一个假期的2048,今天终于完成网页版本的了
开心!!!
刚开始觉得挺难的,无从下手
但是imooc老师特别仔细的讲每一个细节,怎么想,怎么写
一步一步,虽然经常被自己蠢哭,但是还是完成了!开心!!
遇到了很多坑。。。
1.跟着老师一步步走还好,老师写完moveleft之后,让我们自己写其他三个move函数
本以为自己都理解了,可以写,但是!!!right根本就运行不出来,直接死机!
后来,看老师的代码,发现其实自己根本没有弄清楚循环的细节,一步步仔细看原来少了个=。蠢哭!
2.有个bug,说重复移动。这是个很抽象的问题,我一开始根本不知道怎么办,老师说可以转化成很多小问题,如果它累加移动,那我们就设个函数记录累加的次数就可以啊。原来!感觉写代码就是天马行空的写,怎么写都可以。哈哈哈哈哈
3.写完还要考虑性能的问题,比如当初就写了个死循环生成随机位置。后来就会比较慢,怎么解决呢?设函数,记录次数!如果好多次都没有找到,就手动生成。
4.用户体验也是我们需要考虑的问题,比如你生成太快,没有过渡,那么动画效果就不好,那么我们就settimeout。代码不只是写出功能来就大功告成了,用户体验也很重要!
5.就是自己改的bug啦~score设计的是全局变量,所以newgame之后还会是原来的score,怎么办?设函数!自己加了个clearscore,清零分数值,再告诉前台要改就OK啦,就是一些语法要熟练用啊
6.把数字改成“小白-》实习生-》程序猿-》。。。。”这个我原来以为很难啊,其实,很简单!怎么改?设函数!增加了一个getnumbercontent,把首先把randnumber用这个函数转化一下,再用switch转化一下,最后别忘记告诉前台去改展示的文字,大功告成!
<!DOCTYPE html>
<html>
<head>
<title>2048 GAME</title>
<meta charset="utf-8">
<link rel="stylesheet" type="text/css" href="2048.css">
<script type="text/javascript" src="http://libs.baidu.com/jquery/1.11.1/jquery.min.js" ></script>
<link href="http://libs.baidu.com/bootstrap/2.3.2/css/bootstrap.min.css" rel="stylesheet">
<script src="http://libs.baidu.com/bootstrap/2.3.2/js/bootstrap.min.js"></script>
<script type="text/javascript" src="support2048.js"></script>
<script type="text/javascript" src="showanimation2048.js"></script>
<script type="text/javascript" src="main2048.js"></script>
</head>
<body >
<div id="background">
<header>
<h1>2048</h1>
<a href="javascript:newgame();" id="newgamebutton">New Game</a>
<h4>score:<span id="score">0</span></h4>
</header>
<div id="grid-container">
<div class="grid-cell" id="grid-cell-0-0"></div>
<div class="grid-cell" id="grid-cell-0-1"></div>
<div class="grid-cell" id="grid-cell-0-2"></div>
<div class="grid-cell" id="grid-cell-0-3"></div>
<div class="grid-cell" id="grid-cell-1-0"></div>
<div class="grid-cell" id="grid-cell-1-1"></div>
<div class="grid-cell" id="grid-cell-1-2"></div>
<div class="grid-cell" id="grid-cell-1-3"></div>
<div class="grid-cell" id="grid-cell-2-0"></div>
<div class="grid-cell" id="grid-cell-2-1"></div>
<div class="grid-cell" id="grid-cell-2-2"></div>
<div class="grid-cell" id="grid-cell-2-3"></div>
<div class="grid-cell" id="grid-cell-3-0"></div>
<div class="grid-cell" id="grid-cell-3-1"></div>
<div class="grid-cell" id="grid-cell-3-2"></div>
<div class="grid-cell" id="grid-cell-3-3"></div>
</div>
</div>
</body>
</html>
main.js
var board = new Array();
var score =0;
var hasConflicted=new Array();
$(document).ready(function(){
newgame();
});
function newgame(){
//初始化棋盘格
init();
// clear score
clearscore();
//随机产生数字
generateOneNumber();
generateOneNumber();
}
function init(){
for(var i=0;i<4;i++)
for(var j=0;j<4;j++){
var gridCell=$("#grid-cell-"+i+'-'+j);
gridCell.css('top',getPosTop(i,j));
gridCell.css('left',getPosLeft(i,j));
}
for(var i=0;i<4;i++){
board[i]=new Array();
hasConflicted[i]=new Array();
for(var j=0;j<4;j++){
board[i][j]=0;
hasConflicted[i][j]=false;
}
}
updateBoardView();
score=0;
}
function updateBoardView(){
$(".number-cell").remove();
for(var i=0;i<4;i++)
for(var j=0;j<4;j++){
$("#grid-container").append('<div class="number-cell" id="number-cell-'+i+'-'+j+'"></div>');
var theNumberCell = $("#number-cell-"+i+'-'+j);
if (board[i][j]==0){
theNumberCell.css('width','0px');
theNumberCell.css('height','0px');
theNumberCell.css('top',getPosTop(i,j)+50);
theNumberCell.css('left',getPosLeft(i,j)+50);
}else{
theNumberCell.css('width','100px');
theNumberCell.css('height','100px');
theNumberCell.css('top',getPosTop(i,j));
theNumberCell.css('left',getPosLeft(i,j));
theNumberCell.css('background-color',getNumberBackgroundColor(board[i][j]));
theNumberCell.css('color',getNumberColor(board[i][j]));
theNumberCell.text(getNumberContent(board[i][j]));
}
hasConflicted[i][j]=false;
}
}
function generateOneNumber(){
if(nospace(board)){
return false;
}else{
//随机一个positon
var randx =parseInt(Math.floor(Math.random()*4) );
var randy =parseInt(Math.floor(Math.random()*4) );
var times=0;
while (times<50) {
if(board[randx][randy]==0){
break;
}else {
var randx =parseInt(Math.floor(Math.random()*4) );
var randy =parseInt(Math.floor(Math.random()*4) );
times++;
}
}
//优化循环 自动生成超过50次,就手动生成位置
if(times==50) {
for(var i=0;i<4;i++){
for(var j=0;j<4;j++){
if (board[i][j]==0) {
randx=i;
randy=j;
}
}
}
}
//随机一个number
var randNumber =Math.random()<0.5?2:4;
//随机位置显示随机数字
board[randx][randy]=randNumber;
showNumberWithAnimation(randx,randy,randNumber);
return true;
}
}
$(document).keydown(function(event){
switch (event.keyCode) {
case 37://left
if(moveLeft()){
setTimeout("generateOneNumber()",210);
setTimeout("isgameover()",300);
}
break;
case 38://up
if(moveUp()){
setTimeout("generateOneNumber()",210);
setTimeout("isgameover()",300);
}
break;
case 39://right
if(moveRight()){
setTimeout("generateOneNumber()",210);
setTimeout("isgameover()",300);
}
break;
case 40://down
if(moveDown()){
setTimeout("generateOneNumber()",210);
setTimeout("isgameover()",300);
}
break;
default:
break;
}
});
function isgameover(){
if(nospace(board) && nomove(board)){
gameover();
}else {
return false;
}
}
function gameover(){
alert("gameover!");
}
function moveLeft(){
if(!canMoveLeft(board)){
return false;
}
for(var i=0;i<4;i++)
for(var j=1;j<4;j++){
if(board[i][j]!=0){
for(var k=0;k<j;k++){
if(board[i][k]==0 && noBlockHorizontal(i,k,j,board)){
//move
showMoveAnimation(i,j,i,k);
board[i][k]=board[i][j];
board[i][j]=0;
continue;
}else if(board[i][k]==board[i][j] && noBlockHorizontal(i,k,j,board) && !hasConflicted[i][k]){
//move
showMoveAnimation(i,j,i,k);
//add
board[i][k]+=board[i][j];
board[i][j]=0;
//add score
score += board[i][k];
updateScore(score);
hasConflicted[i][k]=true;
continue;
}
}
}
}
updateBoardView();
return true;
}
function moveRight(){
if(!canMoveRight(board)){
return false;
}
for(var i=0;i<4;i++)
for(var j=2;j>=0;j--){
if(board[i][j]!=0){
for(var k=3;k>j;k--){
if(board[i][k]==0 && noBlockHorizontal(i,j,k,board)){
//move
showMoveAnimation(i,j,i,k);
board[i][k]=board[i][j];
board[i][j]=0;
continue;
}else if(board[i][k]==board[i][j] && noBlockHorizontal(i,j,k,board) && !hasConflicted[i][k]){
//move
showMoveAnimation(i,j,i,k);
//add
board[i][k]+=board[i][j];
board[i][j]=0;
score+=board[i][k];
updateScore(score);
hasConflicted[i][k]=true;
continue;
}
}
}
}
updateBoardView();
return true;
}
function moveUp(){
if(!canMoveUp(board)){
return false;
}
for(var j=0;j<4;j++)
for(var i=1;i<4;i++){
if(board[i][j]!=0){
for(var k=0;k<i;k++){
if(board[k][j]==0 && noBlockVertical(j,k,i,board)){
//move
showMoveAnimation(i,j,k,j);
board[k][j]=board[i][j];
board[i][j]=0;
continue;
}else if(board[k][j]==board[i][j] && noBlockVertical(j,k,i,board) && !hasConflicted[k][j]){
//move
showMoveAnimation(i,j,k,j);
//add
board[k][j]+=board[i][j];
board[i][j]=0;
score+=board[k][j];
updateScore(score);
hasConflicted[i][k]=true;
continue;
}
}
}
}
updateBoardView();
return true;
}
function moveDown(){
if(!canMoveDown(board)){
return false;
}
for(var j=0;j<4;j++)
for(var i=2;i>=0;i--){
if(board[i][j]!=0){
for(var k=3;k>i;k--){
if(board[k][j]==0 && noBlockVertical(j,k,i,board)){
//move
showMoveAnimation(i,j,k,j);
board[k][j]=board[i][j];
board[i][j]=0;
continue;
}else if(board[k][j]==board[i][j] && noBlockVertical(j,k,i,board) && !hasConflicted[k][j]){
//move
showMoveAnimation(i,j,k,j);
//add
board[k][j]+=board[i][j];
board[i][j]=0;
score+=board[k][j];
updateScore(score);
hasConflicted[i][k]=true;
continue;
}
}
}
}
updateBoardView();
return true;
}
support2048.js
function getPosTop(i,j) {
return 20+120*i;
}
function getPosLeft(i,j) {
return 20+120*j;
}
function getNumberBackgroundColor(number) {
switch(number){
case 2:return '#FCD6BC';break;
case 4:return '#F8A1B2';break;
case 8:return '#EF4E88';break;
case 16:return '#FBD75E';break;
case 32:return '#A8C065';break;
case 64:return '#76A2B5';break;
case 128:return '#47183E';break;
case 256:return '#1C4150';break;
case 512:return '#88CAD0';break;
case 1024:return '#405DAD';break;
case 2048:return '#C7C47B';break;
case 4096:return '#008080';break;
case 8192:return '#FF0000';break;
}
return "black";
}
function getNumberContent(number){
switch(number){
case 2:return "小白";break;
case 4:return "实习生";break;
case 8:return "程序猿";break;
case 16:return "项目经理";break;
case 32:return "构架师";break;
case 64:return "技术经理";break;
case 128:return "高级经理";break;
case 256:return "技术总监";break;
case 512:return "副总裁";break;
case 1024:return "CTO";break;
case 2048:return "总裁";break;
}
return "无业游民";
//console.log('number');
}
function getNumberColor(number){
if (number<=4)
return '#776e65';
return 'white';
}
function nospace(board){
for(var i=0;i<4;i++)
for(var j=0;j<4;j++){
if(board[i][j]==0){
return false;
}else{
return true;
}
}
}
function nomove(board){
if(canMoveLeft(board)||canMoveRight(board)||canMoveUp(board)||canMoveDown(board)){
return false;
}else {
return true;
}
}
function canMoveLeft(board){
for(var i=0;i<4;i++)
for(var j=1;j<4;j++){
if(board[i][j]!=0){
if(board[i][j-1]==0||board[i][j-1]==board[i][j]){
return true;
}
}
}
return false;
}
function canMoveRight(board){
for(var i=0;i<4;i++)
for(var j=2;j>=0;j--){
if(board[i][j]!=0){
if(board[i][j+1]==0||board[i][j+1]==board[i][j]){
return true;
}
}
}
return false;
}
function canMoveUp(board){
for(var j=0;j<4;j++)
for(var i=1;i<4;i++){
if(board[i][j]!=0){
if(board[i-1][j]==0||board[i-1][j]==board[i][j]){
return true;
}
}
}
return false;
}
function canMoveDown(board){
for(var j=0;j<4;j++)
for(var i=2;i>=0;i--){
if(board[i][j]!=0){
if(board[i+1][j]==0||board[i+1][j]==board[i][j]){
return true;
}
}
}
return false;
}
function noBlockHorizontal(row,col1,col2,board){
for(var i=col1+1;i<col2;i++ ){
if(board[row][i]!=0){
return false;
}
}
return true;
}
function noBlockVertical(col,row1,row2,board){
for(var i=row1+1;i<row2;i++ ){
if(board[i][col]!=0){
return false;
}
}
return true;
}
showanimation.js
function showNumberWithAnimation(i,j,randNumber){
var numberCell = $("#number-cell-"+i+'-'+j);
numberCell.css('background-color',getNumberBackgroundColor(randNumber));
numberCell.css('color',getNumberColor(randNumber));
numberCell.text(getNumberContent(randNumber) );
numberCell.animate({
width:"100px",
height:"100px",
top:getPosTop(i,j),
left:getPosLeft(i,j)
},50);
}
function clearscore(){
score=0;
$("#score").text(score);
}
function showMoveAnimation(fromx,fromy,tox,toy){
var numberCell=$("#number-cell-"+fromx+'-'+fromy);
numberCell.animate({
top:getPosTop(tox,toy),
left:getPosLeft(tox,toy)
},200);
}
function updateScore(score){
$("#score").text(score);
}
2048.css
#background {
position:fixed;
top:0;
left:0;
z-index:-10;
width:100%;
height:100%;
background: #ffa5a5;
background: -moz-linear-gradient(top, #ffa5a5 20%, #fff 100%);
background: -webkit-gradient(linear, left top, left bottom, color-stop(20%,#ffa5a5), color-stop(100%,#fff));
background: -webkit-linear-gradient(top, #ffa5a5 20%,#fff 100%);
background: linear-gradient(top, #ffa5a5 20%,#fff 100%);
}
header{
display: block;
width: 500px;
margin: 0 auto;
text-align: center;
}
#newgamebutton{
border-radius: 5px;
padding: 5px;
background-color: #EF4E88;
font-size: 25px;
color: #fff;
display: inline-block;
}
#grid-container{
width: 460px;
height: 460px;
padding: 20px;
margin: 10px auto;
background: #E6E6E6;
border-radius: 10px;
position: relative;
}
.grid-cell{
width: 100px;
height: 100px;
border-radius: 6px;
position: absolute;
background-color: #ffffff;
}
.number-cell{
border-radius: 6px;
position: absolute;
line-height: 100px;
font-size: 20px;
text-align: center;
}