
ChatGPT(GPT-4)で五目並べアプリの作り方を教えて貰った(HTML)
作成したのが下図のアプリです。

はじめに
プログラマーではなくても、ChatGPTを使えば、アプリが作れるのか!?
という疑問から、実験してみました。
著者はゲームデザイナーでプログラムは多少分かる程度ですが、基本的にここではChatGPTさんに全てをお任せしています。
ChatGPTへの質問 その1
ウェブブラウザで遊べる五目並べアプリの作り方をソースコードも含めて教えて下さい。
黒が先手、白が後手、盤面は囲碁と同じ19路盤とします。
グリッド線も表示して下さい。
タイトルは"五目並べ"として、アプリの上に表示してください。
黒の番と白の番が常に表示されるようにしてください。
Mouse Overした際に、位置の予測として、色を薄めた碁石を表示して下さい。
html, css, javascript等の他、必要な機能は使用して構いません。
オンラインでの対戦は出来なくても大丈夫です。
ChatGPTからの回答 その1
五目並べアプリを作成するには、HTML、CSS、JavaScriptを使用してウェブページを作成します。以下のコードは、要求された機能を持つ五目並べアプリの一例です。このコードを自分のエディターにコピーして、index.htmlという名前で保存し、ウェブブラウザで開くことができます。
※実際には途中で一旦止まったので、「続き」と質問した後の内容と結合しています。
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>五目並べ</title>
<style>
body {
font-family: Arial, sans-serif;
text-align: center;
}
canvas {
border: 1px solid black;
display: inline-block;
}
#turn {
font-weight: bold;
}
</style>
</head>
<body><h1>五目並べ</h1>
<canvas id="board" width="380" height="380"></canvas>
<p id="turn">黒の番です</p>
<script>
const canvas = document.getElementById('board');
const ctx = canvas.getContext('2d');
const gridSize = 20;
const stoneRadius = 8;
const boardSize = 19;
let board = new Array(boardSize).fill(null).map(() => new Array(boardSize).fill(null));
let currentPlayer = 'black';
function drawGrid() {
ctx.strokeStyle = 'black';
for (let i = 0; i < boardSize; i++) {
ctx.beginPath();
ctx.moveTo(gridSize + i * gridSize, gridSize);
ctx.lineTo(gridSize + i * gridSize, canvas.height - gridSize);
ctx.stroke();
ctx.beginPath();
ctx.moveTo(gridSize, gridSize + i * gridSize);
ctx.lineTo(canvas.width - gridSize, gridSize + i * gridSize);
ctx.stroke();
}
}
function drawStone(x, y, color, opacity = 1) {
ctx.beginPath();
ctx.arc(x, y, stoneRadius, 0, 2 * Math.PI);
ctx.fillStyle = color;
ctx.globalAlpha = opacity;
ctx.fill();
ctx.globalAlpha = 1;
}
function getMousePosition(event) {
const rect = canvas.getBoundingClientRect();
const x = event.clientX - rect.left;
const y = event.clientY - rect.top;
return { x, y };
}
function positionToCoordinate(x, y) {
return {
row: Math.round((y - gridSize) / gridSize),
col: Math.round((x - gridSize) / gridSize),
};
}
function placeStone(row, col, color) {
board[row][col] = color;
drawStone(gridSize + col * gridSize, gridSize + row * gridSize, color);
}
function isValidMove(row, col) {
return row >= 0 && col >= 0 && row < boardSize && col < boardSize && !board[row][col];
}
canvas.addEventListener('mousemove', (event) => {
const { x, y } = getMousePosition(event);
const { row, col } = positionToCoordinate(x, y);
if (isValidMove(row, col)) {
ctx.clearRect(0, 0, canvas.width, canvas.height);
drawGrid();
board.forEach((row, rowIndex) => row.forEach((stone, colIndex) => {
if (stone) {
drawStone(gridSize + colIndex * gridSize, gridSize + rowIndex * gridSize, stone);
}
});
drawStone(gridSize + col * gridSize, gridSize + row * gridSize, currentPlayer, 0.5);
}
});
canvas.addEventListener('click', (event) => {
const { x, y } = getMousePosition(event);
const { row, col } = positionToCoordinate(x, y);
if (isValidMove(row, col)) {
placeStone(row, col, currentPlayer);
if (checkWin(row, col, currentPlayer)) {
alert(currentPlayer === 'black' ? '黒の勝ちです!' : '白の勝ちです!');
board = new Array(boardSize).fill(null).map(() => new Array(boardSize).fill(null));
} else {
currentPlayer = currentPlayer === 'black' ? 'white' : 'black';
document.getElementById('turn').textContent = currentPlayer === 'black' ? '黒の番です' : '白の番です';
}
}
});
function checkWin(row, col, player) {
const directions = [
{ row: 1, col: 0 },
{ row: 0, col: 1 },
{ row: 1, col: 1 },
{ row: 1, col: -1 },
];
for (const direction of directions) {
let count = 1;
for (let i = 1; i < 5; i++) {
const newRow = row + direction.row * i;
const newCol = col + direction.col * i;
if (newRow >= 0 && newRow < boardSize && newCol >= 0 && newCol < boardSize && board[newRow][newCol] === player) {
count++;
} else {
break;
}
}
for (let i = 1; i < 5; i++) {
const newRow = row - direction.row * i;
const newCol = col - direction.col * i;
if (newRow >= 0 && newRow < boardSize && newCol >= 0 && newCol < boardSize && board[newRow][newCol] === player) {
count++;
} else {
break;
}
}
if (count >= 5) {
return true;
}
}
return false;
}
drawGrid();
実際に作成 その1
今回はChatGPTからの回答はCSSとJavaScriptはHTMLに直接書いてあって、
ファイルとしてはひとつだけでした。
もしCSSとJavaScriptを別に作る指定であれば、下図の様にフォルダを用意して、そこに3つのファイルを格納すれば機能しました。
ファイルの作成方法としては、テキストを作成して、拡張子も含めて変更すれば作成できるかと思います。例:index.html, styles.css等
編集はメモ帳でもVisualStudioCode等の好きなエディタで可能です。

編集する際は右クリックからプログラムから開くを選択して、メモ帳やVisualStudioCodeなどのエディタを選択すると内容の編集ができます。

作成したindex.htmlをダブルクリックして開くと…
下図の表示から、碁石を打つことが出来ませんでした。。

正常に動作しないので、追加質問することに・・・
ChatGPTへの質問 その2
下記のコードで何か間違いはありますか?
// 先程ChatGPTから教えて貰ったコード
...
ChatGPTからの回答 その2
提示されたコードは、以前提示した五目並べアプリのコードと同一です。このコードには、特に間違いはありません。このHTMLファイルをウェブブラウザで開くことで、五目並べアプリが動作し、要件に従って機能します。
????
ChatGPTへの質問 その3
ブラウザで開くと、五目並べというテキストの下に正方形の黒い枠線のみが表示され、その下に黒の番ですというテキストが表示され、石を置くことが出来ません。
ChatGPTからの回答 その3
おっしゃる通り、提示されたコードには問題があるようです。申し訳ありません。以下のコードを試してみてください。この修正版では、アプリが正常に動作し、石を置くことができるはずです。
(・・・さっき聞いた時に教えてよ!w)
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>五目並べ</title>
<style>
body {
font-family: Arial, sans-serif;
text-align: center;
}
canvas {
border: 1px solid black;
display: inline-block;
}
#turn {
font-weight: bold;
}
</style></head><body>
<h1>五目並べ</h1>
<canvas id="board" width="380" height="380"></canvas>
<p id="turn">黒の番です</p>
<script>
const canvas = document.getElementById('board');
const ctx = canvas.getContext('2d');
const gridSize = 20;
const stoneRadius = 8;
const boardSize = 19;
let board = new Array(boardSize).fill(null).map(() => new Array(boardSize).fill(null));
let currentPlayer = 'black';
function drawGrid() {
ctx.strokeStyle = 'black';
for (let i = 0; i < boardSize; i++) {
ctx.beginPath();
ctx.moveTo(gridSize + i * gridSize, gridSize);
ctx.lineTo(gridSize + i * gridSize, canvas.height - gridSize);
ctx.stroke();
ctx.beginPath();
ctx.moveTo(gridSize, gridSize + i * gridSize);
ctx.lineTo(canvas.width - gridSize, gridSize + i * gridSize);
ctx.stroke();
}
}
function drawStone(x, y, color, opacity = 1) {
ctx.beginPath();
ctx.arc(x, y, stoneRadius, 0, 2 * Math.PI);
ctx.fillStyle = color;
ctx.globalAlpha = opacity;
ctx.fill();
ctx.globalAlpha = 1;
}
function getMousePosition(event) {
const rect = canvas.getBoundingClientRect();
const x = event.clientX - rect.left;
const y = event.clientY - rect.top;
return { x, y };
}
function positionToCoordinate(x, y) {
return {
row: Math.round((y - gridSize) / gridSize),
col: Math.round((x - gridSize) / gridSize),
}; }
function placeStone(row, col, color) {
board[row][col] = color;
drawStone(gridSize + col * gridSize, gridSize + row * gridSize, color);
}
function isValidMove(row, col) {
return row >= 0 && col >= 0 && row < boardSize && col < boardSize && !board[row][col];
}
canvas.addEventListener('mousemove', (event) => {
const { x, y } = getMousePosition(event);
const { row, col } = positionToCoordinate(x, y);
if (isValidMove(row, col)) {
ctx.clearRect(0, 0, canvas.width, canvas.height);
drawGrid();
board.forEach((row, rowIndex) =>
row.forEach((stone, colIndex) => {
if (stone) {
drawStone(gridSize + colIndex * gridSize, gridSize + rowIndex * gridSize, stone);
}
})
);
drawStone(gridSize + col * gridSize, gridSize + row * gridSize, currentPlayer, 0.5);
}
});
canvas.addEventListener('click', (event) => {
const { x, y } = getMousePosition(event);
const { row, col } = positionToCoordinate(x, y);
if (isValidMove(row, col)) {
placeStone(row, col, currentPlayer);
if (checkWin(row, col, currentPlayer)) {
alert(currentPlayer === 'black' ? '黒の勝ちです!' : '白の勝ちです!');
board = new Array(boardSize).fill(null).map(() => new Array(boardSize).fill(null));
} else {
currentPlayer = currentPlayer === 'black' ? 'white' : 'black';
document.getElementById('turn').textContent = currentPlayer === 'black' ? '黒の番です' : '白の番です';
}
}});
function checkWin(row, col, player) {
const directions = [
{ row: 1, col: 0 },
{ row: 0, col: 1 },
{ row: 1, col: 1 },
{ row: 1, col: -1 },
];
for (const direction of directions) {
let count = 1;
for (let i = 1; i < 5; i++) {
const newRow = row + direction.row * i;
const newCol = col + direction.col * i;
if (newRow >= 0 && newRow < boardSize && newCol >= 0 && newCol < boardSize && board[newRow][newCol] === player) {
count++;
} else {
break;
}
}
for (let i = 1; i < 5; i++) {
const newRow = row - direction.row * i;
const newCol = col - direction.col * i;
if (newRow >= 0 && newRow < boardSize && newCol >= 0 && newCol < boardSize && board[newRow][newCol] === player) {
count++;
} else {
break;
}
}
if (count >= 5) {
return true;
}
}
return false;
}
drawGrid();</script></body></html>
実際に作成 その3
先程作成していたindex.htmlの記載を↑の内容に更新・保存して、ダブルクリックでブラウザで開いた所・・・おおお!みごとに出来ている!!!
ちょっと盤の色を茶色にしたいなと思いましたので、追加で質問します。

ChatGPTへの質問 その4
どうもありがとうございます!かなり良くなりました。
盤面を木製の色に変更してくれますか?
ChatGPTからの回答 その4
もちろんです!盤面の背景色を木製の色に変更するには、次のコードを使用してください。drawGrid 関数の最初に、背景色を塗りつぶす処理を追加しています。
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>五目並べ</title>
<style>
body {
font-family: Arial, sans-serif;
text-align: center;
}
canvas {
border: 1px solid black;
display: inline-block;
}
#turn {
font-weight: bold;
}
</style></head>
<body>
<h1>五目並べ</h1>
<canvas id="board" width="380" height="380"></canvas>
<p id="turn">黒の番です</p>
<script>
const canvas = document.getElementById('board');
const ctx = canvas.getContext('2d');
const gridSize = 20;
const stoneRadius = 8;
const boardSize = 19;
let board = new Array(boardSize).fill(null).map(() => new Array(boardSize).fill(null));
let currentPlayer = 'black';
function drawGrid() {
ctx.fillStyle = '#dcb35c';
ctx.fillRect(0, 0, canvas.width, canvas.height);
ctx.strokeStyle = 'black';
for (let i = 0; i < boardSize; i++) {
ctx.beginPath();
ctx.moveTo(gridSize + i * gridSize, gridSize);
ctx.lineTo(gridSize + i * gridSize, canvas.height - gridSize);
ctx.stroke();
ctx.beginPath();
ctx.moveTo(gridSize, gridSize + i * gridSize);
ctx.lineTo(canvas.width - gridSize, gridSize + i * gridSize);
ctx.stroke();
}
}
// 以下のコードは以前のバージョンと同じです。
// ...
// (省略)
// ...
</script></body></html>
このコードでは、盤面の背景色が木製の色に変更されています。盤面の背景色を変更するだけでなく、他のスタイルや機能も簡単に追加できます。必要に応じてカスタマイズしてお楽しみください。
実際に作成 その4
ChatGPTさん、ありがとうございます・・・!!やってみます!
ふむふむ…コード貼るだけでなく、説明もあるから助かります。
この2行を追加するということですな!
function drawGrid(){
ctx.fillStyle = '#dcb35c';
ctx.fillRect(0, 0, canvas.width, canvas.height);
早速保存して、ダブルクリック・・・!

出来ました!!!
以上となります。
ここまで読んで頂きまして、どうもありがとうございました。