オセロ by ChatGPT

ChatGPTで生成したバグってるソースを手直した。変数の宣言がなかったり関数ごと欠損しているソースをデバッグするところからスタートして何となく動くようになったので投稿。初めテトリスを作ろうとしたけど、まともに動かない状態から抜け出せずに挫折… オセロは、テトリスの半分以下で300行程度。

黒の手番です

備忘:CSSに一番苦戦した。borderとborder-radiusが同時に指定できない。border-radiusでコマを描くとborderで描いた枠線が欠落してしまう。最終的にはコマの白黒画像を用意してbackground-imageで読み込むように修正した。


ご参考:
プロンプト:オセロゲームのサンプルをHTML/CSS/JavaScriptで作成してください。
ChatGPT:はい、以下にHTML、CSS、JavaScriptで書かれたオセロゲームのサンプルを用意しました。
・・・

<!DOCTYPE html>
<html>

<head>
	<meta charset="UTF-8">
	<title>オセロゲーム</title>
	<style>
		.container {
			display: flex;
			flex-wrap: wrap;
			width: 320px;
			height: 320px;
			margin: 0 auto;
		}

		.cell {
			width: 40px;
			height: 40px;
			background-color: green;
			border: 1px solid black;
			box-sizing: border-box;
			cursor: pointer;
		}

		.cell.black {
			background-color: black;
		}

		.cell.white {
			background-color: white;
		}

		.turn {
			margin-top: 10px;
			text-align: center;
			font-size: 20px;
		}

		.win {
			margin-top: 10px;
			text-align: center;
			font-size: 30px;
			font-weight: bold;
		}
	</style>
</head>

<body>
	<div class="container"></div>
	<div class="turn">黒の手番です</div>
	<div class="win"></div>
	<script>

		const WHITE = 1;
		const BLACK = -1;
		const EMPTY = 0;

		// ゲームボードのサイズ
		const BOARD_SIZE = 8;

		// ゲームボードの初期化
		let board = [];
		for (let i = 0; i < BOARD_SIZE; i++) {
			board[i] = [];
			for (let j = 0; j < BOARD_SIZE; j++) {
				board[i][j] = 0;
			}
		}
		board[3][3] = board[4][4] = 1;
		board[3][4] = board[4][3] = -1;

		// 現在のプレイヤー(1:黒, -1:白)
		let currentPlayer = 1;

		// 盤面を描画する関数
		function drawBoard() {
			const container = document.querySelector('.container');
			container.innerHTML = '';
			for (let i = 0; i < BOARD_SIZE; i++) {
				for (let j = 0; j < BOARD_SIZE; j++) {
					const cell = document.createElement('div');
					cell.className = 'cell';
					if (board[i][j] === 1) {
						cell.classList.add('black');
					} else if (board[i][j] === -1) {
						cell.classList.add('white');
					}
					cell.dataset.row = i;
					cell.dataset.col = j;
					cell.addEventListener('click', handleClick);
					container.appendChild(cell);
				}
			}
		}

		drawBoard();

		// クリックイベントのハンドラー関数
		function handleClick(event) {
			const row = parseInt(event.target.dataset.row);
			const col = parseInt(event.target.dataset.col);
			if (board[row][col] !== 0) {
				return;
			}
			const directions = [
				{ x: 0, y: -1 }, // 上
				{
					x: 0, y

1 }, // 下
				{ x: -1, y: 0 }, // 左
				{ x: 1, y: 0 }, // 右
				{ x: -1, y: -1 }, // 左上
				{ x: 1, y: -1 }, // 右上
				{ x: -1, y: 1 }, // 左下
				{ x: 1, y: 1 } // 右下
			];
			let canPlace = false;
			for (let d = 0; d < directions.length; d++) {
				const dx = directions[d].x;
				const dy = directions[d].y;
				let x = row + dx;
				let y = col + dy;
				let flipCount = 0;
				while (x >= 0 && x < BOARD_SIZE && y >= 0 && y < BOARD_SIZE) {
					if (board[x][y] === -currentPlayer) {
						flipCount++;
						x += dx;
						y += dy;
					} else if (board[x][y] === currentPlayer) {
						if (flipCount > 0) {
							canPlace = true;
						}
						break;
					} else {
						break;
					}
				}
				if (canPlace) {
					break;
				}
			}
			if (!canPlace) {
				return;
			}
			board[row][col] = currentPlayer;
			event.target.classList.add(currentPlayer === 1 ? 'black' : 'white');
			event.target.removeEventListener('click', handleClick);
			flipStones(row, col);
			currentPlayer = -currentPlayer;
			const turnEl = document.querySelector('.turn');
			turnEl.textContent = ${ currentPlayer === 1 ? '黒' : '白' } の手番です;
			if (!hasPlaceableCell()) {
				currentPlayer = -currentPlayer;
				if (!hasPlaceableCell()) {
					const winEl = document.querySelector('.win');
					const blackCount = countStones(1);
					const whiteCount = countStones(-1);
					if (blackCount > whiteCount) {
						winEl.textContent = '黒の勝ち!';
					} else if (blackCount < whiteCount) {
						winEl.textContent = '白の勝ち!';
					} else {
						winEl.textContent = '引き分け!';
					}
				} else {
					turnEl.textContent = ${ currentPlayer === 1 ? '黒' : '白' } はパスです;
				}
			}
		}

		// 石を返す関数
		function flipStones(row, col) {
			const directions = [
				{ x: 0, y: -1 }, // 上
				{ x: 0, y: 1 }, // 下
				{ x: -1, y: 0 }, // 左
				{ x: 1, y: 0 }, // 右
				{ x: -1, y: -1 }, // 左上
				{ x: 1, y: -1 }, // 右上
				{ x: -1, y: 1 }, // 左下
				{ x: 1, y: 1 } // 右下
			];
			for (let d = 0; d < directions.length; d++) {
				const dx = directions[d].x;

				const dy = directions[d].y;
				let x = row + dx;
				let y = col + dy;
				let flipCount = 0;
				while (x >= 0 && x < BOARD_SIZE && y >= 0 && y < BOARD_SIZE) {
					if (board[x][y] === -currentPlayer) {
						flipCount++;
						x += dx;
						y += dy;
					} else if (board[x][y] === currentPlayer) {
						if (flipCount > 0) {
							for (let i = 1; i <= flipCount; i++) {
								const flipX = row + i * dx;
								const flipY = col + i * dy;
								board[flipX][flipY] = currentPlayer;
								const flipEl = document.querySelector(`[data-row="${flipX}"][data-col="${flipY}"]`);
								flipEl.classList.remove(currentPlayer === 1 ? 'white' : 'black');
								flipEl.classList.add(currentPlayer === 1 ? 'black' : 'white');
							}
						}
						break;
					} else {
						break;
					}
				}
			}
		}

		// 置けるセルがあるかどうかを判定する関数
		function hasPlaceableCell() {
			for (let i = 0; i < BOARD_SIZE; i++) {
				for (let j = 0; j < BOARD_SIZE; j++) {
					if (board[i][j] === 0 && canPlaceStone(i, j)) {
						return true;
					}
				}
			}
			return false;
		}

		// 石の数を数える関数
		function countStones(player) {
			let count = 0;
			for (let i = 0; i < BOARD_SIZE; i++) {
				for (let j = 0; j < BOARD_SIZE; j++) {
					if (board[i][j] === player) {
						count++;
					}
				}
			}
			return count;
		}

		// ゲームをリセットする関数
		function resetGame() {
			board = initializeBoard();
			currentPlayer = 1;
			const cells = document.querySelectorAll('.cell');
			for (let i = 0; i < cells.length; i++) {
				cells[i].classList.remove('black', 'white');
				cells[i].addEventListener('click', handleClick);
			}
			const turnEl = document.querySelector('.turn');
			turnEl.textContent = '黒の手番です';
			const winEl = document.querySelector('.win');
			winEl.textContent = '';
		}

		function canPlaceStone(row, col, color) {
			if (board[row][col] !== EMPTY) {
				return false;
			}
			for (let drow = -1; drow <= 1; drow++) {
				for (let dcol = -1; dcol <= 1; dcol++) {
					if (drow === 0 && dcol === 0) {
						continue;
					}
					let r = row + drow;
					let c = col + dcol;
					let flipped = false;
					while (r >= 0 && r < BOARD_SIZE && c >= 0 && c < BOARD_SIZE) {
						if (board[r][c] === EMPTY) {
							break;
						}
						if (board[r][c] === color) {
							if (flipped) {
								return true;
							} else {
								break;
							}
						}
						flipped = true;
						r += drow;
						c += dcol;
					}
				}
			}
			return false;
		}

		function initializeBoard() {
			for (let row = 0; row < BOARD_SIZE; row++) {
				for (let col = 0; col < BOARD_SIZE; col++) {
					const cell = document.querySelector(`.cell[data-row="${row}"][data-col="${col}"]`);
					cell.classList.remove('black', 'white');
					if ((row === 3 && col === 3) || (row === 4 && col === 4)) {
						cell.classList.add('white');
						board[row][col] = WHITE;
					} else if ((row === 3 && col === 4) || (row === 4 && col === 3)) {
						cell.classList.add('black');
						board[row][col] = BLACK;
					} else {
						board[row][col] = EMPTY;
					}
				}
			}
		}

		// 初期化
		let board = initializeBoard();
		let currentPlayer = 1;
		const cells = document.querySelectorAll('.cell');
		for (let i = 0; i < cells.length; i++) {
			cells[i].addEventListener('click', handleClick);
		}
		const resetBtn = document.querySelector('.reset');
		resetBtn.addEventListener('click', resetGame);
		const turnEl = document.querySelector('.turn');
		turnEl.textContent = '黒の手番です';
}) ();

	</script>
</body>

</html>

※インデントなど整形済み


Comments

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です