ChatGPT编写的一款小游戏:数字融合2048 · 休闲版

玩法说明:
-
方向键控制移动
-
相同数字会合并
-
每步都会随机生成新数字
-
手机滑动支持(触屏滑动)
-
胜利提示(达到 2048)
html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
<title>数字融合2048 · 休闲版</title>
<style>
html,body{
margin:0;
height:100%;
overflow:hidden;
position:fixed;
width:100%;
touch-action:none;
overscroll-behavior:none;
background:url("https://amitofo.icu/lianchi.jpg") center/cover no-repeat fixed;
font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto;
color:white;
display:flex;
justify-content:center;
align-items:center;
}
.container{
text-align:center;
backdrop-filter:blur(8px);
background:rgba(0,0,0,0.35);
padding:20px;
border-radius:20px;
}
.board{
width:92vw;
max-width:420px;
aspect-ratio:1/1;
background:rgba(255,255,255,0.08);
border-radius:20px;
padding:12px;
display:grid;
grid-template-columns:repeat(4,1fr);
gap:12px;
}
.cell{
border-radius:14px;
display:flex;
justify-content:center;
align-items:center;
font-weight:bold;
font-size:clamp(18px,5vw,28px);
background:rgba(255,255,255,0.08);
transition:0.15s;
}
.overlay{
position:fixed;
inset:0;
background:rgba(0,0,0,0.75);
display:none;
justify-content:center;
align-items:center;
flex-direction:column;
font-size:24px;
}
.fall{
position:fixed;
top:-50px;
font-size:26px;
animation:fall 1.8s linear forwards;
}
@keyframes fall{
to{
transform:translateY(110vh) rotate(360deg);
opacity:0;
}
}
</style>
</head>
<body>
<audio id="bgm" src="https://amitofo.icu/beijing.ogg" loop></audio>
<audio id="fx" src="https://amitofo.icu/xiaochu.mp3"></audio>
<div class="container">
<h2>数字融合2048</h2>
<div> 游戏说明:方向键移动,相同数字合并</div>
分数: <span id="score">0</span>
<div class="board" id="board"></div>
<button onclick="restart()">重新开始</button>
</div>
<div class="overlay" id="overlay">
<div id="message"></div>
<button onclick="restart()">再来一局</button>
</div>
<script>
const size=4;
let board=[],score=0,lastMilestone=0;
let bgStarted=false;
function init(){
board=Array(size).fill().map(()=>Array(size).fill(0));
score=0;
lastMilestone=0;
addRandom(); addRandom();
render();
}
function restart(){
document.getElementById("overlay").style.display="none";
init();
}
function render(){
const b=document.getElementById("board");
b.innerHTML="";
board.flat().forEach(num=>{
const cell=document.createElement("div");
cell.className="cell";
if(num){
cell.textContent=num;
cell.style.background=`hsl(${Math.log2(num)*28},70%,55%)`;
}
b.appendChild(cell);
});
document.getElementById("score").textContent=score;
if(score>=lastMilestone+1000){
lastMilestone+=1000;
celebrate();
}
}
function celebrate(){
const fx=document.getElementById("fx");
fx.currentTime=0;
fx.play();
for(let i=0;i<15;i++){
let el=document.createElement("div");
el.className="fall";
el.textContent="🌸";
el.style.left=Math.random()*100+"vw";
document.body.appendChild(el);
setTimeout(()=>el.remove(),1800);
}
}
function addRandom(){
let empty=[];
for(let i=0;i<size;i++)
for(let j=0;j<size;j++)
if(!board[i][j]) empty.push({i,j});
if(!empty.length) return;
const {i,j}=empty[Math.floor(Math.random()*empty.length)];
board[i][j]=Math.random()<0.9?2:4;
}
function slide(row){
let arr=row.filter(n=>n);
for(let i=0;i<arr.length-1;i++){
if(arr[i]===arr[i+1]){
arr[i]*=2;
score+=arr[i];
arr[i+1]=0;
}
}
arr=arr.filter(n=>n);
while(arr.length<size) arr.push(0);
return arr;
}
function move(dir){
let old=JSON.stringify(board);
if(dir==="left")
for(let i=0;i<size;i++) board[i]=slide(board[i]);
if(dir==="right")
for(let i=0;i<size;i++) board[i]=slide(board[i].reverse()).reverse();
if(dir==="up"){
for(let c=0;c<size;c++){
let col=[];
for(let r=0;r<size;r++) col.push(board[r][c]);
col=slide(col);
for(let r=0;r<size;r++) board[r][c]=col[r];
}
}
if(dir==="down"){
for(let c=0;c<size;c++){
let col=[];
for(let r=0;r<size;r++) col.push(board[r][c]);
col=slide(col.reverse()).reverse();
for(let r=0;r<size;r++) board[r][c]=col[r];
}
}
if(JSON.stringify(board)!==old){
addRandom();
render();
if(checkLose()) gameOver();
}
}
function checkLose(){
for(let i=0;i<size;i++)
for(let j=0;j<size;j++){
if(!board[i][j]) return false;
if(j<3 && board[i][j]===board[i][j+1]) return false;
if(i<3 && board[i][j]===board[i+1][j]) return false;
}
return true;
}
function gameOver(){
const fx=document.getElementById("fx");
fx.currentTime=0;
fx.play();
document.getElementById("message").textContent="游戏结束";
document.getElementById("overlay").style.display="flex";
}
document.addEventListener("keydown",e=>{
if(e.key==="ArrowLeft")move("left");
if(e.key==="ArrowRight")move("right");
if(e.key==="ArrowUp")move("up");
if(e.key==="ArrowDown")move("down");
});
const boardEl=document.getElementById("board");
let startX,startY;
boardEl.addEventListener("touchstart",e=>{
e.preventDefault();
if(!bgStarted){
document.getElementById("bgm").play();
bgStarted=true;
}
startX=e.touches[0].clientX;
startY=e.touches[0].clientY;
},{passive:false});
boardEl.addEventListener("touchend",e=>{
e.preventDefault();
let dx=e.changedTouches[0].clientX-startX;
let dy=e.changedTouches[0].clientY-startY;
if(Math.abs(dx)>Math.abs(dy)){
if(dx>30)move("right");
else if(dx<-30)move("left");
}else{
if(dy>30)move("down");
else if(dy<-30)move("up");
}
},{passive:false});
init();
</script>
</body>
</html>