今回のインターンシップの選考課題では、Webブラウザ上で動作する「しりとりアプリ」を実装して提出していただきます。
使用言語やフレームワークに制限はありませんので、得意な環境で取り組んでください。
また、AIの活用について制限はありません、積極的に活用してください。 ただし、後述の通り、使用した場合は「どの部分にどのように活用したか」を README に記入してください。
Webブラウザ上で動作する「しりとりアプリ」を実装して提出してください。詳細を以下に示します。
ソースコードとREADMEを掲載したGitHubリポジトリのリンクを以下のGoogleフォームから提出してください。
このとき、必ずどこかにデプロイし、動作が確認できるURLを用意してください。
README.mdは以下の仕様を満たすよう作成してください。 これ以外の内容が含まれていても問題ありません。
課題提出用Googleフォーム
https://forms.gle/v2rkvJUsamCrWWvS7
まず、以下の仕様を満たすように実装してください。
追加で、便利・面白いと思う任意の機能を考えて、最低2つ以上実装してください。以下に例を示します。
使用する言語やフレームワークの指定は、特にありません。得意なものや、気になっているものを使用して実装してください。
特に環境に拘りの無い方は、以下にDenoを使用して途中まで実装した例を示しますので、Denoを使用して実装してみてください。
GitHubアカウント作成後、数日経過しなければ使用できない機能もあるため、早めに登録することをおすすめします。
作成したWebアプリケーションの提出等に必要なため、GitHubアカウントを作成しましょう。
以下のWebサイトからアカウント登録を行ってください。
既にアカウントをお持ちの方は、そちらのアカウントを使用していただいて構いません
Microsoftが提供しているソースコードエディタです。VSCodeとも呼ばれます。
開発に必要な機能の多くを搭載しており、プラグインの開発も企業・個人問わず行われているので、特に拘りが無ければインストールをおすすめします。
既にお気に入りのエディタがある場合は、インストールせずに進めていただいても構いません。
公式サイトの説明に従い、Visual Studio Codeをインストールしてみましょう。
https://code.visualstudio.com/
ご自身のOSに合わせたものをダウンロードして、インストールしましょう。
VSCode上で、Ctrl(Macの場合はCmd)とJを押すことで、下部のパネルを表示を切り替えることができます。
パネル内にある「ターミナル」からコマンドを実行することができるため、コマンドの実行はこちらを使用してください。
WindowsのPowerShellやMacのターミナルを使用しても構いません。
Denoは、JavaScript/TypeScriptの実行環境(ランタイム)です。これらの言語でサーバーの処理を実装できます。
ここでは、入門者向けとしてJavaScriptを使用します。TypeScriptの使用方法が分かる方は、そちらを使用していただいても問題ありません。
Webフロントエンドで多く用いられるJavaScriptを使用するため、フロントエンドとバックエンドを同一言語で実装できます。
DenoはNode.jsの作者であるライアン・ダール氏によって実装されたランタイムで、Node.jsをブラッシュアップしたものとなっています。
Denoという名前は、Nodeのアナグラムだそうですよ!
公式サイトの説明に従い、Denoをインストールしてみましょう。
https://docs.deno.com/runtime/getting_started/installation/
Download and install の項目に記載されたコマンドをご自身のOSに合わせて実行するだけで、インストールが可能です。
インストールが完了したら、以下のコマンドを実行してみましょう。バージョン情報が表示されればOKです!
バージョン情報は資料作成時のものです。
これと同じか、より新しいバージョンになっていることを確認してください。
# 入力
deno --version
# 出力
deno 2.8.0 (stable, release, aarch64-apple-darwin)
v8 14.9.207.2-rusty
typescript 6.0.3
Hello Worldを出力するプログラムを作って実行してみましょう。
空のフォルダを作り、中に server.js を作成して、以下のプログラムを書き込んでください。
console.log("Hello World!");
保存が完了したら、Denoで実行してみましょう!
deno run server.js
# Hello World!
VS CodeにDenoの拡張機能をインストールしましょう。画面左側の「Extensions」アイコンから拡張機能の画面を開き、「Deno」で検索して、インストールしてください。
server.jsを作成したフォルダで、Denoの拡張機能の設定を行いましょう。「Control+Shift+P」でコマンドパレットを開き、「Deno: Initialize Workspace Configuration」を実行します。.vscode/settings.jsonが作成され、Deno関連の補完が効くようになったらOKです。
追加で、保存時にコードのフォーマットを行うように設定しましょう。
Denoでは、deno fmt コマンドでコードのフォーマットを行うことができますが、VSCode上でファイルを変更し、保存した際に自動で実行されるようにします。
先ほど作成された、.vscode/settings.jsonに以下の内容を追記します。
{
- "deno.enable": true
+ "deno.enable": true,
+ "deno.lint": true,
+ "editor.formatOnSave": true,
+ "editor.defaultFormatter": "denoland.vscode-deno",
+ "[html]": {
+ "editor.defaultFormatter": "vscode.html-language-features",
+ "editor.tabSize": 2,
+ }
}
各設定項目について、簡単に説明しておくと以下のようになります。
"deno.enable": true
"deno.lint": true
"editor.formatOnSave": true
"editor.defaultFormatter": "denoland.vscode-deno"
"[html]"セクションの設定
"editor.defaultFormatter": "vscode.html-language-features"
"editor.tabSize": 2
DenoでHTTPサーバーを立ち上げてみましょう。
HTTPサーバーとは、HTTP (HyperText Transfer Protocol) に則って通信するサーバーです。
HTTPサーバー上に処理やデザイン等を記述することで、様々なWebアプリを動作させられます。
Denoが提供しているserve関数を利用することで、簡単にHTTPサーバーを立ち上げることができます。
以下に実装と作動の手順を示します。
server.jsの内容を以下のように書き換えて保存してください。// server.js
// localhostにDenoのHTTPサーバーを展開
Deno.serve((_req) => new Response("Hello Deno!"));
--allow-netオプションをつけてserver.jsを起動してください。このオプションがない場合、Denoがネットワークにアクセスできません。deno run --allow-net server.js
ブラウザでhttp://localhost:8000にアクセスしてみましょう。
ブラウザにHello Deno!と表示されればOKです!
HTTPサーバー上にアクセス数をカウントする変数を追加して、アクセス数を確認してみましょう。
server.jsファイルを以下の内容に書き換えます。// server.js
// アクセス数を保持する変数をグローバル領域に定義
let count = 0;
// localhostにDenoのHTTPサーバーを展開
Deno.serve((_req) => {
count++;
return new Response(`Hello World! ${count}`);
});
--allow-netに加えて、--watchオプションを追加してserver.jsを起動してください。このオプションを指定すると、Denoがファイルの変更を自動でサーバーに反映してくれます。deno run --allow-net --watch server.js
ブラウザでhttp://localhost:8000にアクセスしてみましょう。
何回かアクセスして、ブラウザにアクセス回数が表示されればOKです!尚、ブラウザが自動で/favicon.icoを取得しようとするため、カウントが2つずつカウントアップすることがあります。
ブラウザにHTMLを表示させてみましょう。レスポンスをHTML形式に変更し、ヘッダ情報にContent-Typeを指定します。
Content-Typeにtext/htmlを指定して、ブラウザにHTML形式のデータを返すことを通知します。Content-Typeには様々なものがあり、例として以下のようなものが挙げられます。
| Content-Type | データ |
|---|---|
| text/html | HTML |
| text/css | CSS |
| text/javascript | JavaScript |
| application/json | JSON形式 |
| image/jpeg | 画像(JPEG)ファイル |
| image/png | 画像(PNG)ファイル |
server.jsファイルを以下の内容で置き換えます。// server.js
// localhostにDenoのHTTPサーバーを展開
Deno.serve((_req) => {
return new Response(
// Responseの第一引数にレスポンスのbodyを設置
"<h1>H1見出しです</h1>",
// Responseの第二引数にヘッダ情報等の付加情報を設置
{
// レスポンスにヘッダ情報を付加
headers: {
// text/html形式のデータで、文字コードはUTF-8であること
"Content-Type": "text/html; charset=utf-8"
}
}
);
});
H1見出しですと大きく表示されればOKです!
前のステップではHTMLを文字列として直接記述しましたが、別のファイルとして保存しておいたHTMLを読み込むようにしてみます
また、ファイルの読み込みが完了するまではレスポンスを返さないように、処理にasync-awaitを追加します。JavaScriptでは非同期処理が採用されているため、async-awaitを記載しなければファイルがうまく表示できない場合があります。
非同期処理について、詳しく解説はしません。気になる方はMDNなどを参考にしてください。 https://developer.mozilla.org/ja/docs/Learn_web_development/Extensions/Async_JS
publicフォルダを作成し、中にindex.htmlを作成します。フォルダ構成は以下のようになります。├─ .vscode/
│ └─ settings.json
├─ public/
│ └─ index.html
└─ server.js
index.htmlファイルに以下の内容を記述します。<!DOCTYPE html>
<html lang="ja">
<head>
<!-- headタグの中にはメタデータ等を記載する -->
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<!-- bodyタグの中には実際に表示するものなどを書く -->
<h1>H1見出しですよ</h1>
</body>
</html>
server.jsファイルを以下の内容で置き換えます。// server.js
// localhostにDenoのHTTPサーバーを展開
Deno.serve(async (_req) => {
const htmlText = await Deno.readTextFile("./public/index.html");
return new Response(
// Responseの第一引数にレスポンスのbodyを設置
htmlText,
// Responseの第二引数にヘッダ情報等の付加情報を設置
{
// レスポンスにヘッダ情報を付加
headers: {
// text/html形式のデータで、文字コードはUTF-8であること
"Content-Type": "text/html; charset=utf-8"
}
}
);
});
--allow-netに加えて、--allow-readが必要になります。しかし、一つずつ許可するのは大変なので、開発時は全てを許可するようにして再度実行します。deno run -A --watch server.js
H1見出しですよと大きく表示されればOKです!
CSSファイルを作成して、読み込めるようにしてみましょう。index.htmlとは別にstyles.cssを作成し、このファイルを読み込めるようにします。
publicフォルダの中に、styles.cssを作成します。├─ .vscode/
│ ├─ settings.json
├─ public/
│ ├─ index.html
│ └─ styles.css
└─ server.js
/* public/styles.css */
body {
background: skyblue;
}
<!-- public/index.html -->
...(省略)
<head>
<!-- headタグの中にはメタデータ等を記載する -->
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
+ <link rel="stylesheet" href="styles.css">
</head>
...(省略)
// server.js
// localhostにDenoのHTTPサーバーを展開
Deno.serve(async (_req) => {
// パス名を取得する
// http://localhost:8000/hoge に接続した場合"/hoge"が取得できる
const pathname = new URL(_req.url).pathname;
console.log(`pathname: ${pathname}`);
// http://localhost:8000/styles.css へのアクセス時、"./public/styles.css"を返す
if (pathname === "/styles.css") {
const cssText = await Deno.readTextFile("./public/styles.css");
return new Response(
cssText,
{
headers: {
// text/css形式のデータで、文字コードはUTF-8であること
"Content-Type": "text/css; charset=utf-8"
}
}
);
}
// http://localhost:8000/ へのアクセス時、"./public/index.html"を返す
const htmlText = await Deno.readTextFile("./public/index.html");
return new Response(
// Responseの第一引数にレスポンスのbodyを設置
htmlText,
// Responseの第二引数にヘッダ情報等の付加情報を設置
{
// レスポンスにヘッダ情報を付加
headers: {
// text/html形式のデータで、文字コードはUTF-8であること
"Content-Type": "text/html; charset=utf-8"
}
}
);
});
1つずつ返すファイルを指定する実装では、ページ数が増えた場合に手間がかかります。
そこで、public以下を静的ファイルサーバーとして公開し、ここに入れたファイルは自動で公開されるようにしてみましょう。
server.jsファイルを以下の内容で置き換えます。// server.js
import { serveDir } from "jsr:@std/http/file-server";
// localhostにDenoのHTTPサーバーを展開
Deno.serve(async (_req) => {
// ./public以下のファイルを公開
return serveDir(
_req,
{
/*
- fsRoot: 公開するフォルダを指定
- urlRoot: フォルダを展開するURLを指定。今回はlocalhost:8000/に直に展開する
- enableCors: CORSの設定を付加するか
*/
fsRoot: "./public/",
urlRoot: "",
enableCors: true,
}
);
});
ブラウザでJavaScriptを実行してみましょう。alert関数を使用して、ブラウザ上でアラートを出力します。
今回は簡単のため、HTMLファイルに直に処理を記述します。
public/index.htmlのbodyに以下のように追記します。 <body>
<!-- bodyタグの中には実際に表示するものなどを書く -->
<h1>H1見出しですよ</h1>
+
+ <!-- JavaScriptを実行 -->
+ <script>
+ alert("Hello JavaScript!");
+ </script>
</body>
ここからは、実際に「しりとり」をするWebアプリを実装します。 実装するアプリは、以下の仕様を満たしたものとします。
このセクションでは、サーバー側の処理を実装します。前セクションまでで実装した内容をベースにして実装を進めましょう。
GET /shiritoriを実装しよう仕様1を満たすため、サーバーに保存されている直前の単語を取得できるようにしましょう。
GET /shiritoriからデータを取得できるようにします。
server.jsファイルを以下の内容で編集します。 // server.js
import { serveDir } from "jsr:@std/http/file-server";
+ // 直前の単語を保持しておく
+ let previousWord = "しりとり";
// localhostにDenoのHTTPサーバーを展開
Deno.serve(async (_req) => {
+ // パス名を取得する
+ // http://localhost:8000/hoge に接続した場合"/hoge"が取得できる
+ const pathname = new URL(_req.url).pathname
+ console.log(`pathname: ${pathname}`);
+
+ // GET /shiritori: 直前の単語を返す
+ if (_req.method === "GET" && pathname === "/shiritori") {
+ return new Response(previousWord);
+ }
+
// ./public以下のファイルを公開
...
http://localhost:8000/shiritoriにアクセスして、「しりとり」と表示されればOKです!POST /shiritoriを実装しよう仕様2を満たすため、サーバーに保存されている単語を、受け取ったデータで更新できるようにしましょう。
POST /shiritoriでデータを更新できるようにします。
server.jsファイルを以下の内容で編集します。 // GET /shiritori: 直前の単語を返す
if (_req.method === "GET" && pathname === "/shiritori") {
return new Response(previousWord);
}
+ // POST /shiritori: 次の単語を受け取って保存する
+ if (_req.method === "POST" && pathname === "/shiritori") {
+ // リクエストのペイロードを取得
+ const requestJson = await _req.json();
+ // JSONの中からnextWordを取得
+ const nextWord = requestJson["nextWord"];
+
+ // previousWordの末尾とnextWordの先頭が同一か確認
+ if (previousWord.slice(-1) === nextWord.slice(0, 1)) {
+ // 同一であれば、previousWordを更新
+ previousWord = nextWord;
+ }
+
+ // 現在の単語を返す
+ return new Response(previousWord);
+ }
+
// ./public以下のファイルを公開
return serveDir(
_req,
POSTのリクエストの送信は専用のツールやOSによって異なるコマンドが必要なので、動作確認はスキップして、次のセクションに進みましょう。もし動作確認の方法が分かるようであれば、動作確認してみてください。前セクションの内容を踏まえて、Web側の処理を実装しましょう。
GET /shiritoriの結果を表示するGET /shiritoriにアクセスして、直前の単語を取得します。以下のようにして実装してみましょう。
public/index.htmlファイルを以下の内容で編集します。fetchを利用してGET /shiritoriにリクエストを送信し、受信したデータをpタグに挿入します。 <body>
<!-- bodyタグの中には実際に表示するものなどを書く -->
- <h1>H1見出しですよ</h1>
+ <h1>しりとり</h1>
+ <!-- 現在の単語を表示する場所 -->
+ <p id="previousWord"></p>
<!-- JavaScriptを実行 -->
<script>
- alert("Hello JavaScript!");
+ window.onload = async (event) => {
+ // GET /shiritoriを実行
+ const response = await fetch("/shiritori", { method: "GET" });
+ // responseの中からレスポンスのテキストデータを取得
+ const previousWord = await response.text();
+ // id: previousWordのタグを取得
+ const paragraph = document.querySelector("#previousWord");
+ // 取得したタグの中身を書き換える
+ paragraph.innerHTML = `前の単語: ${previousWord}`;
+ }
</script>
</body>
http://localhost:8000で再読み込みして、「しりとり」と表示されればOKです!Topic: サーバー側の
previousWordを書き換えて、反映されるか確認してみましょう。
POST /shiritoriに次の単語を送信してみようPOST /shiritoriにアクセスして、次の単語を入力してみましょう。ここでは、ブラウザの起動時に勝手に「りんご」と送信されるようにしてみます。
public/index.htmlファイルを以下の内容で編集します。GET同様、fetchを使用してPOST /shiritoriにリクエストを送信します。 <!-- JavaScriptを実行 -->
<script>
window.onload = async (event) => {
+ // 試しでPOST /shiritoriを実行してみる
+ // りんごと入力……
+ await fetch(
+ "/shiritori",
+ {
+ method: "POST",
+ headers: { "Content-Type": "application/json" },
+ body: JSON.stringify({ nextWord: "りんご" })
+ }
+ );
+
// GET /shiritoriを実行
const response = await fetch("/shiritori", { method: "GET" });
// responseの中からレスポンスのテキストデータを取得
Topic: サーバー側の
previousWordやWeb側のnextWordを書き換えて、反映されるか確認してみましょう。しりとりとして単語が繋がっていなければ、更新されないようになっていることも確認しましょう。
POST /shiritoriに任意の単語を送信してみよう起動時にサーバーの値を書き換えることができました。次に、任意の単語を送信できるようにしてみましょう。
public/index.htmlファイルを以下の内容で編集します。送信ボタンが押下された時にinputタグの中身を取得して、POST /shiritoriに送信します。 <body>
<!-- bodyタグの中には実際に表示するものなどを書く -->
<h1>しりとり</h1>
<!-- 現在の単語を表示する場所 -->
<p id="previousWord"></p>
+ <!-- 次の文字を入力するフォーム -->
+ <input id="nextWordInput" type="text" />
+ <button id="nextWordSendButton">送信</button>
<!-- JavaScriptを実行 -->
<script>
window.onload = async (event) => {
- // 試しでPOST /shiritoriを実行してみる
- // りんごと入力……
- await fetch(
- "/shiritori",
- {
- method: "POST",
- headers: { "Content-Type": "application/json" },
- body: JSON.stringify({ nextWord: "りんご" })
- }
- );
-
// GET /shiritoriを実行
const response = await fetch("/shiritori", { method: "GET" });
// responseの中からレスポンスのテキストデータを取得
const previousWord = await response.text();
// id: previousWordのタグを取得
const paragraph = document.querySelector("#previousWord");
// 取得したタグの中身を書き換える
paragraph.innerHTML = `前の単語: ${previousWord}`;
}
+ // 送信ボタンの押下時に実行
+ document.querySelector("#nextWordSendButton").onclick = async(event) => {
+ // inputタグを取得
+ const nextWordInput = document.querySelector("#nextWordInput");
+ // inputの中身を取得
+ const nextWordInputText = nextWordInput.value;
+ // POST /shiritoriを実行
+ // 次の単語をresponseに格納
+ const response = await fetch(
+ "/shiritori",
+ {
+ method: "POST",
+ headers: { "Content-Type": "application/json" },
+ body: JSON.stringify({ nextWord: nextWordInputText })
+ }
+ );
+
+ const previousWord = await response.text();
+
+ // id: previousWordのタグを取得
+ const paragraph = document.querySelector("#previousWord");
+ // 取得したタグの中身を書き換える
+ paragraph.innerHTML = `前の単語: ${previousWord}`;
+ // inputタグの中身を消去する
+ nextWordInput.value = "";
+ }
</script>
</body>
Topic: 単語を色々入力して、しりとりとして成立しているか確認してみましょう。
「りんご」の次に「らっぱ」などの続かない単語が入力された時に、エラーを表示できるようにしてみましょう。ここでは、application/json形式のデータを返すようにしてみます。Webとサーバーを以下のように書き換えてください。
server.jsファイルを以下の内容で編集します。 // POST /shiritori: 次の単語を受け取って保存する
if (_req.method === "POST" && pathname === "/shiritori") {
// リクエストのペイロードを取得
const requestJson = await _req.json();
// JSONの中からnextWordを取得
const nextWord = requestJson["nextWord"];
// previousWordの末尾とnextWordの先頭が同一か確認
if (previousWord.slice(-1) === nextWord.slice(0, 1)) {
// 同一であれば、previousWordを更新
previousWord = nextWord;
}
+ // 同一でない単語の入力時に、エラーを返す
+ else {
+ return new Response(
+ JSON.stringify({
+ "errorMessage": "前の単語に続いていません",
+ "errorCode": "10001"
+ }),
+ {
+ status: 400,
+ headers: { "Content-Type": "application/json; charset=utf-8" },
+ }
+ );
+ }
// 現在の単語を返す
return new Response(previousWord);
}
public/index.htmlファイルを以下の内容で編集します。 // 送信ボタンの押下時に実行
document.querySelector("#nextWordSendButton").onclick = async(event) => {
// inputタグを取得
const nextWordInput = document.querySelector("#nextWordInput");
// inputの中身を取得
const nextWordInputText = nextWordInput.value;
// POST /shiritoriを実行
// 次の単語をresponseに格納
const response = await fetch(
"/shiritori",
{
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ nextWord: nextWordInputText })
}
);
+
+ // status: 200以外が返ってきた場合にエラーを表示
+ if (response.status !== 200) {
+ const errorJson = await response.text();
+ const errorObj = JSON.parse(errorJson);
+ alert(errorObj["errorMessage"]);
+ return;
+ }
const previousWord = await response.text();
作成したWebアプリをGitHubリポジトリに保存し、コードを公開しましょう。
GitHubは、Gitのリポジトリをインターネット上で管理するためのサービスです。リポジトリをアップロードしておくことで、複数人での開発時のソースコードの共有、ソースコードのバックアップ、ご自身の実績の公開の場として、などの効果を期待できます。
GitHubアカウントでログインしてリポジトリを作成し、成果物をアップロードしてみましょう。
Topic: コミット、プッシュなど、Gitの操作について軽く調べてみましょう。
README.mdも一緒にプッシュしてみました。GitHubでは、README.mdに記述した内容が画面下部に表示されます。ここに環境構築手順やリポジトリの説明等を記載すると分かりやすいです。
注意 GitHubアカウントの作成後、一週間程はDeno Deployの登録ができません。登録できない場合は、Step 12はスキップしてStep 13を先に終わらせてください。
Deno Deployでアカウント登録しましょう。Deno DeployのアカウントはGitHubアカウントと連携する形で作成できるので、先に作成したGitHubアカウントを使用してください。
アカウント作成後、Organizationを作成します。
nameとslugにはこだわりがなければ自分のGitHubのユーザー名をセットしておくのがいいでしょう。
入力後、Create organizationを押して作成します。
早速、Deno Deployのプロジェクトを作ってみましょう。
GitHubのリポジトリを元に、Deno Deployのプロジェクトを作成します。
server.js を指定します。Topic: Entrypointに指定したDenoファイルが、サーバー起動時に自動で実行されます。
設定を閉じて、末尾の「Create App」を押します。
しばらくするとデプロイが完了します。画像のようにBuildの各ステップにチェックが入れば完了です。画面右上に表示されているリンクをクリックしてWebサイトを開いてみましょう!
ここまでで、Deno DeployにWebアプリケーションをデプロイして動作させることができました。Deno DeployはGitHubと連携していますので、GitHubを更新すれば自動で修正された内容がデプロイされるようになっています。
以降はご自身で実装を進めていただきます。
次セクションに実装のヒントを記載していますので、参考にしてみてください。
提出は資料冒頭に記載のGoogle フォームからお願いします。
必ず、仕様を満たしていることを確認し、READMEを記載しましょう!
ここでは、必須仕様を満たすための実装のヒントを掲載します。
以下のWebサイトに必須仕様を満たすWebアプリケーションをデプロイしました。実装の参考にしてみてください。 尚、課題に記載していなかった詳細な仕様については自身で検討して実装していますが、以下に示すのはあくまでも一例ですので、従う必要はありません。
https://dice-deno-shirit-93.deno.dev/
POST /shiritoriを実行した際の処理を修正して、以下の部分に処理を追加するとよさそうです。
// server.js
...
// previousWordの末尾とnextWordの先頭が同一か確認
if (previousWord.slice(-1) === nextWord.slice(0, 1)) {
+ // 末尾が「ん」になっている場合
+ // ifの中に入力された単語の末尾が「ん」になっていることを確認する条件式を追加
+ if (...) {
+ // エラーを返す処理を追加
+ // errorCodeを固有のものにして、末尾が「ん」の時に発生したエラーだとWeb側に通知できるようにする
+ }
+
// 同一であれば、previousWordを更新
previousWord = nextWord;
}
...
// index.html
...
if (response.status !== 200) {
const errorJson = await response.text();
const errorObj = JSON.parse(errorJson);
+ // errorObj["errorCode"]ごとに処理を分岐する
+ // errorCodeが、末尾が「ん」の時のエラーだったら、ゲームを終了する
return;
}
...
ゲームの終了時には、ゲームが終了したことを画面に表示するとよさそうです。
ゲームの終了を画面に表示する方法として、以下のものが考えられます。
1の場合は、HTMLタグの操作や削除など、ここまでに実装した内容の応用で実装が可能です。
2の場合は、HTMLファイルを新しく作成し、ゲーム終了時にゲーム終了画面に遷移するようにすれば実装可能です。
処理を追加する場所は、末尾が「ん」の場合の処理と殆ど変わりません。新しいエラーの処理を実装しましょう。 また、直前より前の単語を保存しておく必要がありますので、その点の処理を追記しましょう。
今までは、直前の単語のみを保存して入力した単語と比較していました。しかし、入力した単語が既に使われているかを確認するには、今までの単語を全て記録しておく必要があります。
そこで、JavaScriptのリストを使用して今までの単語を保存しておきましょう。以下のようにして、単語の保存用の変数をリストにしておき、単語の更新時に逐次保存するようにしておけばよさそうです。
- let previousWord = "しりとり";
+ let wordHistories = ["しりとり"];
また、もし余裕があれば、新しくサーバーを作ったりSaaSを使ったりして、データベース等を使用してみるのも良いかもしれません。
サーバーに、POST /reset等の新しいPOSTメソッドを追加しましょう。また、追加したPOSTメソッドを実行するためのボタンをWebに追加しましょう。
// server.js
...
return new Response(previousWord);
}
+ // POST /reset: リセットする
+ // _req.methodとpathnameを確認
+ if (...) {
+ // 既存の単語の履歴を初期化する
+ // 初期化した単語を返す
+ }
+
// ./public以下のファイルを公開
return serveDir(
_req,
...
// index.html
...
<!-- 次の文字を入力するフォーム -->
<input id="nextWordInput" type="text" />
<button id="nextWordSendButton">送信</button>
+ <button id="resetSendButton">リセット</button>
...
// inputタグの中身を消去する
nextWordInput.value = "";
}
+ // 送信ボタンの押下時に実行
+ document.querySelector("#resetSendButton").onclick = async(event) => {
+ // POST /resetを実行
+ // ページをリロードする
+ }
</script>
...
リセット処理後、必要であればページをリロードして、Webサイトの表示をリセットしましょう。ゲーム終了時に要素を削除していた場合は、リロードの処理が必要になるかと思います。
JavaScriptの関数を検索して、処理を追記してみましょう。