あみだくじを作ってみよう5

 

プログラミング作業のうち、約半分は動作確認、即ちデバッグ作業です。
場合によっては、目的のプログラムよりもデバッグ用のプログラミングの方が
コーディング量が多くなったりします。

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

昨日のあみだをたどるプログラムも、少々デバッグに時間がかかりました。
最終コードからは、削除していますが、各判定後に描画する線の位置を
少しずらしたり、色を変えて、どこが思い通りに動いていないのか、を探ったりしました。
Java は、こういう処理の追加削除が簡単に行えるので便利です。

さて、あみだくじのどの棒をたどるかの指定を含めたプログラム例を以下に示します。

import java.awt.BorderLayout;
import java.awt.Button;
import java.awt.Canvas;
import java.awt.Color;
import java.awt.Frame;
import java.awt.Graphics;
import java.awt.Panel;
import java.awt.TextField;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.awt.image.BufferedImage;
import java.util.Arrays;
import java.util.Random;

public class Amida2 {
	int nn=6;  // 縦棒の数
	int vn=7;   // 横棒の最大本数
	int vd=vn-2; // 横棒の密度
	int x0=40; // 左余白
	int y0=50; // 上余白
	int xlen=210/(nn-1);   // 横棒の長さ
	int ylen=260;  // 縦棒の長さ
	int y1=y0+ylen;  // 縦棒の下端座標
	int yh=(ylen-20)/vn; // 横棒の間隔
	int yh2=yh/2; // 隣の横棒をずらす量

	Frame f;
	MyCanvas cv;
	Graphics g;
	Random rnd=new Random();
	boolean [][] hb=new boolean[16][16];
	String []gs=new String[16];
	TextField tn=new TextField("0",2);
	Button trc=new Button("Trace");

	public Amida2() {
		f=new Frame("Amida");
		f.addWindowListener(new WindowAdapter(){
			public void windowClosing(WindowEvent ev) {
				System.exit(0);
			}
		});
		cv=new MyCanvas(400,500);
		g=cv.b.getGraphics();
		Panel p0=new Panel();
		p0.add(tn); // たどる棒の指定
		trc.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				int t=0;
				drawAmida(nn-1);
				try {
					t=Integer.parseInt(tn.getText());
				} catch (NumberFormatException ex) {
					t=0;
				}
				if (t>=nn) t=nn-1;
				trace(t);
				cv.repaint();
			}
		});
		p0.add(trc); // たどるボタン
		f.add(p0,BorderLayout.NORTH);
		f.add(cv,BorderLayout.CENTER);

		// ゴールの数値セット
		for (int i=0;i<nn;++i) gs[i]=Integer.toString(i);
		for (int i=0;i<nn;++i) { // シャッフル
			int j=rnd.nextInt(nn);
			int k=rnd.nextInt(nn);
			String t=gs[j];
			gs[j]=gs[k]; gs[k]=t;
		}
		g.setColor(Color.WHITE);

		for (int rx=0;rx<=nn;++rx) { // 横棒の有無をクリア
			Arrays.fill(hb[rx], false);
		}
		for (int i=0;i<(nn-1);++i) {  // 乱数で横棒をセット
			for (int j=0;j<vd;++j) {
				int r=rnd.nextInt(vn);
				hb[i][r]=true;
			}
		}
		drawAmida(nn-1);
		f.setSize(300,420);
		f.setVisible(true);
	}
	void drawAmida(int n) {
		g.setColor(Color.BLACK);
		g.fillRect(0, 0, cv.b.getWidth(), cv.b.getHeight());
		g.setColor(Color.WHITE);
		for (int i=0;i<nn;++i) { // 縦棒を描画
			int x=xlen*i+x0;
			g.drawLine(x, y0, x, y1);
			g.drawString(Character.toString((char) ('A'+i)), x-3, y0-6); // 棒の上のラベル
			g.drawString(gs[i], x-3, y1+16); // 棒の下のラベル
		}

		for (int i=0;i<n;++i) {
			for (int v=0;v<vn;++v) {
				if (hb[i][v]) {
					int x=xlen*i+x0;
					int y2=v*yh+y0+yh2+(i&1)*yh2;
					g.drawLine(x, y2, x+xlen, y2);
				}
			}
		}
	}
	void trace(int k) {
		int y2,x;
		int i=k;
		if (i>nn) i=nn;
		y2=x=0;
		g.setColor(Color.CYAN);
		int yt=y0;
		for (int j=0;j<(vn*2);++j) {
			y2=j*yh2+y0+yh2;
			x=i*xlen+x0;
			g.drawLine(x-1, yt, x-1, y2);
			g.drawLine(x+1, yt, x+1, y2);
			yt=y2;
			if ((i&1)==0) { // 偶数(A,C,E,...)なら
				if ((j&1)==0) { // 上段(ずらしていない方)
//					if (i<(nn-1)){
						if (hb[i][j/2]) { // 右に横棒あり?
							g.drawLine(x, yt-1, x+xlen, yt-1);
							g.drawLine(x, yt+1, x+xlen, yt+1);
							++i;
						}
//					}
				}else{ // 下段(ずらしている方)
					if (i>0) {
						if (hb[i-1][j/2]) { // 左に棒あり?
							g.drawLine(x-xlen, yt-1, x, yt-1);
							g.drawLine(x-xlen, yt+1, x, yt+1);
							--i;
						}
					}
				}
			}else{ // 奇数(B,D,F,...)なら
				if ((j&1)==0) { // 上段
					if (i>0) { // 左端でなければ左を見る
						if (hb[i-1][j/2]) { // 左に棒あり?
							g.drawLine(x-xlen, yt-1, x, yt-1);
							g.drawLine(x-xlen, yt+1, x, yt+1);
							--i;
						}
					}
				}else{ // 下段なら右を見る
//					if (i<(nn-1)) {
						if (hb[i][j/2]) { // 右に棒あり?
							g.drawLine(x, yt-1, x+xlen, yt-1);
							g.drawLine(x, yt+1, x+xlen, yt+1);
							++i;
						}
//					}
				}
			}// endif 奇数の棒
		}// for j
		g.setColor(Color.CYAN);
		x=i*xlen+x0;
		g.drawLine(x-1,yt,x-1,y1);
		g.drawLine(x+1,yt,x+1,y1);
	}

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

	public class MyCanvas extends Canvas{
		private static final long serialVersionUID = 1L;
		public BufferedImage b;

		public MyCanvas(int ww,int hh) {
			b=new BufferedImage(ww,hh,BufferedImage.TYPE_INT_RGB);
		}
		public void paint(Graphics g0) {
			g0.drawImage(b,0,0,null);
		}
	}
}

「0」で左端の棒(A)、「1」で2番目の棒(B)をたどります。
ABCなどを入力するようにした方が良いのですが、
デバッグ用なので簡単に済ませています。

下から上にたどる処理も、現状のものを少し変更すればできそうです。
ぜひ、挑戦してみてください。

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

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

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

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