Android SDK で,ゲームを作る (2) [プログラム三昧]
前回は,ひとつのファイルに何もかもゴチャマゼに入れてしまいました.今回は, Model 部分を切りだします.
ゲームロジック(Model オブジェクト)
/* * $Id$ * -------------------------------------------- * File : SeekNumberModel.java * Package : org.noritan.seeknumber * Copyright : Copyright (c) 2010 noritan.org * Organization : noritan.org * Created : 2010/03/12 * -------------------------------------------- */ package org.noritan.seeknumber; import java.util.ArrayList; /** * This <code>SeekNumberModel</code> class is a game logic * of the Seek Number Game. * * @author noritan * @see {@link SeekNumberListener} */ public class SeekNumberModel { private int buttonCount; private int[] indexOrdered; // position to id table private int expected; private ArrayList<SeekNumberListener> listeners = new ArrayList<SeekNumberListener>(); /** * Construct a <code>SeekNumberModel</code> object. * It is assumed that the game has a number of buttons * indicated by the parameter <code>buttonCount</code> * The <code>indexOrdered</code> table and * the <code>expected</code> variable are initialized. * * @param buttonCount The number of buttons to be handled by this object. */ public SeekNumberModel(int buttonCount) { this.buttonCount = buttonCount; indexOrdered = new int[buttonCount]; for (int i = 0; i < buttonCount; i++) { indexOrdered[i] = i; } expected = Integer.MAX_VALUE; } /** * Reorder the <code>indexOrdered</code> table with a random * number generator of <code>Math</code> class. * In addition, the <code>expected</code> variable is * initialized too. * A {@link #notifyInitialize(int[])} event is issued when * the table is initialized. */ public void reorder() { ArrayList<Integer> buttonLeft = new ArrayList<Integer>(); for (int i = 0; i < buttonCount; i++) { buttonLeft.add(i); } for (int i = 0; i < buttonCount; i++) { int k = (int)(Math.random() * (buttonCount - i)); int index = buttonLeft.get(k); indexOrdered[i] = index; buttonLeft.remove(k); } notifyInitialize(indexOrdered); expected = 0; } /** * This method notifies a click event is occurred on a button. * The position of the clicked button is indicated by the * parameter <code>position</code>. * This method cause a {@link #notifyHit(int)} event when * the hit button is an expected one indicated by * the variable <code>expected</code>. * Whe clicked button is the last one, an additional event * {@link #notifyFinish()} is issued too. * * @param position The position of the hit button. */ public void click(int position) { if (expected >= buttonCount) { // Nothing is expected. return; } // Is the button an expected one ? if (indexOrdered[position] == expected) { // Right selection. notifyHit(position); // point next button to be expected. expected++; if (expected >= buttonCount) { // All buttons are clicked. notifyFinish(); } } } /** * Add a {@link SeekNumberListener} object as an event listener * of this object. * * @param listener An event listener to accept events issued by * this object. */ public void addListener(SeekNumberListener listener) { listeners.add(listener); } /** * Notify all event listeners that this object is initialized. * The {@link SeekNumberListener#initialized(int[])} method is * used to issue the event. * The parameter <code>assignment</code> is cloned prior to * issue the event not to modify the assignment map of this * object. * * @param assignment An assignment map from button's position * to the button's order. */ protected void notifyInitialize(int[] assignment) { assignment = assignment.clone(); for (SeekNumberListener listener:listeners) { listener.initialized(assignment); } } /** * Notify all event listeners that this object recognizes * an expected button is clicked at the position. * * @param position The position of the hit button. */ protected void notifyHit(int position) { for (SeekNumberListener listener:listeners) { listener.hit(position); } } /** * Notify all event listeners that this object detects the end * of a game when all buttons are hit. */ protected void notifyFinish() { for (SeekNumberListener listener:listeners ) { listener.finished(); } } }
View に依存する部分を取り去って,ゲームロジックとして独立させました.このオブジェクトは,どのユーザ・インターフェイスにも使用することができます.
このモデルに対してメッセージを伝えるのは, public メソッド reorder() と click(int) です.それぞれ,ユーザがゲームを開始した時とユーザがボタンをクリックした時に呼び出されます.
public メソッドには,もう一つ addListener(SeekNumberListener) というものがあります.このメソッドは,モデルオブジェクトから発生られるメッセージを受け取るオブジェクト(Listener)を登録するために使用されます.
SeekNumberListener インターフェイス
/* * $Id$ * -------------------------------------------- * File : SeekNumberListener.java * Package : org.noritan.seeknumber * Copyright : Copyright (c) 2010 noritan.org * Organization : noritan.org * Created : 2010/03/12 * -------------------------------------------- */ package org.noritan.seeknumber; /** * Objects implementing this <code>SeekNumberListener</code> interface * accepts events issued by a {@link SeekNumberModel} * class instance. * The <code>SeekNumberListener</code> interface is used to be * registered with the * {@link SeekNumberModel#addListener(SeekNumberListener)} * method. * * @author noritan * @see SeekNumberModel * @see SeekNumberModel#addListener(SeekNumberListener) */ public interface SeekNumberListener { /** * Notify the listener that new labels are assigned to the buttons. * * @param assignment An assignment map from the position of * a button to the label corresponding to the button. */ void initialized(int[] assignment); /** * Notify the listener that a button at a <code>position</code> * is hit correctly. * * @param position The position of the hit button. */ void hit(int position); /** * Notify the listener that all buttons are hit and a game * has finished. */ void finished(); }
SeekNumberListener インターフェイスは, Model オブジェクトから発せられたメッセージを受け取ります.三つのメソッド initialized(int[]) hit(int) finished() を装備しており,それぞれ,ゲームの開始を知らせる,当たりボタンが押されたことを示す,ゲームの終了を知らせる,という役割があります.
GUI 関連のコードは,後日.
コメント 0