回答編集履歴

4

GitHub リンク追加

2021/09/07 16:23

投稿

jimbe
jimbe

スコア12670

test CHANGED
@@ -571,3 +571,19 @@
571
571
  }
572
572
 
573
573
  ```
574
+
575
+
576
+
577
+ ----
578
+
579
+
580
+
581
+ 弄ってみたコードを GitHub に入れています。
582
+
583
+
584
+
585
+ [https://github.com/Jimbe-github/teratail_java/tree/master/workspace2/teratail_java/src/teratail_java/q357803](https://github.com/Jimbe-github/teratail_java/tree/master/workspace2/teratail_java/src/teratail_java/q357803)
586
+
587
+
588
+
589
+ C.java はオリジナル、C2.java は GameFrame.java から出した Turtle.java を使って C.java の構造を変えずに番号追加(ついでに点線や繰り返し部分を修正)、GameFrame.java は…まぁこちらのより弄っています ^^;;;

3

文字表示位置計算、50や9の変数化、亀さん修正など

2021/09/07 16:23

投稿

jimbe
jimbe

スコア12670

test CHANGED
@@ -4,7 +4,9 @@
4
4
 
5
5
  各イベントの座標に制限が有るのか無いのかコードから良く分からなかったので、全体を対象にしています。
6
6
 
7
+
8
+
7
- マスの大きさであると文字位置だとかあちこち直接数値が書いてありますので私としてはまだ考える余地のあるコードです
9
+ した見た目は殆ど変わらないのに、コードは修正の度に長く…
8
10
 
9
11
 
10
12
 
@@ -14,21 +16,9 @@
14
16
 
15
17
 
16
18
 
17
- import java.awt.BasicStroke;
18
-
19
- import java.awt.Color;
19
+ import java.awt.*;
20
-
21
- import java.awt.Dimension;
20
+
22
-
23
- import java.awt.Graphics;
24
-
25
- import java.awt.Graphics2D;
21
+ import java.awt.geom.Rectangle2D;
26
-
27
- import java.awt.GridBagConstraints;
28
-
29
- import java.awt.GridBagLayout;
30
-
31
- import java.awt.Point;
32
22
 
33
23
  import java.util.ArrayList;
34
24
 
@@ -86,7 +76,7 @@
86
76
 
87
77
  gbc.anchor = GridBagConstraints.CENTER;
88
78
 
89
- add(new GamePanel(), gbc); //描画領域の追加
79
+ add(new GamePanel(50, 9), gbc); //描画領域の追加
90
80
 
91
81
  }
92
82
 
@@ -102,15 +92,15 @@
102
92
 
103
93
  }
104
94
 
105
- final int number, x, y;
95
+ private int number, x, y;
106
-
96
+
107
- final int gx, gy, size;
97
+ private int gx, gy, size;
108
-
98
+
109
- private Color background;
99
+ private Color background = new Color(0, 170, 0);
110
100
 
111
101
  private Event event;
112
102
 
113
- Square(int number, int x, int y) {
103
+ Square(int number, int x, int y, int size) {
114
104
 
115
105
  this.number = number;
116
106
 
@@ -118,29 +108,23 @@
118
108
 
119
109
  this.y = y;
120
110
 
111
+ this.size = size;
112
+
113
+
114
+
121
- this.gx = x * 50;
115
+ this.gx = x * size;
122
-
116
+
123
- this.gy = y * 50;
117
+ this.gy = y * size;
124
-
125
- this.size = 50;
118
+
126
-
127
- this.background = new Color(0, 170, 0);
128
-
129
- }
119
+ }
130
-
120
+
131
- void setEvent(Event event) {
121
+ void setEvent(Event event) { this.event = event; }
132
-
133
- this.event = event;
134
-
135
- }
136
122
 
137
123
  //イベントがあるか
138
124
 
139
- boolean hasEvent() {
140
-
141
- return event != null;
125
+ boolean hasEvent() { return event != null; }
142
-
126
+
143
- }
127
+ //マスの各方向の座標
144
128
 
145
129
  Point getPoint(Direction dir) {
146
130
 
@@ -184,9 +168,25 @@
184
168
 
185
169
  g.drawRect(gx, gy, size, size); //枠
186
170
 
171
+
172
+
187
- g.drawString(""+number, gx+size-15, gy+size-5); //番号
173
+ drawStringAtBottomRight(g, ""+number); //番号
188
-
174
+
189
- if(hasEvent()) event.draw(g, gx+5, gy+5+10); //イベント
175
+ if(hasEvent()) event.draw(g, gx+2, gy+2); //イベント
176
+
177
+ }
178
+
179
+ private void drawStringAtBottomRight(Graphics g, String text) {
180
+
181
+ FontMetrics fm = g.getFontMetrics();
182
+
183
+ int descent = fm.getDescent(); //ベースラインの高さ
184
+
185
+ Rectangle2D rect = fm.getStringBounds(text, g);
186
+
187
+ int width = (int)rect.getWidth(); //文字列の幅
188
+
189
+ g.drawString(text, gx+size-width-1, gy+size-descent-1); //-1 はちょっと隙間
190
190
 
191
191
  }
192
192
 
@@ -216,9 +216,21 @@
216
216
 
217
217
  void draw(Graphics g, int gx, int gy) {
218
218
 
219
+ FontMetrics fm = g.getFontMetrics();
220
+
221
+ gy += fm.getAscent(); //ベースラインから文字頂までの高さ
222
+
219
223
  g.drawString(text1, gx, gy);
220
224
 
225
+ if(text2 != null) {
226
+
227
+ Rectangle2D rect = fm.getStringBounds(text2, g);
228
+
229
+ gy += (int)rect.getHeight();
230
+
221
- if(text2 != null) g.drawString(text2, gx, gy+13);
231
+ g.drawString(text2, gx, gy);
232
+
233
+ }
222
234
 
223
235
  }
224
236
 
@@ -272,10 +284,18 @@
272
284
 
273
285
 
274
286
 
275
- //亀さん
287
+ //右好きの亀さん
276
288
 
277
289
  private static class Turtle {
278
290
 
291
+ interface Confirm {
292
+
293
+ //安全確認. x,y にマイナスや大きな値が入っても例外を出さないよう注意.
294
+
295
+ boolean isSafe(int x, int y);
296
+
297
+ }
298
+
279
299
  enum Direction {
280
300
 
281
301
  NORTH(0,-1) { Direction right() { return EAST; } },
@@ -288,7 +308,7 @@
288
308
 
289
309
 
290
310
 
291
- int dx, dy;
311
+ final int dx, dy;
292
312
 
293
313
  Direction(int dx, int dy) {
294
314
 
@@ -306,7 +326,9 @@
306
326
 
307
327
  private Direction dir;
308
328
 
329
+ private Confirm confirm;
330
+
309
- Turtle(int x, int y, Direction dir) {
331
+ Turtle(int x, int y, Direction dir, Confirm confirm) {
310
332
 
311
333
  this.x = x;
312
334
 
@@ -314,29 +336,23 @@
314
336
 
315
337
  this.dir = dir;
316
338
 
339
+ this.confirm = confirm;
340
+
317
- }
341
+ }
342
+
318
-
343
+ int getX() { return x; }
344
+
345
+ int getY() { return y; }
346
+
319
- Point forward() {
347
+ void forward() {
320
348
 
321
349
  x += dir.dx;
322
350
 
323
351
  y += dir.dy;
324
352
 
325
- return new Point(x, y);
326
-
327
- }
328
-
329
- Point getRightPoint() {
330
-
331
- Direction right = dir.right();
353
+ Direction sence = dir.right(); //この辺が右好き
332
-
354
+
333
- return new Point(x+right.dx, y+right.dy);
355
+ if(confirm.isSafe(x+sence.dx, y+sence.dy)) dir = sence;
334
-
335
- }
336
-
337
- void turnRight() {
338
-
339
- dir = dir.right();
340
356
 
341
357
  }
342
358
 
@@ -352,13 +368,23 @@
352
368
 
353
369
  private Random random = new Random();
354
370
 
355
-
371
+ private final int square_size;
372
+
356
-
373
+ private final int square_count;
374
+
375
+
376
+
357
- GamePanel() {
377
+ GamePanel(int square_size, int square_count) {
358
378
 
359
379
  super(null);
360
380
 
381
+ this.square_size = square_size;
382
+
383
+ this.square_count = square_count;
384
+
385
+
386
+
361
- setPreferredSize(new Dimension(50*9+50, 50*9));
387
+ setPreferredSize(new Dimension(square_size*(square_count+1), square_size*square_count));
362
388
 
363
389
  setMinimumSize(getPreferredSize());
364
390
 
@@ -398,31 +424,25 @@
398
424
 
399
425
  private void initSquareList() {
400
426
 
401
- int i = 0;
402
-
403
- squareList.add(new Square(i+1, 4, 4));
404
-
405
- Turtle t = new Turtle(4, 4, Turtle.Direction.EAST);
427
+ Turtle turtle = new Turtle(square_count/2, square_count/2, Turtle.Direction.EAST, new Turtle.Confirm() {
406
-
407
- for(i++ ; i<9*9; i++) {
428
+
408
-
409
- Point point = t.forward();
429
+ @Override
410
-
430
+
411
- squareList.add(new Square(i+1, point.x, point.y));
431
+ public boolean isSafe(int x, int y) {
412
-
413
-
414
-
415
- Point right = t.getRightPoint();
432
+
416
-
417
- boolean found = false;
418
-
419
- for(Square s : squareList) {
420
-
421
- if(found = (s.x == right.x && s.y == right.y)) break;
433
+ for(Square s : squareList) if(s.x == x && s.y == y) return false; //既に通った
434
+
435
+ return true;
422
436
 
423
437
  }
424
438
 
439
+ });
440
+
441
+
442
+
443
+ for(int number=1; number<=square_count*square_count; turtle.forward(), number++) {
444
+
425
- if(!found) t.turnRight(); //右に進めるなら右に曲がる
445
+ squareList.add(new Square(number, turtle.getX(), turtle.getY(), square_size));
426
446
 
427
447
  }
428
448
 
@@ -480,7 +500,7 @@
480
500
 
481
501
  private Square getRandomSquare() {
482
502
 
483
- return getRandomSquare(9,0,9,0);
503
+ return getRandomSquare(square_count,0,square_count,0);
484
504
 
485
505
  }
486
506
 
@@ -498,11 +518,7 @@
498
518
 
499
519
  private Square getSquare(int x, int y) {
500
520
 
501
- for(Square s : squareList) {
502
-
503
- if(s.x == x && s.y == y) return s;
521
+ for(Square s : squareList) if(s.x == x && s.y == y) return s;
504
-
505
- }
506
522
 
507
523
  return null;
508
524
 
@@ -520,11 +536,11 @@
520
536
 
521
537
  g.setColor(Color.yellow);
522
538
 
523
- g.fillRect(50*9, 0, 50, 50);
539
+ g.fillRect(square_size*square_count, 0, square_size, square_size);
524
540
 
525
541
  g.setColor(Color.black);
526
542
 
527
- g.drawString("ゴール", 50*9+5, 13);
543
+ g.drawString("ゴール", square_size*square_count+5, 13);
528
544
 
529
545
 
530
546
 
@@ -540,9 +556,9 @@
540
556
 
541
557
  dotLineDrawer.setStart(squareList.get(0).getPoint(Square.Direction.CENTER));
542
558
 
543
- for(int i=1; i<squareList.size()-1; i++) {
559
+ for(Square s : squareList.subList(1, squareList.size()-1)) {
544
-
560
+
545
- dotLineDrawer.draw(g, squareList.get(i).getPoint(Square.Direction.CENTER));
561
+ dotLineDrawer.draw(g, s.getPoint(Square.Direction.CENTER));
546
562
 
547
563
  }
548
564
 

2

点線を BasicStroke 使用に変更、螺旋化を亀さん使用に変更。

2021/09/05 18:20

投稿

jimbe
jimbe

スコア12670

test CHANGED
@@ -14,18 +14,26 @@
14
14
 
15
15
 
16
16
 
17
+ import java.awt.BasicStroke;
18
+
17
19
  import java.awt.Color;
18
20
 
19
21
  import java.awt.Dimension;
20
22
 
21
23
  import java.awt.Graphics;
22
24
 
25
+ import java.awt.Graphics2D;
26
+
23
27
  import java.awt.GridBagConstraints;
24
28
 
25
29
  import java.awt.GridBagLayout;
26
30
 
27
31
  import java.awt.Point;
28
32
 
33
+ import java.util.ArrayList;
34
+
35
+ import java.util.List;
36
+
29
37
  import java.util.Random;
30
38
 
31
39
 
@@ -94,9 +102,9 @@
94
102
 
95
103
  }
96
104
 
97
- private int number;
105
+ final int number, x, y;
98
-
106
+
99
- private int gx, gy, size;
107
+ final int gx, gy, size;
100
108
 
101
109
  private Color background;
102
110
 
@@ -106,6 +114,10 @@
106
114
 
107
115
  this.number = number;
108
116
 
117
+ this.x = x;
118
+
119
+ this.y = y;
120
+
109
121
  this.gx = x * 50;
110
122
 
111
123
  this.gy = y * 50;
@@ -218,19 +230,13 @@
218
230
 
219
231
  private static class DotLineDrawer {
220
232
 
221
- private int count;
222
-
223
233
  private int x, y;
224
234
 
225
- private int solid_period;
235
+ private BasicStroke dashed;
226
-
227
- private int pattern_length;
236
+
228
-
229
- DotLineDrawer(int solid_period, int space_period) {
237
+ DotLineDrawer(int solid_period) {
230
-
231
- this.solid_period = solid_period;
238
+
232
-
233
- this.pattern_length = solid_period + space_period;
239
+ dashed = new BasicStroke(0, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER, 1, new float[]{solid_period}, 0);
234
240
 
235
241
  }
236
242
 
@@ -238,8 +244,6 @@
238
244
 
239
245
  void setStart(Point start) {
240
246
 
241
- count = 0;
242
-
243
247
  x = start.x;
244
248
 
245
249
  y = start.y;
@@ -250,105 +254,177 @@
250
254
 
251
255
  void draw(Graphics g, Point end) {
252
256
 
257
+ Graphics2D g2 = (Graphics2D)g.create();
258
+
259
+ g2.setStroke(dashed);
260
+
261
+ g2.drawLine(x, y, end.x, end.y);
262
+
263
+ g2.dispose();
264
+
265
+ x = end.x;
266
+
267
+ y = end.y;
268
+
269
+ }
270
+
271
+ }
272
+
273
+
274
+
275
+ //亀さん
276
+
277
+ private static class Turtle {
278
+
279
+ enum Direction {
280
+
281
+ NORTH(0,-1) { Direction right() { return EAST; } },
282
+
283
+ SOUTH(0, 1) { Direction right() { return WEST; } },
284
+
285
+ EAST( 1,0) { Direction right() { return SOUTH; } },
286
+
287
+ WEST(-1,0) { Direction right() { return NORTH; } };
288
+
289
+
290
+
291
+ int dx, dy;
292
+
293
+ Direction(int dx, int dy) {
294
+
295
+ this.dx = dx;
296
+
297
+ this.dy = dy;
298
+
299
+ }
300
+
301
+ abstract Direction right();
302
+
303
+ }
304
+
305
+ private int x, y;
306
+
307
+ private Direction dir;
308
+
309
+ Turtle(int x, int y, Direction dir) {
310
+
311
+ this.x = x;
312
+
313
+ this.y = y;
314
+
315
+ this.dir = dir;
316
+
317
+ }
318
+
319
+ Point forward() {
320
+
321
+ x += dir.dx;
322
+
323
+ y += dir.dy;
324
+
325
+ return new Point(x, y);
326
+
327
+ }
328
+
329
+ Point getRightPoint() {
330
+
331
+ Direction right = dir.right();
332
+
333
+ return new Point(x+right.dx, y+right.dy);
334
+
335
+ }
336
+
337
+ void turnRight() {
338
+
339
+ dir = dir.right();
340
+
341
+ }
342
+
343
+ }
344
+
345
+
346
+
347
+ //描画する紙を表すクラス
348
+
349
+ private static class GamePanel extends JPanel {
350
+
351
+ private List<Square> squareList = new ArrayList<>(); //中心を index=0 とし、螺旋を展開した直線状態
352
+
353
+ private Random random = new Random();
354
+
355
+
356
+
357
+ GamePanel() {
358
+
359
+ super(null);
360
+
361
+ setPreferredSize(new Dimension(50*9+50, 50*9));
362
+
363
+ setMinimumSize(getPreferredSize());
364
+
365
+
366
+
367
+ initSquareList();
368
+
369
+
370
+
371
+ squareList.get(0).setEvent(new Event("スタート"));
372
+
373
+
374
+
375
+ setForwardingEvent(); //"進む"イベント(1)
376
+
377
+ setRotateEvent("⤵ 90°"); //盤面回転イベント(1)
378
+
379
+ setForwardingEvent(); //"進む"イベント(2)
380
+
381
+ setRotateEvent("⤵ 180°"); //盤面回転イベント(2)
382
+
383
+ setForwardingEvent(); //"進む"イベント(3)
384
+
253
- if(x != end.x) { //横線?
385
+ setToLeftEvent(); //"左へ"イベント
386
+
254
-
387
+ setForwardingEvent(); //"進む"イベント(4)
388
+
389
+ setForwardingEvent(); //"進む"イベント(5)
390
+
391
+ setForwardingEvent(); //"進む"イベント(6)
392
+
393
+ }
394
+
395
+
396
+
397
+ //マス準備
398
+
399
+ private void initSquareList() {
400
+
401
+ int i = 0;
402
+
403
+ squareList.add(new Square(i+1, 4, 4));
404
+
405
+ Turtle t = new Turtle(4, 4, Turtle.Direction.EAST);
406
+
407
+ for(i++ ; i<9*9; i++) {
408
+
409
+ Point point = t.forward();
410
+
411
+ squareList.add(new Square(i+1, point.x, point.y));
412
+
413
+
414
+
255
- int dx = (int)Math.signum(end.x - x);
415
+ Point right = t.getRightPoint();
416
+
256
-
417
+ boolean found = false;
418
+
257
- for( ; x!=end.x; x+=dx, count=(count+1)%pattern_length) {
419
+ for(Square s : squareList) {
258
-
420
+
259
- if(count < solid_period) g.drawRect(x, y, 0, 0);
421
+ if(found = (s.x == right.x && s.y == right.y)) break;
260
422
 
261
423
  }
262
424
 
263
- } else { //縦線
264
-
265
- int dy = (int)Math.signum(end.y - y);
266
-
267
- for( ; y!=end.y; y+=dy, count=(count+1)%pattern_length) {
268
-
269
- if(count < solid_period) g.drawRect(x, y, 0, 0);
425
+ if(!found) t.turnRight(); //右に進めるなら右に曲がる
270
-
426
+
271
- }
427
+ }
272
-
273
- }
274
-
275
- }
276
-
277
- }
278
-
279
-
280
-
281
- //描画する紙を表すクラス
282
-
283
- private static class GamePanel extends JPanel {
284
-
285
- //螺旋座標
286
-
287
- private static final int POINTS[] = {
288
-
289
- 4,4, 5,4, 5,5, 4,5, 3,5, 3,4, 3,3, 4,3, 5,3,
290
-
291
- 6,3, 6,4, 6,5, 6,6, 5,6, 4,6, 3,6, 2,6, 2,5,
292
-
293
- 2,4, 2,3, 2,2, 3,2, 4,2, 5,2, 6,2, 7,2, 7,3,
294
-
295
- 7,4, 7,5, 7,6, 7,7, 6,7, 5,7, 4,7, 3,7, 2,7,
296
-
297
- 1,7, 1,6, 1,5, 1,4, 1,3, 1,2, 1,1, 2,1, 3,1,
298
-
299
- 4,1, 5,1, 6,1, 7,1, 8,1, 8,2, 8,3, 8,4, 8,5,
300
-
301
- 8,6, 8,7, 8,8, 7,8, 6,8, 5,8, 4,8, 3,8, 2,8,
302
-
303
- 1,8, 0,8, 0,7, 0,6, 0,5, 0,4, 0,3, 0,2, 0,1,
304
-
305
- 0,0, 1,0, 2,0, 3,0, 4,0, 5,0, 6,0, 7,0, 8,0
306
-
307
- };
308
-
309
- private Square squares[] = new Square[9*9]; //中心を [0] とし、螺旋を展開した直線状態
310
-
311
- private Random random = new Random();
312
-
313
-
314
-
315
- GamePanel() {
316
-
317
- super(null);
318
-
319
- setPreferredSize(new Dimension(50*9+50, 50*9));
320
-
321
- setMinimumSize(getPreferredSize());
322
-
323
-
324
-
325
- for(int number=1, i=0, j=0; number<=9*9; number++, i++, j+=2) {
326
-
327
- squares[i] = new Square(number, POINTS[j], POINTS[j+1]);
328
-
329
- }
330
-
331
- squares[0].setEvent(new Event("スタート"));
332
-
333
-
334
-
335
- setForwardingEvent(); //"進む"イベント(1)
336
-
337
- setRotateEvent("⤵ 90°"); //盤面回転イベント(1)
338
-
339
- setForwardingEvent(); //"進む"イベント(2)
340
-
341
- setRotateEvent("⤵ 180°"); //盤面回転イベント(2)
342
-
343
- setForwardingEvent(); //"進む"イベント(3)
344
-
345
- setToLeftEvent(); //"左へ"イベント
346
-
347
- setForwardingEvent(); //"進む"イベント(4)
348
-
349
- setForwardingEvent(); //"進む"イベント(5)
350
-
351
- setForwardingEvent(); //"進む"イベント(6)
352
428
 
353
429
  }
354
430
 
@@ -422,9 +498,9 @@
422
498
 
423
499
  private Square getSquare(int x, int y) {
424
500
 
425
- for(int i=0; i<POINTS.length; i+=2) {
501
+ for(Square s : squareList) {
426
-
502
+
427
- if(POINTS[i] == x && POINTS[i+1] == y) return squares[i/2];
503
+ if(s.x == x && s.y == y) return s;
428
504
 
429
505
  }
430
506
 
@@ -454,27 +530,23 @@
454
530
 
455
531
  //各マス
456
532
 
457
- for(int i=0; i<squares.length; i++) {
458
-
459
- squares[i].draw(g);
533
+ for(Square s : squareList) s.draw(g);
460
-
461
- }
462
534
 
463
535
 
464
536
 
465
537
  //点線
466
538
 
467
- DotLineDrawer dotLineDrawer = new DotLineDrawer(5,5);
539
+ DotLineDrawer dotLineDrawer = new DotLineDrawer(5);
468
-
540
+
469
- dotLineDrawer.setStart(squares[0].getPoint(Square.Direction.CENTER));
541
+ dotLineDrawer.setStart(squareList.get(0).getPoint(Square.Direction.CENTER));
470
-
542
+
471
- for(int i=1; i<squares.length-1; i++) {
543
+ for(int i=1; i<squareList.size()-1; i++) {
472
-
544
+
473
- dotLineDrawer.draw(g, squares[i].getPoint(Square.Direction.CENTER));
545
+ dotLineDrawer.draw(g, squareList.get(i).getPoint(Square.Direction.CENTER));
474
-
546
+
475
- }
547
+ }
476
-
548
+
477
- dotLineDrawer.draw(g, squares[squares.length-1].getPoint(Square.Direction.EAST)); //最後はマスの右端まで
549
+ dotLineDrawer.draw(g, squareList.get(squareList.size()-1).getPoint(Square.Direction.EAST)); //最後はマスの右端まで
478
550
 
479
551
  }
480
552
 

1

getSquare 修正

2021/09/05 13:33

投稿

jimbe
jimbe

スコア12670

test CHANGED
@@ -422,7 +422,13 @@
422
422
 
423
423
  private Square getSquare(int x, int y) {
424
424
 
425
+ for(int i=0; i<POINTS.length; i+=2) {
426
+
427
+ if(POINTS[i] == x && POINTS[i+1] == y) return squares[i/2];
428
+
429
+ }
430
+
425
- return squares[y*9+x];
431
+ return null;
426
432
 
427
433
  }
428
434