最新消息: USBMI致力于为网友们分享Windows、安卓、IOS等主流手机系统相关的资讯以及评测、同时提供相关教程、应用、软件下载等服务。

【gpt实践】同时让chatgpt和claude开发俄罗斯方块

业界 admin 4浏览 0评论

最近chatgpt和claude都在使用,其实大部分日常使用场景表现都没有相差太多,想搞一个有趣的小实验,如果同时让chatgpt和claude开发俄罗斯方块谁会表现的更好呢,说干就干!

claude稳定账号获取
prompt

我选择了用英文描述,毕竟英文数据库更丰富,而且claude封禁比较严格,语言上也是小心翼翼

prompt:I have few development experience, and I want to develope the game 'Tetris' totally basing on html5, css and javascript. I have a few requests: 1, we need a start button, 2, a scoreboard recording score 3, pop up gameover 4, full functionality of a complete Tetris game, their movement, collision detection, scoring, and clearing lines give me all the codes, that can run the game in the browse.

我的开发经验不多,我想开发一款完全基于 html5、css 和 javascript 的 "俄罗斯方块 "游戏。我有几个要求: 1、我们需要一个开始按钮;2、一个记录得分的记分板;3、弹出式游戏结束界面;4、一个完整俄罗斯方块游戏的全部功能,包括移动、碰撞检测、得分和清线。

chatgpt回答

// Define variables and constants
const canvas = document.getElementById('gameCanvas');
const ctx = canvas.getContext('2d');
const startButton = document.getElementById('startButton');
const scoreboard = document.getElementById('score');
const gameOver = document.getElementById('gameOver');
let score = 0;
let gameInterval;
let gameOverFlag = false;

// Define Tetris pieces and their colors
const pieces = [
  [[1, 1, 1, 1]], // I
  [[1, 1, 1], [0, 1, 0]], // T
  [[1, 1, 0], [0, 1, 1]], // Z
  [[0, 1, 1], [1, 1, 0]], // S
  [[1, 1, 1], [0, 1, 0]], // L
  [[1, 1, 1], [1, 0, 0]], // J
  [[1, 1], [1, 1]], // O
];

const colors = ['#00FFFF', '#FF00FF', '#FFA500', '#FFFF00', '#00FF00', '#0000FF', '#FF0000'];

// Define functions for game logic (e.g., draw, move, rotate, check collision, etc.)

// Implement game logic

// Implement startGame function

// Implement gameOver function

// Implement key event listeners for controlling the game (e.g., arrow keys for movement)

// Implement the main game loop

// Implement functions for clearing lines, updating score, etc.

// Implement collision detection and game over check

// Implement rendering functions (e.g., drawPiece, drawBoard, etc.)

// Implement functions for moving and rotating pieces

// Implement functions for handling user input (e.g., start game, pause, resume, etc.)

// Start the game when the start button is clicked
startButton.addEventListener('click', startGame);

考虑篇幅关系,忽略了html和css部分截图,文章最后会给出源码!!!

可以看出chatgpt的做了一些方法定义,但是并没有实现。

claude回答
const canvas = document.getElementById('game-canvas');
const ctx = canvas.getContext('2d');
const scoreDisplay = document.getElementById('score');
const startButton = document.getElementById('start-button');
const gameOverMessage = document.getElementById('game-over-message');

// Game constants
const ROWS = 20;
const COLS = 10;
const BLOCK_SIZE = 20;
const LINE_CLEAR_POINTS = 100;

// Game state
let board = [];
let piece = null;
let isGameOver = false;
let isPlaying = false;
let score = 0;

// Tetromino shapes
const shapes = [
  [
    [0, 0, 0, 0],
    [1, 1, 1, 1],
    [0, 0, 0, 0],
    [0, 0, 0, 0]
  ],
  [
    [1, 0, 0],
    [1, 1, 1],
    [0, 0, 0]
  ],
  [
    [0, 0, 1],
    [1, 1, 1],
    [0, 0, 0]
  ],
  [
    [1, 1, 0],
    [0, 1, 1],
    [0, 0, 0]
  ],
  [
    [0, 1, 1],
    [1, 1, 0],
    [0, 0, 0]
  ],
  [
    [1, 1],
    [1, 1]
  ],
  [
    [0, 1, 0],
    [1, 1, 1],
    [0, 0, 0]
  ]
];

// Helper functions
function drawBoard() {
  ctx.clearRect(0, 0, canvas.width, canvas.height);
  for (let row = 0; row < ROWS; row++) {
    for (let col = 0; col < COLS; col++) {
      if (board[row][col]) {
        ctx.fillStyle = 'yellow';
        ctx.fillRect(col * BLOCK_SIZE, row * BLOCK_SIZE, BLOCK_SIZE, BLOCK_SIZE);
      }
    }
  }

  if (piece) {
    drawPiece(piece.shape, piece.x, piece.y);
  }
}

function drawPiece(shape, x, y) {
  ctx.fillStyle = 'red';
  for (let row = 0; row < shape.length; row++) {
    for (let col = 0; col < shape[row].length; col++) {
      if (shape[row][col]) {
        ctx.fillRect((x + col) * BLOCK_SIZE, (y + row) * BLOCK_SIZE, BLOCK_SIZE, BLOCK_SIZE);
      }
    }
  }
}

function resetBoard() {
  board = Array.from({ length: ROWS }, () => Array(COLS).fill(0));
}

function randomPiece() {
  const randomIndex = Math.floor(Math.random() * shapes.length);
  return {
    shape: shapes[randomIndex],
    x: 3,
    y: 0
  };
}

function movePiece(direction) {
  if (!piece) return;

  const newX = piece.x + (direction === 'left' ? -1 : direction === 'right' ? 1 : 0);
  const newY = piece.y + (direction === 'down' ? 1 : 0);

  if (canMove(piece.shape, newX, newY)) {
    piece.x = newX;
    piece.y = newY;
  } else if (direction === 'down') {
    placePiece();
    clearLines();
    if (!isGameOver) {
      piece = randomPiece();
    }
  }

  drawBoard();
}

function canMove(shape, x, y) {
  for (let row = 0; row < shape.length; row++) {
    for (let col = 0; col < shape[row].length; col++) {
      if (shape[row][col]) {
        const newX = x + col;
        const newY = y + row;

        if (
          newX < 0 ||
          newX >= COLS ||
          newY >= ROWS ||
          (newY >= 0 && board[newY][newX])
        ) {
          return false;
        }
      }
    }
  }
  return true;
}

function placePiece() {
  if (!piece) return;

  for (let row = 0; row < piece.shape.length; row++) {
    for (let col = 0; col < piece.shape[row].length; col++) {
      if (piece.shape[row][col]) {
        board[piece.y + row][piece.x + col] = 1;
      }
    }
  }
}

function clearLines() {
  let linesCleared = 0;
  for (let row = ROWS - 1; row >= 0; row--) {
    let isFull = true;
    for (let col = 0; col < COLS; col++) {
      if (!board[row][col]) {
        isFull = false;
        break;
      }
    }

    if (isFull) {
      linesCleared++;
      for (let r = row; r > 0; r--) {
        for (let c = 0; c < COLS; c++) {
          board[r][c] = board[r - 1][c];
        }
      }
      for (let c = 0; c < COLS; c++) {
        board[0][c] = 0;
      }
    }
  }

  score += linesCleared * LINE_CLEAR_POINTS;
  scoreDisplay.textContent = `Score: ${score}`;
}

function rotatePiece() {
  if (!piece) return;

  const newShape = Array.from({ length: piece.shape[0].length }, () =>
    Array(piece.shape.length).fill(0)
  );

  for (let row = 0; row < piece.shape.length; row++) {
    for (let col = 0; col < piece.shape[row].length; col++) {
      newShape[col][piece.shape.length - 1 - row] = piece.shape[row][col];
    }
  }

  if (canMove(newShape, piece.x, piece.y)) {
    piece.shape = newShape;
  }

  drawBoard();
}

function isGameOverCheck() {
  for (let col = 0; col < COLS; col++) {
    if (board[0][col]) {
      isGameOver = true;
      gameOverMessage.classList.remove('hidden');
      break;
    }
  }
}

// Event listeners
document.addEventListener('keydown', (event) => {
  if (!isPlaying) return;

  switch (event.code) {
    case 'ArrowLeft':
      movePiece('left');
      break;
    case 'ArrowRight':
      movePiece('right');
      break;
    case 'ArrowDown':
      movePiece('down');
      break;
    case 'ArrowUp':
      rotatePiece();
      break;
  }
});

startButton.addEventListener('click', () => {
  if (isPlaying) {
    isPlaying = false;
    startButton.textContent = 'Start';
    gameOverMessage.classList.add('hidden');
  } else {
    isPlaying = true;
    startButton.textContent = 'Pause';
    isGameOver = false;
    score = 0;
    scoreDisplay.textContent = `Score: ${score}`;
    resetBoard();
    piece = randomPiece();
    drawBoard();
  }
});

// Game loop
function gameLoop() {
  if (!isPlaying) return;

  movePiece('down');
  isGameOverCheck();

  if (!isGameOver) {
    requestAnimationFrame(gameLoop);
  }
}

// Start the game
resetBoard();
piece = randomPiece();
drawBoard();
gameLoop();

同样只贴出js部分的代码。可以看到claude给出了相对完善的js逻辑,所以我们直接选择用claude回答的代码进行调试,看看是否能正常在浏览器中运行。

贴出代码:

浏览器打开tetris运行效果:

可以看到,点击开始后方块不会自动下落,需要手动按下,继续反馈优化:

反馈完善功能

prompt:I mean when the game starts without pressing the down button, the cube falls at a constant speed

即当游戏开始时,方块保持匀速下落。

const canvas = document.getElementById('game-canvas');
const ctx = canvas.getContext('2d');
const scoreDisplay = document.getElementById('score');
const startButton = document.getElementById('start-button');
const gameOverMessage = document.getElementById('game-over-message');

// Game constants
const ROWS = 20;
const COLS = 10;
const BLOCK_SIZE = 20;
const LINE_CLEAR_POINTS = 100;
const FALL_SPEED = 500; // Adjust this value to control the falling speed (in milliseconds)

// Game state
let board = [];
let piece = null;
let isGameOver = false;
let isPlaying = false;
let score = 0;
let lastTime = 0;
let fallInterval = null;

// Tetromino shapes
// ... (shapes array remains the same)

// Helper functions
// ... (drawBoard, drawPiece, resetBoard, randomPiece, movePiece, canMove, placePiece, clearLines, rotatePiece, isGameOverCheck functions remain the same)

// Event listeners
document.addEventListener('keydown', (event) => {
  if (!isPlaying) return;

  switch (event.code) {
    case 'ArrowLeft':
      movePiece('left');
      break;
    case 'ArrowRight':
      movePiece('right');
      break;
    case 'ArrowUp':
      rotatePiece();
      break;
  }
});

startButton.addEventListener('click', () => {
  if (isPlaying) {
    isPlaying = false;
    startButton.textContent = 'Start';
    gameOverMessage.classList.add('hidden');
    clearInterval(fallInterval); // Stop the automatic falling
  } else {
    isPlaying = true;
    startButton.textContent = 'Pause';
    isGameOver = false;
    score = 0;
    scoreDisplay.textContent = `Score: ${score}`;
    resetBoard();
    piece = randomPiece();
    drawBoard();
    lastTime = performance.now(); // Get the current time
    fallInterval = setInterval(gameLoop, FALL_SPEED); // Start the automatic falling
  }
});

// Game loop
function gameLoop() {
  if (!isPlaying) return;

  const currentTime = performance.now();
  const deltaTime = currentTime - lastTime;

  if (deltaTime >= FALL_SPEED) {
    movePiece('down');
    isGameOverCheck();
    lastTime = currentTime;
  }

  if (!isGameOver) {
    requestAnimationFrame(gameLoop);
  } else {
    clearInterval(fallInterval); // Stop the automatic falling when the game is over
  }
}

// Start the game
resetBoard();
piece = randomPiece();
drawBoard();

可以看到claude会的的js代码里增加了方块下落的逻辑。点击开始后方块就能匀速下落

当然后面还有几个小问题,比如按下键没有加速下落,方块无法移动到最右端,这些都通过反馈cluade得到了解决,最终能正常运行记分,效果如下:

源码及claude导出文件

https://github/JiangSanJie/gpt-practice/

总结:

claude稳定账号获取

在本次俄罗斯方块的开发prompt中,claude回答相对完善,通过少量的反馈即可完成开发。当然其实chatgpt也能完成,但是需要prompt更加细致,可能针对回答的反馈会繁琐一些,这个感兴趣的读者可以去实验。我相信好的prompt会提高回答满意率!

最近chatgpt和claude都在使用,其实大部分日常使用场景表现都没有相差太多,想搞一个有趣的小实验,如果同时让chatgpt和claude开发俄罗斯方块谁会表现的更好呢,说干就干!

claude稳定账号获取
prompt

我选择了用英文描述,毕竟英文数据库更丰富,而且claude封禁比较严格,语言上也是小心翼翼

prompt:I have few development experience, and I want to develope the game 'Tetris' totally basing on html5, css and javascript. I have a few requests: 1, we need a start button, 2, a scoreboard recording score 3, pop up gameover 4, full functionality of a complete Tetris game, their movement, collision detection, scoring, and clearing lines give me all the codes, that can run the game in the browse.

我的开发经验不多,我想开发一款完全基于 html5、css 和 javascript 的 "俄罗斯方块 "游戏。我有几个要求: 1、我们需要一个开始按钮;2、一个记录得分的记分板;3、弹出式游戏结束界面;4、一个完整俄罗斯方块游戏的全部功能,包括移动、碰撞检测、得分和清线。

chatgpt回答

// Define variables and constants
const canvas = document.getElementById('gameCanvas');
const ctx = canvas.getContext('2d');
const startButton = document.getElementById('startButton');
const scoreboard = document.getElementById('score');
const gameOver = document.getElementById('gameOver');
let score = 0;
let gameInterval;
let gameOverFlag = false;

// Define Tetris pieces and their colors
const pieces = [
  [[1, 1, 1, 1]], // I
  [[1, 1, 1], [0, 1, 0]], // T
  [[1, 1, 0], [0, 1, 1]], // Z
  [[0, 1, 1], [1, 1, 0]], // S
  [[1, 1, 1], [0, 1, 0]], // L
  [[1, 1, 1], [1, 0, 0]], // J
  [[1, 1], [1, 1]], // O
];

const colors = ['#00FFFF', '#FF00FF', '#FFA500', '#FFFF00', '#00FF00', '#0000FF', '#FF0000'];

// Define functions for game logic (e.g., draw, move, rotate, check collision, etc.)

// Implement game logic

// Implement startGame function

// Implement gameOver function

// Implement key event listeners for controlling the game (e.g., arrow keys for movement)

// Implement the main game loop

// Implement functions for clearing lines, updating score, etc.

// Implement collision detection and game over check

// Implement rendering functions (e.g., drawPiece, drawBoard, etc.)

// Implement functions for moving and rotating pieces

// Implement functions for handling user input (e.g., start game, pause, resume, etc.)

// Start the game when the start button is clicked
startButton.addEventListener('click', startGame);

考虑篇幅关系,忽略了html和css部分截图,文章最后会给出源码!!!

可以看出chatgpt的做了一些方法定义,但是并没有实现。

claude回答
const canvas = document.getElementById('game-canvas');
const ctx = canvas.getContext('2d');
const scoreDisplay = document.getElementById('score');
const startButton = document.getElementById('start-button');
const gameOverMessage = document.getElementById('game-over-message');

// Game constants
const ROWS = 20;
const COLS = 10;
const BLOCK_SIZE = 20;
const LINE_CLEAR_POINTS = 100;

// Game state
let board = [];
let piece = null;
let isGameOver = false;
let isPlaying = false;
let score = 0;

// Tetromino shapes
const shapes = [
  [
    [0, 0, 0, 0],
    [1, 1, 1, 1],
    [0, 0, 0, 0],
    [0, 0, 0, 0]
  ],
  [
    [1, 0, 0],
    [1, 1, 1],
    [0, 0, 0]
  ],
  [
    [0, 0, 1],
    [1, 1, 1],
    [0, 0, 0]
  ],
  [
    [1, 1, 0],
    [0, 1, 1],
    [0, 0, 0]
  ],
  [
    [0, 1, 1],
    [1, 1, 0],
    [0, 0, 0]
  ],
  [
    [1, 1],
    [1, 1]
  ],
  [
    [0, 1, 0],
    [1, 1, 1],
    [0, 0, 0]
  ]
];

// Helper functions
function drawBoard() {
  ctx.clearRect(0, 0, canvas.width, canvas.height);
  for (let row = 0; row < ROWS; row++) {
    for (let col = 0; col < COLS; col++) {
      if (board[row][col]) {
        ctx.fillStyle = 'yellow';
        ctx.fillRect(col * BLOCK_SIZE, row * BLOCK_SIZE, BLOCK_SIZE, BLOCK_SIZE);
      }
    }
  }

  if (piece) {
    drawPiece(piece.shape, piece.x, piece.y);
  }
}

function drawPiece(shape, x, y) {
  ctx.fillStyle = 'red';
  for (let row = 0; row < shape.length; row++) {
    for (let col = 0; col < shape[row].length; col++) {
      if (shape[row][col]) {
        ctx.fillRect((x + col) * BLOCK_SIZE, (y + row) * BLOCK_SIZE, BLOCK_SIZE, BLOCK_SIZE);
      }
    }
  }
}

function resetBoard() {
  board = Array.from({ length: ROWS }, () => Array(COLS).fill(0));
}

function randomPiece() {
  const randomIndex = Math.floor(Math.random() * shapes.length);
  return {
    shape: shapes[randomIndex],
    x: 3,
    y: 0
  };
}

function movePiece(direction) {
  if (!piece) return;

  const newX = piece.x + (direction === 'left' ? -1 : direction === 'right' ? 1 : 0);
  const newY = piece.y + (direction === 'down' ? 1 : 0);

  if (canMove(piece.shape, newX, newY)) {
    piece.x = newX;
    piece.y = newY;
  } else if (direction === 'down') {
    placePiece();
    clearLines();
    if (!isGameOver) {
      piece = randomPiece();
    }
  }

  drawBoard();
}

function canMove(shape, x, y) {
  for (let row = 0; row < shape.length; row++) {
    for (let col = 0; col < shape[row].length; col++) {
      if (shape[row][col]) {
        const newX = x + col;
        const newY = y + row;

        if (
          newX < 0 ||
          newX >= COLS ||
          newY >= ROWS ||
          (newY >= 0 && board[newY][newX])
        ) {
          return false;
        }
      }
    }
  }
  return true;
}

function placePiece() {
  if (!piece) return;

  for (let row = 0; row < piece.shape.length; row++) {
    for (let col = 0; col < piece.shape[row].length; col++) {
      if (piece.shape[row][col]) {
        board[piece.y + row][piece.x + col] = 1;
      }
    }
  }
}

function clearLines() {
  let linesCleared = 0;
  for (let row = ROWS - 1; row >= 0; row--) {
    let isFull = true;
    for (let col = 0; col < COLS; col++) {
      if (!board[row][col]) {
        isFull = false;
        break;
      }
    }

    if (isFull) {
      linesCleared++;
      for (let r = row; r > 0; r--) {
        for (let c = 0; c < COLS; c++) {
          board[r][c] = board[r - 1][c];
        }
      }
      for (let c = 0; c < COLS; c++) {
        board[0][c] = 0;
      }
    }
  }

  score += linesCleared * LINE_CLEAR_POINTS;
  scoreDisplay.textContent = `Score: ${score}`;
}

function rotatePiece() {
  if (!piece) return;

  const newShape = Array.from({ length: piece.shape[0].length }, () =>
    Array(piece.shape.length).fill(0)
  );

  for (let row = 0; row < piece.shape.length; row++) {
    for (let col = 0; col < piece.shape[row].length; col++) {
      newShape[col][piece.shape.length - 1 - row] = piece.shape[row][col];
    }
  }

  if (canMove(newShape, piece.x, piece.y)) {
    piece.shape = newShape;
  }

  drawBoard();
}

function isGameOverCheck() {
  for (let col = 0; col < COLS; col++) {
    if (board[0][col]) {
      isGameOver = true;
      gameOverMessage.classList.remove('hidden');
      break;
    }
  }
}

// Event listeners
document.addEventListener('keydown', (event) => {
  if (!isPlaying) return;

  switch (event.code) {
    case 'ArrowLeft':
      movePiece('left');
      break;
    case 'ArrowRight':
      movePiece('right');
      break;
    case 'ArrowDown':
      movePiece('down');
      break;
    case 'ArrowUp':
      rotatePiece();
      break;
  }
});

startButton.addEventListener('click', () => {
  if (isPlaying) {
    isPlaying = false;
    startButton.textContent = 'Start';
    gameOverMessage.classList.add('hidden');
  } else {
    isPlaying = true;
    startButton.textContent = 'Pause';
    isGameOver = false;
    score = 0;
    scoreDisplay.textContent = `Score: ${score}`;
    resetBoard();
    piece = randomPiece();
    drawBoard();
  }
});

// Game loop
function gameLoop() {
  if (!isPlaying) return;

  movePiece('down');
  isGameOverCheck();

  if (!isGameOver) {
    requestAnimationFrame(gameLoop);
  }
}

// Start the game
resetBoard();
piece = randomPiece();
drawBoard();
gameLoop();

同样只贴出js部分的代码。可以看到claude给出了相对完善的js逻辑,所以我们直接选择用claude回答的代码进行调试,看看是否能正常在浏览器中运行。

贴出代码:

浏览器打开tetris运行效果:

可以看到,点击开始后方块不会自动下落,需要手动按下,继续反馈优化:

反馈完善功能

prompt:I mean when the game starts without pressing the down button, the cube falls at a constant speed

即当游戏开始时,方块保持匀速下落。

const canvas = document.getElementById('game-canvas');
const ctx = canvas.getContext('2d');
const scoreDisplay = document.getElementById('score');
const startButton = document.getElementById('start-button');
const gameOverMessage = document.getElementById('game-over-message');

// Game constants
const ROWS = 20;
const COLS = 10;
const BLOCK_SIZE = 20;
const LINE_CLEAR_POINTS = 100;
const FALL_SPEED = 500; // Adjust this value to control the falling speed (in milliseconds)

// Game state
let board = [];
let piece = null;
let isGameOver = false;
let isPlaying = false;
let score = 0;
let lastTime = 0;
let fallInterval = null;

// Tetromino shapes
// ... (shapes array remains the same)

// Helper functions
// ... (drawBoard, drawPiece, resetBoard, randomPiece, movePiece, canMove, placePiece, clearLines, rotatePiece, isGameOverCheck functions remain the same)

// Event listeners
document.addEventListener('keydown', (event) => {
  if (!isPlaying) return;

  switch (event.code) {
    case 'ArrowLeft':
      movePiece('left');
      break;
    case 'ArrowRight':
      movePiece('right');
      break;
    case 'ArrowUp':
      rotatePiece();
      break;
  }
});

startButton.addEventListener('click', () => {
  if (isPlaying) {
    isPlaying = false;
    startButton.textContent = 'Start';
    gameOverMessage.classList.add('hidden');
    clearInterval(fallInterval); // Stop the automatic falling
  } else {
    isPlaying = true;
    startButton.textContent = 'Pause';
    isGameOver = false;
    score = 0;
    scoreDisplay.textContent = `Score: ${score}`;
    resetBoard();
    piece = randomPiece();
    drawBoard();
    lastTime = performance.now(); // Get the current time
    fallInterval = setInterval(gameLoop, FALL_SPEED); // Start the automatic falling
  }
});

// Game loop
function gameLoop() {
  if (!isPlaying) return;

  const currentTime = performance.now();
  const deltaTime = currentTime - lastTime;

  if (deltaTime >= FALL_SPEED) {
    movePiece('down');
    isGameOverCheck();
    lastTime = currentTime;
  }

  if (!isGameOver) {
    requestAnimationFrame(gameLoop);
  } else {
    clearInterval(fallInterval); // Stop the automatic falling when the game is over
  }
}

// Start the game
resetBoard();
piece = randomPiece();
drawBoard();

可以看到claude会的的js代码里增加了方块下落的逻辑。点击开始后方块就能匀速下落

当然后面还有几个小问题,比如按下键没有加速下落,方块无法移动到最右端,这些都通过反馈cluade得到了解决,最终能正常运行记分,效果如下:

源码及claude导出文件

https://github/JiangSanJie/gpt-practice/

总结:

claude稳定账号获取

在本次俄罗斯方块的开发prompt中,claude回答相对完善,通过少量的反馈即可完成开发。当然其实chatgpt也能完成,但是需要prompt更加细致,可能针对回答的反馈会繁琐一些,这个感兴趣的读者可以去实验。我相信好的prompt会提高回答满意率!

发布评论

评论列表 (0)

  1. 暂无评论