Eclipse アプリ作成 Lv7〜Cubeを日付順に並べる〜

イントロダクション

ここ数日の戦いを経て、ようやく先に進めます。※下は戦闘履歴です。

  1. Eclipse アプリ作成 Lv5〜惨敗:CubeにTextureを貼る〜「惨敗」
  2. Java 3DGame LWJGL Retry Lv3 Texture〜動かして理解する3〜「負け越し」
  3. Java 3DGame LWJGL Retry Lv4 デバック〜動かして理解する4〜「黒星」
  4. Java 3DGame LWJGL Retry Lv5 遊んでみる〜動かして理解する5〜「引分け」
  5. Java 3DGame LWJGL Retry Lv6 遊んでみる2〜動かして理解する6〜「白星」

家計簿作成を再開しようと思いますが、その前に戦果の方を見ていただきたく思います。

<現在>

家計簿のためのカレンダー部分が完成しました。

現状では、まだまだわかりづらいのは否めません。。。

しかし、初めに比べれば。。。

<作成当初>

家計簿作成再始動

今回はよりカレンダーらしくするために、カレンダークラスを使用してカレンダーの様にCubeを配置する様にプログラムを変更します。

まずはカレンダー作成

Javaの基本的なクラス(java.util.Calendar)を使用します。作成するクラスは「CalendarPosit」クラスです。

<要件の整理:どんな機能を持たせるか考える>

Cubeを使ってカレンダーを作成しますので。以下の要件を満たす必要があります。→プログラム設計になります。

  1. 対象月の月初の曜日を取得する
  2. 今月の最大日数を取得する
  3. Calendarクラスから取得した曜日が何曜日か判定する
  4. 日曜始まりをデフォルトとして、月曜始まりの場合でも曜日の値(Calendar.DAY_OF_WEEK)を返却する(配列の位置)

実行結果:木のCubeも移動しています

<月曜始まり>の実行結果(isStartMon=true)

<日曜始まり>の実行結果(isStartMon=false)


実装内容:ソースはこちら(Gitでみる)

isStartMonのハンドルを行なっているクラス(DummyGame#init())のソース(2018/11/10現在)

    //// 参照しているフィールド変数(抜粋) ////
    /**
     *  曜日の表示順
     *  true: 月曜始まり false: 日曜始まり
     */
    private boolean isStartMon;
    private static final String[] WEEK_TEXTURE_SUN = new String[]{"Sun", "Mon", "Tue", "Wed", "Thi", "Fri", "Sat"};

    @Override
    public void init(Window window) throws Exception {
        renderer.init(window);
        isStartMon = true;// 月曜始まり、日曜始まりは「false」
        CalendarPosit pos = new CalendarPosit();
        // 月初の曜日
        int firstDayOfWeek = pos.getStartPoint(isStartMon);
        // 今月の最大日数
        int maxDayOfMonth = pos.getMaxDayOfMonth();
        // Cubeの高さ
        ArrayList<float[]> floats = new ArrayList<>();
        floats.add(new float[] {0.0001f, 0.12f, 0.3f, 0.001f, 0.1f, 0.25f, 0.1f});
        floats.add(new float[] {0.15f, 0.19f, 0.23f, 0.2f, 0.08f, 0.13f, 0.12f});
        floats.add(new float[] {0.1f, 0.2f, 0.4f, 0.001f, 0.2f, 0.05f, 0.15f});
        floats.add(new float[] {0.11f, 0.12f, 0.3f, 0.001f, 0.1f, 0.25f, 0.1f});
        floats.add(new float[] {0.12f, 0.13f, 0.14f, 0.015f, 0.16f, 0.17f, 0.18f});
        floats.add(new float[] {0.12f, 0.13f, 0.14f, 0.015f, 0.16f, 0.17f, 0.18f});

        // Cubeの底面のサイズ(正方形)
        final float cubeSize = 0.1f;
        // x軸の初期値
        final float xInit = -0.5f;
        // y軸の初期値
        final float yInit = -0.8f;
        // z軸の初期値
        final float zInit = -2;
        // x軸の増減幅
        final float xWidth = 0.185f;
        // y軸の増減幅
        final float yWidth = 0.033f;
        // z軸の増減幅
        final float zWidth = 0.1f;
        ArrayList arr = new ArrayList();
        
        // マスのカウント
        int box = 0;
        // 日数
        int day = 0;
        // 初めの1回目だけ曜日のテキストプレートを作成する
        boolean isCreateTexture = false;
        // 1ヶ月分(5週間分のマスを作る)
        for(int j = 1; j <= 6; j++) {
        	// 開始点より一列ずらす
        	// X軸の開始点
        	float xStart = xInit - (0.1f * j);
        	// Y軸の開始点
        	float yStart = yInit + (0.06f * j) ;
        	// Z軸の開始点
        	float zStart = zInit - (0.16f * j);
            // 1週間分
        	float[] weekArr = floats.get(j-1);
        	
        	// 1回目だけテクスチャを作成する
        	isCreateTexture = j == 1 ? true: false;
            for(int i = 1; i <= 7; i++) {
            	float xAdd = xWidth * i;
            	float yAdd = yWidth * i;
            	float zAdd = zWidth * i;
        		// 日付をインクリメント
        		box++;
            	if (isCreateTexture) {
            		arr.add(putOnTexturePlate(xStart + xAdd + 0.01f , yStart + yAdd - 0.03f, zStart - zAdd + 0.03f, i-1));
            	}
           	    if (box < firstDayOfWeek) { System.out.println("開始: " + firstDayOfWeek); continue; } day++; if (day >= maxDayOfMonth) {
            		break;
            	}
            	float val = weekArr[i - 1];
        		arr.add(createCube(val,
        				cubeSize, xStart + xAdd, yStart + yAdd, zStart - zAdd));
            }
        }
        // 配列の要素数を指定する
        GameItem[] items = new GameItem[arr.size()];
        // 配列の取り出し
        gameItems = arr.toArray(items);
        
        // DEBUG
        //debug();
    }

ここでのポイントは月曜始まりと、日曜始まりを変更できる様にしたところです。

	/**
	 * 対象月の月初の曜日を取得する
	 * @return Calendar.MONDAY〜SUNDAY
	 */
	public int getStartPoint(boolean isStartMon) {
		int day_week = 0;
		cal.set(Calendar.DATE, 1);
		day_week = cal.get(Calendar.DAY_OF_WEEK);
		if (isStartMon) {
			day_week = day_week == 1 ? 7 : day_week - 1;
		}
		return day_week;
	}

赤字の部分が工夫の部分です、条件文を使って「if文」を使わずに1行で済むし可読性も良い。これを使わないと以下の様なコードになります。(if文を抜粋)

if (isStartMon) {
    if (day_week == 1) {
        day_week = 7;
    } else {
        day_week = day_week -1;
    }
 }

微妙なコードです、なぜかというとif文はネストすると確認しなくてはいけないことが増えるからです。→単純にコード量が多いのもあります。

一応「条件演算子」について、サンプルとして四捨五入の場合です。

/*
 * 返却する値 = 条件式 ? TRUE時の値(式) : FALSE時の値(式)
 * System.in() // 標準入力
 */
int i = System.in;
// 4以下は「0」、5以上は「10」を「response」に代入
int response = i < 5 ? 0 : 10;

そして作成したのが以下のクラス(Gitでみる)です。(ちょっとコード量が多いですが。。。)

package zenryokuservice.gui.lwjgl.kakeibo.util;
import java.util.Calendar;

/**
 * 家計簿の各数値を表示するための領域(日)を作成する
 * @author takunoji
 *
 * 2018/11/10
 */
public class CalendarPosit {
	/** 日本語の曜日 */
	private static final String[] ja_week = new String[] {"日", "月", "火", "水", "木", "金", "土"};
	/** 英語の曜日 */
	private static final String[] en_week = new String[] {"Sun", "Mon", "Tue", "Wed", "thu", "Fri", "Sat"};

	private Calendar cal = null;
	
	public CalendarPosit() {
		cal = Calendar.getInstance();
	}
	
	/**
	 * 今月の最大日数を返す
	 * @return 最大日数
	 */
	public int getMaxDayOfMonth() {
		return cal.getMaximum(Calendar.DATE);
	}

	/**
	 * 今月の最大日数を返す
	 * @move 今月の月からずらす月数
	 * move=1  -> 1ヶ月たす
	 * mobe=-1 -> 1ヶ月引く
	 * 
	 * 
	 * 現在:10月
	 * move=  1  -> 11月の最大日数
	 * move= -1 -> 9月の最大日数
	 * @return 最大日数
	 */
	public int getMaxDayOfMonth(int move) {
		Calendar tmpCal = cal;
		tmpCal.add(Calendar.MONTH, move);
		return tmpCal.getMaximum(Calendar.DATE);
	}

	/**
	 * 対象月の月初の曜日を取得する
	 * @return Calendar.MONDAY〜SUNDAY
	 */
	public int getStartPoint(boolean isStartMon) {
		int day_week = 0;
		cal.set(Calendar.DATE, 1);
		day_week = cal.get(Calendar.DAY_OF_WEEK);
		if (isStartMon) {
			day_week = day_week == 1 ? 7 : day_week - 1;
		}
		return day_week;
	}	

	/**
	 * 現在の年の指定した月初の曜日を返却する
	 * @param month 1-12を指定する
	 * @return 対象月の、月初曜日
	 */
	public int getStartPoint(int month, boolean isStartMon) {
		int day_week = 0;
		Calendar cal = Calendar.getInstance();
		cal.set(Calendar.MONTH, month - 1);
		cal.set(Calendar.DATE, 1);
		
		day_week = cal.get(Calendar.DAY_OF_WEEK);
		return day_week;
	}

	/**
	 * カレンダークラスを返却する。
	 * @return
	 */
	public Calendar getCalendar() {
		return this.cal;
	}
	/**
	 * 開始日付に対応する曜日の値を返す。
	 * @return 曜日の文字列
	 */
	public String getDayOfWeek(boolean isStartMon) {
		return ja_week[getStartPoint(isStartMon)];
	}
	/**
	 * 引数の値が何曜日か判定して返却する
	 * @param value Calendarクラスより取得した、DAY_OF_WEEK
	 * @return 対象の曜日の値
	 */
	public int chkWeek(int value, boolean isStartMon) {
		int day_of_week = 0;
		
		switch(value) {
		case Calendar.MONDAY:
			day_of_week = Calendar.MONDAY;
			break;
		case Calendar.TUESDAY:
			day_of_week = Calendar.TUESDAY;
			break;
		case Calendar.WEDNESDAY:
			day_of_week = Calendar.TUESDAY;
			break;
		case Calendar.THURSDAY:
			day_of_week = Calendar.TUESDAY;
			break;
		case Calendar.FRIDAY:
			day_of_week = Calendar.TUESDAY;
			break;
		case Calendar.SATURDAY:
			day_of_week = Calendar.TUESDAY;
			break;
		case Calendar.SUNDAY:
			day_of_week = Calendar.TUESDAY;
			break;
		default:
			// TODO-[例外処理の実装]
			System.out.println("想定外の曜日です[day_of_week]: " + day_of_week);
			System.exit(-1);
		}

		// 日曜始まり=true, 月曜始まり=false
		if (isStartMon == false) {
			day_of_week = day_of_week < 7 ? day_of_week + 1 : 1;
		}
		return day_of_week;
	}
}

いろんなパターンに対応できる様に先にコードだけ作りました。

関連ページ一覧

<家計簿アプリ作成>

  1. Eclipse アプリ作成 Lv1〜家計簿を作る準備〜
  2. Eclipse アプリ作成 Lv2〜家計簿を作る土台作り〜
  3. Eclipse アプリ作成 Lv3〜3Dグラフ用Cube作り〜
  4. Eclipse アプリ作成 Lv4〜3Dグラフ用Cubeに高さを与える〜
  5. Eclipse アプリ作成 Lv5〜惨敗:CubeにTextureを貼る〜
  6. Eclipse アプリ作成 Lv7〜Cubeを日付順に並べる

Java Basic

  1. Java Basic Level 1 〜Hello Java〜
  2. Java Basic Level2 〜Arithmetic Calculate〜
  3. Java Basic Level3 〜About String class〜
  4. Java Basic Level 4〜Boolean〜
  5. Java Basic Level 5〜If Statement〜
  6. Java Basic Summary from Level1 to 5
  7. Java Basic Level 6 〜Traning of If statement〜
  8. Java Basic Level8 〜How to use for statement〜
  9. Java Basic Level 8.5 〜Array〜
  10. Java Basic Level 9〜Training of for statement〜
  11. Java Basic Level 10 〜While statement 〜
  12. Java Basic Swing〜オブジェクト指向〜
  13. Java Basic Swing Level 2〜オブジェクト指向2〜
  14. サンプル実装〜コンソールゲーム〜
  15. Java Basic インターフェース・抽象クラスの作り方
  16. Java Basic クラスとは〜Step2_1〜
  17. Java Basic JUnit 〜テストスイートの作り方〜