2025-9-23 10:59:45 [显示全部楼层]
5浏览
查看: 5|回复: 0

[M10项目] ESP32-C5——断网可玩的局域网2048游戏

[复制链接]
在某些特殊的场合之下,比如没有网络的大兴安岭,克拉玛利,比如不允许上网的某些研究所,比如在飞机上。那么我们如何连接热点,上网连线一款游戏解闷呢?前些天本人收到了dfrobot寄来的Firebbetle Esp32-C5试用板,心想刚好可以利用其自带的wifi以及http功能,将其作为微型服务器,利用Ap模式发出局域网热点信号,连接热点访问其中的小游戏。
ESP32-C5——断网可玩的局域网2048游戏图3
废话不说,先上效果
ESP32-C5——断网可玩的局域网2048游戏图1
目前只需要连接ESP32的wifi热点,以及输入密码12345678就可以啦。下面有四个方向箭,点击就可以实现对于2048小游戏的控制。得益于esp32c5的优越性能,目前游玩过程很流畅,也很顺利。如果有多人接入,只需要避免同时一次性大量访问就好。
视频演示
ESP32-C5——断网可玩的局域网2048游戏图2
当然由于是试用版的缘故,以及科学上网变得更加困难,折腾了一段时间,开发板具体的使用方法是,下载Arduino2.3.6,将ESP32-C5——断网可玩的局域网2048游戏图3
附件当中的json文件保存到下面的文件夹下,注意将原来的package_index.json删除,将这个json重命名为package_index.json。注意arduino当中文件-首选项-其余开发板链接当中的链接全部删除,然后再打开arduino,选择esp32 espress的下面的3.3.0-alpha-cn进行开发
ESP32-C5——断网可玩的局域网2048游戏图5
arduino源代码展示如下
  1. #include <WiFi.h>
  2. #include <WebServer.h>
  3. /* Put your SSID & Password */
  4. const char* ssid     = "ESP32";     // Enter SSID here
  5. const char* password = "12345678";  // Enter Password here
  6. /* Put IP Address details */
  7. IPAddress local_ip(192,168,1,1);
  8. IPAddress gateway(192,168,1,1);
  9. IPAddress subnet(255,255,255,0);
  10. WebServer server(80);
  11. void setup()
  12. {
  13.     Serial.begin(115200);
  14.     WiFi.softAP(ssid, password);
  15.     WiFi.softAPConfig(local_ip, gateway, subnet);
  16.     delay(100);
  17.     server.on("/", handle_on_connect);
  18.     server.onNotFound(handle_not_found);
  19.     server.begin();
  20.     Serial.println("HTTP server started");
  21. }
  22. void loop()
  23. {
  24.     server.handleClient();
  25. }
  26. void handle_on_connect()
  27. {
  28.     Serial.println("Client connected");
  29.     server.send(200, "text/html", send_2048_html());
  30. }
  31. void handle_not_found()
  32. {
  33.     server.send(404, "text/plain", "Not found");
  34. }
  35. String send_2048_html()
  36. {
  37.     String ptr = "<!DOCTYPE html>\n";
  38.     ptr += "<html lang='zh'>\n";
  39.     ptr += "<head>\n";
  40.     ptr += "  <meta charset='UTF-8'>\n";
  41.     ptr += "  <meta name='viewport' content='width=device-width, initial-scale=1.0, user-scalable=no'>\n";
  42.     ptr += "  <title>ESP32 2048游戏</title>\n";
  43.     ptr += "  <style>\n";
  44.     ptr += "    body {\n";
  45.     ptr += "      font-family: Arial, sans-serif;\n";
  46.     ptr += "      text-align: center;\n";
  47.     ptr += "      background-color: #faf8ef;\n";
  48.     ptr += "      margin: 0;\n";
  49.     ptr += "      padding: 20px;\n";
  50.     ptr += "    }\n";
  51.     ptr += "    h1 {\n";
  52.     ptr += "      color: #776e65;\n";
  53.     ptr += "      font-size: 28px;\n";
  54.     ptr += "      margin-bottom: 10px;\n";
  55.     ptr += "    }\n";
  56.     ptr += "    .game-container {\n";
  57.     ptr += "      display: flex;\n";
  58.     ptr += "      flex-direction: column;\n";
  59.     ptr += "      align-items: center;\n";
  60.     ptr += "      margin-top: 20px;\n";
  61.     ptr += "    }\n";
  62.     ptr += "    .game-header {\n";
  63.     ptr += "      display: flex;\n";
  64.     ptr += "      justify-content: space-between;\n";
  65.     ptr += "      width: 300px;\n";
  66.     ptr += "      margin-bottom: 20px;\n";
  67.     ptr += "    }\n";
  68.     ptr += "    .score-container {\n";
  69.     ptr += "      background: #bbada0;\n";
  70.     ptr += "      padding: 10px 15px;\n";
  71.     ptr += "      border-radius: 5px;\n";
  72.     ptr += "      color: white;\n";
  73.     ptr += "      font-weight: bold;\n";
  74.     ptr += "      text-align: center;\n";
  75.     ptr += "      min-width: 80px;\n";
  76.     ptr += "    }\n";
  77.     ptr += "    .score-title {\n";
  78.     ptr += "      font-size: 14px;\n";
  79.     ptr += "      color: #eee4da;\n";
  80.     ptr += "    }\n";
  81.     ptr += "    .score-value {\n";
  82.     ptr += "      font-size: 20px;\n";
  83.     ptr += "    }\n";
  84.     ptr += "    .grid-container {\n";
  85.     ptr += "      background-color: #bbada0;\n";
  86.     ptr += "      border-radius: 6px;\n";
  87.     ptr += "      width: 300px;\n";
  88.     ptr += "      height: 300px;\n";
  89.     ptr += "      padding: 10px;\n";
  90.     ptr += "      position: relative;\n";
  91.     ptr += "      box-sizing: border-box;\n";
  92.     ptr += "    }\n";
  93.     ptr += "    .grid-row {\n";
  94.     ptr += "      display: flex;\n";
  95.     ptr += "      margin-bottom: 10px;\n";
  96.     ptr += "      height: 65px;\n";
  97.     ptr += "    }\n";
  98.     ptr += "    .grid-row:last-child {\n";
  99.     ptr += "      margin-bottom: 0;\n";
  100.     ptr += "    }\n";
  101.     ptr += "    .grid-cell {\n";
  102.     ptr += "      width: 65px;\n";
  103.     ptr += "      height: 65px;\n";
  104.     ptr += "      margin-right: 10px;\n";
  105.     ptr += "      background-color: #cdc1b4;\n";
  106.     ptr += "      border-radius: 3px;\n";
  107.     ptr += "      display: flex;\n";
  108.     ptr += "      justify-content: center;\n";
  109.     ptr += "      align-items: center;\n";
  110.     ptr += "      font-size: 24px;\n";
  111.     ptr += "      font-weight: bold;\n";
  112.     ptr += "      color: #776e65;\n";
  113.     ptr += "    }\n";
  114.     ptr += "    .grid-cell:last-child {\n";
  115.     ptr += "      margin-right: 0;\n";
  116.     ptr += "    }\n";
  117.     ptr += "    .tile-2 { background-color: #eee4da; }\n";
  118.     ptr += "    .tile-4 { background-color: #ede0c8; }\n";
  119.     ptr += "    .tile-8 { background-color: #f2b179; color: #f9f6f2; }\n";
  120.     ptr += "    .tile-16 { background-color: #f59563; color: #f9f6f2; }\n";
  121.     ptr += "    .tile-32 { background-color: #f67c5f; color: #f9f6f2; }\n";
  122.     ptr += "    .tile-64 { background-color: #f65e3b; color: #f9f6f2; }\n";
  123.     ptr += "    .tile-128 { background-color: #edcf72; color: #f9f6f2; font-size: 20px; }\n";
  124.     ptr += "    .tile-256 { background-color: #edcc61; color: #f9f6f2; font-size: 20px; }\n";
  125.     ptr += "    .tile-512 { background-color: #edc850; color: #f9f6f2; font-size: 20px; }\n";
  126.     ptr += "    .tile-1024 { background-color: #edc53f; color: #f9f6f2; font-size: 16px; }\n";
  127.     ptr += "    .tile-2048 { background-color: #edc22e; color: #f9f6f2; font-size: 16px; }\n";
  128.     ptr += "    .controls {\n";
  129.     ptr += "      margin-top: 20px;\n";
  130.     ptr += "    }\n";
  131.     ptr += "    .btn {\n";
  132.     ptr += "      background-color: #8f7a66;\n";
  133.     ptr += "      color: white;\n";
  134.     ptr += "      border: none;\n";
  135.     ptr += "      border-radius: 5px;\n";
  136.     ptr += "      padding: 10px 20px;\n";
  137.     ptr += "      font-weight: bold;\n";
  138.     ptr += "      cursor: pointer;\n";
  139.     ptr += "      margin: 5px;\n";
  140.     ptr += "    }\n";
  141.     ptr += "    .btn:hover {\n";
  142.     ptr += "      background-color: #7c6957;\n";
  143.     ptr += "    }\n";
  144.     ptr += "    .game-message {\n";
  145.     ptr += "      display: none;\n";
  146.     ptr += "      position: absolute;\n";
  147.     ptr += "      top: 0;\n";
  148.     ptr += "      left: 0;\n";
  149.     ptr += "      right: 0;\n";
  150.     ptr += "      bottom: 0;\n";
  151.     ptr += "      background: rgba(238, 228, 218, 0.73);\n";
  152.     ptr += "      z-index: 100;\n";
  153.     ptr += "      flex-direction: column;\n";
  154.     ptr += "      align-items: center;\n";
  155.     ptr += "      justify-content: center;\n";
  156.     ptr += "      border-radius: 6px;\n";
  157.     ptr += "      color: #776e65;\n";
  158.     ptr += "      font-weight: bold;\n";
  159.     ptr += "      font-size: 30px;\n";
  160.     ptr += "    }\n";
  161.     ptr += "    .game-message.game-won {\n";
  162.     ptr += "      background: rgba(237, 194, 46, 0.5);\n";
  163.     ptr += "      color: #f9f6f2;\n";
  164.     ptr += "    }\n";
  165.     ptr += "    .game-message p {\n";
  166.     ptr += "      margin: 0;\n";
  167.     ptr += "      margin-bottom: 20px;\n";
  168.     ptr += "    }\n";
  169.     ptr += "    .swipe-controls {\n";
  170.     ptr += "      display: flex;\n";
  171.     ptr += "      flex-wrap: wrap;\n";
  172.     ptr += "      justify-content: center;\n";
  173.     ptr += "      margin-top: 20px;\n";
  174.     ptr += "    }\n";
  175.     ptr += "    .swipe-btn {\n";
  176.     ptr += "      width: 80px;\n";
  177.     ptr += "      height: 80px;\n";
  178.     ptr += "      margin: 5px;\n";
  179.     ptr += "      font-size: 30px;\n";
  180.     ptr += "      background-color: #bbada0;\n";
  181.     ptr += "      color: white;\n";
  182.     ptr += "      border: none;\n";
  183.     ptr += "      border-radius: 5px;\n";
  184.     ptr += "      display: flex;\n";
  185.     ptr += "      justify-content: center;\n";
  186.     ptr += "      align-items: center;\n";
  187.     ptr += "      cursor: pointer;\n";
  188.     ptr += "    }\n";
  189.     ptr += "    .swipe-btn:active {\n";
  190.     ptr += "      background-color: #8f7a66;\n";
  191.     ptr += "    }\n";
  192.     ptr += "    .footer {\n";
  193.     ptr += "      margin-top: 30px;\n";
  194.     ptr += "      font-size: 14px;\n";
  195.     ptr += "      color: #776e65;\n";
  196.     ptr += "    }\n";
  197.     ptr += "  </style>\n";
  198.     ptr += "</head>\n";
  199.     ptr += "<body>\n";
  200.     ptr += "  <h1>ESP32 2048游戏</h1>\n";
  201.     ptr += "  <div class='game-container'>\n";
  202.     ptr += "    <div class='game-header'>\n";
  203.     ptr += "      <div class='score-container'>\n";
  204.     ptr += "        <div class='score-title'>分数</div>\n";
  205.     ptr += "        <div id='score' class='score-value'>0</div>\n";
  206.     ptr += "      </div>\n";
  207.     ptr += "      <div class='score-container'>\n";
  208.     ptr += "        <div class='score-title'>最高分</div>\n";
  209.     ptr += "        <div id='best-score' class='score-value'>0</div>\n";
  210.     ptr += "      </div>\n";
  211.     ptr += "    </div>\n";
  212.     ptr += "    <div class='grid-container'>\n";
  213.     ptr += "      <div id='game-message' class='game-message'>\n";
  214.     ptr += "        <p></p>\n";
  215.     ptr += "        <button id='retry-btn' class='btn'>再试一次</button>\n";
  216.     ptr += "      </div>\n";
  217.     ptr += "      <div class='grid-row'>\n";
  218.     ptr += "        <div id='cell-0-0' class='grid-cell'></div>\n";
  219.     ptr += "        <div id='cell-0-1' class='grid-cell'></div>\n";
  220.     ptr += "        <div id='cell-0-2' class='grid-cell'></div>\n";
  221.     ptr += "        <div id='cell-0-3' class='grid-cell'></div>\n";
  222.     ptr += "      </div>\n";
  223.     ptr += "      <div class='grid-row'>\n";
  224.     ptr += "        <div id='cell-1-0' class='grid-cell'></div>\n";
  225.     ptr += "        <div id='cell-1-1' class='grid-cell'></div>\n";
  226.     ptr += "        <div id='cell-1-2' class='grid-cell'></div>\n";
  227.     ptr += "        <div id='cell-1-3' class='grid-cell'></div>\n";
  228.     ptr += "      </div>\n";
  229.     ptr += "      <div class='grid-row'>\n";
  230.     ptr += "        <div id='cell-2-0' class='grid-cell'></div>\n";
  231.     ptr += "        <div id='cell-2-1' class='grid-cell'></div>\n";
  232.     ptr += "        <div id='cell-2-2' class='grid-cell'></div>\n";
  233.     ptr += "        <div id='cell-2-3' class='grid-cell'></div>\n";
  234.     ptr += "      </div>\n";
  235.     ptr += "      <div class='grid-row'>\n";
  236.     ptr += "        <div id='cell-3-0' class='grid-cell'></div>\n";
  237.     ptr += "        <div id='cell-3-1' class='grid-cell'></div>\n";
  238.     ptr += "        <div id='cell-3-2' class='grid-cell'></div>\n";
  239.     ptr += "        <div id='cell-3-3' class='grid-cell'></div>\n";
  240.     ptr += "      </div>\n";
  241.     ptr += "    </div>\n";
  242.     ptr += "    <div class='controls'>\n";
  243.     ptr += "      <button id='new-game-btn' class='btn'>新游戏</button>\n";
  244.     ptr += "    </div>\n";
  245.     ptr += "    <div class='swipe-controls'>\n";
  246.     ptr += "      <div style='width: 90px; height: 90px;'></div>\n";
  247.     ptr += "      <button id='up-btn' class='swipe-btn'>↑</button>\n";
  248.     ptr += "      <div style='width: 90px; height: 90px;'></div>\n";
  249.     ptr += "      <button id='left-btn' class='swipe-btn'>←</button>\n";
  250.     ptr += "      <div style='width: 90px; height: 90px;'></div>\n";
  251.     ptr += "      <button id='right-btn' class='swipe-btn'>→</button>\n";
  252.     ptr += "      <div style='width: 90px; height: 90px;'></div>\n";
  253.     ptr += "      <button id='down-btn' class='swipe-btn'>↓</button>\n";
  254.     ptr += "      <div style='width: 90px; height: 90px;'></div>\n";
  255.     ptr += "    </div>\n";
  256.     ptr += "  </div>\n";
  257.     ptr += "  <div class='footer'>\n";
  258.     ptr += "    <p>ESP32网页2048游戏 - 基于ESP32 Web Server</p>\n";
  259.     ptr += "  </div>\n";
  260.    
  261.     // 添加JavaScript代码
  262.     ptr += "  <script>\n";
  263.     ptr += "    // 游戏状态变量\n";
  264.     ptr += "    let grid = [\n";
  265.     ptr += "      [0, 0, 0, 0],\n";
  266.     ptr += "      [0, 0, 0, 0],\n";
  267.     ptr += "      [0, 0, 0, 0],\n";
  268.     ptr += "      [0, 0, 0, 0]\n";
  269.     ptr += "    ];\n";
  270.     ptr += "    let score = 0;\n";
  271.     ptr += "    let bestScore = 0;\n";
  272.     ptr += "    let gameOver = false;\n";
  273.     ptr += "    let gameWon = false;\n";
  274.    
  275.     ptr += "    // DOM元素\n";
  276.     ptr += "    const scoreElement = document.getElementById('score');\n";
  277.     ptr += "    const bestScoreElement = document.getElementById('best-score');\n";
  278.     ptr += "    const gameMessageElement = document.getElementById('game-message');\n";
  279.     ptr += "    const newGameBtn = document.getElementById('new-game-btn');\n";
  280.     ptr += "    const retryBtn = document.getElementById('retry-btn');\n";
  281.     ptr += "    const upBtn = document.getElementById('up-btn');\n";
  282.     ptr += "    const leftBtn = document.getElementById('left-btn');\n";
  283.     ptr += "    const rightBtn = document.getElementById('right-btn');\n";
  284.     ptr += "    const downBtn = document.getElementById('down-btn');\n";
  285.    
  286.     ptr += "    // 初始化游戏\n";
  287.     ptr += "    function initGame() {\n";
  288.     ptr += "      grid = [\n";
  289.     ptr += "        [0, 0, 0, 0],\n";
  290.     ptr += "        [0, 0, 0, 0],\n";
  291.     ptr += "        [0, 0, 0, 0],\n";
  292.     ptr += "        [0, 0, 0, 0]\n";
  293.     ptr += "      ];\n";
  294.     ptr += "      score = 0;\n";
  295.     ptr += "      gameOver = false;\n";
  296.     ptr += "      gameWon = false;\n";
  297.     ptr += "      scoreElement.textContent = '0';\n";
  298.     ptr += "      gameMessageElement.style.display = 'none';\n";
  299.     ptr += "      \n";
  300.     ptr += "      // 添加两个初始方块\n";
  301.     ptr += "      addRandomTile();\n";
  302.     ptr += "      addRandomTile();\n";
  303.     ptr += "      \n";
  304.     ptr += "      updateGrid();\n";
  305.     ptr += "    }\n";
  306.    
  307.     ptr += "    // 更新网格显示\n";
  308.     ptr += "    function updateGrid() {\n";
  309.     ptr += "      for (let row = 0; row < 4; row++) {\n";
  310.     ptr += "        for (let col = 0; col < 4; col++) {\n";
  311.     ptr += "          const cell = document.getElementById(`cell-${row}-${col}`);\n";
  312.     ptr += "          const value = grid[row][col];\n";
  313.     ptr += "          \n";
  314.     ptr += "          // 清除所有类\n";
  315.     ptr += "          cell.className = 'grid-cell';\n";
  316.     ptr += "          cell.textContent = '';\n";
  317.     ptr += "          \n";
  318.     ptr += "          if (value !== 0) {\n";
  319.     ptr += "            cell.textContent = value;\n";
  320.     ptr += "            cell.classList.add(`tile-${value}`);\n";
  321.     ptr += "          }\n";
  322.     ptr += "        }\n";
  323.     ptr += "      }\n";
  324.     ptr += "    }\n";
  325.    
  326.     ptr += "    // 添加随机方块\n";
  327.     ptr += "    function addRandomTile() {\n";
  328.     ptr += "      const emptyCells = [];\n";
  329.     ptr += "      \n";
  330.     ptr += "      // 找出所有空单元格\n";
  331.     ptr += "      for (let row = 0; row < 4; row++) {\n";
  332.     ptr += "        for (let col = 0; col < 4; col++) {\n";
  333.     ptr += "          if (grid[row][col] === 0) {\n";
  334.     ptr += "            emptyCells.push({ row, col });\n";
  335.     ptr += "          }\n";
  336.     ptr += "        }\n";
  337.     ptr += "      }\n";
  338.     ptr += "      \n";
  339.     ptr += "      // 如果有空单元格,随机选择一个并添加2或4\n";
  340.     ptr += "      if (emptyCells.length > 0) {\n";
  341.     ptr += "        const randomCell = emptyCells[Math.floor(Math.random() * emptyCells.length)];\n";
  342.     ptr += "        grid[randomCell.row][randomCell.col] = Math.random() < 0.9 ? 2 : 4;\n";
  343.     ptr += "      }\n";
  344.     ptr += "    }\n";
  345.    
  346.     ptr += "    // 检查游戏是否结束\n";
  347.     ptr += "    function checkGameOver() {\n";
  348.     ptr += "      // 检查是否有空单元格\n";
  349.     ptr += "      for (let row = 0; row < 4; row++) {\n";
  350.     ptr += "        for (let col = 0; col < 4; col++) {\n";
  351.     ptr += "          if (grid[row][col] === 0) {\n";
  352.     ptr += "            return false;\n";
  353.     ptr += "          }\n";
  354.     ptr += "        }\n";
  355.     ptr += "      }\n";
  356.     ptr += "      \n";
  357.     ptr += "      // 检查是否有可合并的相邻单元格\n";
  358.     ptr += "      for (let row = 0; row < 4; row++) {\n";
  359.     ptr += "        for (let col = 0; col < 4; col++) {\n";
  360.     ptr += "          const value = grid[row][col];\n";
  361.     ptr += "          \n";
  362.     ptr += "          // 检查右侧\n";
  363.     ptr += "          if (col < 3 && grid[row][col + 1] === value) {\n";
  364.     ptr += "            return false;\n";
  365.     ptr += "          }\n";
  366.     ptr += "          \n";
  367.     ptr += "          // 检查下方\n";
  368.     ptr += "          if (row < 3 && grid[row + 1][col] === value) {\n";
  369.     ptr += "            return false;\n";
  370.     ptr += "          }\n";
  371.     ptr += "        }\n";
  372.     ptr += "      }\n";
  373.     ptr += "      \n";
  374.     ptr += "      return true;\n";
  375.     ptr += "    }\n";
  376.    
  377.     ptr += "    // 检查是否获胜(达到2048)\n";
  378.     ptr += "    function checkWin() {\n";
  379.     ptr += "      for (let row = 0; row < 4; row++) {\n";
  380.     ptr += "        for (let col = 0; col < 4; col++) {\n";
  381.     ptr += "          if (grid[row][col] === 2048) {\n";
  382.     ptr += "            return true;\n";
  383.     ptr += "          }\n";
  384.     ptr += "        }\n";
  385.     ptr += "      }\n";
  386.     ptr += "      return false;\n";
  387.     ptr += "    }\n";
  388.    
  389.     ptr += "    // 更新分数\n";
  390.     ptr += "    function updateScore(points) {\n";
  391.     ptr += "      score += points;\n";
  392.     ptr += "      scoreElement.textContent = score;\n";
  393.     ptr += "      \n";
  394.     ptr += "      if (score > bestScore) {\n";
  395.     ptr += "        bestScore = score;\n";
  396.     ptr += "        bestScoreElement.textContent = bestScore;\n";
  397.     ptr += "        localStorage.setItem('bestScore', bestScore);\n";
  398.     ptr += "      }\n";
  399.     ptr += "    }\n";
  400.    
  401.     ptr += "    // 显示游戏结束或胜利消息\n";
  402.     ptr += "    function showGameMessage(won) {\n";
  403.     ptr += "      gameMessageElement.style.display = 'flex';\n";
  404.     ptr += "      gameMessageElement.querySelector('p').textContent = won ? '你赢了!' : '游戏结束!';\n";
  405.     ptr += "      if (won) {\n";
  406.     ptr += "        gameMessageElement.classList.add('game-won');\n";
  407.     ptr += "      } else {\n";
  408.     ptr += "        gameMessageElement.classList.remove('game-won');\n";
  409.     ptr += "      }\n";
  410.     ptr += "    }\n";
  411.    
  412.     ptr += "    // 移动方向处理函数\n";
  413.     ptr += "    function move(direction) {\n";
  414.     ptr += "      if (gameOver || gameWon) return;\n";
  415.     ptr += "      \n";
  416.     ptr += "      let moved = false;\n";
  417.     ptr += "      \n";
  418.     ptr += "      // 创建网格副本用于比较\n";
  419.     ptr += "      const previousGrid = JSON.parse(JSON.stringify(grid));\n";
  420.     ptr += "      \n";
  421.     ptr += "      // 根据方向执行移动\n";
  422.     ptr += "      switch (direction) {\n";
  423.     ptr += "        case 'up':\n";
  424.     ptr += "          moved = moveUp();\n";
  425.     ptr += "          break;\n";
  426.     ptr += "        case 'right':\n";
  427.     ptr += "          moved = moveRight();\n";
  428.     ptr += "          break;\n";
  429.     ptr += "        case 'down':\n";
  430.     ptr += "          moved = moveDown();\n";
  431.     ptr += "          break;\n";
  432.     ptr += "        case 'left':\n";
  433.     ptr += "          moved = moveLeft();\n";
  434.     ptr += "          break;\n";
  435.     ptr += "      }\n";
  436.     ptr += "      \n";
  437.     ptr += "      // 如果有移动,添加新方块并更新网格\n";
  438.     ptr += "      if (moved) {\n";
  439.     ptr += "        addRandomTile();\n";
  440.     ptr += "        updateGrid();\n";
  441.     ptr += "        \n";
  442.     ptr += "        // 检查是否获胜\n";
  443.     ptr += "        if (checkWin()) {\n";
  444.     ptr += "          gameWon = true;\n";
  445.     ptr += "          showGameMessage(true);\n";
  446.     ptr += "        }\n";
  447.     ptr += "        // 检查是否游戏结束\n";
  448.     ptr += "        else if (checkGameOver()) {\n";
  449.     ptr += "          gameOver = true;\n";
  450.     ptr += "          showGameMessage(false);\n";
  451.     ptr += "        }\n";
  452.     ptr += "      }\n";
  453.     ptr += "    }\n";
  454.    
  455.     ptr += "    // 向上移动\n";
  456.     ptr += "    function moveUp() {\n";
  457.     ptr += "      let moved = false;\n";
  458.     ptr += "      \n";
  459.     ptr += "      for (let col = 0; col < 4; col++) {\n";
  460.     ptr += "        // 合并相同的数字\n";
  461.     ptr += "        for (let row = 0; row < 3; row++) {\n";
  462.     ptr += "          if (grid[row][col] !== 0) {\n";
  463.     ptr += "            for (let nextRow = row + 1; nextRow < 4; nextRow++) {\n";
  464.     ptr += "              if (grid[nextRow][col] !== 0) {\n";
  465.     ptr += "                if (grid[row][col] === grid[nextRow][col]) {\n";
  466.     ptr += "                  grid[row][col] *= 2;\n";
  467.     ptr += "                  grid[nextRow][col] = 0;\n";
  468.     ptr += "                  updateScore(grid[row][col]);\n";
  469.     ptr += "                  moved = true;\n";
  470.     ptr += "                }\n";
  471.     ptr += "                break;\n";
  472.     ptr += "              }\n";
  473.     ptr += "            }\n";
  474.     ptr += "          }\n";
  475.     ptr += "        }\n";
  476.     ptr += "        \n";
  477.     ptr += "        // 移动所有方块\n";
  478.     ptr += "        for (let row = 0; row < 3; row++) {\n";
  479.     ptr += "          if (grid[row][col] === 0) {\n";
  480.     ptr += "            for (let nextRow = row + 1; nextRow < 4; nextRow++) {\n";
  481.     ptr += "              if (grid[nextRow][col] !== 0) {\n";
  482.     ptr += "                grid[row][col] = grid[nextRow][col];\n";
  483.     ptr += "                grid[nextRow][col] = 0;\n";
  484.     ptr += "                moved = true;\n";
  485.     ptr += "                row--; // 重新检查当前行\n";
  486.     ptr += "                break;\n";
  487.     ptr += "              }\n";
  488.     ptr += "            }\n";
  489.     ptr += "          }\n";
  490.     ptr += "        }\n";
  491.     ptr += "      }\n";
  492.     ptr += "      \n";
  493.     ptr += "      return moved;\n";
  494.     ptr += "    }\n";
  495.    
  496.     ptr += "    // 向右移动\n";
  497.     ptr += "    function moveRight() {\n";
  498.     ptr += "      let moved = false;\n";
  499.     ptr += "      \n";
  500.     ptr += "      for (let row = 0; row < 4; row++) {\n";
  501.     ptr += "        // 合并相同的数字\n";
  502.     ptr += "        for (let col = 3; col > 0; col--) {\n";
  503.     ptr += "          if (grid[row][col] !== 0) {\n";
  504.     ptr += "            for (let prevCol = col - 1; prevCol >= 0; prevCol--) {\n";
  505.     ptr += "              if (grid[row][prevCol] !== 0) {\n";
  506.     ptr += "                if (grid[row][col] === grid[row][prevCol]) {\n";
  507.     ptr += "                  grid[row][col] *= 2;\n";
  508.     ptr += "                  grid[row][prevCol] = 0;\n";
  509.     ptr += "                  updateScore(grid[row][col]);\n";
  510.     ptr += "                  moved = true;\n";
  511.     ptr += "                }\n";
  512.     ptr += "                break;\n";
  513.     ptr += "              }\n";
  514.     ptr += "            }\n";
  515.     ptr += "          }\n";
  516.     ptr += "        }\n";
  517.     ptr += "        \n";
  518.     ptr += "        // 移动所有方块\n";
  519.     ptr += "        for (let col = 3; col > 0; col--) {\n";
  520.     ptr += "          if (grid[row][col] === 0) {\n";
  521.     ptr += "            for (let prevCol = col - 1; prevCol >= 0; prevCol--) {\n";
  522.     ptr += "              if (grid[row][prevCol] !== 0) {\n";
  523.     ptr += "                grid[row][col] = grid[row][prevCol];\n";
  524.     ptr += "                grid[row][prevCol] = 0;\n";
  525.     ptr += "                moved = true;\n";
  526.     ptr += "                col++; // 重新检查当前列\n";
  527.     ptr += "                break;\n";
  528.     ptr += "              }\n";
  529.     ptr += "            }\n";
  530.     ptr += "          }\n";
  531.     ptr += "        }\n";
  532.     ptr += "      }\n";
  533.     ptr += "      \n";
  534.     ptr += "      return moved;\n";
  535.     ptr += "    }\n";
  536.    
  537.     ptr += "    // 向下移动\n";
  538.     ptr += "    function moveDown() {\n";
  539.     ptr += "      let moved = false;\n";
  540.     ptr += "      \n";
  541.     ptr += "      for (let col = 0; col < 4; col++) {\n";
  542.     ptr += "        // 合并相同的数字\n";
  543.     ptr += "        for (let row = 3; row > 0; row--) {\n";
  544.     ptr += "          if (grid[row][col] !== 0) {\n";
  545.     ptr += "            for (let prevRow = row - 1; prevRow >= 0; prevRow--) {\n";
  546.     ptr += "              if (grid[prevRow][col] !== 0) {\n";
  547.     ptr += "                if (grid[row][col] === grid[prevRow][col]) {\n";
  548.     ptr += "                  grid[row][col] *= 2;\n";
  549.     ptr += "                  grid[prevRow][col] = 0;\n";
  550.     ptr += "                  updateScore(grid[row][col]);\n";
  551.     ptr += "                  moved = true;\n";
  552.     ptr += "                }\n";
  553.     ptr += "                break;\n";
  554.     ptr += "              }\n";
  555.     ptr += "            }\n";
  556.     ptr += "          }\n";
  557.     ptr += "        }\n";
  558.     ptr += "        \n";
  559.     ptr += "        // 移动所有方块\n";
  560.     ptr += "        for (let row = 3; row > 0; row--) {\n";
  561.     ptr += "          if (grid[row][col] === 0) {\n";
  562.     ptr += "            for (let prevRow = row - 1; prevRow >= 0; prevRow--) {\n";
  563.     ptr += "              if (grid[prevRow][col] !== 0) {\n";
  564.     ptr += "                grid[row][col] = grid[prevRow][col];\n";
  565.     ptr += "                grid[prevRow][col] = 0;\n";
  566.     ptr += "                moved = true;\n";
  567.     ptr += "                row++; // 重新检查当前行\n";
  568.     ptr += "                break;\n";
  569.     ptr += "              }\n";
  570.     ptr += "            }\n";
  571.     ptr += "          }\n";
  572.     ptr += "        }\n";
  573.     ptr += "      }\n";
  574.     ptr += "      \n";
  575.     ptr += "      return moved;\n";
  576.     ptr += "    }\n";
  577.    
  578.     ptr += "    // 向左移动\n";
  579.     ptr += "    function moveLeft() {\n";
  580.     ptr += "      let moved = false;\n";
  581.     ptr += "      \n";
  582.     ptr += "      for (let row = 0; row < 4; row++) {\n";
  583.     ptr += "        // 合并相同的数字\n";
  584.     ptr += "        for (let col = 0; col < 3; col++) {\n";
  585.     ptr += "          if (grid[row][col] !== 0) {\n";
  586.     ptr += "            for (let nextCol = col + 1; nextCol < 4; nextCol++) {\n";
  587.     ptr += "              if (grid[row][nextCol] !== 0) {\n";
  588.     ptr += "                if (grid[row][col] === grid[row][nextCol]) {\n";
  589.     ptr += "                  grid[row][col] *= 2;\n";
  590.     ptr += "                  grid[row][nextCol] = 0;\n";
  591.     ptr += "                  updateScore(grid[row][col]);\n";
  592.     ptr += "                  moved = true;\n";
  593.     ptr += "                }\n";
  594.     ptr += "                break;\n";
  595.     ptr += "              }\n";
  596.     ptr += "            }\n";
  597.     ptr += "          }\n";
  598.     ptr += "        }\n";
  599.     ptr += "        \n";
  600.     ptr += "        // 移动所有方块\n";
  601.     ptr += "        for (let col = 0; col < 3; col++) {\n";
  602.     ptr += "          if (grid[row][col] === 0) {\n";
  603.     ptr += "            for (let nextCol = col + 1; nextCol < 4; nextCol++) {\n";
  604.     ptr += "              if (grid[row][nextCol] !== 0) {\n";
  605.     ptr += "                grid[row][col] = grid[row][nextCol];\n";
  606.     ptr += "                grid[row][nextCol] = 0;\n";
  607.     ptr += "                moved = true;\n";
  608.     ptr += "                col--; // 重新检查当前列\n";
  609.     ptr += "                break;\n";
  610.     ptr += "              }\n";
  611.     ptr += "            }\n";
  612.     ptr += "          }\n";
  613.     ptr += "        }\n";
  614.     ptr += "      }\n";
  615.     ptr += "      \n";
  616.     ptr += "      return moved;\n";
  617.     ptr += "    }\n";
  618.    
  619.     // 修复事件***和初始化代码
  620.     ptr += "    // 加载最高分\n";
  621.     ptr += "    function loadBestScore() {\n";
  622.     ptr += "      const savedBestScore = localStorage.getItem('bestScore');\n";
  623.     ptr += "      if (savedBestScore) {\n";
  624.     ptr += "        bestScore = parseInt(savedBestScore);\n";
  625.     ptr += "        bestScoreElement.textContent = bestScore;\n";
  626.     ptr += "      }\n";
  627.     ptr += "    }\n";
  628.    
  629.     ptr += "    // 事件***\n";
  630.     ptr += "    newGameBtn.addEventListener('click', initGame);\n";
  631.     ptr += "    retryBtn.addEventListener('click', initGame);\n";
  632.     ptr += "    upBtn.addEventListener('click', () => move('up'));\n";
  633.     ptr += "    rightBtn.addEventListener('click', () => move('right'));\n";
  634.     ptr += "    downBtn.addEventListener('click', () => move('down'));\n";
  635.     ptr += "    leftBtn.addEventListener('click', () => move('left'));\n";
  636.    
  637.     ptr += "    // 键盘控制\n";
  638.     ptr += "    document.addEventListener('keydown', (e) => {\n";
  639.     ptr += "      if (gameOver || gameWon) return;\n";
  640.     ptr += "      \n";
  641.     ptr += "      switch (e.key) {\n";
  642.     ptr += "        case 'ArrowUp':\n";
  643.     ptr += "          move('up');\n";
  644.     ptr += "          break;\n";
  645.     ptr += "        case 'ArrowRight':\n";
  646.     ptr += "          move('right');\n";
  647.     ptr += "          break;\n";
  648.     ptr += "        case 'ArrowDown':\n";
  649.     ptr += "          move('down');\n";
  650.     ptr += "          break;\n";
  651.     ptr += "        case 'ArrowLeft':\n";
  652.     ptr += "          move('left');\n";
  653.     ptr += "          break;\n";
  654.     ptr += "      }\n";
  655.     ptr += "    });\n";
  656.    
  657.     ptr += "    // 触摸控制\n";
  658.     ptr += "    let touchStartX = 0;\n";
  659.     ptr += "    let touchStartY = 0;\n";
  660.     ptr += "    let touchEndX = 0;\n";
  661.     ptr += "    let touchEndY = 0;\n";
  662.    
  663.     ptr += "    document.addEventListener('touchstart', (e) => {\n";
  664.     ptr += "      touchStartX = e.touches[0].clientX;\n";
  665.     ptr += "      touchStartY = e.touches[0].clientY;\n";
  666.     ptr += "    }, false);\n";
  667.    
  668.     ptr += "    document.addEventListener('touchend', (e) => {\n";
  669.     ptr += "      if (gameOver || gameWon) return;\n";
  670.     ptr += "      \n";
  671.     ptr += "      touchEndX = e.changedTouches[0].clientX;\n";
  672.     ptr += "      touchEndY = e.changedTouches[0].clientY;\n";
  673.     ptr += "      \n";
  674.     ptr += "      const deltaX = touchEndX - touchStartX;\n";
  675.     ptr += "      const deltaY = touchEndY - touchStartY;\n";
  676.     ptr += "      \n";
  677.     ptr += "      // 确定滑动方向\n";
  678.     ptr += "      if (Math.abs(deltaX) > Math.abs(deltaY)) {\n";
  679.     ptr += "        // 水平滑动\n";
  680.     ptr += "        if (deltaX > 20) {\n";
  681.     ptr += "          move('right');\n";
  682.     ptr += "        } else if (deltaX < -20) {\n";
  683.     ptr += "          move('left');\n";
  684.     ptr += "        }\n";
  685.     ptr += "      } else {\n";
  686.     ptr += "        // 垂直滑动\n";
  687.     ptr += "        if (deltaY > 20) {\n";
  688.     ptr += "          move('down');\n";
  689.     ptr += "        } else if (deltaY < -20) {\n";
  690.     ptr += "          move('up');\n";
  691.     ptr += "        }\n";
  692.     ptr += "      }\n";
  693.     ptr += "    }, false);\n";
  694.    
  695.     ptr += "    // 阻止页面滚动\n";
  696.     ptr += "    document.addEventListener('touchmove', (e) => {\n";
  697.     ptr += "      if (e.target.closest('.grid-container')) {\n";
  698.     ptr += "        e.preventDefault();\n";
  699.     ptr += "      }\n";
  700.     ptr += "    }, { passive: false });\n";
  701.    
  702.     ptr += "    // 初始化\n";
  703.     ptr += "    loadBestScore();\n";
  704.     ptr += "    initGame();\n";
  705.     ptr += "  </script>\n";
  706.     ptr += "</body>\n";
  707.     ptr += "</html>\n";
  708.    
  709.     return ptr;
  710. }
复制代码

TueSeptember-202509233258..png
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

为本项目制作心愿单
购买心愿单
心愿单 编辑
[[wsData.name]]

硬件清单

  • [[d.name]]
btnicon
我也要做!
点击进入购买页面
上海智位机器人股份有限公司 沪ICP备09038501号-4 备案 沪公网安备31011502402448

© 2013-2025 Comsenz Inc. Powered by Discuz! X3.4 Licensed

mail