じゃんけんゲームを作ってみよう5
昨日、書き忘れたのですが、Eclipseから動かす場合、読み込む
画像ファイル(janken.png)はプロジェクト名フォルダの直下、
すなわちsrcやbin フォルダと同列に置いてください。
毎度、管理人イガジーです。
さて、昨日は部分的なコードしか掲載しなかったので
今日は画面づくりの全体を掲載します。
描画して終わりなので、まだ動作はしません(ハリボテです)。
import java.awt.BorderLayout;
import java.awt.Canvas;
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
public class Janken1 {
final int CVWIDTH=360, CVHEIGHT=360;
final int ICONSZ=60;
final int MSGJANKEN=0, MSGAIKO=1, MSGYOUWIN=2,MSGPCWIN=3;
final int GBTNSTART=4, GBTNAGAIN=5;
final int MSGYOU=7,MSGPC=8;
JFrame f=new JFrame("じゃんけん");
MyCanvas cv=new MyCanvas();
JLabel resl=new JLabel();
BufferedImage bb=new BufferedImage(CVWIDTH, CVHEIGHT,BufferedImage.TYPE_INT_RGB);
Graphics g,g2;
JButton []bj=new JButton [3];
BufferedImage []bi = new BufferedImage[3];
BufferedImage imc=null;
Janken1(){
String picname="janken.png";
try {
imc=ImageIO.read(new File(picname));
} catch (IOException e) {
System.out.println(picname + " read error!");
System.exit(1);
}
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
resl.setFont(new Font(Font.MONOSPACED,Font.PLAIN,14));
JPanel bp=new JPanel();
g=bb.getGraphics();
cls();
f.add(resl,BorderLayout.NORTH);
f.add(cv,BorderLayout.CENTER);
f.add(bp,BorderLayout.SOUTH);
g.setColor(Color.BLACK);
// test messages (dummy)
resl.setText("10戦 あなたの 5勝 3敗 2分け 勝率50.0%");
// dispmsg(MSGJANKEN, 20, 130); // じゃんけん勝負!
dispmsg(MSGPC,0,0);
dispmsg(12,80,20); // パー
dispmsg(MSGYOU,0,160);
dispmsg(10,100,180); // グー
dispmsg(MSGPCWIN, 80, 130);
dispmsg(GBTNAGAIN,130,300);
for (int i=0;i<3;++i) {
bi[i]=new BufferedImage(ICONSZ,ICONSZ,BufferedImage.TYPE_INT_ARGB);
g2=bi[i].getGraphics();
g2.drawImage(imc, 0, 0, ICONSZ, ICONSZ, 100*i, 0, 100*i+100, 100, f);
g2.dispose();
bj[i]=new JButton(new ImageIcon(bi[i]));
bp.add(bj[i]);
}
f.setSize(CVWIDTH+4,CVHEIGHT+ICONSZ+100);
f.setVisible(true);
}// constructor
public static void main(String[] args) {
new Janken1();
}
void cls(){
g.setColor(Color.WHITE);
g.fillRect(0, 0, CVWIDTH, CVHEIGHT);
}
void dispmsg(int msgn, int x, int y){
int gy=msgn*50+100;
int gx=12;
int gw=260,gh=50;
switch (msgn) {
//case 4: // 始めるボタン
case GBTNSTART:
gw=120;break;
// case 5: // もう一度ボタン
case GBTNAGAIN:
gw=220; break;
// case 7: // あなた
case MSGYOU:
gy=200; gw=100;
break;
// case 8: // PC
case MSGPC:
gy=250; gw=70;
break;
case 10: // グー // 10
gx=gy=0; gw=gh=100;
break;
case 11: // チョキ
gx=100;gy=0; gw=gh=100;
break;
case 12: // パー
gx=200; gy=0; gw=gh=100;
break;
}
g.drawImage(imc, x, y, x+gw, y+gh, gx, gy, gx+gw, gy+gh, f);
}
class MyCanvas extends Canvas{
private static final long serialVersionUID = 1L;
@Override
public void paint(Graphics g0){
g0.drawImage(bb, 0, 0, f);
}
}
}
ボタンを押したら、じゃんけんをプレイできるようにするには
ボタン(bj[])にActionListener を登録します。
ボタンはグー、チョキ、パーの3個あるのですが
処理はほとんど同じで、出す「手」が違うだけです。
ですから、ActionListener を受け持つクラスに
お前は「グー」だ、お前は「チョキ」だ、お前は「パー」だと指定して
ActionListenerは「指定された手を出す」ようにすれば、
1つのクラスで済みます。
ちょっと分かりにくいかもしれませんが、
クラス(ひな形)は1つで、それを3個のオブジェクト(実体)
即ち、「グー」の処理をするインスタンス、
「チョキ」の処理をするインスタンス、
「パー」の処理をするインスタンス、を生成して使うのです。
具体的には、クラス(ひな形)は次のようになります。
class Pon implements ActionListener {
int yk; // 0=グー, 1=チョキ, 2=パー
Pon(int kk) { // constructor
yk=kk;
} // end of constructor
@Override
public void actionPerformed(ActionEvent arg0) {
// 暫定処理=手を描画するだけ
cls();
dispmsg(yk+10,100,180);
cv.repaint();
}
}
グーの処理、チョキの処理、パーの処理といった具体的な処理を
「手(yk=0,1,2)の処理」に抽象化しているわけです。
この抽象化によって、(一見)分かりにくくなりますが
処理が共通化できるために、コードが簡潔になります。
処理を変更したり追加する場合も、1箇所で済みます。
このクラスPon に対して
new Pon(0); // 0=グー
と new する時に「0」を与えると
グー(yk=0)の処理をするインスタンスが生成されます。
同様に
new Pon(1); // 1=チョキ
と new する時に「1」を与えると
チョキ(yk=1)の処理をするインスタンスが生成されます。
ですから、ボタンを生成するループを次のようにすれば良いわけです。
for (int i=0;i<3;++i) {
bi[i]=new BufferedImage(ICONSZ,ICONSZ,BufferedImage.TYPE_INT_ARGB);
g2=bi[i].getGraphics();
g2.drawImage(imc, 0, 0, ICONSZ, ICONSZ, 100*i, 0, 100*i+100, 100, f);
g2.dispose();
bj[i]=new JButton(new ImageIcon(bi[i]));
bj[i].addActionListener(new Pon(i)); // ActionListener登録
bp.add(bj[i]);
}
上記のActionListenerは、手を表示するだけですが
次回はパソコン側の手も表示させて、勝敗判定も追加してみます。
ご意見、ご質問、リクエストなどは、お気軽にコメント、あるいは
メールフォームからどうぞ。
この記事へのコメントはこちら