実行結果はこうなります
100枚の場合
$ java Hanoi8 100
これは整数に切り捨てする場所が間違っているからです。
fillRect()は引数に整数を要求しますから、最後は切り捨てなり四捨五入なり整数化が必要ですが、ここでは計算途中で整数化してしまっています。
特にdr。これは円板の半径の差ですが、枚数が多くなると1より小さくなります。これを切り捨てると0になってしまいます。すると全部の円板が同じ半径になってしまうのです。
public void paintComponent(Graphics myg){ super.paintComponent(myg); int boux =(int)getWidth()/2; int minrad =(int)(boux*0.1); int dr =(int)(boux*0.8/(dmax-1)); //ここで0になったら int bottom =(int)(getHeight()*0.9); int dh =(int)(getHeight()*0.8/dmax); int mai = 0; for ( int diskn : pile ){ mai++; int g =(int)(127+128/dmax*diskn); int b =(int)(255-255/dmax*(diskn-1)); myg.setColor(new Color(0,g,b)); int radius = minrad+dr*(diskn-1); //何をかけても0 int x = boux-radius; int y = bottom-dh*mai; myg.fillRect(x,y,radius*2,dh); //半径は皆同じに myg.setColor(new Color(0,0,0)); myg.drawRect(x,y,radius*2,dh); } }
この点は、途中doubleで計算し、最後に切り捨てすることで解消できます。次の改良されたpaintComponent()では半径以外も最後に切り捨てしています。
public void paintComponent(Graphics myg){ super.paintComponent(myg); double boux =getWidth()/2; double minrad =boux*0.1; double dr =boux*0.8/(dmax-1); //doubleで計算しておく。 double bottom =getHeight()*0.9; double dh =getHeight()*0.8/dmax; int mai = 0; for ( int diskn : pile ){ mai++; int g =(int)(127+128/dmax*diskn); int b =(int)(255-255/dmax*(diskn-1)); myg.setColor(new Color(0,g,b)); double radius = minrad+dr*(diskn-1); //ここもdoubleで。 int x = (int)(boux-radius); int y = (int)(bottom-dh*mai); myg.fillRect(x,y,(int)(radius*2),(int)dh); //最後に切り捨て。 myg.setColor(new Color(0,0,0)); myg.drawRect(x,y,(int)(radius*2),(int)dh); } }
この改良で、次の様になります。
色が黒くなるのはdhが小さいため、drawRectで描かれる枠でfillRectの塗りつぶしが隠れてしまうためでしょう。