人力検索はてな
モバイル版を表示しています。PC版はこちら
i-mobile

回答によっては1000ポイントまたはそれ以上進呈。
数度の質問で解決した場合は解決後のポイント贈呈もあります。

以下は携帯電話の待ち受け画面で携帯が開閉される度に画像を変えるものです。画像4枚を交互に表示します。
今回は日付けによって画像も変わります。
わからない(不完全)部分がありますのでご指導おねがいいたします。コードはこちらのURLです。
http://homepage2.nifty.com/h/MAp2/hatena821.html

●質問者: DreamStar
●カテゴリ:コンピュータ ゲーム
✍キーワード:コード ポイント 携帯 携帯電話 画像
○ 状態 :終了
└ 回答数 : 5/5件

▽最新の回答へ

1 ● hive7134
●0ポイント

プログラミングのテクニック的には色々と修正したい部分がありますが、

とりあえず応急処置的に修正を加えてみました。



今回、MAppliGazoクラスは使用しません。

MAppliCanvasクラスを以下のものに差し替えて下さい。


import java.util.Calendar;

import com.nttdocomo.ui.*;

public class MAppliCanvas extends Canvas {
Image[] image;

MAppli app = (MAppli) IApplication.getCurrentApp();

MAppliCanvas() {
// イメージの読み込み
image = new Image[4];

try {
MediaImage m;

// 4つ分の画像データ読み込む
String[] filename = { "apple", "banana", "lemon", "orange" };
for (int i = 0; i < 4; i++) {
m = MediaManager
.getImage("resource:///" + filename[i] + ".gif");
m.use();
image[i] = m.getImage();
}

} catch (Exception e) {
e.printStackTrace();
}

}

// 描画
public void paint(Graphics g) {
// イメージの表示
g.drawImage(getImage(), 0, 0);
}

/**
 * イメージデータを、日付に合わせて並び替え、 次に表示すべきImageを返す。
 * 
 * @return 次に表示すべきImage
 */
private Image getImage() {

Image todaysImages[] = new Image[image.length];

Calendar now = Calendar.getInstance();
// year と month は使用していないようなのでコメントアウト
// int year, month, date;
int date;

// year = now.get(Calendar.YEAR);
// month=now.get(Calendar.MONTH)+1;
date = now.get(Calendar.DATE);

switch (date) {
case 1:
case 2:
todaysImages[0] = image[0];
todaysImages[1] = image[1];
todaysImages[2] = image[2];
todaysImages[3] = image[3];
break;
case 3:
todaysImages[0] = image[1];
todaysImages[1] = image[3];
todaysImages[2] = image[1];
todaysImages[3] = image[3];
break;
case 4:
case 5:
case 6:
todaysImages[0] = image[1];
todaysImages[1] = image[2];
todaysImages[2] = image[3];
todaysImages[3] = image[1];
break;
case 7:
case 8:
todaysImages[0] = image[2];
todaysImages[1] = image[2];
todaysImages[2] = image[2];
todaysImages[3] = image[2];
break;

//以下、どういう順番にしたいのかわからないため省略。
//※ 完全にランダムにするか、
// 法則性を持たせて数式で表せられれば、
// このような単調な入力作業はなくせます。
default:
todaysImages[0] = image[3];
todaysImages[1] = image[2];
todaysImages[2] = image[1];
todaysImages[3] = image[0];
}

return todaysImages[app.i];
}
}



「日付によって画像の並びを変える」の部分の法則性がわからないため、

とりあえずこんな感じでどうでしょうか。

◎質問者からの返答

ありがとうございます。MAppliGazoのような別クラス(別ファイル)として日付、画像を分離して管理する方法はありませんか?あと7月30日と31日にlemon.gifの表示を追加してみてください。動作確認はOKでしたか?他の方で別の方法があれば投稿お願いします。


2 ● hive7134
●0ポイント

やや強引になってしまいましたが、MAppliGazoを利用するように修正したものも、参考までに提示いたします。



MAppliCanvas.java


import com.nttdocomo.ui.*;

public class MAppliCanvas extends Canvas {
Image[] image;

MAppli app = (MAppli) IApplication.getCurrentApp();

MAppliGazo gazo = new MAppliGazo();

MAppliCanvas() {
image = new Image[4];

try {
MediaImage m;

String[] filename = { "apple", "banana", "lemon", "orange" };
for (int i = 0; i < 4; i++) {
m = MediaManager.getImage("resource:///" + filename[i] + ".gif");
m.use();
image[i] = m.getImage();
}

} catch (Exception e) {
e.printStackTrace();
}

}

public void paint(Graphics g) {
g.drawImage(image[gazo.getTodaysIndex(app.i)], 0, 0);
}
}




MAppliGazo.java

import java.util.*;

public class MAppliGazo {
Random random = new Random();

/**
 * イメージデータを、日付に合わせて並び替え、 次に表示すべきImageのindex(添え字)を返す。
 * 
 * @return 次に表示すべきImageのindex
 */
public int getTodaysIndex(int i) {

Calendar now = Calendar.getInstance();
int date = now.get(Calendar.DATE);

switch (date) {
case 1:
case 2:
//image[]の順番どおりに表示(apple, banana, lemon, orange)
return i;
case 3:
//MAppliのiが偶数ならimage[]の添え字は1(banana)、奇数ならば3(orange)
return i%2 == 0 ? 1 : 3;
case 4:
case 5:
case 6:
//MAppliのiが0?2のときはimage[]の添え字はi+1(banana, lemon, orange)、ただしiが3なら添え字は1(banana)
return i==3 ? 1 : i+1;
case 7:
case 8:
//常に2(lemon)
return 2;
default:
//ほかの日は完全にランダムにしてみました。
int rnd = random.nextInt(); // 整数値の乱数を発生
rnd &= 0x7fffffff; // 負数を削除
rnd %= 4; // 0?3までの取得
return rnd;
}
}
}



なお、

コメント

主な変更点

で、色分けしてあります。

◎質問者からの返答

hive7134様、ありがとうございます。大変参考になりました。画像は乱数での気ままな表示はできません。不規則ながらルールがあります。現段階では手入力でコツコツ入力します。


3 ● hive7134
●2000ポイント

おっと!

回答作成中にお返事があったようですね^^;

見逃してしまいました。

数回にわたって解答してしまったことをお詫びいたします。



さて、

7月30日と31日にlemon.gifの表示を追加してみてください。

ですが、先ほどの回答のMAppliGazoクラス内default:の手前に

case 30:
case 31:
if(now.get(Calendar.MONTH) == Calendar.JULY){
return 2;
}

を加えればOKです。

なお、動作確認はDoJa-4.1を用いて行っております。

(開発環境はJDK1.5 & Eclipse3.2)


4 ● tsyk
●0ポイント

「MAppliクラスとMAppliCanvasクラスにどう関連つけるのか」という質問ですが、MAppliGazoクラスのインスタンスを生成して、MAppliCanvasクラスの変数にそのオブジェクトを保持しておけば、MAppliCanvasからMAppliGazoのメソッドを呼び出すことができるので、そのメソッドで日付けによって表示する画像の順番を変更する処理を行えば良いです。MAppliクラスは特に修正は必要ありません。

// MAppliCanvas.java
public class MAppliCanvas extends Canvas {
Image[] image;
MAppli app = (MAppli)IApplication.getCurrentApp();
MAppliGazo gazo; //追加
String[] name = {"apple", "banana", "lemon", "orange"}; //追加

MAppliCanvas() {
image = new Image[4];
gazo = new MAppliGazo(); //追加
try {
MediaImage m;
for (int i=0; i<4; i++) {
//m = MediaManager.getImage("resource:///" + i + ".gif");
m = MediaManager.getImage("resource:///" + name[i] + ".gif"); //変更
m.use();
image[i] = m.getImage();
}

}
}

public void paint(Graphics g) {
int pattern[] = gazo.getPattern(); //追加
//g.drawImage(image[app.i], 0, 0);
g.drawImage(image[pattern[app.i]], 0, 0); //変更
}
}

MAppliGazoクラスでは、switch/case文で365日分の条件を延々と記述するのではなく、以下のように多次元配列を使って画像の切り替えパターンをテーブル化しておく方法が無難だと思います。ここでは、apple → 0, banana → 1, lemon → 2, orange → 3 のように数値化してあります。

「表示する画像は日付けにより変わる」というのは、実際には、同じパターンが複数の日で使用されるようですが、その法則が不明ですので、基本的には365日分の表示する順番のパターンを用意するように考えました。2006年と2007年では、また違うパターンになるのでしょうか?

このコードでは、真夜中12時を跨いで携帯の開閉が行われた場合に、今日の2番目の画像の次には明日の3番目の画像というようにパターンの途中から継続するようになります。それを嫌う場合には日付けの変化を検出してインデックスを初期化するなどの処理が必要です。

365日分の初期化データを書くのは大変なので、テスト用に乱数を使って初期化する処理に変更してあります。

// MAppliGazo.java
import java.util.*;

public class MAppliGazo {
int year, month, date;
// [12][31][4]の3次元配列にデータを保持しておく(パターンはは例示のためにデタラメなものです)
// 日数の少ない月は31日分になるようにダミーのデータで埋めておく
//int table[][][] = {
//// 1日, 2日, 3日, .., 31日
//{ {0,1,2,3}, {1,3,0,2}, {2,1,3,0} },// 1月
//{ {3,3,2,2}, {0,0,3,1}, {0,1,2,3} },// 2月
// ...
//{ {1,1,2,0}, {3,0,3,2}, {2,3,0,1} },// 12月
//};
int table[][][] = new int [12][31][4]; //テスト用に動的確保する

//テスト用コンストラクタ
MAppliGazo() {
Random rand = new Random();
for (int i=0; i<12; i++) {
for (int j=0; j<31; j++) {
for (int k=0; k<4; k++) {
table[i][j][k] = (rand.nextInt() >>> 1) % 4;
}
}
}
}

public int[] getPattern() {
Calendar now = Calendar.getInstance();
year = now.get(Calendar.YEAR);
month = now.get(Calendar.MONTH)+1;
date = now.get(Calendar.DATE);
int pattern[] = table[month-1][date-1];
return pattern;
}
}
◎質問者からの返答

tsyk様、ありがとうございます。参考にさせていただきます。上にも書きましたが表示に不規則なルールがありますので手入力で記入します。7月30、31、8月1日?8月8日までの表示でかまいませんからまとめてみていただけませんか?


5 ● tsyk
●2000ポイント ベストアンサー

7月30,31日,8月1?8日だけデータを設定してみました。表示のテストが出来るように8月23?25日も追加してあります。2006年のデータのみですが、2007年以降にも対応するには、table2007,table2008などを作成してHashtableに追加してください。

当然ですが、データを設定していない日付にアクセスすると、例外(ArrayIndexOutOfBoundsException)が発生するので、配列にアクセスするまえにデータの存在をチェックする処理を書くか、または全ての日付のデータを作成してください。

今回は直していませんが、画像のファイル名、データの読み込み、画像のインデックス更新など、一連の画像の取り扱いに関する処理をMAppliCanvasとMAppliGazoクラスに分散させずにMAppiGazoだけに集中管理させるほうが、プログラム的には美しいかもしれませんね。

// MAppli.java

import com.nttdocomo.ui.*;

public class MAppli extends MApplication {

int i;
MAppliCanvas c;

public void start() {
c = new MAppliCanvas();
Display.setCurrent(c);
}

public void processSystemEvent(int type, int param) {
if (type == FOLD_CHANGED_EVENT && param == 0) {
deactivate();
sleep();
}
else if (type == FOLD_CHANGED_EVENT && param == 1) {
i = i + 1;
i = i % 4;
c.repaint();
}
}

void exit() {
if (getLaunchType() == LAUNCHED_AS_CONCIERGE) {
deactivate();
}
else {
terminate();
}
}

}
// MAppliCanvas.java

import com.nttdocomo.ui.*;

public class MAppliCanvas extends Canvas {
Image[] image;
MAppli app = (MAppli)IApplication.getCurrentApp();
MAppliGazo gazo;
String[] name = {"apple", "banana", "lemon", "orange"};

MAppliCanvas() {
image = new Image[4];
gazo = new MAppliGazo();
try {
MediaImage m;
for (int i=0; i<4; i++) {
m = MediaManager.getImage("resource:///" + name[i] + ".gif");
m.use();
image[i] = m.getImage();
}
} catch (Exception e) {
;
}
}

public void paint(Graphics g) {
int pattern[] = gazo.getPattern();
g.drawImage(image[pattern[app.i]], 0, 0);
}

}
// MAppliGazo.java

import java.util.*;

public class MAppliGazo {
int year, month, date;
Hashtable tables;
static final int table2006[][][] = {
{ {-1} },// 1月
{ {-1} },// 2月
{ {-1} },// 3月
{ {-1} },// 4月
{ {-1} },// 5月
{ {-1} },// 6月
{{-1},{-1},{-1},{-1},{-1},{-1},{-1},{-1},{-1},{-1},// 7月1?10日
{-1},{-1},{-1},{-1},{-1},{-1},{-1},{-1},{-1},{-1},// 7月11?20日
{-1},{-1},{-1},{-1},{-1},{-1},{-1},{-1},{-1},// 7月21?29日
{2,2,2,2}, {2,2,2,2},// 7月30,31日
},// 7月
{{0,1,2,3}, {0,1,2,3},// 8月1,2日
{1,3,1,3},// 8月3日
{1,2,3,1}, {1,2,3,1}, {1,2,3,1},// 8月4,5,6日
{2,2,2,2}, {2,2,2,2},// 8月7,8日
{-1},{-1},// 8月9?10日
{-1},{-1},{-1},{-1},{-1},{-1},{-1},{-1},{-1},{-1},// 8月11?20日
{-1},{-1},// 8月21?22日
{1,3,0,2},{2,0,3,1},{3,2,1,0},// 8月23,24日,25日
},// 8月
{ {-1} },// 9月
{ {-1} },// 10月
{ {-1} },// 11月
{ {-1} },// 12月
};

MAppliGazo() {
tables = new Hashtable();
tables.put(new Integer(2006), table2006);
}

public int[] getPattern() {
Calendar now = Calendar.getInstance();
year = now.get(Calendar.YEAR);
month = now.get(Calendar.MONTH)+1;
date = now.get(Calendar.DATE);
int[][][] table = (int[][][])tables.get(new Integer(year));
int pattern[] = table[month-1][date-1];
return pattern;
}

}

関連質問


●質問をもっと探す●



0.人力検索はてなトップ
8.このページを友達に紹介
9.このページの先頭へ
対応機種一覧
お問い合わせ
ヘルプ/お知らせ
ログイン
無料ユーザー登録
はてなトップ