SNSフォローボタン

まさかこんなに簡単に!? AI エディタ Cursor に指示を出すだけでオセロゲームが完成した話

こんにちは、フリーランスエンジニアの剛(ごう)です。
AI エディタ「Cursor」に出会った際に、試しにオセロゲームを作ってみたところ、
予想以上に簡単に実装できてしまい、その便利さに驚きました。
今回は、この驚きの体験と共に、Cursor の基本的な使い方をご紹介したいと思います。

Cursorとは?

Cursor は、AI を搭載したコードエディタです。
一般的な Visual Studio Code エディタと同じような見た目と操作感なので、VS Code ユーザーなら すぐに馴染めます。
Cursor の紹介についてはこちらの記事をご覧ください。

VS Codeをベースに、GPT-4やClaude等のAIを統合した新しいエディタ「Cursor」を紹介しています。

Cursor って何ができるの?

Cursor の主な機能を3つご紹介します。

1. AI チャット機能

– コードの質問ができる
– エラーの解決方法を提案してくれる
– コードの改善案を提示してくれる

2. コード補完機能
– 文脈を理解した賢い補完
– 複数行のコードブロックも予測
– 関数やクラスの実装も提案

3. リアルタイムのエラーチェック
– タイプミスや構文エラーを即座に指摘
– 修正案も同時に提示

今回はAIチャット機能について紹介し、実際にコードを生成してみたいと思います。

AI チャット機能

Cursorの最大の魅力は、強力なAIチャット機能です。
コードの生成自体を依頼することもできますし、コードを書いている最中に疑問が生じたら、エディタ上で直接AIに質問できます。

たとえば、以下のような質問が可能です。

  • 「この関数の使い方を教えてください」
  • 「このエラーの原因と解決方法を教えてください」
  •  「○○の機能を実装するコードを生成してください」
  •  「CSSでグラデーションを実装する方法を教えてください」

これまでは、開発中に不明点があると作業を中断し、検索エンジンで調べる必要がありました。Cursorを使えば、エディタを離れることなく即座に回答が得られます。

また、検索エンジンでは同じような一般的な解説が書かれたページばかりがヒットし、自分の特定の状況に合った解決策を見つけるのが困難なことがあります。CursorのAIチャット機能は、あなたのコードの文脈を理解した上で、的確なアドバイスを提供してくれます。

オセロゲームを作ってみる!

AIチャット機能を使って、簡単なオセロゲームを作ってもらうよう以下のプロンプトを実行してみました。

「HTMLとJavaScriptでオセロゲームを作ってください」

生成してくれたコードが以下です。

<!DOCTYPE html>
<html lang="ja">
  <head>
    <meta charset="UTF-8">
    <title>オセロゲーム</title>
    <style>
      .board {
        display: grid;
        grid-template-columns: repeat(8, 50px);
        gap: 2px;
        background-color: #228b22;
        padding: 10px;
        width: fit-content;
      }
      .cell {
        width: 50px;
        height: 50px;
        background-color: #228b22;
        border: 1px solid #000;
        display: flex;
        justify-content: center;
        align-items: center;
        cursor: pointer;
      }
      .disc {
        width: 40px;
        height: 40px;
        border-radius: 50%;
      }
      .black {
        background-color: #000;
      }
      .white {
        background-color: #fff;
      }
    </style>
  </head>
  <body>
    <h1>オセロゲーム</h1>
    <div id="turn">黒の番です</div>
    <div id="board" class="board"></div>
<script>
const EMPTY = 0;
const BLACK = 1;
const WHITE = 2;
let currentPlayer = BLACK;
let board = Array(8).fill().map(() => Array(8).fill(EMPTY));

// 初期配置
board[3][3] = WHITE;
board[3][4] = BLACK;
board[4][3] = BLACK;
board[4][4] = WHITE;

function createBoard() {
  const boardElement = document.getElementById('board');
  for (let i = 0; i < 8; i++) {
    for (let j = 0; j < 8; j++) {
      const cell = document.createElement('div');
      cell.className = 'cell';
      cell.dataset.row = i;
      cell.dataset.col = j;
      cell.addEventListener('click', handleClick);
      boardElement.appendChild(cell);
    }
  }
  updateBoard();
}

function updateBoard() {
  const cells = document.querySelectorAll('.cell');
  cells.forEach(cell => {
    const row = parseInt(cell.dataset.row);
    const col = parseInt(cell.dataset.col);
    cell.innerHTML = '';
    if (board[row][col] !== EMPTY) {
      const disc = document.createElement('div');
      disc.className = `disc ${board[row][col] === BLACK ? 'black' : 'white'}`;
      cell.appendChild(disc);
    }
  });
  document.getElementById('turn').textContent = `${currentPlayer === BLACK ? '黒' : '白'}の番です`;
}

function handleClick(e) {
  const row = parseInt(e.target.dataset.row);
  const col = parseInt(e.target.dataset.col);

  if (isValidMove(row, col)) {
    makeMove(row, col);
    currentPlayer = currentPlayer === BLACK ? WHITE : BLACK;
    updateBoard();

    if (!hasValidMoves()) {
      currentPlayer = currentPlayer === BLACK ? WHITE : BLACK;
      if (!hasValidMoves()) {
        endGame();
      }
    }
  }
}

function isValidMove(row, col) {
  if (board[row][col] !== EMPTY) return false;

  const directions = [
    [-1, -1], [-1, 0], [-1, 1],
    [0, -1], [0, 1],
    [1, -1], [1, 0], [1, 1]
  ];

  return directions.some(([dx, dy]) => {
    return canFlip(row, col, dx, dy);
  });
}

function canFlip(row, col, dx, dy) {
  let x = row + dx;
  let y = col + dy;
  let hasOpponent = false;

  while (x >= 0 && x < 8 && y >= 0 && y < 8) {
    if (board[x][y] === EMPTY) return false;
    if (board[x][y] === currentPlayer) {
      return hasOpponent;
    }
    hasOpponent = true;
    x += dx;
    y += dy;
  }
  return false;
}

function makeMove(row, col) {
  board[row][col] = currentPlayer;

  const directions = [
    [-1, -1], [-1, 0], [-1, 1],
    [0, -1], [0, 1],
    [1, -1], [1, 0], [1, 1]
  ];

  directions.forEach(([dx, dy]) => {
    if (canFlip(row, col, dx, dy)) {
      let x = row + dx;
      let y = col + dy;
      while (board[x][y] !== currentPlayer) {
        board[x][y] = currentPlayer;
        x += dx;
        y += dy;
      }
    }
  });
}

function hasValidMoves() {
  for (let i = 0; i < 8; i++) {
    for (let j = 0; j < 8; j++) {
      if (isValidMove(i, j)) return true;
    }
  }
  return false;
}

function endGame() {
  let blackCount = 0;
  let whiteCount = 0;

  for (let i = 0; i < 8; i++) {
    for (let j = 0; j < 8; j++) {
      if (board[i][j] === BLACK) blackCount++;
        if (board[i][j] === WHITE) whiteCount++;
    }
  }

  let message = `ゲーム終了!\n黒: ${blackCount} 白: ${whiteCount}\n`;
  if (blackCount > whiteCount) {
    message += '黒の勝ち!';
  } else if (whiteCount > blackCount) {
    message += '白の勝ち!';
  } else {
    message += '引き分け!';
  }
  alert(message);
}

createBoard();
</script>
  </body>
</html>

なんと、CSSとHTMLを含めて200行程度のコードを数十秒で出力してくれました!

こちらを実際に設置したページがこちらとなります。

シンプルながらも完全に動作するオセロゲームができました。

具体的には

  • 8×8のゲームボード
  • 黒白の交互の手番
  • 合法手のチェック
  • 石の自動反転
  • 勝敗判定

といった基本的な機能が全て実装されています。

もちろん、こちらのコードをベースに、

  • アニメーション効果の追加
  • 石を置ける場所の表示
  • ゲーム履歴の実装
  • AIプレイヤーの追加

などの機能拡張していくことも可能かと思います。

このように、Cursorを使えば、プロトタイプの作成から本格的な実装まで、
驚くほど効率的に進められることが分かりました。

まとめ

今回は試しにオセロゲームの実装を依頼してみましたが、予想をはるかに超える速さと品質でコードが生成されました。
記事で紹介したオセロゲームの実装例は、Cursorの可能性を示す一例に過ぎません。
実用的なコードの生成はもちろん、エラーの解決策の提案や、既存コードの改善、機能拡張のサポートまで、開発のあらゆる場面で強力な味方となってくれます。

Cursorは、単なるコードエディタの枠を超え、私たちの開発プロセス全体を革新する可能性を秘めています。
まだ使ったことのない方は、ぜひ一度体験してみてください。

スポンサーリンク

記事のシェアはこちらからどうぞ。