目次


Java、Ajax、Cloudant を使ってハングマン・ゲームを作成する

Comments

皆さんは、「ハングマン」という、紙と鉛筆を使って言い当てるゲームで遊んだことがありますか?このチュートリアルでは、皆さんが自分 1 人で遊べるオンライン・ハングマン・ゲームをプログラミングする方法を紹介します。このオンライン・ハングマン・ゲームでは、アプリケーションが皆さんの対戦相手をシミュレーションします。このチュートリアルで説明するのは、このアプリケーションを作成するために IBM Bluemix に用意されている 2 つのサービス ― Liberty for Java ランタイムと Cloudant NoSQL データベース ― を利用するステップについてです。

作成するアプリケーションに必要となるもの

アプリを実行するコードを入手する

アプリケーションのバック・エンドとフロント・エンドを作成し、web.xml ファイルに変更を加えます。

Bluemix のサービスを利用するのが、どれほど簡単であるのか、それだけを知りたいのであれば、コードを入手してステップ 1、2、3、5 に従ってください。さらに楽しみたければ、ステップ 4 にも従って、このアプリケーションが JSP テクノロジー、サーブレット、Ajax、CSS、JavaScript、Cloudant 接続をどのように使用しているかを学んでください。

ステップ 1: Bluemix の中で Java Web アプリケーションを作成する

  1. Bluemix にログインします。
  2. カタログ内で、「Runtimes (ランタイム)」の下にある「Liberty for Java」をクリックします。
  3. アプリケーション名とホスト名を選択または入力し、プランとしては「Default (デフォルト)」を選択して、「Create (作成)」をクリックします。
  4. カタログ内で、「Data Management (データ管理)」にある「Cloudant NoSQL DB」をクリックします。リストからアプリケーションを選択し、プランとしては「Shared (共有)」を選択して、「Create (作成)」をクリックします。
  5. ダッシュボード内で、作成したアプリケーションをクリックして概要ページを開きます。Bluemix ダッシュボード内のハングマン・アプリケーションのエントリー画面のスクリーンショット
    Bluemix ダッシュボード内のハングマン・アプリケーションのエントリー画面のスクリーンショット

ステップ 2: Cloudant NoSQL DB データベースにデータを追加する

  1. アプリケーションの概要ページでは、「Development Services (開発サービス)」の下にある「Cloudant NoSQL DB」サービスをクリックします。
  2. 「Launch (起動)」をクリックして Cloudant コンソールを起動します。
  3. メニューにある「Databases (データベース)」をクリックするのに続いて「Add New Database (新規データベースの追加)」をクリックし、「category」という名前のデータベースと「word」という名前のデータベースを追加します。
  4. 「New (新規)」 > 「Document (文書)」の順にメニュー項目を選択し、category データベースに以下のドキュメントを (1 つずつ順番に) 追加します。
    {"_id":"0","name":"Animals"}
    {"_id":"1","name":"Food"}
    {"_id":"2","name":"Music"}
    {"_id":"3","name":"Movies"}
    {"_id":"4","name":"Names"}
    {"_id":"5","name":"Video Games"}
  5. word データベースに以下のドキュメントを (1 つずつ順番に) 追加します。
    {"name":"CAIMAN","category_id":"0"}
    {"name":"BEAR","category_id":"0"}
    {"name":"CARROTS","category_id":"1"}
    {"name":"AVOCADO","category_id":"1"}
    {"name":"LEOPOLDO","category_id":"4"}
    {"name":"ISMAEL","category_id":"4"}
    {"name":"LOREN","category_id":"4"}
    {"name":"SPACE RUN","category_id":"5"}
    {"name":"WATCH DOG","category_id":"5"}

ステップ 3: スターター・アプリケーション・パッケージをダウンロードする

  1. アプリケーションの概要ページで、以下の「VIEW QUICK START (クイック・スタートの表示)」をクリックします。「VIEW QUICK START (クイック・スタートの表示)」ボタンのスクリーンショット
    「VIEW QUICK START (クイック・スタートの表示)」ボタンのスクリーンショット
  2. 「Download the starter application package (スターター・アプリケーション・パッケージのダウンロード)」リンクをクリックして、ローカル PC にスターター・アプリケーション・パッケージのファイルを保存します。

ステップ 4: アプリケーションを作成する

このステップでは、アプリケーションのバック・エンドとフロント・エンドを作成し、web.xml ファイルに変更を加えます。(このチュートリアルの始めにある「コードを入手する」ボタンをクリックして、完全な CSS ファイル、JavaScript ファイル、Java クラス、そしてその他アプリケーションが必要とするすべてのファイルをダウンロードします。)

環境を準備する

  1. IDE に新規 Java 動的 Web プロジェクトを作成します。
  2. 作成したプロジェクトにスターター・アプリケーション・パッケージをインポートします。
  3. プロジェクトのライブラリー・フォルダー (WEB-INF/lib) に org.ektorp.jar ファイルを追加します。さらに、このライブラリーの依存関係も追加します。このチュートリアルの「コードを入手する」ボタンを利用することで、すべてのライブラリーを DevOps Services から入手することができます。

バック・エンドを作成する

  1. Category.java クラスと Word.java クラスを作成し、それぞれ以下の属性を持たせます。
    • Category: String idString revisionString name
    • Word: String idString revisionString nameString category_id
  2. ゲッターとセッターを作成します。以下のように @JsonIgnoreProperties アノテーションと @JsonProperty アノテーションを使用します。この 2 つのアノテーションによって、JSON プロパティーの処理が無視されます。
    @JsonIgnoreProperties({"id", "revision"})
    
    public class Category {
       
       @JsonProperty("_id")
       private String id;
       
       @JsonProperty("_rev")
          private String revision;
  3. CategoryRepository.java クラスと WordRepository.java クラスを作成します。この 2 つのクラスでは、CouchDbRepositorySupport<T> クラスを継承するとともに (CouchDbRepositorySupport<T> クラスは、永続クラスを対象に作成、読み取り、更新、削除というすべての操作を提供する汎用的なリポジトリー・サポート・クラスです)、以下のコンストラクターを追加します。
    public CategoryRepository(CouchDbConnector db) {
         super(Category.class, db);
    }
  4. CloudantConnection.java クラスを作成します。以下に示すように、ランタイムの VCAP_SERVICES 環境変数を使用して、追加したコンストラクターでの接続を設定します。
    JSONObject obj = new JSONObject(System.getenv("VCAP_SERVICES"));
       String[] names = JSONObject.getNames(obj);
    
       if (names != null) {
       for (String name : names) {
          if (name.equals("cloudantNoSQLDB")) {
          JSONArray val = obj.getJSONArray(name);
          JSONObject serviceAttr = val.getJSONObject(0);
          JSONObject credentials = serviceAttr.getJSONObject("credentials");
          httpClient = new StdHttpClient.Builder()
             .url(credentials.getString("url"))
             .build();
          break;
          }
          }
       }

    環境変数は、ご使用の Liberty for Java ランタイムの概要の中で見つけることができます。VCAP_SERVICES 変数には皆さんのデータベース情報のすべて (ユーザー名、パスワード、ホスト、ポート、および URL) が含まれています。Cloudant サービスの下にある「Show Credentials (資格情報を表示)」をクリックすると、データベース情報が表示されます。 Cloudant の資格情報のスクリーンショット
    Cloudant の資格情報のスクリーンショット
  5. Cloudant データベースからデータを取得するための getCategories() メソッドと getWords() メソッドを作成します。データを読み取るには、リポジトリー・クラスを使用します。
    public List<Word> getWords(){
       CouchDbInstance dbInstance = new StdCouchDbInstance(httpClient);
       CouchDbConnector db = new StdCouchDbConnector("word", dbInstance);
       WordRepository wordRepo = new WordRepository(db);
       return wordRepo.getAll();
    }
  6. カテゴリー別の単語のリストを取得するための getWordsByCategory() メソッドと、カテゴリーごとにランダムな単語を取得するための getRandomWordByCategory() メソッドを作成します。getWordsByCategory() メソッドでは、利用可能な単語を取得するために getWords() メソッドを呼び出し、取得された単語のリストを繰り返し処理して、カテゴリー別の単語を見つけます。getRandomWordByCategory() では、ゲームで使用される単語を選択するために乱数を生成します。
    List<Word> words = this.getWordsByCategory(category_id);
    Random generator = new Random();
    if(words.size()>0){
       int random = generator.nextInt(words.size());
       word = words.get(random);
    }

    私は、ランダムに整数値を生成するために、(java.util パッケージに用意されている) Random オブジェクトを使用しました。
  7. LoadIndex.java サーブレットを作成します。このサーブレットはカテゴリー情報を index Web ページにロードするために使用します。以下のように CloudantConnection クラスを使用する場合のみ doGet() メソッドが必要です。
    CloudantConnection cloudantConnection = new CloudantConnection();
    List<Category> categories = cloudantConnection.getCategories();
    request.setAttribute("categories", categories);   
     request.getRequestDispatcher("index.jsp").forward(request, response);
  8. LoadGame.java サーブレットを作成します。このサーブレットでは、doPost() メソッドを使用して、HttpServletResponse オブジェクトにランダムな単語を設定します。ランダムな単語は、HttpServlerRequest で送られるカテゴリーに基づいて生成されます。
    String action = request.getParameter("action");
    String value = request.getParameter("value");
    
    if ((action != null)&&(value != null)) {
     CloudantConnection cloudantConnection = new CloudantConnection();
     Word word = cloudantConnection.getRandomWordByCategory(value);
     if(word!=null){
        response.setContentType("text/html");
        response.getWriter().write(word.getName());
     }
    }

    Ajax の実装ではこのメソッドを使用することになります。

フロント・エンドを作成する

  1. index.jsp ファイルを作成し、以下のように必要なライブラリーをインポートします。
    <%@ page import="java.util.List" %>
    <%@ page import="com.bluemix.hangman.model.Category" %>
  2. CSS ファイルと JavaScript ファイルへの参照を追加します。
    <link rel="stylesheet" href="style.css" />
    <script src="index.js"></script>
    <script src="dojo.js"></script>
  3. 本体では、複数の <div> タグを追加します。その 1 つには <select> ドロップダウン・リストを追加します。このドロップダウン・リストは、LoadIndex サーブレットから得られるカテゴリーのリストで満たします。また、もう 1 つの <div> タグには <img> タグと複数の <table> タグを追加します (これらのタグはこの時点では空であり、後ほど動的に満たされます)。
    <div id="menu">
          <select onChange="javascript:loadWord(this.value);">
          <option value="">Select category</option>
          <%  List<Category> categories = (List<Category>) request.getAttribute("categories");
          for(int index=0; index<categories.size(); index++){
           %>
          <option value="<%=categories.get(index).getId()%>"
          ><%=categories.get(index).getName() %></option>
          <%
          }
           %>
        </select>
    </div>
    <div id="content">
       <img id="hangmanImage" style="visibility:hidden"><br><br>
       <table id="wordTable"></table><br>
       <table id="lettersTable"></table>
       </div>
  4. <table> タグ、<div> タグ、<a> タグに CSS スタイルを提供するために style.css を作成します。これらのスタイル・クラスは、ゲームで使用されるアルファベットの文字を表示します。(class="myclassname" を使用することで、あらゆる HTML 要素にスタイル・クラスを適用できること覚えておいてください。)
  5. index.js という JavaScript ファイルを作成し、その中でグローバル変数を定義します。WebContent フォルダーには dojo.js ファイルをコピーしておき、index.js に loadWord 関数を追加します。この関数では Dojo の機能を利用して Ajax を実装しており、その Ajax によって LoadGame サーブレットから単語を取得しています。
    function loadWord(category) {
       dojo.xhrPost({
          url: "game.do",
          postData: "action=loadWord&value="+category,
          handleAs: "text",
          load: function(text){
                updateWord(text);
          },
          error: function(error){
                alert(error);
          }          
       });
    }
    loadWord 関数で呼び出している updateWord 関数では、JavaScript 変数を初期化し、index.jsp ファイルで定義されている HTML タグを動的に満たすように他の関数を呼び出します。ここでは、<img> タグは document.getElementById() という JavaScript メソッドによって満たされ、新しいゲームが開始されたことが示されます。
    document.getElementById("hangmanImage").style.visibility = "visible";
    loadWordTable 関数は、言い当てる単語を UI 内に追加するために使用され、この関数内では単語の文字数や空白を数えるために string.split(separator) という JavaScript メソッドが使用されます。loadLettersTable 関数は、ゲームで使用されるアルファベットの文字を出力するために使用され、updateImage 関数は、UI 内の画像を更新するために使用されます。ご覧のように、document.getElementById("elementId") は HTML 要素にアクセスして HTML 要素を更新するために使用されます。
    var table = "<tr>";
    for(var index=0; index<word.split('').length; index++){
       table += "<td ><a id='wordLetter"+index+"' class='wordLetter'>_</a></td>";
    }
    table += "</tr>";
    document.getElementById("wordTable").innerHTML = table;\
  6. ゲームのステータスを制御して更新するための関数を作成します。verifyLetter 関数は、ユーザーがアルファベットの文字をクリックすると呼び出され、あと何回チャンスがあるかをチェックします。updateGame 関数は、指定された文字が単語の中に存在するかどうかをチェックし、画像とアルファベットの文字を更新して、文字のステータスを修正します。ストリングをサブストリングの配列に分けるために、ここでも JavaScript の split(separator) メソッドを使用します。この場合、メソッドがセパレーターとして用いているのは空のストリングであるため、元のストリングは各文字の後ろで分割されます。
    var wordSplit = globalWord.split('');
    for(var index=0; index<wordSplit.length; index++){
           if(letter == wordSplit[index]){
       document.getElementById("wordLetter"+index).innerHTML = wordSplit[index];
       correctLetters+=1;
       find = true;
        }
    }
  7. WebContent フォルダー内に img フォルダーを作成し、画像ファイルを追加します。

web.xml ファイルを編集する

  1. web.xml ファイルの中で LoadIndex サーブレットと LoadGame サーブレットを以下のように構成します。
    <servlet>
        <servlet-name>LoadIndex</servlet-name>
        <servlet-class>com.bluemix.hangman.controller.LoadIndex</servlet-class>
    </servlet>
    <servlet>
        <servlet-name>LoadGame</servlet-name>
        <servlet-class>com.bluemix.hangman.controller.LoadGame</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>LoadIndex</servlet-name>
        <url-pattern>/play.do</url-pattern>
    </servlet-mapping>
       <servlet-mapping>
        <servlet-name>LoadGame</servlet-name>
        <url-pattern>/game.do</url-pattern>
    </servlet-mapping>
  2. LoadIndex サーブレットを呼び出すことで、Web アプリケーションのデフォルト・ページを指定します。
    <welcome-file-list>
        <welcome-file>play.do</welcome-file>
    </welcome-file-list>

ステップ 5: アプリケーションを実行する

  1. Java Web プロジェクトをコンパイルし、WAR ファイルを生成します。
  2. コマンドラインで、WAR ファイルを保存したディレクトリーがカレント・ディレクトリーとなるように変更します。
  3. cf api bluemix_domain を実行することで、Bluemix に接続します。
  4. cf login -u username を実行することで Bluemix にログインした後、cf target -o username -s space を実行することで皆さんの環境 (Bluemix スペース) をターゲットに設定します。
  5. cf push appname -p appname.war コマンドを実行することで、アプリケーションをデプロイします。

これで皆さんは、ご自分の Bluemix ドメイン (たとえば、http://hangmangame.mybluemix.net) にあるアプリケーションにアクセスし、ゲームで遊ぶことができます。

吊るされている人が部分的に完成した状態のゲームのスクリーンショット
吊るされている人が部分的に完成した状態のゲームのスクリーンショット

まとめ

Bluemix を利用すると、クラウド・アプリケーションを迅速にデプロイして、管理することができます。私は、ハングマン・アプリケーションをクラウド内にデプロイするのに 1 つのランタイムと 1 つのサービスしか使用しませんでしたが、Bluemix にはソフトウェア・ポートフォリオが豊富に用意されています。皆さんも早速 Bluemix を利用してアプリケーションを作成してみてください!


ダウンロード可能なリソース


関連トピック


コメント

コメントを登録するにはサインインあるいは登録してください。

static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=60
Zone=Java technology, Cloud computing
ArticleID=989150
ArticleTitle=Java、Ajax、Cloudant を使ってハングマン・ゲームを作成する
publish-date=11132014