先看Claude的AI:https://claude.ai/chat


我:

请使用HTML网页写一个扫雷游戏

AI:

这里是一个使用HTML+JavaScript实现的简单扫雷网页游戏:

<!DOCTYPE html>
<html>
<head>
  <title>扫雷游戏</title>
</head>
<body>
  <div id="minefield"></div>

  <script>
    // 游戏逻辑
  </script>

  <style>
    #minefield {
      display: grid;
      grid-template-columns: repeat(10, 30px);
      grid-template-rows: repeat(10, 30px);
    }
    .cell {
      border: 1px solid #ccc;
      text-align: center;
      line-height: 30px;
    }
  </style>

</body>
</html>

JavaScript代码:

// 初始化游戏
let field = [];
let mines = []; 

// 生成场景
for (let i = 0; i < 10; i++) {
  let row = [];
  for (let j = 0; j < 10; j++) {
    row.push(0);
  }
  field.push(row);
}

// 随机生成地雷
for (let i = 0; i < 10; i++) {
  let x = Math.floor(Math.random() * 10);
  let y = Math.floor(Math.random() * 10);
  
  mines.push([x, y]);
  field[y][x] = -1; 
}

// 渲染场景
function render() {
  let minefield = document.getElementById('minefield');
  minefield.innerHTML = '';
  for (let i = 0; i < 10; i++) {
    for (let j = 0; j < 10; j++) {
      let cell = document.createElement('div');
      cell.classList.add('cell');
      cell.textContent = field[i][j];
      minefield.appendChild(cell);
    }
  }
}

render();

这实现了一个10x10的扫雷场景渲染。你可以继续完善游戏逻辑,实现点击、判断游戏结束等功能。

我:

继续完善游戏逻辑,实现点击、判断游戏结束等功能。

AI:

好的,我们可以继续完善游戏逻辑,实现点击格子和判断游戏结束等功能:

// 点击 handlers
for (let i=0; i<10; i++) {
  for (let j=0; j<10; j++) {
    let cell = document.querySelector(`#minefield div:nth-child(${i*10 + j+1})`);
    cell.addEventListener('click', function() {
      handleClick(i, j); 
    });
  }
}

function handleClick(i, j) {
  if (mines.includes([i, j])) {
    gameOver(); 
  } else {
    let count = 0;
    // 计算周围雷数
    for (let x=i-1; x<=i+1; x++) {
      for (let y=j-1; y<=j+1; y++) {
        if (x>=0 && x<10 && y>=0 && y<10) {
          if (mines.includes([x, y])) {
            count++;
          }
        }
      }
    }
    field[i][j] = count;
    render();
  }
}

function gameOver() {
  alert('游戏结束');
  
  // 显示所有地雷
  render(); 
}

这实现了点击处理逻辑,计算周围地雷数量,判断游戏结束等功能。你可以继续扩展更多特性,丰富游戏体验。


好,现在咱们复制到本地,运行一下。

运行得到的截图:
扫雷

以我的理解,雷区直接显示出来还玩个毛线???哈哈哈。等等,有bug的味道。

  1. 坐标写错。截图为证。Claude chat
  2. 错误使用内置函数。在handleClick函数,AI的目的应该是查找mines二维数组里有没有包含当前点击的&点击区域周围格子的坐标,但是Javascript数组之间的比较是和对象一样的,不是直接比较元素的值啊。。。
  3. 监听器丢失。点击一次后,调用渲染函数,渲染函数使用的是创建元素操作添加cell,但是监听器的添加并不在render函数中,导致监听器丢失。

在我指出代码有bug时,代码有bug,AI的输出:

对于这个扫雷游戏代码,可能存在的一些bug和需要改进的地方:

  1. 生成地雷的逻辑可以改进,避免生成重复或聚集的地雷:
// 随机生成地雷
let mines = new Set();
while(mines.size < 10) {
  let x = Math.floor(Math.random() * 10);
  let y = Math.floor(Math.random() * 10);
  mines.add([x, y]);
}
  1. 计算周围地雷数量时需要注意边界情况,避免访问越界:
let count = 0;
for (let x = Math.max(0, i-1); x <= Math.min(9, i+1); x++) {
  ...
}
  1. 点击 handlers 中可能存在逻辑错误,点击后需要更新 field 数据。
  2. 游戏结束后需要阻止继续点击,避免错误。
  3. UI显示可以改进,如区分未点击和已点击格子样式。
  4. 可以添加重新开始游戏的按钮。
  5. 增加更多游戏设置自定义选项。
  6. 需要进行更全面的测试,发现边界条件下的潜在问题。
  7. 可以添加提示标记等辅助功能提高游戏体验。
  8. 可以保存历史最高分、游戏次数等数据。

Overall Code: 用于计算数组或对象中某属性总和的高阶函数。

输入数组和属性键名,返回该属性的总和。

function overall(array, key) {
  return array.reduce((a, b) => a + (b[key] || 0), 0);
}

// Usage
const users = [
  { name: "John", age: 20 },
  { name: "Jane", age: 30 },
  { name: "Jim", age: 40 }
];

overall(users, "age"); // 90

使用 Array.reduce() 迭代数组,在每个对象中取出 指定属性,并将其累加。

对于没有该属性的对象,默认为 0 以避免 NaN。

这样可以轻松计算数组对象任意属性的总和,非常灵活。

看样子没有发现我提出的那3个bug

虽然代码有bug,但是能写出这个程度的代码,我也被吓到了。

再看chatgpt免费版本:https://chat.openai.com/

我:

请使用HTML网页写一个扫雷游戏

AI:

当我们在聊天中使用纯文本来交流时,我无法直接为您提供一个可以运行的HTML网页。但是,我可以为您提供一个基本的HTML代码示例,您可以将其复制并粘贴到一个HTML文件中,并在浏览器中运行以查看扫雷游戏的基本结构。请注意,这只是一个简单的示例,缺少游戏逻辑和交互性。

<!DOCTYPE html>
<html>
<head>
    <title>Minesweeper</title>
    <style>
        .cell {
            width: 20px;
            height: 20px;
            border: 1px solid #000;
            display: inline-block;
            text-align: center;
        }
    </style>
</head>
<body>
    <h1>Minesweeper</h1>
  
    <div id="board"></div>
  
    <script>
        // 游戏设置
        var rows = 10; // 行数
        var columns = 10; // 列数
        var mines = 10; // 雷数
      
        // 创建游戏板
        var board = document.getElementById('board');
      
        for (var i = 0; i < rows; i++) {
            for (var j = 0; j < columns; j++) {
                var cell = document.createElement('div');
                cell.className = 'cell';
                cell.setAttribute('data-row', i);
                cell.setAttribute('data-col', j);
                board.appendChild(cell);
            }
          
            var lineBreak = document.createElement('br');
            board.appendChild(lineBreak);
        }
      
        // 为每个格子添加点击事件
        var cells = document.getElementsByClassName('cell');
      
        for (var i = 0; i < cells.length; i++) {
            cells[i].addEventListener('click', function() {
                var row = parseInt(this.getAttribute('data-row'));
                var col = parseInt(this.getAttribute('data-col'));
              
                // TODO: 处理点击事件
              
                console.log('Clicked cell:', row, col);
            });
        }
    </script>
</body>
</html>

请注意,这只是一个基本的HTML结构,缺少游戏逻辑和地雷的生成等功能。您可以根据您的需求自定义和扩展代码,以实现完整的扫雷游戏功能。

我:

请完善游戏逻辑和地雷的生成等功能

AI:

当然,我可以为您提供一个稍微完善一些的扫雷游戏示例,包括游戏逻辑和地雷的生成。请注意,以下代码仅供参考,您可以根据自己的需求进行修改和扩展。

<!DOCTYPE html>
<html>
<head>
    <title>Minesweeper</title>
    <style>
        .cell {
            width: 20px;
            height: 20px;
            border: 1px solid #000;
            display: inline-block;
            text-align: center;
            background-color: #ccc;
            cursor: pointer;
        }
    </style>
</head>
<body>
    <h1>Minesweeper</h1>
  
    <div id="board"></div>
  
    <script>
        // 游戏设置
        var rows = 10; // 行数
        var columns = 10; // 列数
        var mines = 10; // 雷数
      
        var board = []; // 游戏板数据
      
        // 创建游戏板
        var boardContainer = document.getElementById('board');
      
        for (var i = 0; i < rows; i++) {
            var row = [];
          
            for (var j = 0; j < columns; j++) {
                var cell = document.createElement('div');
                cell.className = 'cell';
                cell.setAttribute('data-row', i);
                cell.setAttribute('data-col', j);
                cell.addEventListener('click', handleCellClick);
              
                boardContainer.appendChild(cell);
              
                row.push({
                    element: cell,
                    isMine: false,
                    isRevealed: false,
                    neighborMineCount: 0
                });
            }
          
            board.push(row);
          
            var lineBreak = document.createElement('br');
            boardContainer.appendChild(lineBreak);
        }
      
        // 生成地雷
        var mineCount = 0;
      
        while (mineCount < mines) {
            var randomRow = Math.floor(Math.random() * rows);
            var randomCol = Math.floor(Math.random() * columns);
          
            if (!board[randomRow][randomCol].isMine) {
                board[randomRow][randomCol].isMine = true;
                mineCount++;
            }
        }
      
        // 点击格子的处理函数
        function handleCellClick() {
            var row = parseInt(this.getAttribute('data-row'));
            var col = parseInt(this.getAttribute('data-col'));
          
            if (board[row][col].isMine) {
                // 点击到雷,游戏结束
                revealAllCells();
                alert('Game Over!');
            } else {
                // 计算周围的雷数
                var neighborMineCount = countNeighborMines(row, col);
              
                // 更新格子状态
                board[row][col].isRevealed = true;
                board[row][col].element.innerHTML = neighborMineCount;
                board[row][col].element.style.backgroundColor = '#fff';
              
                // 如果周围没有雷,则继续展开相邻格子
                if (neighborMineCount === 0) {
                    revealNeighborCells(row, col);
                }
              
                // 检查是否胜利
                if (checkWin()) {
                    revealAllCells();
                    alert('Congratulations! You Win!');
                }
            }
        }
      
        // 计算周围的雷数
        function countNeighborMines(row, col) {
            var count = 0;
          
            for (var i = Math.max(row - 1, 0); i <= Math.min(row + 1, rows - 1); i++) {
                for (var j = Math.max(col - 1, 0); j <= Math.min(col + 1, columns - 1); j++) {
                    if (board[i][j].isMine) {
                        count++;
                    }
                }
            }
          
            return count;
        }
      
        // 展开相邻格子
        function revealNeighborCells(row, col) {
            for (var i = Math.max(row - 1, 0); i <= Math.min(row + 1, rows - 1); i++) {
                for (var j = Math.max(col - 1, 0); j <= Math.min(col + 1, columns - 1); j++) {
                    if (!board[i][j].isMine && !board[i][j].isRevealed) {
                        var neighborMineCount = countNeighborMines(i, j);
                      
                        board[i][j].isRevealed = true;
                        board[i][j].element.innerHTML = neighborMineCount;
                        board[i][j].element.style.backgroundColor = '#fff';
                      
                        if (neighborMineCount === 0) {
                            revealNeighborCells(i, j);
                        }
                    }
                }
            }
        }
      
        // 检查是否胜利
        function checkWin() {
            for (var i = 0; i < rows; i++) {
                for (var j = 0; j < columns; j++) {
                    if (!board[i][j].isMine && !board[i][j].isRevealed) {
                        return false;
                    }
                }
            }
          
            return true;
        }
      
        // 揭示所有格子
        function revealAllCells() {
            for (var i = 0; i < rows; i++) {
                for (var j = 0; j < columns; j++) {
                    var cell = board[i][j];
                  
                    if (cell.isMine) {
                        cell.element.style.backgroundColor = '#f00';
                        cell.element.innerHTML = 'X';
                    } else {
                        var neighborMineCount = countNeighborMines(i, j);
                        cell.element.style.backgroundColor = '#fff';
                        cell.element.innerHTML = neighborMineCount;
                    }
                  
                    cell.element.removeEventListener('click', handleCellClick);
                }
            }
        }
    </script>
</body>
</html>

这段代码将会生成一个带有游戏板的扫雷游戏。游戏逻辑包括点击格子进行揭示,检查是否点击到雷,计算周围的雷数,展开相邻格子等。当游戏结束时,会弹出相关提示。您可以根据需要对代码进行修改和扩展,以满足您的特定需求。请注意,这只是一个简单的示例,并没有处理高级功能,如标记雷、计时器等。

好,咱们还是复制本地,运行

运行截图,看起来比claude好多了。具体你可以自己试试。

chatgpt的扫雷

可以真正地玩起来,就是样式有些不对:
样式有bug

看来在写代码上,chatgpt比claude强。

最后修改:2023 年 07 月 17 日
如果觉得我的文章对你有用,请随意赞赏