JavaScript【趣味】做一个网页版2048

news2024/11/25 11:54:32

文章目录

  • 🌟前言
  • 🌟先看效果(粉丝特权哈哈)
  • 🌟代码实现
    • 🌟页面布局 【index.html】
    • 🌟样式文件【2048.css】
    • 🌟index.html 里用到的JS文件
      • 🌟jquery.min.js
      • 🌟util.js
      • 🌟2048.js
  • 🌟结语

在这里插入图片描述

🌟前言

哈喽小伙伴们,从这篇文章开始,我会开始新的专栏JavaScript【趣味JS七十二变】;这个专栏里边会收录一些JavaScript的趣味玩法和一些小游戏,目的是为了大家在娱乐的过程中也可以去学习到很多知识点,喜欢的话希望大家可以订阅并持续关注;今天我们开始这个专栏的第一篇文章,使用Jquery 来做一个网页版的 2048 ;让我们一起来看看吧🤘

🌟先看效果(粉丝特权哈哈)

在这里插入图片描述

JS实现一个网页版2048小游戏

🌟代码实现

🌟页面布局 【index.html】


<!DOCTYPE html>
<html lang="en">
<head>
	<meta charset="UTF-8">
	<title>2048</title>
	<link rel="stylesheet" href="css/2048.css">
	<script src="js/jquery.min.js"></script>
	<script src="js/util.js"></script>
	<script src="js/2048.js"></script>
</head>
<body>
	<header>
		<h3>2048</h3>
		<div class="score hscore" style="line-height: 40px;">最高分数:<span>0</span></div>
		<div class="score" style="line-height: 10px;">分数:<span>0</span></div>
	</header>
	<div class="btn-group">
		<div class="newgame" onclick="newGame()" onmousedown="return false">新游戏</div>
	</div>
	<!-- 棋盘区域 -->
	<div class="grid">
	</div>
</body>
</html>

🌟样式文件【2048.css】

body,ul,li,h3{
	margin: 0;
	padding: 0;
	list-style: none;
}
body{
	background: #fcfad3;
}
a{
	text-decoration: none;
}
header{
	width: 500px;
	margin: 0 auto;
	text-align: center;
	font-family: arial;
	height: 60px;
}
header .score{
	float: right;
	width: 50%;
	height: 30px;
	line-height: 30px;
	font-size: 14px;
	text-align: right;
	color:#666;
}
header .score span{
	display: inline-block;
	width: 40px;
	padding:0 10px;
	color:#ff6529;
}
header h3{
	width: 40%;
	height: 60px;
	font-size: 44px;
	line-height: 60px;
	text-align: left;
	font-family:"arial";
	color:#ff6529;
	float: left;
}
.grid{
	width: 500px;
	height: 500px;
	background: #c4b6ab;
	margin: 10px auto 0px;
	border-radius: 20px;
	position: relative;
}
.grid-cell{
	width: 100px;
	height: 100px;
	border-radius: 10px;
	position: absolute;
	background: #d2c8be;
}
.number-cell{
	font-family: arial;
	font-size: 60px;
	font-weight: bold;
	text-align: center;
	line-height: 100px;
	position: absolute;
	border-radius: 10px;
}
.btn-group{
	margin:0 2%;
	text-align: center;
}
.newgame{
	display: inline-block;
	padding: 4px 12px;
	background: #ff6529;
	color: #fff;
	font-size: 18px;
	margin-top: 10px;
	border-radius: 0.5rem;
}
.newgame:active{
	opacity: 0.6;
}

🌟index.html 里用到的JS文件

🌟jquery.min.js

这个文件就不给大家输出了,如果小伙伴没有的话,我这里给大家推介一个CDN网站,大家可以自行去下载

BootCDN
稳定、快速、免费的前端开源项目 CDN 加速服务;共收录了 4381 个前端开源项目

在这里插入图片描述

🌟util.js

这个是封装了一个工具类,里边包含了一些相关的函数,封装起来也是为了方便复用

//工具类
var util ={
	pos:function(n){//获取x y位置
		return n*120+20;
	},
	//检测界面中是否有空间
	space:function(d){
		for(var i=0;i<4;i++){
			for(var j=0;j<4;j++){
				if(d[i][j]==0){
					return false;
				}
			}
		}
		return true;
	},
	//动画显示一个numbercell + 数字
	showNumber:function(x,y,num){
		var numberCell = $('#n'+x+y);
		numberCell.css({
			backgroundColor:bgColor[num],
			color:fontColor(num)
		}).text(num).animate({width:100,height:100,left:util.pos(y),top:util.pos(x)},50);
	},
	//消除动画
	moveAnimate:function (fi,fj,ti,tj){
		$('#n'+fi+fj).animate({
			left:util.pos(tj),
			top:util.pos(ti)
		},100)
	},
	//更新分数
	updateScore:function(){
		$('.score span').text(score);
		this.hightScore()
	},
	//最高分数
	hightScore:function(){
		if(!localStorage.getItem('hscore')){
			localStorage.setItem('hscore',0);
		}
		var oldH = localStorage.getItem('hscore');
		if(oldH<score){
			localStorage.setItem('hscore',score);
			$('.hscore span').text(score);
		}else{
			$('.hscore span').text(oldH);
		}
	}
}

🌟2048.js

核心JS文件,处理游戏的大部分逻辑

/*
	2048游戏逻辑
	# 变量组
	data 存放数据
	score 存放分数

	1. 绘制界面  4*4 双层 for 计算left top

*/
var data = [];//数据
var score = 0; //分数
var flag = true;
var bgColor = {//不同数字单元格背景颜色
	2:'#eee4da',
	4:'#ede0c8',
	8:'#f2b179',
	16:'#f59563',
	32:'#f67c5f',
	64:'#f65e3b',
	128:'#edcf72',
	256:'#edcc61',
	512:'#9c0',
	1024:'#33b5e5',
	2048:'#09c',
	4096:'#a6c',
	8192:'#93c'
}
var fontColor=function(num){//数字颜色
	if(num<=4){
		return "#776e65";
	}
	return "#fff";
}

$(function(){
	newGame()

})
// 新游戏
function newGame(){
	//绘制界面
	drawSence();
	score =0;
	util.updateScore();
	util.hightScore();
	//随机生成2个数字
	getNumber();
	getNumber();
	flag=true;
}

//绘制界面函数
function drawSence(){
	var grid=$('.grid');
	grid.empty();
	for (var i = 0; i < 4; i++) {
		for(var j = 0; j < 4; j++){
			$('<div>').attr({
				class:'grid-cell',
				id:'g'+i+j
			}).css({
				top:util.pos(i),
				left:util.pos(j)
			}).appendTo(grid)
		}
	}

	//初始化数据
	for(var i=0;i<4;i++){
		data[i]=[];
		for(var j=0;j<4;j++){
			data[i][j]=0;
		}
	}

	//创建number-cell
	showdata()
	console.log(data)
}
function showdata(){
	var grid=$('.grid');
	$('.number-cell').remove(); //清除所有number-cell元素
	for(var i=0;i<4;i++){
		for(var j=0;j<4;j++){
			var numberCell = $('<div>');
			numberCell.attr({
				class:'number-cell',
				id:'n'+i+j
			}).appendTo(grid);
			if(data[i][j]==0){
				numberCell.css({
					width:0,
					height:0,
					left:util.pos(j)+50,
					top:util.pos(i)+50
				})
			}else{
				numberCell.css({
					width:100,
					height:100,
					left:util.pos(j),
					top:util.pos(i)
				})
				numberCell.css({
					backgroundColor:bgColor[data[i][j]],
					color:fontColor(data[i][j]),
				}).text(data[i][j]);
			}
		}
	}
}


function getNumber(){
	if(util.space(data)){
		return true;
	}
	//随机单元格 位置
	var x = Math.floor(Math.random()*4);
	var y = Math.floor(Math.random()*4);
	while(data[x][y]!=0){
		x = Math.floor(Math.random()*4);
		y = Math.floor(Math.random()*4);
	}
	//随机数字
	var num = Math.random()<0.5?2:4;
	data[x][y] = num;
	util.showNumber(x,y,num);

	console.log(data)
	return false;
}

// 监听键盘按键
$(document).keydown(function(e){
	if(!flag){return;}
	switch(e.keyCode){
		case 37:
		moveLeft();
		break;
		case 38:
		moveTop();
		break;
		case 39:
		moveRight();
		break;
		case 40:
		moveBottom();
		break;
		default:
		break;
	}
})
// 键盘左键
function moveLeft(){
	isGameOver();
	if(!canMoveLeft()){
		return false;
	}

	for(var i=0;i<4;i++){
		for(var j=1;j<4;j++){
			if(data[i][j]!=0){
				for(var k=0;k<j;k++){
					if(data[i][k]==0&&noBlockH(i,k,j,data)){
						//move()
						util.moveAnimate(i,j,i,k);
						data[i][k]=data[i][j];
						data[i][j]=0;
						continue;
					}else if(data[i][k]==data[i][j]&&noBlockH(i,k,j,data)){
						//move()
						util.moveAnimate(i,j,i,k);
						//add
						data[i][k]+=data[i][j];
						data[i][j]=0;
						score+=data[i][k];//增加分数
						util.updateScore();//更新分数
						continue;
					}
				}
			}
		}
	}
	setTimeout(getNumber,100);
	setTimeout(showdata,100);
}
// 键盘上键
function moveTop(){
	isGameOver();
	if(!canMoveTop()){
		return false;
	}

	for(var i=1;i<4;i++){
		for(var j=0;j<4;j++){
			if(data[i][j]!=0){
				for(var k=0;k<i;k++){
					if(data[k][j]==0&&noBlockV(j,k,i,data)){
						//move()
						util.moveAnimate(i,j,k,j);
						data[k][j]=data[i][j];
						data[i][j]=0;
						continue;
					}else if(data[k][j]==data[i][j]&&noBlockV(j,k,i,data)){
						//move()
						util.moveAnimate(i,j,k,j);
						//add
						data[k][j]+=data[i][j];
						data[i][j]=0;
						score+=data[k][j];//增加分数
						util.updateScore();//更新分数
						continue;
					}
				}
			}
		}
	}
	setTimeout(getNumber,100);
	setTimeout(showdata,100);
}
// 键盘下键
function moveBottom(){
	isGameOver();
	if(!canMoveBottom()){
		return false;
	}
	for(var i=2;i>=0;i--){
		for(var j=0;j<4;j++){
			if(data[i][j]!=0){
				for(var k=3;k>i;k--){
					if(data[k][j]==0&&noBlockV(j,i,k,data)){
						//move()
						util.moveAnimate(i,j,k,j);
						data[k][j]=data[i][j];
						data[i][j]=0;
						continue;
					}else if(data[k][j]==data[i][j]&&noBlockV(j,i,k,data)){
						//move()
						util.moveAnimate(i,j,k,j);
						//add
						data[k][j]+=data[i][j];
						data[i][j]=0;
						score+=data[k][j];//增加分数
						util.updateScore();//更新分数
						continue;
					}
				}
			}
		}
	}
	setTimeout(getNumber,100);
	setTimeout(showdata,100);
}
// 键盘右键
function moveRight(){
	isGameOver();
	if(!canMoveRight()){
		return false;
	}

	for(var i=0;i<4;i++){
		for(var j=2;j>=0;j--){
			if(data[i][j]!=0){
				for(var k=3;k>j;k--){
					if(data[i][k]==0&&noBlockH(i,j,k,data)){
						//move()
						util.moveAnimate(i,j,i,k);
						data[i][k]=data[i][j];
						data[i][j]=0;
						continue;
					}else if(data[i][k]==data[i][j]&&noBlockH(i,j,k,data)){
						//move()
						util.moveAnimate(i,j,i,k);
						//add
						data[i][k]+=data[i][j];
						data[i][j]=0;
						score+=data[i][k];//增加分数
						util.updateScore();//更新分数
						continue;
					}
				}
			}
		}
	}
	setTimeout(getNumber,100);
	setTimeout(showdata,100);
}

function canMoveLeft(){
	for(var i=0;i<4;i++){
		for(var j=1;j<4;j++){
			if(data[i][j]!=0){
				if(data[i][j-1]==0||data[i][j-1]==data[i][j]){
					return true;
				}
			}
		}
	}
	return false;
}

function canMoveTop(){
	for(var i=1;i<4;i++){
		for(var j=0;j<4;j++){
			if(data[i][j]!=0){
				if(data[i-1][j]==0||data[i-1][j]==data[i][j]){
					return true;
				}
			}
		}
	}
	return false;
}

function canMoveRight(){
	for(var i=0;i<4;i++){
		for(var j=0;j<3;j++){
			if(data[i][j]!=0){
				if(data[i][j+1]==0||data[i][j+1]==data[i][j]){
					return true;
				}
			}
		}
	}
	return false;
}

function canMoveBottom(){
	for(var i=0;i<3;i++){
		for(var j=0;j<4;j++){
			if(data[i][j]!=0){
				if(data[i+1][j]==0||data[i+1][j]==data[i][j]){
					return true;
				}
			}
		}
	}
	return false;
}


function noBlockH(row,col1,col2,data){
	for(var i=col1+1;i<col2;i++){
		if(data[row][i]!=0){
			return false;
		}
	}
	return true;
}
function noBlockV(col,row1,row2,data){
	for(var i=row1+1;i<row2;i++){
		if(data[i][col]!=0){
			return false;
		}
	}
	return true;
}
// 游戏结束
function isGameOver(){
	if(!canMoveTop()&&!canMoveBottom()&&!canMoveLeft()&&!canMoveRight()){
		alert('GameOver');
		flag=false;
	}
}

🌟结语

喜欢的话大家一定要关注这篇专栏,后续也会不定期持续输出JS相关的趣味玩法。各位小伙伴让我们 let’s be prepared at all times!

✨原创不易,还希望各位大佬支持一下!
👍 点赞,你的认可是我创作的动力!
⭐️ 收藏,你的青睐是我努力的方向!
✏️ 评论,你的意见是我进步的财富!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/425937.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

300元左右的蓝牙耳机哪个好?300左右音质最好的蓝牙耳机

无线耳机是人们日常生活中必不可少的设备&#xff0c;无论是听音乐化石看电影都能获得身临其境的感觉&#xff0c;由于科技真在发展中&#xff0c;不断地的发生变化&#xff0c;百元价位就可以感受到不错的音色&#xff0c;下面小编整理了几款300左右音质表现不错的蓝牙耳机。 …

Linux 、Android将在汽车舞台上开战

导读在 CES 2017 上&#xff0c;AGL 宣布&#xff0c;Mercedes-Benz 的母公司 Daimler 正式加入。这是第十家汽车制造商加入 AGL&#xff0c;也是第一家德国公司加入 AGL。AGL&#xff08;Automotive Grade Linux&#xff09;&#xff0c;是 Linux 基金会的一个相互协作的开源组…

mallox勒索病毒数据恢复|金蝶、用友、管家婆、OA、速达、ERP等软件数据库恢复

目录 前言&#xff1a; 一、mallox勒索病毒及xollam勒索病毒的特点 二、mallox勒索病毒及xollam勒索病毒的影响 三、mallox勒索病毒及xollam勒索病毒数据恢复服务 四、mallox勒索病毒及xollam勒索病毒加密数据库恢复案例 五、以下是预防mallox勒索病毒及xollam勒索病毒安全…

解读CANDT测试项-采样点测试

原标题&#xff1a;解读CANDT测试项-采样点测试 一、为什么要进行采样点测试&#xff1f; 本文引用地址&#xff1a;http://www.eepw.com.cn/article/202004/411611.htm 为了保证有效的通信&#xff0c;对于一个只有两个节点的CAN网络&#xff0c;其两边距离不超过最大的传输…

day12 共享内存(内存映射的使用、注意事项、进程间通信、systemV共享内存)

内存映射的基本使用 概念&#xff1a; 功能共享内存可以通过mmap&#xff08;&#xff09;映射普通文件。 是一个磁盘文件与内存中的一个缓冲区相映射&#xff0c;进程可以像访问普通内存一样对文件进行访问&#xff0c;不必在调用read 、write。 mmap&#xff08;&#xf…

ChatGPT 与 MindShow 一分钟搞定一个PPT

前言 PPT制作是商务、教育和各种场合演讲的重要组成部分。然而&#xff0c;很多人会花费大量时间和精力在内容生成和视觉设计方面。为了解决这个问题&#xff0c;我们可以利用两个强大的工具——ChatGPT和MindShow&#xff0c;来提高制作PPT的效率。 一、ChatGPT 与 MindShow…

JUC-01 线程的创建和状态转换

本次我们主要讲三个问题 线程是什么&#xff1f;线程有哪些状态&#xff1f;各状态间的转换了解吗&#xff1f;创建线程的3种方法你都了解吗&#xff1f; 1. 线程是什么&#xff1f;&#xff08;了解即可&#xff09; 进程&#xff1a; 进程是一个具有一定独立功能的程序在一…

四次挥手刨根问底19问详解,全网最全

1.请描述一下TCP连接的四次挥手过程&#xff1f; 回答&#xff1a;TCP连接的四次挥手过程包括以下步骤&#xff1a; 步骤1&#xff1a;客户端向服务器端发送一个FIN报文段&#xff0c;请求关闭连接。 步骤2&#xff1a;服务器端收到FIN报文段后&#xff0c;向客户端发送一个…

python列表,元组和字典

1、python列表 1.1.列表的定义 list是一种有序的集合、基于 链表实现,name[ ] ,全局定义:list2list([ ])。 1.2下标索引 python不仅有负索引也有正索引。正索引从0开始,负索引从-1开始。这两个可以混用,但指向还是那个位置 a[0]a[-9]//length为10的数组a1.3列表的切片 列表可…

navicat如何使用orcale(详细步骤)

目录前言操作1.连接数据库2.建库问题总结前言 看过我昨天文章的兄弟姐妹都知道最近接手另一个国企项目&#xff0c;数据库用的是orcale。实话实说&#xff0c;也有快三年没用过orcale数据库了。 这期间问题不断&#xff0c;因为orcale日渐消沉&#xff0c;网上资料也是真真假…

UE4 回放系统升级到UE5之后的代码报错问题解决

关键词&#xff1a; UE4 回放系统 升级 UE5 报错 DemoNetDriver GetDemoCurrentTime GetDemoTotalTime 背景 照着网上教的UE4的回放系统&#xff0c;也叫重播系统&#xff0c;英文Replay。做完了&#xff0c;测试运行正常&#xff0c;可升级到UE5却报了一堆 WorldSetting 和 …

(20230417)最大数合并区间重新排列单词间的空格 按奇偶排序数组 II 数组形式的整数加法

最大数&#xff08;回顾等级&#xff1a;值得&#xff0c;已达最优解&#xff09; 来源&#xff1a;自己LeetCode刷题 usa long cmp(const void* e1, const void* e2) {int* p1(int*)e1;int* p2(int*)e2;long n110;long n210;while(*p1>n1){n1*10;}while(*p2>n2){n2*1…

利用AOP实现统一功能处理

目录 一、实现用户登录校验 实现自定义拦截器 将自定义的拦截器添加到框架的配置中&#xff0c;并且设置拦截的规则 二、实现统一异常处理 三、实现统一数据格式封装 一、实现用户登录校验 在之前的项目中&#xff0c;在需要验证用户登录的部分&#xff0c;每次都需要利…

RK3568平台开发系列讲解(环境篇)使用USB线缆升级固件

🚀返回专栏总目录 文章目录 一、进入升级模式1.1、硬件方式进入Loader模式1.2、软件方式进入Loader模式二、安装烧写工具2.1、Windows操作系统2.2、Linux操作系统沉淀、分享、成长,让自己和他人都能有所收获!😄 📢本篇将介绍了如何将主机上的固件,通过USB数据线烧录到…

Typora(Mckbook版)的使用方法

1、标题&#xff08;⌘ 数字&#xff09; 一级标题&#xff1a;&#xff08;⌘ 1&#xff09; 二级标题&#xff1a;&#xff08;⌘ 2&#xff09; 三级标题&#xff1a;&#xff08;⌘ 3&#xff09; 四级标题&#xff1a;&#xff08;⌘ 4&#xff09; ... 六级标…

0303github搜索案例-react应用

文章目录1 前言2 静态组件2.1 静态页面和样式2.2 静态组件3 axios请求github接口4 优化案例结语1 前言 学习了脚手架配置axios&#xff0c;我们通过访问github的接口来做个练习。实例效果如下所示&#xff1a; 搜索框输入github用户名关键字&#xff0c;点击搜索&#xff0c;列…

AD633JRZ-ASEMI代理ADI亚德诺AD633JRZ车规级芯片

编辑-Z AD633JRZ芯片参数&#xff1a; 型号&#xff1a;AD633JRZ 总误差&#xff1a;1% 标度电压错误&#xff1a;0.25% 电源干扰&#xff1a;0.01% 输出偏移电压&#xff1a;5mV 小信号带宽&#xff1a;1MHz 斜率&#xff1a;20V/s 沉降时间达到1%&#xff1a;2s 宽…

在 Rocky linux 8.7 使用 Kubespray v2.21.0 离线部署 kubernetes v1.24.0 集群

文章目录前言创建7台虚拟机要求配置代理下载介质介质初始化安装工具包配置互信编写 inventory.ini创建 offline.ymlt他、部署 offline repo部署 kubespray报错2报错3报错报错&#xff1a;container-engine/containerd : containerd &#xff5c; Create registry directories分…

5.Dockerfile

1.什么是Dockerfile Dockerfile其实就是一个文本文件&#xff0c;由一系列命令和参数构成&#xff0c;Docker可以读取Dockerfile文件并根据Dockerfile文件的描述来构建镜像。 1、对于开发人员&#xff1a;可以为开发团队提供一个完全一致的开发环境&#xff1b; 2、对于测试人…

Servlet API

目录 1.HttpServlet 1.doGet 2.doPost 2.HttpServletRequest 2.1方法 2.2打印请求信息 2.3获取GET请求的参数 2.4post请求body格式 1.x-www-form-urlencoded 2.json 3.HttpServletResponse 3.1方法 3.2设置状态码 3.3自动刷新 3.4构造重定向的响应 1.HttpServlet 方法…