原生 JS 實現掃雷 (分析+代碼實現)

来源:https://www.cnblogs.com/kilomChou/archive/2019/04/05/10652405.html
-Advertisement-
Play Games

原生 JavaScript 實現掃雷 完整思路分析,代碼實現。 ...


閱讀這篇文章需要掌握的基礎知識:Html5、CSS、JavaScript

線上Demo:查看

掃雷規則

在寫掃雷之前,我們先瞭解下它的游戲規則

● 掃雷是一個矩陣,地雷隨機分佈在方格上。

● 方格上的數字代表著這個方格所在的九宮格內有多少個地雷。

● 方格上的旗幟為玩家所作標記。

● 踩到地雷,游戲失敗。

● 打開所有非雷方格,游戲勝利。

 

功能實現思路分析

矩陣的生成

  • 矩陣的生成有多種方式可以實現,我們這裡使用<table>+<span>標簽。
  • 通過 js 給定行數與列數在<table>的 innerHtml 寫入<span>標簽來動態生成矩陣。

方格的打開與標記

  • 通過 onmousedown 事件,傳入點擊的方格的坐標及event,判斷event為左鍵還是右鍵。
  • 左鍵打開方格,右鍵標記方格。

地雷的隨機分佈

  • 由於第一次打開的方格不能為地雷所以我們把生成地雷的函數放在第一次點擊方格時。
  • 我們通過迴圈用 Math.random() 函數來隨機生成地雷的二維坐標。
  • 判斷坐標是否不為第一次點擊方格的坐標以及沒有雷存在。
  • 是則將方格設置為地雷,當前地雷數+1,並且將九宮格內的方格的計雷數+1。
  • 否則跳過進入下個迴圈,直到地雷的數量達到設定的最大雷數,結束迴圈。

踩到地雷游戲結束

  • 打開方格為地雷時,提示游戲結束。
  • 通過遍歷矩陣來打開所有地雷

連鎖打開方格

  • 當打開的方格為計雷數為0的方格,自動打開九宮格內的非雷方格。
  • 如果打開的非雷方格九宮格內仍有非雷方格,繼續打開九宮格內的非雷方格,直到沒有為止。

游戲勝利條件

  • 當所有非雷方格被打開即為游戲勝利。
  • 在每次打開方格函數中都遍歷一遍矩陣,當找到有未打開的非雷方格時則結束遍歷。
  • 當遍歷完未找到未打開的非雷方格則提示游戲勝利。

剩餘地雷數與計時器

  • 地雷的總數減去玩家標記的方格數即為剩餘地雷數
  • 計時器可以用setInterval()函數實現

 

代碼實現

生成矩陣

我們先在<body>里寫一個<table>標簽,設定個 id='grid'

<table id='grid'></table>

然後在<script>里 定義兩個變數 row--行數 col--列數

通過兩個for迴圈把 (方格)<span> 寫入到 (矩陣)<table> 里,通過<td><tr>標簽控制行列。

var row = 10; //行數
var col = 10; //列數

//生成矩陣html  <tr>--行標簽 <td>--列標簽
let gridHtml = '';
for (let i = 0; i < row; i++) {
  gridHtml += '<tr>'
  for (let j = 0; j < col; j++) {
    gridHtml += '<td><span class="blocks"></span></td>';
  }
  gridHtml += '<tr>'
}
//寫入html
document.getElementById('grid').innerHTML = gridHtml;

 寫一下矩陣和方格的CSS樣式。

#grid {
    margin: auto;  /* 讓矩陣居中顯示於頁面 */
}

.blocks {
    width: 30px;
    height: 30px;
    line-height: 30px;
    display: block;   /* 讓span以block方式顯示 */
    text-align: center;
    border: solid 1px #000;
    user-select: none;  /* 設置不可拖拽選中 */
    cursor: pointer;  /* 設置滑鼠停留樣式 */
}

.blocks:hover {
    background: #0af;  /* 滑鼠停留時背景顏色變化 */
}

至此打開頁面,矩陣就初步顯示出來了。

把矩陣的方格放入二維數組中

我們先定義一個全局變數grid。

把剛纔寫的生成矩陣的代碼寫成一個函數 function init_grid()

document.getElementsByClassName('blocks') 返回的是一個一維數組,我們把它通過兩個for迴圈轉化為二維數組。

給每個方格定義一個屬性 count 計雷數 ---  blocks[i].count = 0;

然後把返回值賦值給grid ---  grid = init_grid();

var row = 10; //行數
var col = 10; //列數
var grid = init_grid();

//初始化矩陣 (row-行數 col-列數)
function init_grid() {

    //生成矩陣html <tr>--行標簽 <td>--列標簽
    let gridHtml = '';
    for (let i = 0; i < row; i++) {
        gridHtml += '<tr>'
        for (let j = 0; j < col; j++) {
            gridHtml +=
                '<td><span class="blocks"></span></td>';
        }
        gridHtml += '<tr>'
    }
    //寫入html
    document.getElementById('grid').innerHTML = gridHtml;

    //返回矩陣二維數組
    let blocks = document.getElementsByClassName('blocks');
    let grid = new Array();
    for (let i = 0; i < blocks.length; i++) {
        if (i % col === 0) {
            grid.push(new Array());
        }
        //初始化計雷數
        blocks[i].count = 0;
        grid[parseInt(i / col)].push(blocks[i]);
    }
    return grid;
}

寫完了這段我們先寫一段代碼測試下grid有沒有賦值成功,遍歷grid把方格的值改為對應的坐標。

for (let i = 0; i < row; i++) {
    for (let j = 0; j < col; j++) {
        grid[i][j].innerHTML = i + ',' + j;
    }
}

可以看到 grid 已經賦值成功!沒成功的回去檢查下代碼。(Tip:測試完記得把測試代碼刪除)

方格的點擊事件

定義一個函數 function block_click( _i, _j, e) 的大致框架

e為傳入的滑鼠事件,e.button ( 0為左鍵,2為右鍵 )。

isOpen屬性為自定義屬性,用來判斷方格是否打開。

//方格點擊事件 _i:坐標i _j:坐標j e:滑鼠事件
function block_click(_i, _j, e) {

    //跳過已打開的方格
    if (grid[_i][_j].isOpen) {
        return;
    }

    //滑鼠左鍵打開方格
    if (e.button === 0) {

    }
    //滑鼠右鍵標記方格
    else if (e.button === 2) {

    }
}

然後修改下之前寫在 init_grid 函數里的<span>的屬性,綁定 onmousedown 事件,傳入 i,j 坐標,和滑鼠事件 event

gridHtml += '<td><span class="blocks" onmousedown="block_click(' + i + ',' + j + ',event)"></span></td>';

修改下body的屬性 加入防拖拽生成新頁面和屏蔽右鍵菜單。

<!-- ondragstart:防拖拽生成新頁面 oncontextmenu:屏蔽右鍵菜單-->
<body ondragstart='return false' oncontextmenu='self.event.returnValue=false'>

我們在滑鼠左鍵事件裡面寫下測試代碼,當左鍵方格時顯示它的坐標。

//滑鼠左鍵打開方格
if (e.button === 0) {
    grid[_i][_j].innerHTML = _i + ',' + _j;
}

 效果如下,沒成功的回去檢查下代碼。(Tip:測試完記得把測試代碼刪除)

方格的標記

在滑鼠右鍵事件寫標記代碼,這裡用 ▲ 來作為標記。

右擊一次添加標記,再次右擊刪除標記。

//滑鼠右鍵標記方格
else if (e.button === 2) {

    let block = grid[_i][_j];
    if (block.innerHTML !== '▲') {
        block.innerHTML = '▲';
    } else {
        block.innerHTML = '';
    }
}

效果如下:

隨機生成地雷

由於第一次打開的方格不能為地雷所以我們把生成地雷的函數放在第一次點擊方格時。

先定義全局變數 maxCount --- 最大地雷數  isFirstOpen --- 是否第一次打開方格。

var row = 10; //行數
var col = 10; //列數
var grid = init_grid();
var maxCount = 10; //最大地雷數量
var isFirstOpen = true; //第一次打開方格

在滑鼠左鍵事件裡面寫第一次打開方格生成地雷的代碼的大致框架。

//滑鼠左鍵打開方格
if (e.button === 0) {

    //第一次打開
    if (isFirstOpen) {

        isFirstOpen = false;
        let count = 0; //當前地雷數

        //生成地雷
        while (count < maxCount) {
            //........
        }
    }
}

完善生成地雷代碼:

生成隨機坐標 ri,rj,判斷該坐標不等於第一次點擊方格的坐標以及該坐標表方格不為地雷。

條件成立,將坐標對應方格的 isMine 設置為true,當前地雷數+1,並使九宮格內非雷方格的計雷數 count +1

自定義屬性isMine代表方格為地雷。

自定義屬性count為計雷數。

當地雷數大於最大地雷數,結束迴圈。

//生成地雷
while (count < maxCount) {

    //生成隨機坐標
    let ri = Math.floor(Math.random() * row);
    let rj = Math.floor(Math.random() * col);

    //坐標不等於第一次點擊方格的坐標 && 非雷方格
    if (!(ri === _i && rj === _j) && !grid[ri][rj].isMine) {
        grid[ri][rj].isMine = true; //自定義屬性isMine代表方格為地雷
        count++; //當前地雷數+1

        //更新九宮格內非雷方格的計雷數
        for (let i = ri - 1; i < ri + 2; i++) {
            for (let j = rj - 1; j < rj + 2; j++) {
                //判斷坐標防越界
                if (i > -1 && j > -1 && i < row && j < col) {
                    //計雷數+1
                    grid[i][j].count++;
                }
            }
        }
    }
}

寫個測試代碼在生成地雷後顯示所有方格的狀態。(Tip:測試完記得把測試代碼刪除)

for (let i = 0; i < row; i++) {
    for (let j = 0; j < col; j++) {
        //判斷方格是否為雷
        if (grid[i][j].isMine) {
            //顯示為雷
            grid[i][j].innerHTML = '雷';
        } else {
            //否則顯示計雷數
            grid[i][j].innerHTML = grid[i][j].count;
        }
    }
}

效果如下:可以看到已經隨機生成了雷,計雷數也正確顯示了。

方格的打開事件

在生成地雷的代碼下,加入方格打開代碼函數 block_open(_i,_j) 的大致框架。

定義 function op(block) 函數設定打開方格的狀態與樣式。

判定打開的方格的類型

block.isMine 為打開地雷方格 --> 游戲結束

block.count === 0 為打開計雷數為0的方格 --> 連鎖打開非雷方格

else 為打開計雷數大於0的方格 --> 顯示方格計雷數

//滑鼠左鍵打開方格
if (e.button === 0) {

    //第一次打開
    if (isFirstOpen) {
        //.......
    }

    //執行打開方格函數
    block_open(_i, _j);

    //打開方格函數
    function block_open(_i, _j) {

        let block = grid[_i][_j];
        op(block);

        //設定打開方格的狀態與樣式
        function op(block) {
            block.isOpen = true; //isOpen為自定義屬性,設置為true代表已打開
            block.style.background = '#ccc'; //將背景設置為灰色
            block.style.cursor = 'default'; //將滑鼠停留樣式設置為預設
        }

        if (block.isMine) {
            //踩雷
        } else if (block.count === 0) {
            //打開計雷數為0的方格
        } else {
            //打開計雷數不為0的方格
        }
    }
}

打開非雷方格顯示計雷數

 我們先把最簡單的顯示方格計雷數搞定。

else {
    //打開計雷數不為0的方格
    block.innerHTML = block.count;  //顯示計雷數
}

效果如下:

踩雷游戲結束

接下來寫踩雷代碼,當打開的方格為雷時,將其顯示為'雷',並打開所有的地雷,提示游戲結束。

if (block.isMine) {
    //踩雷
    block.innerHTML = '雷'; //顯示為 '雷'
    //遍歷矩陣打開所有的地雷方格
    for (let i = 0; i < row; i++) {
        for (let j = 0; j < col; j++) {
            //找到地雷
            block = grid[i][j];
            if (!block.isOpen && block.isMine) {
                op(block); //設置打開狀態和樣式
                block.innerHTML = '雷'; //顯示為 '雷'
            }
        }
    }
    //提示游戲結束
    alert("游戲結束");
}

效果如下:

連鎖打開方格

打開的方格為計雷數為0的方格,自動打開九宮格內的非雷方格,迴圈遞歸到沒有為止。

計雷數為0就沒必要讓innerHtml顯示0了,保持空白就行。

else if (block.count === 0) {
    //打開計雷數為0的方格
    //遍歷九宮格內的方格
    for (let i = _i - 1; i < _i + 2; i++) {
        for (let j = _j - 1; j < _j + 2; j++) {
            //判斷是否越界&&跳過已打開的方格&&非雷
            if (i > -1 && j > -1 && i < row && j < col && !grid[i][j].isOpen && !grid[i][j].ismine) {
                //遞歸打開方格函數
                block_open(i, j);
            }
        }
    }
}

效果如下:

游戲勝利條件

掃雷大體框架已經出來了,我們現在做勝利條件的判定。

在方格點擊函數最後寫判斷代碼。

//方塊點擊事件 _i:坐標i _j:坐標j e:滑鼠事件
function block_click(_i, _j, e) {

    //跳過已打開的方塊
    if (grid[_i][_j].isOpen) {
        //...
    }
    //滑鼠左鍵打開方塊
    if (e.button === 0) {
        //...
    }
    //滑鼠右鍵標記方塊
    else if (e.button === 2) {
        //...
    }

    //遍歷矩陣
    let isWin = true;
    for (let i = 0; i < row; i++) {
        for (let j = 0; j < col; j++) {
       let block = grid[i][j];
//判斷游戲勝利條件(所有的非雷方格已打開) if (!block.isMine && !block.isOpen) { //如果有未打開的非雷方塊 條件不成立 isWin = false; } } } if (isWin) { alert("游戲勝利"); } }

效果如下:(還專門玩了一遍^ ^)

游戲部分到這裡就完成了!

剩餘地雷數與計時器

最後,我們做一下剩餘地雷數和計時器的顯示。

我們寫個 <div> 在 <table> 的上面,放兩個 <span> 來做顯示框,<label> 用來給 js 計數。

<div id='bar'>
    <span class='bar'>剩餘雷數:<label id='count'>0</label></span>
    <span class='bar'>計時:<label id='time'>0</label>s</span>
</div>

<table id='grid'></table>

再寫下CSS樣式:

#bar {
    text-align: center;
    margin-bottom: 20px;
}

.bar {
    height: 25px;
    width: 150px;
    line-height: 25px;
    display: inline-block;
    border: solid 1px #000;
    margin-left: 20px;
    margin-right: 20px;
}

效果如下:

在 js 中定義兩個全局變數拿到 <lable> count 和 time

然後讓地雷數量等於最大地雷數,設置個100ms定時器,每次+0.1s,保留一位小數。

var count = document.getElementById('count'); //剩餘地雷數
count.innerHTML = maxCount; //初始化剩餘雷數

var time = document.getElementById('time'); //計時器
var timer = setInterval(function () {
  let seconds = (parseFloat(time.innerHTML) + 0.1).toFixed(1); //保留一位小數
  time.innerHTML = seconds;
}, 100) //定時器 100ms執行一次

我們修改下方格點擊事件中遍歷矩陣的代碼,更新剩餘地雷數,勝利時結束計時。

//遍歷矩陣
let isWin = true;
count.innerHTML = maxCount; //重置剩餘地雷數
for (let i = 0; i < row; i++) {
    for (let j = 0; j < col; j++) {
        let block = grid[i][j];

        //找到標記
        if (block.innerHTML === '▲') {
            count.innerHTML = parseInt(count.innerHTML) - 1; //剩餘地雷數-1
        }

        //判斷游戲勝利條件(所有的非雷方格已打開)
        if (!block.isMine && !block.isOpen) {
            //如果有未打開的非雷方塊 條件不成立
            isWin = false;
        }
    }
}
if (isWin) {
    clearInterval(timer); //游戲勝利結束計時,清除定時器
    alert("游戲勝利");
}

再修改踩雷的代碼,結束計時。

if (block.isMine) {
    //踩雷
    block.innerHTML = '雷'; //顯示為 '雷'
    //遍歷矩陣打開所有的地雷方格
    for (let i = 0; i < row; i++) {
        for (let j = 0; j < col; j++) {
            //找到地雷
            block = grid[i][j];
            if (!block.isOpen && block.isMine) {
                op(block); //設置打開狀態和樣式
                block.innerHTML = '雷'; //顯示為 '雷'
            }
        }
    }
    clearInterval(timer); //游戲結束停止計時,清除定時器
    //提示游戲結束
    alert("游戲結束");
}

OK,大功告成!!!後續還可以加入選擇難度的功能,重新開始按鈕,動畫效果等等,這個就看你們發揮了!!

 

 

完整代碼

<!DOCTYPE html>
<html>

<head>
  <title>掃雷</title>
  <style>
    #bar {
      text-align: center;
      margin-bottom:20px;
    }

    .bar {
      height: 25px;
      width: 150px;
      line-height: 25px;
      display: inline-block;
      border: solid 1px #000;
      margin-left: 20px;
      margin-right: 20px;
    }

    #grid {
      margin: auto;
    }

    .blocks {
      width: 30px;
      height: 30px;
      line-height: 30px;
      display: block;
      text-align: center;
      border: solid 1px #000;
      user-select: none;
      cursor: pointer;
    }

    .blocks:hover {
      background: #0af;
    }
  </style>
</head>

<!-- ondragstart:防拖拽生成新頁面 oncontextmenu:屏蔽右鍵菜單-->

<body ondragstart='return false' oncontextmenu='self.event.returnValue=false'>

  <div id='bar'>
    <span class='bar'>剩餘雷數:<label id='count'>0</label></span>
    <span class='bar'>計時:<label id='time'>0</label>s</span>
  </div>
  <table id='grid'></table>

  <script>
    var row = 10; //行數
    var col = 10; //列數
    var maxCount = 10; //最大地雷數量
    var isFirstOpen = true; //第一次打開方格
    var grid = init_grid(); //初始化
    var count = document.getElementById('count'); //剩餘雷數
    var time = document.getElementById('time'); //計時

    //初始化矩陣 (row-行數 col-列數)
    function init_grid() {

      //生成矩陣html <tr>--行標簽 <td>--列標簽
      let gridHtml = '';
      for (let i = 0; i < row; i++) {
        gridHtml += '<tr>'
        for (let j = 0; j < col; j++) {
          gridHtml +=
            '<td><span class="blocks" onmousedown="block_click(' + i + ',' + j + ',event)"></span></td>';
        }
        gridHtml += '<tr>'
      }
      //寫入html
      document.getElementById('grid').innerHTML = gridHtml;

      //返回矩陣二維數組
      let blocks = document.getElementsByClassName('blocks');
      let grid = new Array();
      for (let i = 0; i < blocks.length; i++) {
        if (i % col === 0) {
          grid.push(new Array());
        }
        //初始化計雷數
        blocks[i].count = 0;
        grid[parseInt(i / col)].push(blocks[i]);
      }
      return grid;
    }

    //方格點擊事件 _i:坐標i _j:坐標j e:滑鼠事件
    function block_click(_i, _j, e) {

      //跳過已打開的方格
      if (grid[_i][_j].isOpen) {
        return;
      }

      //滑鼠左鍵打開方格
      if (e.button === 	   

您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 簡介: 倒計時秒殺組件在電商網站中層出不窮 不過思路萬變不離其蹤,我自己根據其他資料設計了一個vue版的 核心思路:1、時間不能是本地客戶端的時間 必須是伺服器的時間這裡用一個settimeout代替 以為時間必須統一 2、開始時間,結束時間通過父組件傳入,當伺服器時間在這個開始時間和結束時間的範圍 ...
  • 不要慌!下麵開始幫你找到,很簡單! ...
  • emmmmm.....標題我就覺得起的很變態。閑話不多說,先說出現的背景吧~~。 因為業務上的需求,跟一個硬體對接,要做大屏展示大廳客流熱力圖分佈(背景圖是客戶那邊給的)。然後這個機子傳過來的數據就可能20來條。如果用最新的echarts4來做,但是數據太小不足以畫出圖來,但是如果數據太大傳輸也是一 ...
  • "官方文檔" 前言 所謂視頻上傳,是指開發者或其用戶將視頻文件上傳到點播的視頻存儲中,以便進行視頻處理、分發等。 一、簡介 騰訊雲點播支持如下幾種視頻上傳方式: 1. 控制臺上傳:在點播控制臺上進行操作,將本地視頻上傳到雲點播,適用於直接管理少量視頻的場景,具有方便快捷、無技術門檻的優點; 2. 服 ...
  • 數組方法: 1、Array.join([param]) 方法:將數組中所有的元素都轉換為字元串並連接起來,通過字元 param 連接,預設使用逗號,返回最後生成的字元串 2、Array.reverse() 方法:將數組中的元素顛倒順序(在原數組中重新排列它們),返回逆序數組 3、Array.sort ...
  • 一、HTML5簡介 HTML 5 的第一份正式草案已於2008年1月22日公佈。HTML5 仍處於完善之中。然而,大部分現代瀏覽器已經具備了某些 HTML5 支持。 2014年10月29日,萬維網聯盟宣佈,經過幾乎8年的艱辛努力,HTML5標準規範終於最終制定完成了,並已公開發佈。 HTML5不僅僅 ...
  • 一. 提前準備工作 1.Node.js環境 2.Windows10 3.npm(前端包管理工具) 4.webpack(前端資源載入/打包工具) 二. 開始安裝 1.。下載並安裝Node.js 下載地址:https://nodejs.org/en/download/ 2.在cmd中查看node.js是 ...
  • 基本實現: 解析GET參數: 解析POST: ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...