当前位置:网站首页>使用js写一个2048
使用js写一个2048
2022-08-08 06:27:00 【写做四月一日的四月一日】
为什么标题叫使用js写一个2048呢?因为我不会页面美化(在这里给div加外边距和内边距已经是我做页面美化的极限了)!!!!本来打算导入SemanticUI来美化页面的,结果发现SemanticUI的弹出层需要jquery支持。那我用原生js写不是显得很呆?那就不对页面做美化了,能看就行,消息提示也使用尊贵的alert()来完成吧。

首先我们创建一个html文件,在body标签体内写我们需要的东西
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
</head>
<body>
<input type="button" id="initBtn" value="开始" onclick="initBoard()" /><!--开始和重新开始按钮-->
<div id="boardDiv"></div><!--展示图片-->
</body>
</html>然后准备一些图片,用来展示
以我高超的美术功底,这些工作很快就能完成

在html文件同级目录下新建一个img文件夹,然后把这些图片丢进去

开始准备写js代码
准备一些常量(分数这个东西因为我忘了写计分功能,就没啥用了)
//棋盘
var BOARD = [[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]];
//行列数
var ROW = 5;
var COL = 5;
//开始标志
var startFlag = false;
//数据列表
var LIST = [2,4,8,16,32,64,128,256,512,1024,2048];
//分数
var sore = 0;
//存储按下鼠标的位置
var startX = 0;
var startY = 0;
//不移动阈值
var LIMIT = 10;获取页面上一些等会要用的元素
var initBtn = document.getElementById('initBtn');
var boardDiv = document.getElementById('boardDiv');
var body = document.getElementById('body');写几个函数(写循环的时候把i,j和行列的对应关系搞的有点混,幸亏是一个行数列数一样的矩阵)
初始化棋盘的函数
/**
* 初始化棋盘
*/
function initBoard(){
startFlag = true;
initBtn.value = "重新开始";
for(var i = 0; i < ROW; i++){
for(var j = 0; j < COL; j++){
BOARD[i][j] = 0;
}
}
var count = 0;
while(count < 4){
var i = Math.floor(Math.random() * COL);
var j = Math.floor(Math.random() * ROW);
if(BOARD[i][j] !== 0){
continue;
}
BOARD[i][j] = 2;
count++;
}
showBoard();
}展示棋盘的函数
/**
* 展示棋盘
*/
function showBoard(){
boardDiv.innerHTML = "";
for(var i = 0; i < ROW; i++){
for(var j = 0; j < COL; j++){
boardDiv.innerHTML += "<img src='img/" + BOARD[i][j] + ".png'/>";
}
boardDiv.innerHTML += "<br\>";
}
}向棋盘添加数据的函数(如果棋盘满了就不加,没满就随机找一个空位添加)
/**
* 添加数据到棋盘
*/
function addNum(){
var flag = true;
for(var i = 0; i < COL; i++){
for(var j = 0; j < ROW; j++){
if(0 == BOARD[i][j]){
flag = false;
break;
}
}
}
if(flag){
return;
}
var x;
var y;
do{
x = Math.floor(Math.random() * COL);
y = Math.floor(Math.random() * ROW);
}while(BOARD[x][y] != 0);
BOARD[x][y] = LIST[Math.floor(Math.random() * 4)];
}向四个方向移动数据并合并的函数
/**
* 向左合并
*/
function mergeLeft(){
for(var i = 0 ; i < ROW; i++){
//记录需要附加移动的数
var count = (0 == BOARD[i][COL - 1]? 0 : 1);
for(var j = COL - 1; j > 0; j--){
if(0 == BOARD[i][j - 1] || BOARD[i][j - 1] == BOARD[i][j]){
//相等相加
BOARD[i][j - 1] += BOARD[i][j];
if(2048 == BOARD[i][j - 1]){
BOARD[i][j - 1] = 0
}
BOARD[i][j] = 0;
//复制附件移动的数
if(count > 0){
for(k = j + 1;k < j + 1 + count;k++){
if(k > COL - 1){
break;
}
BOARD[i][k - 1] = BOARD[i][k];
BOARD[i][k] = 0;
}
}
}else if(BOARD[i][j - 1] != BOARD[i][j]){
count++;
}
}
}
}
/**
* 向右合并
*/
function mergeRight(){
for(var i = 0 ; i < ROW; i++){
var count = (0 == BOARD[i][0]? 0 : 1);
for(var j = 0; j < COL - 1; j++){
if(0 == BOARD[i][j + 1] || BOARD[i][j + 1] == BOARD[i][j]){
BOARD[i][j + 1] += BOARD[i][j];
if(2048 == BOARD[i][j + 1]){
BOARD[i][j + 1] = 0
}
BOARD[i][j] = 0;
if(count > 0){
for(k = j - 1;k > j - 1 - count;k--){
if(k < 0){
break;
}
BOARD[i][k + 1] = BOARD[i][k];
BOARD[i][k] = 0;
}
}
}else if(BOARD[i][j + 1] != BOARD[i][j]){
count++;
}
}
}
}
/**
* 向下合并
*/
function mergeDown(){
for(var j = 0; j < COL; j++){
var count = (0 == BOARD[0][j]? 0 : 1);
for(var i = 0; i < ROW - 1; i++){
if(0 == BOARD[i + 1][j] || BOARD[i + 1][j] == BOARD[i][j]){
BOARD[i + 1][j] += BOARD[i][j];
if(2048 == BOARD[i + 1][j]){
BOARD[i + 1][j] = 0
}
BOARD[i][j] = 0;
if(count > 0){
for(k = i - 1;k > i - 1 - count;k--){
if(k < 0){
break;
}
BOARD[k + 1][j] = BOARD[k][j];
BOARD[k][j] = 0;
}
}
}else if(BOARD[i + 1][j] != BOARD[i][j]){
count++;
}
}
}
}
/**
* 向上合并
*/
function mergeUp(){
for(var j = 0; j < COL; j++){
var count = (0 == BOARD[ROW - 1][j]? 0 : 1);
for(var i = ROW - 1; i > 0; i--){
if(0 == BOARD[i - 1][j] || BOARD[i - 1][j] == BOARD[i][j]){
BOARD[i - 1][j] += BOARD[i][j];
if(2048 == BOARD[i - 1][j]){
BOARD[i - 1][j] = 0
}
BOARD[i][j] = 0;
if(count > 0){
for(k = i + 1;k < i + 1 + count;k++){
if(k > ROW - 1){
break;
}
BOARD[k - 1][j] = BOARD[k][j];
BOARD[k][j] = 0;
}
}
}else if(BOARD[i - 1][j] != BOARD[i][j]){
count++;
}
}
}
}判断游戏结束的函数(游戏结束的判定标准是数据无法移动也无法合并)
/**
* 判断当前位置是否可以使游戏继续
* @param {Object} x x坐标
* @param {Object} y y坐标
*/
function coludContinue(x,y){
if(0 == BOARD[x][y]){
return true;
}
return BOARD[x - 1][y] == BOARD[x][y] ||
BOARD[x][y - 1] == BOARD[x][y] ||
BOARD[x][y + 1] == BOARD[x][y] ||
BOARD[x + 1][y] == BOARD[x][y];
}
/**
* 判断游戏是否失败
*/
function isFalse(){
for(var x = 0; x < COL; x++){
if(0 == BOARD[0][x] || 0 == BOARD[ROW - 1][x] || 0 == BOARD[x][0] || 0 == BOARD[x][COL - 1]){
return false;
}
}
for(var i = 1; i < ROW - 1; i++){
for(var j = 1; j < COL - 1; j++){
if(coludContinue(i,j)){
return false;
}
}
}
return true;
}判断当前用户指定的移动方向以及游戏进行的函数
/**
* 鼠标按下时获取按下时的坐标
* @param {Object} event 鼠标按下事件,js自动传入
*/
document.onmousedown = function(event){
startX = event.pageX;
startY = event.pageY;
}
/**
* 鼠标松开时判断是否要进行移动
* @param {Object} event 鼠标松开事件,js自动传入
*/
document.onmouseup = function(event){
if(!startFlag){
return;
}
if(0 == startX && 0 == startY){
return
}
var endX = event.pageX;
var endY = event.pageY;
var x = endX - startX;
var y = endY - startY;
startX = 0;
startY = 0;
if(x > LIMIT || x < -LIMIT || y > LIMIT || y < -LIMIT){
var absX = Math.abs(x);
var absY = Math.abs(y);
if(absX > absY){
if(x > 0){
mergeRight();
}else{
mergeLeft();
}
}else{
if(y > 0){
mergeDown();
}else{
mergeUp();
}
}
if(isFalse()){
alert("您输了");
startFlag = false;
}
addNum();
showBoard();
}
}完整的代码长这个样子
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<style>
#boardDiv{
margin-top: 10px;
}
img{
margin-top: 2px;
margin-right: 2px;
}
</style>
</head>
<body id="body" onselectstart="return false">
<input type="button" id="initBtn" value="开始" onclick="initBoard()" /><!--开始和重新开始按钮-->
<div id="boardDiv"></div><!--展示图片-->
</body>
<script>
//棋盘
var BOARD = [[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]];
//行列数
var ROW = 5;
var COL = 5;
//开始标志
var startFlag = false;
//数据列表
var LIST = [2,4,8,16,32,64,128,256,512,1024,2048];
//分数
var sore = 0;
//存储按下鼠标的位置
var startX = 0;
var startY = 0;
//不移动阈值
var LIMIT = 10;
var initBtn = document.getElementById('initBtn');
var boardDiv = document.getElementById('boardDiv');
var body = document.getElementById('body');
var sorceMsg = document.getElementById('sorceMsg');
/**
* 初始化棋盘
*/
function initBoard(){
startFlag = true;
initBtn.value = "重新开始";
for(var i = 0; i < ROW; i++){
for(var j = 0; j < COL; j++){
BOARD[i][j] = 0;
}
}
var count = 0;
while(count < 4){
var i = Math.floor(Math.random() * COL);
var j = Math.floor(Math.random() * ROW);
if(BOARD[i][j] !== 0){
continue;
}
BOARD[i][j] = 2;
count++;
}
showBoard();
}
/**
* 添加数据到棋盘
*/
function addNum(){
var flag = true;
for(var i = 0; i < COL; i++){
for(var j = 0; j < ROW; j++){
if(0 == BOARD[i][j]){
flag = false;
break;
}
}
}
if(flag){
return;
}
var x;
var y;
do{
x = Math.floor(Math.random() * COL);
y = Math.floor(Math.random() * ROW);
}while(BOARD[x][y] != 0);
BOARD[x][y] = LIST[Math.floor(Math.random() * 4)];
}
/**
* 展示棋盘
*/
function showBoard(){
boardDiv.innerHTML = "";
for(var i = 0; i < ROW; i++){
for(var j = 0; j < COL; j++){
boardDiv.innerHTML += "<img src='img/" + BOARD[i][j] + ".png'/>";
}
boardDiv.innerHTML += "<br\>";
}
}
/**
* 向左合并
*/
function mergeLeft(){
for(var i = 0 ; i < ROW; i++){
//记录需要附加移动的数
var count = (0 == BOARD[i][COL - 1]? 0 : 1);
for(var j = COL - 1; j > 0; j--){
if(0 == BOARD[i][j - 1] || BOARD[i][j - 1] == BOARD[i][j]){
//相等相加
BOARD[i][j - 1] += BOARD[i][j];
if(2048 == BOARD[i][j - 1]){
BOARD[i][j - 1] = 0
}
BOARD[i][j] = 0;
//复制附件移动的数
if(count > 0){
for(k = j + 1;k < j + 1 + count;k++){
if(k > COL - 1){
break;
}
BOARD[i][k - 1] = BOARD[i][k];
BOARD[i][k] = 0;
}
}
}else if(BOARD[i][j - 1] != BOARD[i][j]){
count++;
}
}
}
}
/**
* 向右合并
*/
function mergeRight(){
for(var i = 0 ; i < ROW; i++){
var count = (0 == BOARD[i][0]? 0 : 1);
for(var j = 0; j < COL - 1; j++){
if(0 == BOARD[i][j + 1] || BOARD[i][j + 1] == BOARD[i][j]){
BOARD[i][j + 1] += BOARD[i][j];
if(2048 == BOARD[i][j + 1]){
BOARD[i][j + 1] = 0
}
BOARD[i][j] = 0;
if(count > 0){
for(k = j - 1;k > j - 1 - count;k--){
if(k < 0){
break;
}
BOARD[i][k + 1] = BOARD[i][k];
BOARD[i][k] = 0;
}
}
}else if(BOARD[i][j + 1] != BOARD[i][j]){
count++;
}
}
}
}
/**
* 向下合并
*/
function mergeDown(){
for(var j = 0; j < COL; j++){
var count = (0 == BOARD[0][j]? 0 : 1);
for(var i = 0; i < ROW - 1; i++){
if(0 == BOARD[i + 1][j] || BOARD[i + 1][j] == BOARD[i][j]){
BOARD[i + 1][j] += BOARD[i][j];
if(2048 == BOARD[i + 1][j]){
BOARD[i + 1][j] = 0
}
BOARD[i][j] = 0;
if(count > 0){
for(k = i - 1;k > i - 1 - count;k--){
if(k < 0){
break;
}
BOARD[k + 1][j] = BOARD[k][j];
BOARD[k][j] = 0;
}
}
}else if(BOARD[i + 1][j] != BOARD[i][j]){
count++;
}
}
}
}
/**
* 向上合并
*/
function mergeUp(){
for(var j = 0; j < COL; j++){
var count = (0 == BOARD[ROW - 1][j]? 0 : 1);
for(var i = ROW - 1; i > 0; i--){
if(0 == BOARD[i - 1][j] || BOARD[i - 1][j] == BOARD[i][j]){
BOARD[i - 1][j] += BOARD[i][j];
if(2048 == BOARD[i - 1][j]){
BOARD[i - 1][j] = 0
}
BOARD[i][j] = 0;
if(count > 0){
for(k = i + 1;k < i + 1 + count;k++){
if(k > ROW - 1){
break;
}
BOARD[k - 1][j] = BOARD[k][j];
BOARD[k][j] = 0;
}
}
}else if(BOARD[i - 1][j] != BOARD[i][j]){
count++;
}
}
}
}
/**
* 判断当前位置是否可以使游戏继续
* @param {Object} x x坐标
* @param {Object} y y坐标
*/
function coludContinue(x,y){
if(0 == BOARD[x][y]){
return true;
}
return BOARD[x - 1][y] == BOARD[x][y] ||
BOARD[x][y - 1] == BOARD[x][y] ||
BOARD[x][y + 1] == BOARD[x][y] ||
BOARD[x + 1][y] == BOARD[x][y];
}
/**
* 判断游戏是否失败
*/
function isFalse(){
for(var x = 0; x < COL; x++){
if(0 == BOARD[0][x] || 0 == BOARD[ROW - 1][x] || 0 == BOARD[x][0] || 0 == BOARD[x][COL - 1]){
return false;
}
}
for(var i = 1; i < ROW - 1; i++){
for(var j = 1; j < COL - 1; j++){
if(coludContinue(i,j)){
return false;
}
}
}
return true;
}
/**
* 鼠标按下时获取按下时的坐标
* @param {Object} event 鼠标按下事件,js自动传入
*/
document.onmousedown = function(event){
startX = event.pageX;
startY = event.pageY;
}
/**
* 鼠标松开时判断是否要进行移动
* @param {Object} event 鼠标松开事件,js自动传入
*/
document.onmouseup = function(event){
if(!startFlag){
return;
}
if(0 == startX && 0 == startY){
return
}
var endX = event.pageX;
var endY = event.pageY;
var x = endX - startX;
var y = endY - startY;
startX = 0;
startY = 0;
if(x > LIMIT || x < -LIMIT || y > LIMIT || y < -LIMIT){
var absX = Math.abs(x);
var absY = Math.abs(y);
if(absX > absY){
if(x > 0){
mergeRight();
}else{
mergeLeft();
}
}else{
if(y > 0){
mergeDown();
}else{
mergeUp();
}
}
if(isFalse()){
alert("您输了");
startFlag = false;
}
addNum();
showBoard();
}
}
</script>
</html>
跑一下试试
跑起来了也没有报错,欸嘿

开始瞧瞧

失败提示

我需要的功能都完成了
边栏推荐
猜你喜欢

Solved the problem that when VRTK transmission under Unity HDRP, the screen fades in and out, and the visual occlusion cannot be displayed correctly when passing through the wall

【图形学】08 3D坐标系的变换(一)

用户管理 用户的增删改查 切换用户 用户组 用户组相关文件

网络开发相关

Unity 物体颜色渐变效果(判断逻辑实现)

CSDN21天学习挑战赛之顺序查找
![[Unity] GPU动画实现(四)——生成动画数据](/img/c4/39fd5e781e0f0bc2acf0e4d6ada648.png)
[Unity] GPU动画实现(四)——生成动画数据

win11+MX250+CUDA Tookit 10.1 update 2
![[Unity] 自定义日志系统 解决Unity Log的痛点](/img/2e/761761882b64dbf67418542fb21833.png)
[Unity] 自定义日志系统 解决Unity Log的痛点

【图形学】12 UnityShader语法入门
随机推荐
软件工具 | 04.Typora搭配PicGo-Core实现用时间命名图片
C# Unicode (Universal Code) text conversion
编程更改镜像总结
类与对象之动静态方法,继承,名字的查找顺序,经典类和新式类,派生方法
Next主题美化
3.关于剪枝论文的分类和整理(随笔)
CSDN21天学习挑战赛之顺序查找
The state machine control shift register multisim simulation in the process of state variables and state transition conditions don't match
Unity_折线图+UI动画
【图形学】09 UnityShader入门(一)
P02 线程的用途
Unity_常用数据分析总结:折线图、条形图(柱状图)、扇形图(饼状图)、雷达图(属性图)
Leetcode topic sharing and explanation
NVIDIA CUDA 高度并行处理器编程(九):并行模式:稀疏矩阵-向量乘法
rhcsa第二天
Implementation of bubble sort in C language and optimization of bubble sort
Stack queue OJ question sharing and explanation
背包问题小结
[总结] Unity Lightmap使用总结
【图形学】11 UnityShader入门(三)