ローリングコインタワー
テレビでやってたやつ。
円柱状の物体、というか所謂コインを積んでいって、倒したら負けというゲーム。
あのゲームの、現時点での置ける範囲を計算するシミュレーションを作ってみた。
A simulation program for "Coin Tower", a coin-stacking game. — Gist
import java.awt.*; import java.awt.event.*; import java.awt.geom.*; import java.util.*; import javax.swing.*; public class CoinTower extends JFrame { private ArrayList<Coin> tower; public CoinTower() { super("Rolling Coin Tower Demo"); tower = new ArrayList<Coin>(); setSize(800,600); setDefaultCloseOperation(EXIT_ON_CLOSE); getContentPane().add(panel = new MyPanel()); setVisible(true); } private class Coin { private double w; private double x; private double y; private double r; public Coin(double w, double x, double y, double r) { this.w=w;this.x=x;this.y=y;this.r=r; } } private MyPanel panel; private class MyPanel extends JPanel implements MouseListener { private MyPanel() { super(true); addMouseListener(this); } @Override public void paint(Graphics g_) { Graphics2D g = (Graphics2D)g_; for(int i = 0; i < tower.size(); i++) { Coin c = tower.get(i); Arc2D arc = new Arc2D.Double(c.x-c.r, c.y-c.r, c.r*2, c.r*2, 0, 360, Arc2D.CHORD); g.setColor(Color.WHITE); g.fill(arc); g.setColor(Color.BLACK); g.draw(arc); } int ws=0, xs=0, ys=0; int nw=10; Area area = null; for(int i = tower.size()-1; i >= 0; i--) { Coin c = tower.get(i); // ( (xs+nx*nw) / (ws+nw) - c.x ) ^2 + ( (ys+ny*nw) / (ws+nw) - c.y ) ^2 < c.r^2 // ( (xs+nx*nw) - c.x * (ws+nw) ) ^2 + ( (ys+ny*nw) - c.y * (ws+nw) ) ^2 < (c.r*(ws+nw))^2 // ( nx*nw - (c.x*(ws+nw)-xs) ) ^2 + ( ny*nw - (c.y*(ws+nw)-ys) ) ^2 < (c.r*(ws+nw))^2 // ( nx - (c.x*(ws+nw)-xs)/nw ) ^2 + ( ny - (c.y*(ws+nw)-ys)/nw ) ^2 < (c.r*(ws+nw)/nw)^2 double nxc=(c.x*(ws+nw)-xs)/nw; double nyc=(c.y*(ws+nw)-ys)/nw; double nr=c.r*(ws+nw)/nw; System.out.println("("+nxc+","+nyc+")->"+nr); Arc2D arc = new Arc2D.Double(nxc-nr, nyc-nr, nr*2, nr*2, 0, 360, Arc2D.CHORD); Area carea = new Area(arc); if(area == null) { area = carea; } else { area.intersect(carea); } ws += c.w; xs += c.w*c.x; ys += c.w*c.y; } if(area != null) { Path2D path = new Path2D.Double(); path.append(area.getPathIterator(null), false); g.setColor(new Color(255,0,0,128)); g.fill(path); } } @Override public void mouseExited(MouseEvent evt) {} @Override public void mouseEntered(MouseEvent evt) {} @Override public void mouseReleased(MouseEvent evt) {} @Override public void mousePressed(MouseEvent evt) {} @Override public void mouseClicked(MouseEvent evt) { tower.add(new Coin(10, evt.getX(), evt.getY(), 200)); repaint(); } } public static void main(String[] args) { new CoinTower(); } }