2048小游戏(简易版)
前言
刚学完前端三件套(HTML + CSS + JavaScript) 的同学们已经可以试着做些小项目来实践自己的学习成果了,我花了两天时间做了个简易版的2048小游戏用来作为实践。以下为大家展示游戏画面和代码。
游戏截图
HTML
<!DOCTYPE html>
<html>
<head>
<title>尤乐娃子的2048(简易版)</title>
<link rel="stylesheet" href="./study.css">
</head>
<body>
<!-- 游戏网格 -->
<div class="full">
<div class="number" id="li1col1"></div>
<div class="number" id="li1col2"></div>
<div class="number" id="li1col3"></div>
<div class="number" id="li1col4"></div>
<div class="number" id="li2col1"></div>
<div class="number" id="li2col2"></div>
<div class="number" id="li2col3"></div>
<div class="number" id="li2col4"></div>
<div class="number" id="li3col1"></div>
<div class="number" id="li3col2"></div>
<div class="number" id="li3col3"></div>
<div class="number" id="li3col4"></div>
<div class="number" id="li4col1"></div>
<div class="number" id="li4col2"></div>
<div class="number" id="li4col3"></div>
<div class="number" id="li4col4"></div>
<!-- 展示框 -->
<div class="scores"></div>
<div class="bestScores"></div>
</div>
<!-- 刷新游戏 -->
<div class="newgame">新游戏</div>
<script src="./study.js"></script>
</body>
</html>
CSS
*{
margin: 0;
padding: 0;
list-style: none;
font-family:'Franklin Gothic Medium', 'Arial Narrow', 'Arial', 'sans-serif', 'SimHei';
}
body {
background-color: #FAF8EF;
}
.full {
position: relative;
display: grid;
padding: 10px;
margin: 100px auto 0px;
border-radius: 10px;
background-color: #BBADA0;
grid-template-columns: repeat(4, 1fr);
grid-template-rows: repeat(4, 1fr);
grid-gap: 10px;
width: 600px;
height: 600px;
}
.number {
background-color: #f0f0f0;
display: flex;
background-color: #CDC1B4;
border-radius: 10px ;
justify-content: center;
align-items: center;
font-size: 60px;
color: #776E65;
}
.newgame {
margin: 30px auto;
height: 80px;
width: 250px;
border-radius: 40px;
text-align: center;
line-height: 80px;
font-size: 40px;
color: #776E65;
background-color: #CDC1B4;
cursor: pointer;
}
.scores {
position: absolute;
border-radius: 10px;
left: 650px;
top: 250px;
height: 100px;
width: 240px;
text-align: center;
line-height: 100px;
font-size: 50px;
color: #F9F6F2;
background-color: #BBADA0;
transition: .1s;
}
.scores::after {
position: absolute;
content: "分数";
left: 50%;
transform: translate(-50%, 0);
top: -80px;
font-size: 40px;
color: #776E65;
}
.bestScores {
position: absolute;
border-radius: 10px;
left: 650px;
top: 50px;
height: 100px;
width: 240px;
text-align: center;
line-height: 100px;
font-size: 50px;
color: #F9F6F2;
background-color: #BBADA0;
transition: .1s;
}
.bestScores::after {
position: absolute;
content: "最高分";
left: 50%;
transform: translate(-50%, 0);
top: -80px;
font-size: 40px;
color: #776E65;
}
JavaScript
var grade = [ [0,0,0,0],
[0,0,0,0],
[0,0,0,0],
[0,0,0,0] ];
var gradeant = [ [0,0,0,0],
[0,0,0,0],
[0,0,0,0],
[0,0,0,0] ];
let mod = null
let pos = null
let nextnumber = null
let sum = 0
let presum = null
let maxSum = -1
//随机摇数(2/4)
function sorteianum(){
nextnumber = Math.floor(Math.random()*3) + 2;//随机获得 2,3,4
if(nextnumber==3) {
return sorteianum();
} else {
return
}
}
//随机摇位置(行列皆为0-3)
function sorteiapos(){
posicao = Math.floor(Math.random()*16);//0-15
mod = Math.floor(posicao/4);//0-3
pos = posicao % 4;//0-3
if(grade[mod][pos]!=0){
return sorteiapos();
} else {
return
}
}
//将值写入矩阵中
function insertion(){
sorteiapos();
sorteianum();
grade[mod][pos]=nextnumber
gradeant[mod][pos]=nextnumber;
}
//创建新元素
function exibegrade(){
for(i = 0; i < 4; i++){
for(j = 0; j < 4; j++){
//创建新元素
let aimElement=`li${i + 1}col${j + 1}`;
const Element = document.getElementById(aimElement)
Element.innerHTML = grade[i][j];
//新元素上色
let color = null
switch(grade[i][j]) {
case 2:
color = '#EEE4DA'
break;
case 4:
color = '#EDE0C8'
break;
case 8:
color = '#F2B179'
break;
case 16:
color = '#F59563'
break;
case 32:
color = '#F67C5F'
break;
case 64:
color = '#F65E3B'
break;
case 128:
color = '#EDCF72'
break;
case 256:
color = '#EDCC61'
break;
case 512:
color = '#EDC850'
break;
case 1024:
color = '#EDC53F'
break;
case 2048:
color = '#EBC12D'
break;
}
Element.style.backgroundColor = color
//新元素动画
if(i == mod && j == pos) {
Element.style.transform = 'scale(0, 0)'
setTimeout(() => {
Element.style.transition = '.1s'
Element.style.transform = 'scale(1, 1)'
},100)
setTimeout(() => {
Element.style.transition = '0s'
},200)
}
}
}
}
//跳跃动画
function jump(i, j) {
let aimElement = `li${i + 1}col${j + 1}`;
const Element = document.getElementById(aimElement)
Element.style.transform = 'scale(1.2, 1.2)'
Element.style.transition = '.1s'
setTimeout(() => {
Element.style.transform = 'scale(1, 1)'
},100)
setTimeout(() => {
Element.style.transition = '0s'
},200)
}
//分数统计
function scores(sum) {
if(presum == sum)return
presum = sum
const scoresElement = document.querySelector(".scores")
scoresElement.innerHTML = `${sum}`
scoresElement.style.fontSize = '60px'
setTimeout(() => {
scoresElement.style.fontSize = '50px'
},100)
if(sum > maxSum) {
maxSum = sum
const scoresElement = document.querySelector(".bestScores")
scoresElement.innerHTML = `${maxSum}`
scoresElement.style.fontSize = '60px'
setTimeout(() => {
scoresElement.style.fontSize = '50px'
},100)
}
}
// 方向按键
function buttonselect(e){
let Key = e.keyCode;
switch(Key){
case 65:
left()
break;
case 37:
left()
break;
case 87:
up()
break;
case 38:
up()
break;
case 68:
right()
break;
case 39:
right()
break;
case 83:
down()
break;
case 40:
down()
break;
}
}
function left(){
for(let i = 0; i < 4; i++) {
//将方向边界为空的行移依将方块次动至边界
for(let j = 0; j < 3; j++) {
for(let k = 0; k < 3; k++) {
if(grade[i][k] == 0) {
for(let o = k; o < 3; o++)grade[i][o] = grade[i][o + 1]
grade[i][3] = 0
}
}
}
//合并
for(let j = 0; j < 3; j++) {
if(grade[i][j] == grade[i][j + 1] && grade[i][j] !== 0) {
grade[i][j] *= 2
jump(i,j)
sum += grade[i][j]
for(let k = j + 1; k < 3; k++)grade[i][k] = grade[i][k + 1]
grade[i][3] = 0
if(j == 0 && grade[i][1] == grade[i][2] && grade[i][1] !== 0) {
grade[i][1] *= 2
jump(i,1)
sum += grade[i][j]
grade[i][2] = 0
}
}
}
}
next()
}
function up(){
for(j = 0; j < 4; j++){
//将方向边界为空的行移依将方块次动至边界
for(let i = 0; i < 3; i++) {
for(let k = 0; k < 3; k++) {
if(grade[k][j] == 0) {
for(let o = k; o < 3; o++)grade[o][j] = grade[o + 1][j]
grade[3][j] = 0
}
}
}
//合并
for(let i = 0; i < 3; i++) {
if(grade[i][j] == grade[i + 1][j] && grade[i][j] !== 0) {
grade[i][j] *= 2
jump(i,j)
sum += grade[i][j]
for(let k = i + 1; k < 3; k++)grade[k][j] = grade[k + 1][j]
grade[3][j] = 0
if(i == 0 && grade[1][j] == grade[2][j] && grade[1][j] !== 0) {
grade[1][j] *= 2
jump(1,j)
sum += grade[i][j]
grade[2][j] = 0
}
}
}
}
next();
}
function right(){
for(i = 0; i < 4; i++){
//将方向边界为空的行移依将方块次动至边界
for(let j = 0; j < 3; j++) {
for(let k = 3; k >= 0; k--) {
if(grade[i][k] == 0) {
for(let o = k; o > 0; o--)grade[i][o] = grade[i][o - 1]
grade[i][0] = 0
}
}
}
//合并
for(let j = 3; j > 0; j--) {
if(grade[i][j] == grade[i][j - 1] && grade[i][j] !== 0) {
grade[i][j] *= 2
jump(i,j)
sum += grade[i][j]
for(let k = j - 1; k > 0; k--)grade[i][k] = grade[i][k - 1]
grade[i][0] = 0
if(j == 3 && grade[i][2] == grade[i][1] && grade[i][2] !== 0) {
grade[i][2] *= 2
jump(i,2)
sum += grade[i][j]
grade[i][1] = 0
}
}
}
}
next()
}
function down(){
for(let j = 0; j < 4; j++){
//将方向边界为空的行移依将方块次动至边界
for(let i = 0; i < 3; i++) {
for(let k = 3; k >= 0; k--) {
if(grade[k][j] == 0) {
for(let o = k; o > 0; o--)grade[o][j] = grade[o - 1][j]
grade[0][j] = 0
}
}
}
//合并
for(let i = 3; i > 0; i--) {
if(grade[i][j] == grade[i - 1][j] && grade[i][j] !== 0) {
grade[i][j] *= 2
jump(i,j)
sum += grade[i][j]
for(let k = i - 1; k > 0; k--)grade[k][j] = grade[k - 1][j]
grade[0][j] = 0
if(i == 3 && grade[2][j] == grade[1][j] && grade[2][j] !== 0) {
grade[2][j] *= 2
jump(2,j)
sum += grade[i][j]
grade[1][j] = 0
}
}
}
}
next()
}
//向网格空出添加新的方块
function play(){
insertion()
exibegrade()
scores(sum)
}
function next(){
let flag = 0
let over1 = 1
let over2 = 1
for (let i = 0; i < 4; i++) {
for(let j = 0; j < 4; j++){
//与上一次方块做比较
if(grade[i][j]!=gradeant[i][j]){
gradeant[i][j]=grade[i][j];
flag = 1;
}
//是否还存在空方块&&都与相邻不同
if(grade[i][j] == 0)over2 = 0
if(j < 3 && grade[i][j] == grade[i][j + 1])over1 = 0
if(i < 3 && grade[i][j] == grade[i + 1][j])over1 = 0
}
}
if(flag == 0){
if(over1 == 1 && over2 == 1)alert("结束")
return
} else{
play()
}
}
//重新开始
const newGame = document.querySelector(".newgame")
newGame.onclick = function() {
grade.forEach((arr) => arr.fill(0))
gradeant.forEach((arr) => arr.fill(0))
sum = 0
play()
}
play();
document.onkeydown = buttonselect;