解決策その2の続き。
クリアまでの時間を競うというのもゲームのよくあるパターンです。やってみましょう

System.currentTimeMillis()は現在時をミリ秒単位で知らせてくれます。戻り値はintでなくlongです。(実際には1970年1月1日からの現在までの経過時間を返します)
ゲームの最初に
long time0 = System.currentTimeMillis();
として時刻を記録し、ゲームの終わりに、
long time1 = System.currentTimeMillis();
として時刻を再度記録します。
time1-time0
は、かかった時間をミリ秒単位で計測したものになります。つまり16000となれば16秒ということです。
普通は1000で割って秒に直します。
(time1-time0)/1000
longとintの計算なので整数に切り捨てられます。
少数点以下も表現したいときは次のようにします。
(time1-time0)/1000.0
いまさらですが、green, blue は斜めの線にしておくと跳ね返りの方向が分かっていいでしょう。全角のバックスラッシュは「きごう」で変換すると出てきます。"/"は「すらっしゅ」を変換してもOKです。
rbtn = new JButton("start");
gbtn = new JButton("\");
bbtn = new JButton("/");
import java.awt.*;
import javax.swing.*;
import java.awt.event.*;
import java.awt.image.*;
public class MoveDisk8 extends JFrame implements ActionListener{
JButton rbtn;
JButton gbtn;
JButton bbtn;
MyPanel mypnl;
JPanel btnpnl;
BufferedImage buffimg;
Graphics bfg;
int gctgrn = 0;
int gctblu = 0;
int clct = 0;
int bnct = 0;
int tmax = 2;
Target[] ts = new Target[tmax];
//constructor
public MoveDisk8() {
setDefaultCloseOperation(EXIT_ON_CLOSE);
setTitle("MoveDisk");
mypnl = new MyPanel();
rbtn = new JButton("start");
gbtn = new JButton("\");
bbtn = new JButton("/");
btnpnl = new JPanel();
btnpnl.setLayout(new GridLayout(1,3,0,0));
btnpnl.add(rbtn);
btnpnl.add(gbtn);
btnpnl.add(bbtn);
setLayout(new BorderLayout());
add(mypnl, BorderLayout.CENTER);
add(btnpnl,BorderLayout.SOUTH);
rbtn.addActionListener(this);
gbtn.addActionListener(this);
bbtn.addActionListener(this);
pack();
setVisible(true);
//BufferedImageを作るのはpaintComponentに移した
}
//イベント処理
@Override
public void actionPerformed(ActionEvent e) {
if (e.getSource() == rbtn) {
clct=0;
gctblu=0;
gctgrn=0;
bnct =0;
rbtn.setEnabled(false);
rbtn.setText("busy");
Thread thread = new moveDisk(mypnl,buffimg);
thread.start();
}
if (e.getSource() == gbtn) {
gctgrn++;
}
if (e.getSource() == bbtn) {
gctblu++;
}
}
public static void main(String[] args){
MoveDisk8 myframe = new MoveDisk8();
}
//内部クラス
public class MyPanel extends JPanel{
Color bc= new Color(255,255,191); //背景の色
Color c = new Color(0,0,0); //楕円の色
boolean firsttime = true;
public MyPanel(){
setBackground(new Color(255,255,191));
setPreferredSize(new Dimension(400,400));
//panel側で大きさを指定する
}
@Override
public void paintComponent(Graphics myg){
super.paintComponent(myg);
if (firsttime){ //1回目の描画でBufferedImageをつくる
buffimg = new BufferedImage(
getSize().width,
getSize().height,
BufferedImage.TYPE_INT_RGB);
bfg = buffimg.createGraphics();
bfg.setColor(bc);
bfg.fillRect(0, 0, getSize().width, getSize().height);
firsttime = false; //次回はやらない
}
myg.drawImage(buffimg, 0, 0
,getSize().width, getSize().height,this);
//getSize().widthはMyPanelのインスタンスの幅
}
//円を動かすメソッド→下記内部クラスに
}// end of class MyPanel
//円を動かすクラス
class moveDisk extends Thread{
MyPanel pnl;
BufferedImage image;
int x ;
int y ;
int lx =0;
int ly =0;
int d = 10;
int dx = 5;
int dy = 0;
int stime = 50; //sleeptime dx=10:stime=100
int ctgrn;
int ctblu;
//constructor
public moveDisk(MyPanel pn, BufferedImage im) {
this.pnl = pn;
this.image = im;
y = (int)(image.getHeight()*Math.random());
int w = image.getWidth();
int h = image.getHeight();
for(int i=0 ; tmax>i ; i++){
ts[i] = new Target(w,h);
}
ctgrn = gctgrn;
ctblu = gctblu;
}
@Override
public void run() {
Graphics thg = image.createGraphics();
Color bc= new Color(255,255,191); //背景の色
thg.setColor(bc);
thg.fillRect(0,0,image.getWidth(),image.getHeight());
thg.setColor(Color.blue);
for(int i=0 ; tmax>i ; i++){
if (ts[i].cleared) continue;
thg.fillOval(ts[i].x-d/2,ts[i].y-d/2,d,d);
}
while ( ! rbtn.isEnabled() ){
if (gctgrn != ctgrn) {
int tmp = dx;
dx = dy;
dy = tmp;
ctgrn = gctgrn;
}
if (gctblu != ctblu) {
int tmp = dy;
dy = -dx;
dx = -tmp;
ctblu = gctblu;
}
thg.setColor(bc);
thg.fillOval(lx-d/2,ly-d/2,d,d);
for(int i=0 ; tmax>i ; i++){
if (ts[i].cleared) continue;
if (d/2>Math.abs(ts[i].x-x)){
if (d/2>Math.abs(ts[i].y-y)){
ts[i].cleared = true;
thg.fillOval(ts[i].x-d/2,ts[i].y-d/2,d,d);
clct++;
}
}
}
thg.setColor(Color.red);
thg.fillOval(x-d/2,y-d/2,d,d);
if (clct==tmax) {
int sx = x+8;
if (sx>image.getWidth()-60) sx=image.getWidth()-60;
int sy = y+16;
if (sy>image.getHeight()-60) sy=image.getHeight()-60;
thg.drawString("Cleared",sx,sy);
thg.drawString("Click "+(gctgrn+gctblu),sx,sy+16);
thg.drawString("Bounce "+bnct,sx,sy+16*2);
rbtn.setEnabled(true);
rbtn.setText("replay");
}
pnl.repaint();
lx = x;
ly = y;
x += dx;
y += dy;
if (x >image.getWidth()){
x = 2*image.getWidth()-x;
dx = -dx;
}
if (0 > x){
x = -x;
dx = -dx;
}
if (y >image.getHeight()){
y = 2*image.getHeight()-y;
dy = -dy;
}
if (0 > y){
y = -y;
dy = -dy;
}
//(stime÷1000 秒)停止
try {
Thread.sleep(stime);
}
catch(InterruptedException ex) {
System.err.println(ex);
}
}//end of while
}//end of run
}//end of class moveDisk
class Target{
int x; //x位置
int y; //y位置
boolean cleared = false; //クリアされたかどうか
public Target(int w,int h){
x = (int)(w*Math.random());
y = (int)(h*Math.random());
}
}//end of class Target
}
主な変更点
MoveDisk8.javaに書き加えます。
1回のゲームが終わるたびに Click 3 などとクリック数が表示されています
その下の bouns 0 は壁の跳ね返り数を数えるためのものですが、これはまだ実装されていません。跳ね返り数は bnct という変数を使うように、宣言して初期値は入っています。跳ね返るところに bnct++ などと加えて正しい数が表示されるようにしなさい。
また、上記を参考にクリアにかかった秒数も表示するようにしなさい。