Javaでオブジェクト指向的な「あみだくじ」プログラムを作ってみました。
Javaの特徴については以下をご覧ください。
https://urashita.com/archives/923
オブジェクト指向的な考え方とプログラムのサンプルに自由にお使いください。
C言語やC#、JavaScriptでも応用できると思います。
Java「あみだくじ」プログラム概説
以下の考え方でオブジェクト指向的あみだくじプログラムを作ってみました。
汎用的なあみだくじを作るクラスAmidaKujiクラスを作る
実行クラスであるRunAmidaKujiクラスから、AmidaKujiクラスのインスタンスを生成する
「あみだくじ」プログラム実行時のスクリーンショット
「あみだくじ」プログラム実行時のスクリーンショットです。
「初期化」で下の数字がランダムで変更されます。
「あみだくじ生成」を押すとランダムであみだくじを生成します。
人数を変更することも可能です。
Java「あみだくじ」プログラム全文
以下のプログラムは、Eclipseで実行出来ます。
RunAmidakuji.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 |
// RunAmidaKuji // 2014/12/10 // Written by urashita.com // Version 1.0 package AmidaKuji; import java.awt.BorderLayout; import java.awt.Button; import java.awt.FlowLayout; import java.awt.Frame; import java.awt.Panel; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; public class RunAmidakuji implements ActionListener { /** * RumAmidakujiクラスのメインメソッド */ public static void main(String[] args) { new RunAmidakuji(); } /** * RunAmidakujiクラス あみだくじ選択画面を生成する */ RunAmidakuji() { Frame frameRunAmidakuji = new Frame("あみだくじ"); frameRunAmidakuji.addWindowListener(new WindowAdapter() { public void windowClosing(WindowEvent ev) { System.exit(0); } }); /* メインパネルにボタンを貼り付ける */ Panel panelMain = new Panel(); Button generalAmidakuji = new Button("汎用的なあみだくじ"); generalAmidakuji.addActionListener(this); panelMain.add(generalAmidakuji); frameRunAmidakuji.add(panelMain, BorderLayout.CENTER); frameRunAmidakuji.setSize(250, 100); frameRunAmidakuji.setVisible(true); } /** * RunAmidaKujiクラスで描画されるボタンのリスナー */ public void actionPerformed(ActionEvent e) { /* ボタンが押されるとAmidakujiインスタンスが生成される */ if (e.getActionCommand().equals("汎用的なあみだくじ")) { new Amidakuji(); } } } |
Amidakuji.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 |
// RunAmidaKuji // 2014/12/10 // Written by urashita.com // Version 1.0 package AmidaKuji; import java.awt.BorderLayout; import java.awt.Button; import java.awt.Canvas; import java.awt.Color; import java.awt.FlowLayout; import java.awt.Frame; import java.awt.Graphics; import java.awt.Label; import java.awt.Panel; import java.awt.TextField; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; import java.awt.image.BufferedImage; import java.util.Arrays; import java.util.Random; /** * Amidakujiクラス */ public class Amidakuji implements Runnable { /** 汎用的なあみだくじ*/ static final String GENERAL_AMIDAKUJI = "汎用的なあみだくじ"; int verticalNumber = 5; // 縦棒の数 int horizontalMaxNumber = 9; // 横棒の最大本数 int yh = 26; int horizontalDensity = horizontalMaxNumber - 2; // 横棒の密度 int x0 = 40; // 左余白 int y0 = 50; // 上余白 int horizontalLength = 210 / (verticalNumber - 1); // 横棒の長さ int verticalLength = yh * (horizontalMaxNumber + 1); // 縦棒の長さ int y1 = y0 + verticalLength; // 縦棒の下端座標 int yh2 = yh / 2; // 隣の横棒をずらす量 Amidakuji amidaKuji; Frame frameAmidakuji; AmidaCanvas amidaCanvas; Graphics graPhics; Random rnd = new Random(); boolean[][] hb = new boolean[10][horizontalMaxNumber]; boolean isGenerated = false; String[] gs = new String[10]; Button initializeButton, generateButton; TextField textField = new TextField("5", 2); // 棒数の初期値(5本) int animationSpeed = 200; int gn; boolean up; boolean running = false; /** * 汎用的なあみだくじのコンストラクタ */ public Amidakuji() { amidaKuji = this; frameAmidakuji = new Frame(GENERAL_AMIDAKUJI); frameAmidakuji.addWindowListener(new WindowAdapter() { public void windowClosing(WindowEvent ev) { frameAmidakuji.dispose(); } }); amidaCanvas = new AmidaCanvas(300, 350); graPhics = amidaCanvas.bufferedImage.getGraphics(); frameAmidakuji.add(amidaCanvas, BorderLayout.CENTER); Panel panelNorth = new Panel(); Panel panelSouth = new Panel(); Panel panelWest = new Panel(); Panel panelEast = new Panel(); panelNorth.setLayout(new FlowLayout(FlowLayout.LEFT)); initializeButton = new Button("初期化"); initializeButton.addActionListener(new InitializeAmidaKuji()); //textField.addActionListener(new InitializeAmidaKuji()); generateButton = new Button("あみだくじ生成"); generateButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { if (isGenerated) { drawAmida(verticalNumber - 1); amidaCanvas.repaint(); } } }); panelNorth.add(new Label("人数:")); panelNorth.add(textField); panelNorth.add(initializeButton); panelNorth.add(generateButton); frameAmidakuji.add(panelNorth, BorderLayout.NORTH); frameAmidakuji.add(panelSouth, BorderLayout.SOUTH); frameAmidakuji.add(panelWest, BorderLayout.WEST); frameAmidakuji.add(panelEast, BorderLayout.EAST); frameAmidakuji.setSize(360, 440); frameAmidakuji.setVisible(true); } /** * あみだくじを描画するメソッド */ void drawAmida(int n) { // n=(縦棒の数-1) graPhics.setColor(Color.GRAY); graPhics.fillRect(0, 0, amidaCanvas.bufferedImage.getWidth(), amidaCanvas.bufferedImage.getHeight()); graPhics.setColor(Color.BLACK); graPhics.drawString("文字の近辺をクリックしてください", 5, 20); for (int i = 0; i < verticalNumber; ++i) { // 縦棒を描画 int x = horizontalLength * i + x0; graPhics.drawLine(x, y0, x, y1); graPhics.drawString(Character.toString((char) ('A' + i)), x - 3, y0 - 6); // 棒の上のラベル graPhics.drawString(gs[i], x - 3, y1 + 16); // 棒の下のラベル } for (int i = 0; i < n; ++i) { for (int v = 0; v < horizontalMaxNumber; ++v) { if (hb[i][v]) { int x = horizontalLength * i + x0; int y2 = v * yh + y0 + yh2 + (i & 1) * yh2; graPhics.drawLine(x, y2, x + horizontalLength, y2); } } } } /** * あみだをたどるアニメ描画スレッド */ public void run() { if (running) { return; } running = true; int y2, x, yt, j, ye; int i = gn; if (i >= verticalNumber) { i = verticalNumber - 1; } y2 = x = 0; graPhics.setColor(Color.CYAN); yt = y0; ye = y1; if (up) { yt = y1; ye = y0; graPhics.setColor(Color.YELLOW); } for (int j2 = 0; j2 < horizontalMaxNumber * 2; ++j2) { j = j2; if (up) { j = horizontalMaxNumber * 2 - j2 - 1; } y2 = j * yh2 + y0 + yh2; x = i * horizontalLength + x0; if (up) { graPhics.fillRect(x - 1, y2, 3, yt - y2); } else { graPhics.fillRect(x - 1, yt, 3, yh2); } repaintwait(animationSpeed); yt = y2; if (((j ^ i) & 1) == 0) { // 偶数上段 or 奇数下段 // 右を見る if (i < (verticalNumber - 1)) { // 右端でなければ if (hb[i][j / 2]) { // 右に横棒あり? graPhics.fillRect(x, yt - 1, horizontalLength + 2, 3); repaintwait(animationSpeed); ++i; } } } else { // 偶数下段 or 奇数上段 // 左を見る if (i > 0) { // 左端でなければ if (hb[i - 1][j / 2]) { // 左に棒あり? graPhics.fillRect(x - horizontalLength, yt - 1, horizontalLength + 2, 3); repaintwait(animationSpeed); --i; } } } }// for j x = i * horizontalLength + x0; if (up) { graPhics.fillRect(x - 1, ye, 3, yh2); } else { graPhics.fillRect(x - 1, yt, 3, ye - yt); } repaintwait(animationSpeed); running = false; } /** * 再描画メソッド */ void repaintwait(int wt) { amidaCanvas.repaint(); try { Thread.sleep(wt); } catch (InterruptedException e) { System.out.println("sleep Excepton!"); } } /** * 汎用的なあみだくじの初期化クラス */ class InitializeAmidaKuji implements ActionListener { public InitializeAmidaKuji() { subInitializeAmidaKuji(); } public void subInitializeAmidaKuji() { if (running) { return; } try { verticalNumber = Integer.parseInt(textField.getText()); } catch (NumberFormatException ex) { verticalNumber = 6; } if (verticalNumber < 2) { verticalNumber = 2; } if (verticalNumber > 10) { verticalNumber = 10; } textField.setText(Integer.toString(verticalNumber)); horizontalLength = 210 / (verticalNumber - 1); // 横棒の長さ // ゴールの数値セット for (int i = 0; i < verticalNumber; ++i) { gs[i] = Integer.toString(i); } for (int i = 0; i < verticalNumber; ++i) { // シャッフル int j = rnd.nextInt(verticalNumber); int k = rnd.nextInt(verticalNumber); String t = gs[j]; gs[j] = gs[k]; gs[k] = t; } for (int rx = 0; rx < verticalNumber; ++rx) { // 横棒の有無をクリア Arrays.fill(hb[rx], false); } for (int i = 0; i < (verticalNumber - 1); ++i) { // 乱数で横棒をセット for (int j = 0; j < horizontalDensity; ++j) { int r = rnd.nextInt(horizontalMaxNumber); hb[i][r] = true; } } // 縦棒のみ描画 graPhics.setColor(Color.GRAY); graPhics.fillRect(0, 0, amidaCanvas.bufferedImage.getWidth(), amidaCanvas.bufferedImage.getHeight()); graPhics.setColor(Color.BLACK); for (int i = 0; i < verticalNumber; ++i) { // 縦棒を描画 int x = horizontalLength * i + x0; graPhics.drawLine(x, y0, x, y1); graPhics.drawString(Character.toString((char) ('A' + i)), x - 3, y0 - 6); // 棒の上のラベル graPhics.drawString(gs[i], x - 3, y1 + 16); // 棒の下のラベル } amidaCanvas.repaint(); isGenerated = true; } public void actionPerformed(ActionEvent e) { this.subInitializeAmidaKuji(); } } /** * あみだくじのキャンバス */ public class AmidaCanvas extends Canvas { private static final long serialVersionUID = 1L; public BufferedImage bufferedImage; public AmidaCanvas(int width, int height) { bufferedImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB); this.addMouseListener(new ClickHandler()); } public void paint(Graphics graPhics) { graPhics.drawImage(bufferedImage, 0, 0, null); } public void update(Graphics graPhics) { paint(graPhics); } } /** * マウスがクリックされたときのハンドラー */ class ClickHandler extends MouseAdapter { public void mouseClicked(MouseEvent me) { if (!isGenerated) { return; } if (running) { return; } int cky = -1; int ckx = -1; int y = me.getY(); if ((y > (y0 - 20)) && (y < y0)) { cky = 0; // 棒の上(アルファベット) } else if ((y > y1) && (y < (y1 + 20))) { cky = 1; // 棒の下(数字) } if (cky >= 0) { int x = me.getX(); int x2 = (x - x0 + 8) / horizontalLength; int x3 = x2 * horizontalLength + 8 + x0; if ((x > (x0 - 8)) && (x < x3)) { ckx = x2; } if (ckx >= 0) { gn = ckx; up = (cky == 1); drawAmida(verticalNumber - 1); new Thread(amidaKuji).start(); } } } } } |
「あみだくじ」プログラムまとめ
このプログラムだけで、Swingやスレッドの基本的な理解もできると思います。
あみだくじのロジックは、交点とぶつかれば必ず曲がるということで、わかりやすいと思います。
プログラミングの無料レッスン体験
約8,000名の受講生と80社以上の導入実績のあるプログラミングやWebデザインのオンラインマンツーマンレッスンCodecamp
<Codecampの特徴>
1 現役エンジニアによる指導
2オンラインでのマンツーマン形式の講義
3大手企業にも導入されている実践的なカリキュラム
↓無料体験レッスン実施中です。
コメント
[…] […]