学生向けプログラミング入門 | 無料

学生向けにプログラミングを無料で解説。Java、C++、Ruby、PHP、データベース、Ruby on Rails, Python, Django

Javaプログラミング入門その30 乱数を用いたプログラム

>>この記事には書き直した新しいページがあります。<<


<<前  [TOP]  次>>


>>注意<<
JDK9からJavaアプレットのAudioClipは非推奨となっており、このページ通りにプログラムを作成しても音楽は再生出来ません。



ゲームなどで使用する乱数や指数関数、対数関数、平方根、および三角関数といった基本的な数値処理はjava.lang.Mathクラスの各メソッドを利用します。
Mathクラスのメソッドはstaticなメソッドですので、直接メソッドを使用します。
今回使用するメソッドを紹介します。

//ramdomは0.0〜1.0までの疑似乱数を発生。適当な値を掛けて使用します。
int a = (int)(Math.ramdom()*100);

//doubleの平方根を返します。引数もdoubleです。
int a = (int)Math.sqrt(9.0);

//doubleのsin値を返します。
//引数はdouble型のラジアンなので、度から求めるには「(2π/360)*度」=「度*π/180」
double a = Math.sin(90*Math.PI/180);



以下のサンプルプログラムを作成して下さい。


【AwtMathTest1.java】

import java.awt.*;
import java.awt.event.*;

public class AwtMathTest1 extends Canvas implements MouseListener, Runnable {

	//キャンバスの幅と高さ
	private final int WIDTH = 500;
	private final int HEIGHT = 400;

	private Graphics offg;	//ダブルバッファリング用
	private Image offImage;
	private int x = 0;		//矩形の座標
	private int y = 100;
	private int w = 40;		//矩形の幅と高さ
	private int h = 40;
	private int mx, my;		//マウスの座標取得用
	private int sec = 20;	//制限時間は20秒
	private int score = 0;	//スコアは0から;

	//音声用
	private PlayAudio bgm;
	private PlayAudio se;

	/**コンストラクタ*/
	public AwtMathTest1() {

		//super();が省略されている
		setSize(WIDTH, HEIGHT);
		setBackground(Color.black);

		//Canvasで発生したイベントを通知
		addMouseListener(this);

		//音声再生用
		bgm = new PlayAudio("merrygo1.mid");
		se = new PlayAudio("bom01.wav");

		bgm.loop();	//bgmはループ
	}

	/**メインの処理(スレッド処理)*/
	public void run() {
		while (sec >= 0) {	//secが0未満になるまで繰り返し
			try {
				Thread.sleep(1000);	//1000ミリ秒(1秒)スリープ
			}
			catch (InterruptedException ex) {
				System.err.println(ex);
			}
			repaint();
			sec--;	//1秒減らす
		}
		bgm.stop();	//制限時間が過ぎたらbgmを停止
	}


	/**再描写が必要な場合の処理*/
	public void update(Graphics g) {

		//全画面消去をオフスクリーン・バッファへの描き込み
		offg.setColor(Color.black);
		offg.fillRect(0, 0, WIDTH, HEIGHT);

		//矩形の座標を乱数で決定
		x = (int)(Math.random()*(WIDTH-w));	//キャンバス幅 - 矩形幅の範囲
		y = (int)(Math.random()*(HEIGHT-h));	//キャンバス高さ - 矩形高さの範囲

		//オフスクリーン・バッファへの矩形描き込み
		offg.setColor(Color.red);
		offg.fillRect(x, y, w, h);

		//残り時間を描画
		offg.setColor(Color.yellow);
		offg.drawString("Time: " + sec, 10, 10);

		//スコアを描画
		offg.setColor(Color.yellow);
		offg.drawString("Score: " + score, 300, 10);

		//オフスクリーン・バッファに描かれたものを画面に表示
		g.drawImage(offImage, 0, 0, this);
	}

	/**キャンバスで描画の必要があるときに呼ばれるメソッド*/
	public void paint(Graphics g) {

		//オフスクリーン・バッファの領域がない場合は作成
		if (offg == null) {

			//キャンバスと同じ大きさの仮想画面を生成
			offImage = createImage(getSize().width, getSize().height);

			//offImageから仮想画面描画用のグラフィックスコンテキストを取得	
			offg = offImage.getGraphics();
		}

		//矩形と文字列の描画
		g.setColor(Color.red);
		g.fillRect(x, y, w, h);
		g.setColor(Color.yellow);
		g.drawString("Time: " + sec, 10, 10);
		g.setColor(Color.yellow);
		g.drawString("Score: " + score, 300, 10);
	}

	/**マウスがクリックされたときの処理*/
	public void mouseClicked(MouseEvent evt) {

		mx = evt.getX();
		my = evt.getY();

		hantei();		//判定メソッドへ
	}

	/**その他のマウス処理*/
	public void mouseEntered(MouseEvent evt) { }
	public void mouseExited(MouseEvent evt) { }
	public void mousePressed(MouseEvent evt) { }
        public void mouseReleased(MouseEvent evt) { }

	public void hantei() {

		//クリックした座標が矩形の中だった場合当たり
		if (mx >= x && mx <= x+w && my >= y && my <= y+h) {
			se.play();	//当たったら音で知らせる
			score++;
		}
	}

	/**main()*/
	public static void main(String[] args) {

		AwtMathTest1 canvas = new AwtMathTest1();

		MyFrame frame = new MyFrame("MathTest1");
		frame.add(canvas);
		frame.pack();
		frame.setVisible(true);

		//スレッドを生成して開始(runメソッドの呼び出し)
		new Thread(canvas).start();
	}
}



なお、このプログラムを実行するには「merrygo1.mid」と「bom01.wav」が必要になります。
以下の音楽ファイルを保存してください。
[merrygo1.mid]
[bom01.wav]
>>注意<<
JDK9からJavaアプレットのAudioClipは非推奨となっており、このページ通りにプログラムを作成しても音楽は再生出来ません。



これまでのプログラムでオブジェクトのメソッドを利用する際は、生成したインスタンスに対しての参照先を変数などで指定して、「変数.メソッド()」のように呼び出していました。
このようなメソッドを「インスタンス・メソッド(instance method)」あるいは「非static」メソッドと呼ばれます。
これに対してstaticなメソッドは「クラス・メソッド(class method)」とも呼ばれ、特定のオブジェクトへの参照無しで呼び出すことが出来ますから、一般にインスタンス生成に伴う余分なオーバーヘッドなどを避けることが出来ます。
JavaのプログラムはJVMからmain()を呼び出すことで始まりますが、最初の時点ではオブジェクトは1つも生成されていないので、main()はstaticとなっています。


これまでクラスを継承したプログラムを作成する際、特に子クラス(サブクラス)のコンストラクタでは何も指定していませんでしたが、正確に記述するならばサブクラスのコンストラクタの始めで「super();」が実行されています。
つまり「親クラス(スーパークラス)のコンストラクタを引数無しで呼び出し」しているわけです(superはコンストラクタの先頭でのみ使用できます)。
このことは逆に言うとスーパークラスで引数無しのコンストラクタがない場合は、今までのようにコンストラクタで何も記述しないとコンパイル時にエラーとなることを示しています。
また、クラスでコンストラクタの定義をしない場合は、「引数無しのコンストラクタが定義される」という規則になっています。


では、サンプルプログラムを実行してみましょう。
前回作成した[MyFrame.java]を利用していますのでクローズボタンを使って終了できます。
実行すると、BGM(merrygo1.mid)が流れます。
乱数を用いて、逃げる四角を時間内にマウスでクリックし、点数を表示します。
クリックしたときに爆発音(bom01.wav)が出ます。
終了後もあたり判定が有効なままになっています(クリックすると爆発音が出ます)。








以下のサンプルプログラムを作成してみましょう。


【AwtMathTest2.java】

/**
*sin関数を利用した動き
*/
import java.awt.*;

public class AwtMathTest2 extends Canvas implements Runnable {
	//キャンバスの幅と高さ
	private final int WIDTH = 600;
	private final int HEIGHT = 350;

	private Graphics offg; //ダブルバッファリング用
	private Image offImage;
	private int x = 0; //矩形の座標
	private int y = 300;
	private int w = 40; //矩形の幅と高さ
	private int h = 40;
	private int step = 20; //矩形のx座標移動距離
	private int angle = 0; //sin関数で利用する角度

	/**コンストラクタ*/
	public AwtMathTest2() {
		setSize(WIDTH, HEIGHT);
		setBackground(Color.black);
	}

	/**メインの処理(スレッド処理)*/
	public void run() {
		while (true) { //永久に繰り返し
			try {
				Thread.sleep(100); //100ミリ秒(0.1秒)スリープ
			}
			catch (InterruptedException ex) {
				System.err.println(ex);
			}
			repaint();
		}
	}

	/**再描写が必要な場合の処理*/
	public void update(Graphics g) {
		//全画面消去をオフスクリーン・バッファへの描き込み
		offg.setColor(Color.black);
		offg.fillRect(0, 0, WIDTH, HEIGHT);

		//矩形のx座標は端まで行くと方向転換
		if (x >= WIDTH-w) {
			step = -20;
		}
		else if (x <=0) {
			step = 20;
		}
		x += step;

		//矩形のy座標をsin関数で決定
		y = 300-(int)(Math.sin(angle*Math.PI/180)*100);

		//値を表示
		System.out.println("angle=" + angle + " x=" + x + " y=" + y);
		angle += 15;

		if (angle >= 180) {
			angle = 0;
		}
		//オフスクリーン・バッファへの矩形描き込み
		offg.setColor(Color.red);
		offg.fillRect(x, y, w, h);

		//オフスクリーン・バッファに描かれたものを画面に表示
		g.drawImage(offImage, 0, 0, this);
	}

	/**キャンバスで描画の必要があるときに呼ばれるメソッド*/
	public void paint(Graphics g) {

		//オフスクリーン・バッファの領域がない場合は作成
		if (offg == null) {

			offImage = createImage(getSize().width, getSize().height);

			offg = offImage.getGraphics();
		}

		//矩形の描画
		g.setColor(Color.red);
		g.fillRect(x, y, w, h);
	}

	/**main()*/
	public static void main(String[] args) {

		AwtMathTest2 canvas = new AwtMathTest2();

		MyFrame frame = new MyFrame("AwtMathTest2");
		frame.add(canvas);
		frame.pack();
		frame.setVisible(true);

		new Thread(canvas).start();
	}
}



実行結果を確認してみましょう。
前回作成した[MyFrame.java]を利用していますのでクローズボタンを使って終了できます。
sin関数を用いて、矩形がsin波上を移動します。
コマンドプロンプト上に矩形の位置をリアルタイムで表示します。








<<前  [TOP]  次>>