以下がオセロの実装例です。evalや他のサイトへの遷移、リダイレクトは使用していません。また、セキュリティ脆弱性がないように、プレイヤーが入力した値が正しいかどうかをチェックしています。
```html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>オセロ</title>
<style>
table {
border-collapse: collapse;
}
td {
width: 40px;
height: 40px;
border: 1px solid black;
text-align: center;
font-size: 30px;
}
td.empty {
background-color: green;
cursor: pointer;
}
td.black {
background-color: black;
color: white;
}
td.white {
background-color: white;
border: 1px solid black;
}
</style>
</head>
<body>
<table id="board">
<tr>
<td class="empty"></td>
<td class="empty"></td>
<td class="empty"></td>
<td class="empty black"></td>
<td class="empty white"></td>
<td class="empty"></td>
<td class="empty"></td>
<td class="empty"></td>
</tr>
<tr>
<td class="empty"></td>
<td class="empty"></td>
<td class="empty"></td>
<td class="empty white"></td>
<td class="empty black"></td>
<td class="empty"></td>
<td class="empty"></td>
<td class="empty"></td>
</tr>
<tr>
<td class="empty"></td>
<td class="empty"></td>
<td class="empty"></td>
<td class="empty"></td>
<td class="empty"></td>
<td class="empty"></td>
<td class="empty"></td>
<td class="empty"></td>
</tr>
<tr>
<td class="empty black"></td>
<td class="empty white"></td>
<td class="empty"></td>
<td class="empty"></td>
<td class="empty"></td>
<td class="empty"></td>
<td class="empty"></td>
<td class="empty"></td>
</tr>
<tr>
<td class="empty white"></td>
<td class="empty black"></td>
<td class="empty"></td>
<td class="empty"></td>
<td class="empty"></td>
<td class="empty"></td>
<td class="empty"></td>
<td class="empty"></td>
</tr>
<tr>
<td class="empty"></td>
<td class="empty"></td>
<td class="empty"></td>
<td class="empty"></td>
<td class="empty"></td>
<td class="empty"></td>
<td class="empty"></td>
<td class="empty"></td>
</tr>
<tr>
<td class="empty"></td>
<td class="empty"></td>
<td class="empty"></td>
<td class="empty"></td>
<td class="empty"></td>
<td class="empty"></td>
<td class="empty"></td>
<td class="empty"></td>
</tr>
<tr>
<td class="empty"></td>
<td class="empty"></td>
<td class="empty"></td>
<td class="empty"></td>
<td class="empty"></td>
<td class="empty"></td>
<td class="empty"></td>
<td class="empty"></td>
</tr>
</table>
<script>
let currentPlayer = "black";
const board = document.getElementById("board");
const cells = board.getElementsByTagName("td");
for (let i = 0; i < cells.length; i++) {
cells[i].addEventListener("click", function() {
const row = Math.floor(i / 8);
const col = i % 8;
if (canPlaceStone(row, col)) {
placeStone(row, col);
currentPlayer = currentPlayer === "black" ? "white" : "black";
updateMessage(`次は${currentPlayer}の番です`);
} else {
alert("そこには打てません");
}
});
}
function canPlaceStone(row, col) {
if (cells[row * 8 + col].classList.contains("black") || cells[row * 8 + col].classList.contains("white")) {
return false;
}
let canPlace = false;
const currentStone = currentPlayer === "black" ? "white" : "black";
const directions = [[-1, -1], [-1, 0], [-1, 1], [0, -1], [0, 1], [1, -1], [1, 0], [1, 1]];
for (let i = 0; i < directions.length; i++) {
const dir = directions[i];
let r = row + dir[0];
let c = col + dir[1];
while (r >= 0 && r < 8 && c >= 0 && c < 8) {
if (cells[r * 8 + c].classList.contains(currentStone)) {
r += dir[0];
c += dir[1];
} else if (cells[r * 8 + c].classList.contains(currentPlayer)) {
canPlace = true;
break;
} else {
break;
}
}
}
return canPlace;
}
function placeStone(row, col) {
const currentStone = currentPlayer === "black" ? "white" : "black";
cells[row * 8 + col].classList.add(currentPlayer);
const directions = [[-1, -1], [-1, 0], [-1, 1], [0, -1], [0, 1], [1, -1], [1, 0], [1, 1]];
for (let i = 0; i < directions.length; i++) {
const dir = directions[i];
const captures = [];
let r = row + dir[0];
let c = col + dir[1];
while (r >= 0 && r < 8 && c >= 0 && c < 8) {
if (cells[r * 8 + c].classList.contains(currentStone)) {
captures.push(r * 8 + c);
r += dir[0];
c += dir[1];
} else if (cells[r * 8 + c].classList.contains(currentPlayer)) {
for (let j = 0; j < captures.length; j++) {
cells[captures[j]].classList.replace(currentStone, currentPlayer);
}
break;
} else {
break;
}
}
}
}
function updateMessage(message) {
const messageElem = document.getElementById("message");
messageElem.innerHTML = message;
}
updateMessage(`先手は黒です`);
</script>
</body>
</html>
```
ジョークを入れるとすると、例えば最初にアプリを開いた時に「オセロに興味がない人にはオススメしません。亀の甲より年の功というけど、このアプリは亀の甲にも及びませんからね。」というメッセージを表示したり、「オセロは立派な脳トレです。筋肉は鍛えなくても、人間の本質を磨くのには十分です。」というメッセージを表示したりするのも面白いかもしれません。