じゃんけんゲームを作ってみよう6

 

プログラムをどういう使い勝手にするか、即ちユーザインタフェースを
設計するには悩ましいことが多々生じてきます。

毎度、管理人イガジーです。

特に画面遷移、つまり、ある画面(窓)から別の画面に進み、そこからまた
別の画面に、あるいは戻ったり、といった場合の処理は複雑になりがちです。

じゃんけんゲームも、ひとつの画面で済ませる事もできますが
動かしてみると、うーん、いまいち、と感じたりします。
ともかく、実際にそこまで作ってみてから考える事にしましょう。
昨日の、Pon クラスの ActionListener に処理を加えていきます。

グーなり、チョキなり、パーのボタンが押されたら
(1)PCの手を乱数で決める
(2)PCの手を表示する
(3)人(あなた)の手を表示する
(4)勝敗を判定する
(5)判定結果を表示する
(6)勝ち数、負け数、引き分け数などをカウントする
(7)勝ち数、負け数、引き分け数を表示する
といったことを行います。

(1)は
pck=rnd.nextInt(3);で済みますね。
rndは、new Random() してあるもの(インスタンス)です。
(2)と(3)は、dispmesg()メソッドを使うのですが、グー、チョキ、パーで
処理を分けなくても
dispmesg(10+手, xpos,ypos); と一般化できます。
ここで「手」は 0,1,2 の数値です。
dispmesg(10 xpos,ypos); でグーの絵が
dispmesg(11 xpos,ypos); でチョキの絵が
dispmesg(12 xpos,ypos); でパーの絵が表示できますから。

(4)の判定は、少し前に試したものが使えますね。
(5)は、「PCの勝ち」、「人(あなた)の勝ち」、「引き分け」の3通りを
それぞれ分けて処理すれば良いでしょう。
それぞれの処理で、(6)のカウントもおこなってしまいます。
(7)は、JLabelにsetTextすればOKです。
実際のプログラム例を以下に示します。

import java.awt.BorderLayout;
import java.awt.Canvas;
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.Random;

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 Janken3 {
	final int CVWIDTH=360, CVHEIGHT=360;
	final int ICONSZ=60;
	final int MSGJANKEN=0, MSGDRAW=1, MSGYOUWIN=2,MSGPCWIN=3,MSGYOU=7,MSGPC=8;
	final int GBTNSTART=4, GBTNAGAIN=5;
	final int IDLE=0,PLAYING=1;
	int pck=0;
	int ywin,pwin,draw;
	Random rnd=new Random();
	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 [4];
	BufferedImage []bi = new BufferedImage[3];
	BufferedImage imc=null;

	Janken3(){
		String picname="janken.png";
		try {
			imc=ImageIO.read(new File(picname));
		} catch (IOException e) {
			System.out.println(picname + " read error!");
			System.exit(1);
		}
		ywin=pwin=draw=0;
		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);
		dispmsg(MSGJANKEN,50,60);
		g.drawImage(imc, 10, 140, 310, 240, 0, 0, 300, 100, f);
//		dispmsg(GBTNSTART,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]));
			bj[i].addActionListener(new Pon(i));
			bp.add(bj[i]);
		}
		f.setSize(CVWIDTH+4,CVHEIGHT+ICONSZ+100);
		f.setVisible(true);
	}// constructor

	public static void main(String[] args) {
		new Janken3();
	}

	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 GBTNSTART:
			gw=120;break;
		case GBTNAGAIN:
			gw=220; break;
		case MSGYOU: // あなた
			gy=200; gw=100;
			break;
		case MSGPC:  //PC
			gy=250; gw=70;
			break;
		case 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 Pon implements ActionListener {
		final int DRAWDRAW=0, PC_WIN=1, YOU_WIN=2;
		int yk;  // 0=グー, 1=チョキ, 2=パー
		Pon(int kk) {
			yk=kk;
		}// constructor
		@Override
		public void actionPerformed(ActionEvent arg0) {
			pck=rnd.nextInt(3);
			cls();
			dispmsg(MSGPC,0,0); // PC
			dispmsg(10+pck,80,20); //PCの手

			dispmsg(MSGYOU,0,160); // あなた
			dispmsg(10+yk,100,180); //人の手

			// 勝敗判定
			int winlose=DRAWDRAW; // assume draw
			if (pck!=yk) {
				if ((yk==(pck+1))||(yk==(pck-2))) winlose=PC_WIN;
				else winlose=YOU_WIN;
			} // end else

			// 勝敗表示&カウント
			int msgnn=MSGDRAW;
			switch (winlose){
			case YOU_WIN:
				++ywin;
				msgnn=MSGYOUWIN;
				break;
			case PC_WIN:
				++pwin;
				msgnn=MSGPCWIN;
				break;

//			case DRAWDRAW:
			default:
				++draw;
				break;
			}
			dispmsg(msgnn,80,130);
			int round=ywin+pwin+draw;
			resl.setText(String.format("%d戦 あなたの %d勝 %d敗 %d分け",
					round,ywin,pwin,draw));
			cv.repaint();
		}// actionPerformed

	}// class Pon

	class MyCanvas extends Canvas{
		private static final long serialVersionUID = 1L;
		@Override
		public void paint(Graphics g0){
			g0.drawImage(bb, 0, 0, f);
		}
	}
}

これで、一応じゃんけんをプレイできます。が、
画面がひとつなので、前回と同じ手になった時などには
画面の変化が分かりにくいですね。
(よく見れば、ゲーム数は増えていますが)

そこで、勝敗結果表示と、プレイの間にワンクッション
置いてみましょう。「もう一度勝負」ボタンをクリックして
もらうようにするのです。

「もう一度勝負」ボタンを、普通に JButton()で実装しても良い
のですが(その方が簡単ですが)、
練習を兼ねて MouseListener でグラフィック(絵として描いた)
ボタンをクリックするようにしてみましょう。

その例は、また次回。

ご意見、ご質問、リクエスト等ございましたら、お気軽にコメントか
メールフォームをご利用ください。

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

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

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

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