Google Apps Script(GAS)を活用して、HTML・CSS・JavaScriptで〇×ゲームを作成!
初心者でも手軽にGASを利用したWEBゲーム開発を簡単に始めることができるように、詳しいコードの解説を入れたサイトです。
初めに
GASを使ってHTML CSS JavaScriptでつくる〇×ゲームをご紹介します。
2人のプレイヤーが交互に”X”と”O”をマスに配置し、先に3つ並べたプレイヤーが勝者となります。
以下はゲームの特徴です。
- 直感的なプレイ: プレイヤーはクリックするだけでマスに”X”または”O”を配置できます。
- 美しいデザイン: シンプルで清潔なデザインが、ゲームプレイをより楽しくします。
- 結果表示: 勝者が決まると、または引き分けの場合には結果が表示されます。
HTML CSS JavaScriptのファイルを準備
HTMLファイル、CSSファイル、JavaScriptファイルをそれぞれindex.html、style.html、java.htmlとして保存してください。
HTML、CSS、JavaScriptのコードはそれぞれ別のファイルに分割保存して、メインのHTMLファイルにインポートします。
詳しくは下記のサイトをご覧ください。
GASの作成
GASでは下記の4つのファイルを作成します。
コード.gs
function doGet() {
return HtmlService.createTemplateFromFile('index').evaluate().addMetaTag('viewport', 'width=device-width, initial-scale=1');
}
function include(filename) {
return HtmlService.createHtmlOutputFromFile(filename)
.getContent();
}
doGet()関数
WEBアプリがリクエストを受け取ったときに呼び出され、レスポンスとしてHTMLコンテンツを返します。GASのWEBアプリは、doGet()
または doPost()
関数がエントリーポイントになります。
ユーザーがWEBアプリのURLにアクセスすると、この関数が実行され、テンプレートファイル(index.html
)がレンダリングされてブラウザに返されます。
include()関数
他のHTMLファイルを読み込み、その内容を返す汎用関数です。主に、index.html
内で別のHTMLファイルをインクルード(埋め込み)する際に使用されます。
HtmlService.createHtmlOutputFromFile(filename)
- 引数として渡された
filename
(例:'header'
)に対応するHTMLファイルを読み込みます。 - ファイル名には拡張子
.html
を含める必要はありません。
.getContent()
- 読み込んだHTMLの中身(文字列)を取得し、返します。
- この関数をテンプレート内で呼び出すことで、動的に別のHTMLファイルを埋め込むことができます。
全体の流れ
- リクエストが来た場合
ユーザーがWEBアプリのURLにアクセスすると、doGet()
が実行されます。 - HTMLテンプレートの評価と返送
doGet()
ではindex.html
をテンプレートとして処理し、その結果をブラウザに返します。- 必要に応じて
include()
関数を利用して、他のHTMLファイルを動的に挿入します。
- レスポンシブ対応
- ビューポートメタタグを追加することで、スマートフォンやタブレットでの表示が最適化されます。
index.html
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<?!= include('style'); ?>
<title>Tic Tac Toe</title>
</head>
<body>
<div id="board" class="board">
<div class="cell" onclick="handleClick(0)"></div>
<div class="cell" onclick="handleClick(1)"></div>
<div class="cell" onclick="handleClick(2)"></div>
<div class="cell" onclick="handleClick(3)"></div>
<div class="cell" onclick="handleClick(4)"></div>
<div class="cell" onclick="handleClick(5)"></div>
<div class="cell" onclick="handleClick(6)"></div>
<div class="cell" onclick="handleClick(7)"></div>
<div class="cell" onclick="handleClick(8)"></div>
</div>
<div id="result" class="result"></div>
<?!= include('java') ?>
</body>
</html>
<!DOCTYPE html>
: HTML5で書かれていることを示します。
<html lang="ja">
: ページの言語を日本語(ja
)として設定。
<meta charset="UTF-8">
: 文字コードをUTF-8に設定し、日本語を含むすべての文字を正しく表示。
<meta name="viewport" content="width=device-width, initial-scale=1.0">
: モバイルデバイスで適切に表示されるように設定。<title>
: ページのタイトルを「シンプルなTic Tac Toeゲーム」と設定。
<div id="board" class="board">
: ゲームボードを定義。
<div class="cell" onclick="handleClick(0)">
: 各マス(セル)を定義。クリック時にhandleClick
関数を呼び出す。
style.html
<style>
body {
display: flex;
align-items: center;
justify-content: center;
height: 100vh;
margin: 0;
background-color: #f0f0f0;
}
.board {
display: grid;
grid-template-columns: repeat(3, 100px);
grid-gap: 5px;
}
.cell {
width: 100px;
height: 100px;
background-color: #fff;
border: 2px solid #ccc;
display: flex;
align-items: center;
justify-content: center;
font-size: 24px;
font-weight: bold;
cursor: pointer;
}
.cell:hover {
background-color: #e0e0e0;
}
.result {
margin-top: 20px;
font-size: 36px; /* 大きな文字サイズ */
font-weight: bold;
color: #333;
text-align: center; /* 中央揃え */
position: absolute; /* 画面中央に配置 */
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
</style>
display: flex;
Flexboxを使用して、要素を中央揃えにします。
align-items
と justify-content
縦横中央に整列します。
background-color: #f0f0f0;
背景色を淡いグレーに設定。
display: grid;
グリッドレイアウトを使用して3×3のマスを配置。
grid-template-columns
3列(100px幅)を設定。
grid-gap
各セル間の間隔を5pxに設定。
セルのデザイン:
白背景、境界線、クリック時のポインター表示などを設定。
java.html
<script>
let currentPlayer = 'X';
let board = ['', '', '', '', '', '', '', '', ''];
let gameActive = true;
function handleClick(index) {
if (gameActive && board[index] === '') {
board[index] = currentPlayer;
document.getElementsByClassName('cell')[index].innerText = currentPlayer;
if (checkWinner()) {
document.getElementById('result').innerText = `${currentPlayer} wins!`;
gameActive = false;
document.body.style.backgroundColor = "rgba(0, 0, 0, 0.8)"; /* 背景を暗く */
document.getElementById('result').style.color = "#ff0000"; /* メッセージを赤に変更 */
} else if (board.every(cell => cell !== '')) {
document.getElementById('result').innerText = 'It\'s a draw!';
gameActive = false;
} else {
currentPlayer = currentPlayer === 'X' ? 'O' : 'X';
}
}
}
function checkWinner() {
const winningCombos = [
[0, 1, 2], [3, 4, 5], [6, 7, 8], // Rows
[0, 3, 6], [1, 4, 7], [2, 5, 8], // Columns
[0, 4, 8], [2, 4, 6] // Diagonals
];
return winningCombos.some(combo =>
combo.every(index => board[index] === currentPlayer)
);
}
</script>
currentPlayer
: 現在のプレイヤーを管理する変数(最初はX
)。
board
: 各マスの状態を記録する配列(空文字''
は未使用のマス)。
gameActive
: ゲームが終了したかどうかを示すフラグ。
handleClick(index)
クリックされたセル(index
)の処理を行う。
セルが未使用の場合、現在のプレイヤーを設定。勝敗判定をcheckWinner()
で確認。全マスが埋まった場合は引き分けメッセージを表示。
checkWinner()
勝利条件を定義した配列winningCombos
をチェック。
いずれかの組み合わせ(行、列、斜め)が全て同じプレイヤーである場合に勝利と判定。
デプロイ
最後にデプロイして動作を確認してみましょう。
プレイヤーがマスをクリックすると、handleClick
関数が呼び出されます。
セルが空であれば、現在のプレイヤーがそのセルを埋めます。
勝利条件や引き分けをチェックし、結果を表示します。
ターンが交代して次のプレイヤーが動きます。
勝者または引き分けが確定した場合、ゲームが終了します。
遊び方
- プレイヤー1は”X”で、プレイヤー2は”O”です。
- 交互に空いているマスをクリックして”X”または”O”を配置します。
- 先に横、縦、または斜めに3つ並べたプレイヤーが勝者となります。
- ゲームが引き分けになるか、どちらかが勝つと結果が表示されます。
クリックすることでこのようになればうまく動作しています。