まずは index.html を開き、先攻後攻ボタンを追加します。
<!DOCTYPE html>
<html>
<head>
︙
</head>
<body>
<div class="buttons">
<h1>〇×ゲーム</h1>
<button id="atk_first" class="attack">先攻</button><button id="atk_after" class="attack">後攻</button><br>
<button id="start">スタート</button>
</div>
<div id="game" style="display: none;">
︙
</div>
<script src="./js/index.js"></script>
</body>
</html>
javascriptで操作をするために、2つとものボタンに attack クラスを付与しています。また、各ボタンには違う名前のidを付与します。
続いて style.css を開き、先攻後攻ボタンを押した際に、ボタンが押し続けられた状態になるスタイル(色をグレーにし、文字色を反転)を追加します。
.pushed {
background-color: gray;
color: white;
}
配置を真ん中に、周囲の余白を20px確保するように設定します。
index.js に処理を追加します。
先攻後攻ボタンについて、押したボタンにより先攻後攻を判断し man_attack 変数に結果を格納します。
押したボタンに pushed クラスを付与し、押下した状態を保持し続けるようにします。
$(function() {
// 定数定義
const FIRST = 0
const LAST = 1
︙
let man_attack = FIRST // 自分が先攻か後攻か
︙
/**
* 「スタート」ボタン押下
*/
$("#start").click(function() {
$("#game").css("display", "block")
})
︙
/**
* 「先攻後攻」ボタン押下
*/
$(".attack").click(function() {
let id_name = $(this).attr("id")
// 「先攻」ボタン押下時
if (id_name == 'atk_first') { man_attack = FIRST }
// 「後攻」ボタン押下時
else { man_attack = LAST }
$(this).addClass("pushed")
})
})
このページでは、空いているマス目からランダムに選択し、入力する処理を作成します。index.js に処理を追記します。
$(function() {
// 定数定義
let last_cells_count = 9
let finished_com = true // COMによる自動入力が完了したかどうか
︙
$("td").click(function() {
// 入力済みのセルをタップした場合
if ($(this).html()) {
alert("入力できません")
// 勝敗がついたあとに空のセルをタップした場合
} else if (got_match) {
alert("リセットボタンを押してください")
} else {
︙
// 決着がついていない場合、COMの操作を継続
if (! got_match) {
input_by_com()
}
}
})
︙
/**
* COMによる自動入力
*/
function input_by_com() {
finished_com = false // 自動入力開始
setTimeout(function() {
let com_result_symbol = do_input_by_com()
now_attack = !now_attack // 先攻後攻入れ替え
last_cells_count--
// 勝敗判定
if (check_complete()) {
got_match = !got_match
alert(com_result_symbol + "の勝ち!")
}
// 引き分け判定
if (! last_cells_count) {
alert("引き分け!")
return
}
finished_com = true // 自動入力完了
}, 500)
}
/**
* COMによる自動入力実行
*/
function do_input_by_com() {
// 現在の入力情報を取得
let results = $("td").get()
// COMのマーク
let com_result_symbol = now_attack ? BATSU : MARU
let empty_cells = [] // 未入力セル情報
// ゲーム盤情報確認
for (let cnt = 0; cnt < results.length; cnt++) {
// 未入力の場合
if (! $(results[cnt]).html()) {
empty_cells.push(results[cnt])
}
}
// 未入力セルがある場合
if (empty_cells.length) {
logic(empty_cells, com_result_symbol)
}
return com_result_symbol
}
/**
* ロジック
*/
function logic(empty_cells, com_result_symbol) {
let target
// ランダムに1つ取得
target = empty_cells[Math.floor(Math.random() * empty_cells.length)]
// 結果を入れる
$(target).html(com_result_symbol)
}
})
index.html ファイルを再度読み直してください。コンピュータ対戦ができていれば問題ありません。
1. 先攻 or 後攻を押下後にもう一方を選択すると、下図のように2つとも選択される表示となります。
先攻と後攻の両方が選択されることは望ましくなく、どちらか一方のみの選択状態としたいです。
このような場合に、もう一方の選択状態を解除するようにしてください。
【ヒント】pushed クラスをjQueryで付与する前後で、片方のボタンに付与されている pushed クラスを削除する。
2.先攻・後攻を選択していなくても「スタート」を押せばゲームが始まってしまいます。ボタンを押していない場合、下図のように「先攻・後攻を選択してください。」というアラートを出し、ゲームを開始させないでください。
【ヒント】「スタート」ボタン押下時に、.attack クラスが付与されたボタンに .pushed クラスがついている要素があるかどうかを判定する。
3.COMが入力完了するまで、プレイヤーが入力できないように制御してください。現在、プレイヤーが入力完了してから0.5秒後に入力をするように制御していますが、0.5秒たたないうちにプレイヤーが入力可能な状態であり、競合する可能性があります。
【ヒント】冒頭にある、マス目をクリックした際の入力可否、画面リロードorリセットを促すアラートを出す箇所にて、COMが入力中である場合はアラートを出すように制御してください。
4. 「リセット」ボタンを押下した際に、先攻後攻の選択状態が解除されるように、実装を修正してください。
5.「後攻」を選択した場合、COMが先に入力するように制御してください。
【ヒント】「スタート」ボタン押下時に、先攻後攻フラグを確認し、後攻である場合にCOMによる自動入力を開始する。