以下が具体的な実装例です。セキュリティ脆弱性の問題がないように実装しています。
```html
<!DOCTYPE html>
<html>
<head>
<title>九蓮宝燈麻雀ゲーム</title>
<style>
#gameArea {
width: 500px;
margin: 0 auto;
padding: 20px;
}
.tile {
width: 50px;
height: 70px;
background-color: #ffffff;
border: 1px solid #000000;
float: left;
margin-right: 10px;
margin-top: 10px;
}
.clear {
clear: both;
}
</style>
</head>
<body>
<div id="gameArea">
<h1>九蓮宝燈麻雀</h1>
<div>
<button id="startGameButton">ゲーム開始</button>
</div>
<div id="tilesArea">
</div>
<div class="clear"></div>
<div>
<button id="drawButton">牌を一枚引く</button>
<button id="discardButton">捨てる</button>
<button id="winButton">上がり</button>
</div>
<p id="result"></p>
</div>
<script>
// 麻雀牌のデータ
const tiles = ["m1", "m2", "m3", "m4", "m5", "m6", "m7", "m8", "m9",
"p1", "p2", "p3", "p4", "p5", "p6", "p7", "p8", "p9",
"s1", "s2", "s3", "s4", "s5", "s6", "s7", "s8", "s9",
"ton", "nan", "sha", "pei", "haku", "hatsu", "chun"];
let hand = []; // プレイヤーの手牌
let drawTile = ""; // 引いた牌
// プレイヤーの初期手牌を設定する関数
function initHand() {
hand = [];
for (let i = 0; i < 13; i++) {
const tileIndex = Math.floor(Math.random() * tiles.length); // ランダムに牌を選ぶ
const tile = tiles.splice(tileIndex, 1)[0]; // 選ばれた牌を配列から削除して取り出す
hand.push(tile);
createTileHtml(tile);
}
}
// 牌をHTML要素として描画する関数
function createTileHtml(tile) {
const tileDiv = document.createElement("div");
tileDiv.classList.add("tile");
tileDiv.textContent = tile;
tileDiv.addEventListener("click", () => {
// クリックされた牌を選択状態にする
tileDiv.classList.toggle("selected");
});
document.getElementById("tilesArea").appendChild(tileDiv);
}
// 引いた牌をHTML要素として描画する関数
function drawTileHtml() {
const tileDiv = document.createElement("div");
tileDiv.classList.add("tile");
tileDiv.textContent = drawTile;
document.getElementById("tilesArea").appendChild(tileDiv);
}
// 選択された牌を手牌から削除する関数
function discardSelectedTiles() {
const selectedTiles = document.querySelectorAll(".selected");
for (let i = 0; i < selectedTiles.length; i++) {
const selectedTile = selectedTiles[i];
const index = hand.indexOf(selectedTile.textContent);
hand.splice(index, 1);
selectedTile.remove();
}
}
// 上がり判定を行う関数
function checkWin() {
if (hand.length != 14) {
document.getElementById("result").textContent = "手牌が14枚ではありません!";
return;
}
const suitCount = {"m": 0, "p": 0, "s": 0, "z": 0};
for (let i = 0; i < hand.length; i++) {
const tile = hand[i];
const suit = tile.charAt(0);
suitCount[suit]++;
}
if (suitCount["z"] > 0) {
document.getElementById("result").textContent = "字牌が含まれています!";
return;
}
for (let suit in suitCount) {
if (suitCount[suit] == 0) {
document.getElementById("result").textContent = "各種類の牌が一枚以上ありません!";
return;
}
}
const tilesCopy = [...hand];
tilesCopy.sort();
const EXPECTED_HAND = ["m1", "m2", "m3", "m4", "m5", "m6", "m7", "m8", "m9",
"p1", "p2", "p3", "p4", "p5", "p6", "p7", "p8", "p9",
"s1", "s2", "s3", "s4", "s5", "s6", "s7", "s8", "s9",
"ton", "nan", "sha", "pei", "haku", "hatsu", "chun"];
if (JSON.stringify(tilesCopy) != JSON.stringify(EXPECTED_HAND)) {
document.getElementById("result").textContent = "九蓮宝燈ではありません!";
return;
}
document.getElementById("result").textContent = "あがり!";
document.getElementById("tilesArea").innerHTML = "";
document.getElementById("drawButton").disabled = true;
document.getElementById("discardButton").disabled = true;
document.getElementById("winButton").disabled = true;
}
// ゲーム開始ボタンがクリックされたときの処理
document.getElementById("startGameButton").addEventListener("click", () => {
initHand();
document.getElementById("startGameButton").disabled = true;
document.getElementById("drawButton").disabled = false;
});
// 牌を一枚引くボタンがクリックされたときの処理
document.getElementById("drawButton").addEventListener("click", () => {
const tileIndex = Math.floor(Math.random() * tiles.length); // ランダムに牌を選ぶ
drawTile = tiles.splice(tileIndex, 1)[0]; // 選ばれた牌を配列から削除して取り出す
drawTileHtml();
document.getElementById("discardButton").disabled = false;
document.getElementById("winButton").disabled = false;
});
// 捨てるボタンがクリックされたときの処理
document.getElementById("discardButton").addEventListener("click", () => {
discardSelectedTiles();
document.getElementById("discardButton").disabled = true;
document.getElementById("winButton").disabled = true;
});
// 上がりボタンがクリックされたときの処理
document.getElementById("winButton").addEventListener("click", () => {
checkWin();
});
</script>
</body>
</html>
```
ジョークとして、ゲーム画面に「いい手ですね!」というボタンを設置して、クリックすると「まあまあです」というアラートを表示するようにすると良いでしょう。