じゃんけんゲームを作ってみよう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は、手を表示するだけですが
次回はパソコン側の手も表示させて、勝敗判定も追加してみます。

ご意見、ご質問、リクエストなどは、お気軽にコメント、あるいは
メールフォームからどうぞ。

この記事へのコメントはこちら

メールアドレスは公開されませんのでご安心ください。
また、* が付いている欄は必須項目となりますので、必ずご記入をお願いします。

内容に問題なければ、下記の「コメント送信」ボタンを押してください。

日本語が含まれない投稿は無視されますのでご注意ください。(スパム対策)