じゃんけんゲームを作ってみよう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 でグラフィック(絵として描いた)
ボタンをクリックするようにしてみましょう。
その例は、また次回。
ご意見、ご質問、リクエスト等ございましたら、お気軽にコメントか
メールフォームをご利用ください。
この記事へのコメントはこちら