/** Program: SamRoid Purpose: SamRoidパズル @author segi.tetsu@ss.bch.ntt.jp @version 2.10; 7 April 1996 */ import java.applet.Applet; import java.applet.AudioClip; import java.awt.*; import java.util.Random; import java.util.StringTokenizer; public class SamRoid extends Applet { public void init() { AudioClip au; Image images[]; String labels[]; String lbls = null; String imgs = null; String audiofile = null; int last = 0; String s; s = getParameter("imagelabel"); if (s != null) lbls = s; s = getParameter("imagefile"); if (s != null) imgs = s; s = getParameter("audiofile"); if (s != null) audiofile = s; s = getParameter("last"); if (s != null) last = Integer.parseInt(s); images = new Image[last]; labels = new String[last]; StringTokenizer stlbl = new StringTokenizer(lbls); StringTokenizer stimg = new StringTokenizer(imgs); for (int i = 0; i < last && (stlbl.hasMoreTokens() || stimg.hasMoreTokens()); i++) { //ラベルの読み込み labels[i] = stlbl.nextToken(); //イメージの読み込み images[i] = getImage(getDocumentBase(), stimg.nextToken()); } //完成したときのサウンドの読み込み au = getAudioClip(getDocumentBase(), audiofile); setLayout(new BorderLayout()); PieceCanvas c = new PieceCanvas(images, au); add("Center", c); add("South", new NewGameButton("NewGame", c)); add("North", new SelectImage(labels, c)); } } class PieceCanvas extends Canvas { Piece aPiece[] = new Piece[16]; AudioClip au; Image images[]; Image off_im; Graphics off_g; final int piecewidth = 80; final int pieceheight = 60; int pushedpiecenum = 0; //押されたピースの番号 int imagenum = 0; boolean solvedflag = true; //完成しているかどうか boolean paintall = true; //すべてのピースを描くかどうか boolean draworiginal = true; void changeImage(int imagenum) { this.imagenum = imagenum; repaint(); } PieceCanvas(Image images[], AudioClip au) { this.images = new Image[images.length]; for (int i = 0; i < images.length; i++) this.images[i] = images[i]; this.au = au; //ピースを順番に並べる for (int i = 0; i < 4; i++) for (int j = 0; j < 4; j++) aPiece[i * 4 + j] = new Piece(i, j); } public void shufflePiece() { Random aRandom = new Random(); solvedflag = false; paintall = true; //ピースを並べ替える for (int i = 0; i < 1000; i++) { //上下左右のどの方向に空きスペースを動かすか決める int direction = aRandom.nextInt() % 4; if (direction < 0) direction = -direction; switch (direction) { //0なら空きピースを上に動かす case 0: movePiece(aPiece[15].tellRow() - 1, aPiece[15].tellCol()); break; //1なら空きピースを下に動かす case 1: movePiece(aPiece[15].tellRow() + 1, aPiece[15].tellCol()); break; //2なら空きピースを左に動かす case 2: movePiece(aPiece[15].tellRow(), aPiece[15].tellCol() - 1); break; //3なら空きピースを右に動かす case 3: movePiece(aPiece[15].tellRow(), aPiece[15].tellCol() + 1); break; default: break; } } repaint(); } public void paint(Graphics g) { int x, y; if (off_g == null) { off_im = createImage(320, 480); off_g = off_im.getGraphics(); } off_g.drawImage(images[imagenum], 0, 0, this); if (paintall) { //すべてを描く場合 for (int i = 0; i < 16; i++) paintPiece(g, i); } else { //押されたピースと空きピースを描く paintPiece(g, pushedpiecenum); paintPiece(g, 15); } g.drawImage(off_im, 0, -240, this); } public void paintPiece(Graphics g, int i) { //一つのピースを描く int from_x = aPiece[i].init_col * piecewidth; int from_y = aPiece[i].init_row * pieceheight; int to_x = aPiece[i].tellCol() * piecewidth; int to_y = aPiece[i].tellRow() * pieceheight + 240; if (i == 15 && !solvedflag) { //解けていない場合の空きピース off_g.setColor(Color.blue); off_g.fillRect(to_x, to_y, piecewidth, pieceheight); } else { //普通のピースと解けた場合の空きピース off_g.copyArea(from_x, from_y, piecewidth, pieceheight, to_x - from_x, to_y - from_y); } if (!solvedflag) { //解けていない場合は黒枠を描く off_g.setColor(Color.black); off_g.drawRect(to_x, to_y, piecewidth, pieceheight); } } public void update(Graphics g) { //ちらつきをなくすために、updateをoverwriteする。 paint(g); } public boolean mouseDown(Event e, int x, int y) { //どのピースが押されたか調べる int colpushed = x / piecewidth; int rowpushed = y / pieceheight; if (!solvedflag) { //解けていない場合はピースを動かす movePiece(rowpushed, colpushed); paintall = false; repaint(); paintall = true; } if (solvePuzzle() && !solvedflag) { //解けていた場合はサウンドをならし、フラグをたてる au.play(); solvedflag = true; repaint(); } return true; } public void movePiece(int i, int j) { pushedpiecenum = pushedPiece(i, j); //どのピースが押されたか調べる if (i >= 0 && i <= 3 && j >= 0 && j <= 3) { if (i - 1 == aPiece[15].tellRow() && j == aPiece[15].tellCol()) { //上に空きピースがある aPiece[pushedpiecenum].moveUp(); aPiece[15].moveDown(); } else if (i + 1 == aPiece[15].tellRow() && j == aPiece[15].tellCol()) { //下に空きピースがある aPiece[pushedpiecenum].moveDown(); aPiece[15].moveUp(); } else if (i == aPiece[15].tellRow() && j - 1 == aPiece[15].tellCol()) { //左に空きピースがある aPiece[pushedpiecenum].moveLeft(); aPiece[15].moveRight(); } else if (i == aPiece[15].tellRow() && j + 1 == aPiece[15].tellCol()) { //右に空きピースがある aPiece[pushedpiecenum].moveRight(); aPiece[15].moveLeft(); } } } public int pushedPiece(int i, int j) { //各ピースの位置を調べ、押された位置と等しいものを返す for (int k = 0; k < 16; k++) { if (aPiece[k].tellRow() == i && aPiece[k].tellCol() == j) return k; } //該当ピースがない場合は負を返す return -1; } public boolean solvePuzzle() { //いくつのピースが正しい位置にあるか調べる int count = 0; for (int i = 0; i < 16; i++) if (aPiece[i].correctPiece()) count++; //16のピースが正しい位置にあれば、解けたということ return (count == 16); } } //ボタンのクラス class NewGameButton extends Button { PieceCanvas c; //PieceCanvasのメソッドを呼び出すために必要 NewGameButton(String label, PieceCanvas c) { setLabel(label); //ラベルをセット this.c = c; //PiecsCanvas を受け渡す } public boolean action(Event e, Object o) { if (e.target instanceof Button) { if ("NewGame".equals(o)) //NewGameボタンが押されていたら c.shufflePiece(); //PieceCanvasのshufflePiece()を呼ぶ return true; } return false; } } //チョイスのクラス class SelectImage extends Panel { PieceCanvas canvas; String labels[]; int lastlabel; public boolean action(Event e, Object o) { if (e.target instanceof Choice) { for (int i = 0; i < lastlabel; i++) { if (labels[i].equals(o)) //リストが選択されたら canvas.changeImage(i); //PieceCanvasのchangeImage(int) } //を呼ぶ return true; } return false; } SelectImage(String labels[], PieceCanvas canvas) { this.canvas = canvas; lastlabel = labels.length; this.labels = new String[labels.length]; add(new Label("Select Image : ")); Choice shapes = new Choice(); for (int i = 0; i < labels.length; i++) { shapes.addItem(labels[i]); //ラベルを読み込んで this.labels[i] = labels[i]; //チョイスに加える } add(shapes); } }