回答編集履歴
4
GitHub リンク追加
answer
CHANGED
@@ -284,4 +284,12 @@
|
|
284
284
|
}
|
285
285
|
}
|
286
286
|
}
|
287
|
-
```
|
287
|
+
```
|
288
|
+
|
289
|
+
----
|
290
|
+
|
291
|
+
弄ってみたコードを GitHub に入れています。
|
292
|
+
|
293
|
+
[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)
|
294
|
+
|
295
|
+
C.java はオリジナル、C2.java は GameFrame.java から出した Turtle.java を使って C.java の構造を変えずに番号追加(ついでに点線や繰り返し部分を修正)、GameFrame.java は…まぁこちらのより弄っています ^^;;;
|
3
文字表示位置計算、50や9の変数化、亀さん修正など
answer
CHANGED
@@ -1,19 +1,14 @@
|
|
1
1
|
取り敢えず描画のみ似せて見ました。
|
2
2
|
各マスやイベントをクラスにしたり、点線も専用クラスにしています。
|
3
3
|
各イベントの座標に制限が有るのか無いのかコードから良く分からなかったので、全体を対象にしています。
|
4
|
-
マスの大きさであるとか文字の位置だとかあちこちに直接数値が書いてありますので、私としてはまだ考える余地のあるコードです。
|
5
4
|
|
5
|
+
動かした見た目は殆ど変わらないのに、コードは修正の度に長く…。
|
6
|
+
|
6
7
|
```java
|
7
8
|
package teratail_java.q357803;
|
8
9
|
|
9
|
-
import java.awt.BasicStroke;
|
10
|
-
import java.awt.
|
10
|
+
import java.awt.*;
|
11
|
-
import java.awt.Dimension;
|
12
|
-
import java.awt.Graphics;
|
13
|
-
import java.awt.
|
11
|
+
import java.awt.geom.Rectangle2D;
|
14
|
-
import java.awt.GridBagConstraints;
|
15
|
-
import java.awt.GridBagLayout;
|
16
|
-
import java.awt.Point;
|
17
12
|
import java.util.ArrayList;
|
18
13
|
import java.util.List;
|
19
14
|
import java.util.Random;
|
@@ -42,7 +37,7 @@
|
|
42
37
|
gbc.gridwidth = 1;
|
43
38
|
gbc.gridheight = 1;
|
44
39
|
gbc.anchor = GridBagConstraints.CENTER;
|
45
|
-
add(new GamePanel(), gbc); //描画領域の追加
|
40
|
+
add(new GamePanel(50, 9), gbc); //描画領域の追加
|
46
41
|
}
|
47
42
|
|
48
43
|
//マス
|
@@ -50,26 +45,23 @@
|
|
50
45
|
enum Direction {
|
51
46
|
CENTER, EAST, WEST, NORTH, SOUTH;
|
52
47
|
}
|
53
|
-
|
48
|
+
private int number, x, y;
|
54
|
-
|
49
|
+
private int gx, gy, size;
|
55
|
-
private Color background;
|
50
|
+
private Color background = new Color(0, 170, 0);
|
56
51
|
private Event event;
|
57
|
-
Square(int number, int x, int y) {
|
52
|
+
Square(int number, int x, int y, int size) {
|
58
53
|
this.number = number;
|
59
54
|
this.x = x;
|
60
55
|
this.y = y;
|
56
|
+
this.size = size;
|
57
|
+
|
61
|
-
this.gx = x *
|
58
|
+
this.gx = x * size;
|
62
|
-
this.gy = y *
|
59
|
+
this.gy = y * size;
|
63
|
-
this.size = 50;
|
64
|
-
this.background = new Color(0, 170, 0);
|
65
60
|
}
|
66
|
-
void setEvent(Event event) {
|
61
|
+
void setEvent(Event event) { this.event = event; }
|
67
|
-
this.event = event;
|
68
|
-
}
|
69
62
|
//イベントがあるか
|
70
|
-
boolean hasEvent() {
|
71
|
-
|
63
|
+
boolean hasEvent() { return event != null; }
|
72
|
-
|
64
|
+
//マスの各方向の座標
|
73
65
|
Point getPoint(Direction dir) {
|
74
66
|
switch(dir) {
|
75
67
|
case EAST:
|
@@ -91,9 +83,17 @@
|
|
91
83
|
g2.dispose();
|
92
84
|
|
93
85
|
g.drawRect(gx, gy, size, size); //枠
|
86
|
+
|
94
|
-
|
87
|
+
drawStringAtBottomRight(g, ""+number); //番号
|
95
|
-
if(hasEvent()) event.draw(g, gx+
|
88
|
+
if(hasEvent()) event.draw(g, gx+2, gy+2); //イベント
|
96
89
|
}
|
90
|
+
private void drawStringAtBottomRight(Graphics g, String text) {
|
91
|
+
FontMetrics fm = g.getFontMetrics();
|
92
|
+
int descent = fm.getDescent(); //ベースラインの高さ
|
93
|
+
Rectangle2D rect = fm.getStringBounds(text, g);
|
94
|
+
int width = (int)rect.getWidth(); //文字列の幅
|
95
|
+
g.drawString(text, gx+size-width-1, gy+size-descent-1); //-1 はちょっと隙間
|
96
|
+
}
|
97
97
|
}
|
98
98
|
|
99
99
|
//イベント
|
@@ -107,8 +107,14 @@
|
|
107
107
|
this.text2 = text2;
|
108
108
|
}
|
109
109
|
void draw(Graphics g, int gx, int gy) {
|
110
|
+
FontMetrics fm = g.getFontMetrics();
|
111
|
+
gy += fm.getAscent(); //ベースラインから文字頂までの高さ
|
110
112
|
g.drawString(text1, gx, gy);
|
113
|
+
if(text2 != null) {
|
114
|
+
Rectangle2D rect = fm.getStringBounds(text2, g);
|
115
|
+
gy += (int)rect.getHeight();
|
111
|
-
|
116
|
+
g.drawString(text2, gx, gy);
|
117
|
+
}
|
112
118
|
}
|
113
119
|
}
|
114
120
|
|
@@ -135,15 +141,19 @@
|
|
135
141
|
}
|
136
142
|
}
|
137
143
|
|
138
|
-
//亀さん
|
144
|
+
//右好きの亀さん
|
139
145
|
private static class Turtle {
|
146
|
+
interface Confirm {
|
147
|
+
//安全確認. x,y にマイナスや大きな値が入っても例外を出さないよう注意.
|
148
|
+
boolean isSafe(int x, int y);
|
149
|
+
}
|
140
150
|
enum Direction {
|
141
151
|
NORTH(0,-1) { Direction right() { return EAST; } },
|
142
152
|
SOUTH(0, 1) { Direction right() { return WEST; } },
|
143
153
|
EAST( 1,0) { Direction right() { return SOUTH; } },
|
144
154
|
WEST(-1,0) { Direction right() { return NORTH; } };
|
145
155
|
|
146
|
-
int dx, dy;
|
156
|
+
final int dx, dy;
|
147
157
|
Direction(int dx, int dy) {
|
148
158
|
this.dx = dx;
|
149
159
|
this.dy = dy;
|
@@ -152,33 +162,36 @@
|
|
152
162
|
}
|
153
163
|
private int x, y;
|
154
164
|
private Direction dir;
|
165
|
+
private Confirm confirm;
|
155
|
-
Turtle(int x, int y, Direction dir) {
|
166
|
+
Turtle(int x, int y, Direction dir, Confirm confirm) {
|
156
167
|
this.x = x;
|
157
168
|
this.y = y;
|
158
169
|
this.dir = dir;
|
170
|
+
this.confirm = confirm;
|
159
171
|
}
|
172
|
+
int getX() { return x; }
|
173
|
+
int getY() { return y; }
|
160
|
-
|
174
|
+
void forward() {
|
161
175
|
x += dir.dx;
|
162
176
|
y += dir.dy;
|
163
|
-
|
177
|
+
Direction sence = dir.right(); //この辺が右好き
|
178
|
+
if(confirm.isSafe(x+sence.dx, y+sence.dy)) dir = sence;
|
164
179
|
}
|
165
|
-
Point getRightPoint() {
|
166
|
-
Direction right = dir.right();
|
167
|
-
return new Point(x+right.dx, y+right.dy);
|
168
|
-
}
|
169
|
-
void turnRight() {
|
170
|
-
dir = dir.right();
|
171
|
-
}
|
172
180
|
}
|
173
181
|
|
174
182
|
//描画する紙を表すクラス
|
175
183
|
private static class GamePanel extends JPanel {
|
176
184
|
private List<Square> squareList = new ArrayList<>(); //中心を index=0 とし、螺旋を展開した直線状態
|
177
185
|
private Random random = new Random();
|
186
|
+
private final int square_size;
|
187
|
+
private final int square_count;
|
178
188
|
|
179
|
-
GamePanel() {
|
189
|
+
GamePanel(int square_size, int square_count) {
|
180
190
|
super(null);
|
191
|
+
this.square_size = square_size;
|
192
|
+
this.square_count = square_count;
|
193
|
+
|
181
|
-
setPreferredSize(new Dimension(
|
194
|
+
setPreferredSize(new Dimension(square_size*(square_count+1), square_size*square_count));
|
182
195
|
setMinimumSize(getPreferredSize());
|
183
196
|
|
184
197
|
initSquareList();
|
@@ -198,19 +211,16 @@
|
|
198
211
|
|
199
212
|
//マス準備
|
200
213
|
private void initSquareList() {
|
201
|
-
int i = 0;
|
202
|
-
squareList.add(new Square(i+1, 4, 4));
|
203
|
-
Turtle
|
214
|
+
Turtle turtle = new Turtle(square_count/2, square_count/2, Turtle.Direction.EAST, new Turtle.Confirm() {
|
204
|
-
for(i++ ; i<9*9; i++) {
|
205
|
-
|
215
|
+
@Override
|
206
|
-
|
216
|
+
public boolean isSafe(int x, int y) {
|
217
|
+
for(Square s : squareList) if(s.x == x && s.y == y) return false; //既に通った
|
218
|
+
return true;
|
219
|
+
}
|
220
|
+
});
|
207
221
|
|
208
|
-
Point right = t.getRightPoint();
|
209
|
-
boolean found = false;
|
210
|
-
|
222
|
+
for(int number=1; number<=square_count*square_count; turtle.forward(), number++) {
|
211
|
-
|
223
|
+
squareList.add(new Square(number, turtle.getX(), turtle.getY(), square_size));
|
212
|
-
}
|
213
|
-
if(!found) t.turnRight(); //右に進めるなら右に曲がる
|
214
224
|
}
|
215
225
|
}
|
216
226
|
|
@@ -239,7 +249,7 @@
|
|
239
249
|
|
240
250
|
//ランダムにマスを選択
|
241
251
|
private Square getRandomSquare() {
|
242
|
-
return getRandomSquare(
|
252
|
+
return getRandomSquare(square_count,0,square_count,0);
|
243
253
|
}
|
244
254
|
private Square getRandomSquare(int xbound, int xoffset, int ybound, int yoffset) {
|
245
255
|
int x = random.nextInt(xbound) + xoffset;
|
@@ -248,9 +258,7 @@
|
|
248
258
|
}
|
249
259
|
//x,y指定から Square を得る
|
250
260
|
private Square getSquare(int x, int y) {
|
251
|
-
for(Square s : squareList) {
|
252
|
-
|
261
|
+
for(Square s : squareList) if(s.x == x && s.y == y) return s;
|
253
|
-
}
|
254
262
|
return null;
|
255
263
|
}
|
256
264
|
|
@@ -259,9 +267,9 @@
|
|
259
267
|
|
260
268
|
//ゴール
|
261
269
|
g.setColor(Color.yellow);
|
262
|
-
g.fillRect(
|
270
|
+
g.fillRect(square_size*square_count, 0, square_size, square_size);
|
263
271
|
g.setColor(Color.black);
|
264
|
-
g.drawString("ゴール",
|
272
|
+
g.drawString("ゴール", square_size*square_count+5, 13);
|
265
273
|
|
266
274
|
//各マス
|
267
275
|
for(Square s : squareList) s.draw(g);
|
@@ -269,8 +277,8 @@
|
|
269
277
|
//点線
|
270
278
|
DotLineDrawer dotLineDrawer = new DotLineDrawer(5);
|
271
279
|
dotLineDrawer.setStart(squareList.get(0).getPoint(Square.Direction.CENTER));
|
272
|
-
for(
|
280
|
+
for(Square s : squareList.subList(1, squareList.size()-1)) {
|
273
|
-
dotLineDrawer.draw(g,
|
281
|
+
dotLineDrawer.draw(g, s.getPoint(Square.Direction.CENTER));
|
274
282
|
}
|
275
283
|
dotLineDrawer.draw(g, squareList.get(squareList.size()-1).getPoint(Square.Direction.EAST)); //最後はマスの右端まで
|
276
284
|
}
|
2
点線を BasicStroke 使用に変更、螺旋化を亀さん使用に変更。
answer
CHANGED
@@ -6,12 +6,16 @@
|
|
6
6
|
```java
|
7
7
|
package teratail_java.q357803;
|
8
8
|
|
9
|
+
import java.awt.BasicStroke;
|
9
10
|
import java.awt.Color;
|
10
11
|
import java.awt.Dimension;
|
11
12
|
import java.awt.Graphics;
|
13
|
+
import java.awt.Graphics2D;
|
12
14
|
import java.awt.GridBagConstraints;
|
13
15
|
import java.awt.GridBagLayout;
|
14
16
|
import java.awt.Point;
|
17
|
+
import java.util.ArrayList;
|
18
|
+
import java.util.List;
|
15
19
|
import java.util.Random;
|
16
20
|
|
17
21
|
import javax.swing.JFrame;
|
@@ -46,12 +50,14 @@
|
|
46
50
|
enum Direction {
|
47
51
|
CENTER, EAST, WEST, NORTH, SOUTH;
|
48
52
|
}
|
49
|
-
|
53
|
+
final int number, x, y;
|
50
|
-
|
54
|
+
final int gx, gy, size;
|
51
55
|
private Color background;
|
52
56
|
private Event event;
|
53
57
|
Square(int number, int x, int y) {
|
54
58
|
this.number = number;
|
59
|
+
this.x = x;
|
60
|
+
this.y = y;
|
55
61
|
this.gx = x * 50;
|
56
62
|
this.gy = y * 50;
|
57
63
|
this.size = 50;
|
@@ -108,51 +114,66 @@
|
|
108
114
|
|
109
115
|
//点線描画
|
110
116
|
private static class DotLineDrawer {
|
111
|
-
private int count;
|
112
117
|
private int x, y;
|
113
|
-
private
|
118
|
+
private BasicStroke dashed;
|
114
|
-
private int pattern_length;
|
115
|
-
DotLineDrawer(int solid_period
|
119
|
+
DotLineDrawer(int solid_period) {
|
116
|
-
this.solid_period = solid_period;
|
117
|
-
|
120
|
+
dashed = new BasicStroke(0, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER, 1, new float[]{solid_period}, 0);
|
118
121
|
}
|
119
122
|
//始点
|
120
123
|
void setStart(Point start) {
|
121
|
-
count = 0;
|
122
124
|
x = start.x;
|
123
125
|
y = start.y;
|
124
126
|
}
|
125
127
|
//始点もしくは最後に draw した後から描画
|
126
128
|
void draw(Graphics g, Point end) {
|
127
|
-
|
129
|
+
Graphics2D g2 = (Graphics2D)g.create();
|
130
|
+
g2.setStroke(dashed);
|
128
|
-
|
131
|
+
g2.drawLine(x, y, end.x, end.y);
|
129
|
-
for( ; x!=end.x; x+=dx, count=(count+1)%pattern_length) {
|
130
|
-
|
132
|
+
g2.dispose();
|
133
|
+
x = end.x;
|
134
|
+
y = end.y;
|
131
|
-
|
135
|
+
}
|
132
|
-
} else { //縦線
|
133
|
-
int dy = (int)Math.signum(end.y - y);
|
134
|
-
for( ; y!=end.y; y+=dy, count=(count+1)%pattern_length) {
|
135
|
-
if(count < solid_period) g.drawRect(x, y, 0, 0);
|
136
|
-
|
136
|
+
}
|
137
|
+
|
138
|
+
//亀さん
|
139
|
+
private static class Turtle {
|
140
|
+
enum Direction {
|
141
|
+
NORTH(0,-1) { Direction right() { return EAST; } },
|
142
|
+
SOUTH(0, 1) { Direction right() { return WEST; } },
|
143
|
+
EAST( 1,0) { Direction right() { return SOUTH; } },
|
144
|
+
WEST(-1,0) { Direction right() { return NORTH; } };
|
145
|
+
|
146
|
+
int dx, dy;
|
147
|
+
Direction(int dx, int dy) {
|
148
|
+
this.dx = dx;
|
149
|
+
this.dy = dy;
|
137
150
|
}
|
151
|
+
abstract Direction right();
|
138
152
|
}
|
153
|
+
private int x, y;
|
154
|
+
private Direction dir;
|
155
|
+
Turtle(int x, int y, Direction dir) {
|
156
|
+
this.x = x;
|
157
|
+
this.y = y;
|
158
|
+
this.dir = dir;
|
159
|
+
}
|
160
|
+
Point forward() {
|
161
|
+
x += dir.dx;
|
162
|
+
y += dir.dy;
|
163
|
+
return new Point(x, y);
|
164
|
+
}
|
165
|
+
Point getRightPoint() {
|
166
|
+
Direction right = dir.right();
|
167
|
+
return new Point(x+right.dx, y+right.dy);
|
168
|
+
}
|
169
|
+
void turnRight() {
|
170
|
+
dir = dir.right();
|
171
|
+
}
|
139
172
|
}
|
140
173
|
|
141
174
|
//描画する紙を表すクラス
|
142
175
|
private static class GamePanel extends JPanel {
|
143
|
-
//螺旋座標
|
144
|
-
private static final int POINTS[] = {
|
145
|
-
4,4, 5,4, 5,5, 4,5, 3,5, 3,4, 3,3, 4,3, 5,3,
|
146
|
-
6,3, 6,4, 6,5, 6,6, 5,6, 4,6, 3,6, 2,6, 2,5,
|
147
|
-
2,4, 2,3, 2,2, 3,2, 4,2, 5,2, 6,2, 7,2, 7,3,
|
148
|
-
7,4, 7,5, 7,6, 7,7, 6,7, 5,7, 4,7, 3,7, 2,7,
|
149
|
-
1,7, 1,6, 1,5, 1,4, 1,3, 1,2, 1,1, 2,1, 3,1,
|
150
|
-
4,1, 5,1, 6,1, 7,1, 8,1, 8,2, 8,3, 8,4, 8,5,
|
151
|
-
8,6, 8,7, 8,8, 7,8, 6,8, 5,8, 4,8, 3,8, 2,8,
|
152
|
-
1,8, 0,8, 0,7, 0,6, 0,5, 0,4, 0,3, 0,2, 0,1,
|
153
|
-
0,0, 1,0, 2,0, 3,0, 4,0, 5,0, 6,0, 7,0, 8,0
|
154
|
-
};
|
155
|
-
private Square
|
176
|
+
private List<Square> squareList = new ArrayList<>(); //中心を index=0 とし、螺旋を展開した直線状態
|
156
177
|
private Random random = new Random();
|
157
178
|
|
158
179
|
GamePanel() {
|
@@ -160,11 +181,10 @@
|
|
160
181
|
setPreferredSize(new Dimension(50*9+50, 50*9));
|
161
182
|
setMinimumSize(getPreferredSize());
|
162
183
|
|
163
|
-
for(int number=1, i=0, j=0; number<=9*9; number++, i++, j+=2) {
|
164
|
-
|
184
|
+
initSquareList();
|
165
|
-
}
|
166
|
-
squares[0].setEvent(new Event("スタート"));
|
167
185
|
|
186
|
+
squareList.get(0).setEvent(new Event("スタート"));
|
187
|
+
|
168
188
|
setForwardingEvent(); //"進む"イベント(1)
|
169
189
|
setRotateEvent("⤵ 90°"); //盤面回転イベント(1)
|
170
190
|
setForwardingEvent(); //"進む"イベント(2)
|
@@ -176,6 +196,24 @@
|
|
176
196
|
setForwardingEvent(); //"進む"イベント(6)
|
177
197
|
}
|
178
198
|
|
199
|
+
//マス準備
|
200
|
+
private void initSquareList() {
|
201
|
+
int i = 0;
|
202
|
+
squareList.add(new Square(i+1, 4, 4));
|
203
|
+
Turtle t = new Turtle(4, 4, Turtle.Direction.EAST);
|
204
|
+
for(i++ ; i<9*9; i++) {
|
205
|
+
Point point = t.forward();
|
206
|
+
squareList.add(new Square(i+1, point.x, point.y));
|
207
|
+
|
208
|
+
Point right = t.getRightPoint();
|
209
|
+
boolean found = false;
|
210
|
+
for(Square s : squareList) {
|
211
|
+
if(found = (s.x == right.x && s.y == right.y)) break;
|
212
|
+
}
|
213
|
+
if(!found) t.turnRight(); //右に進めるなら右に曲がる
|
214
|
+
}
|
215
|
+
}
|
216
|
+
|
179
217
|
//"進む"イベント
|
180
218
|
private void setForwardingEvent() {
|
181
219
|
Square square = getRandomSquare();
|
@@ -210,8 +248,8 @@
|
|
210
248
|
}
|
211
249
|
//x,y指定から Square を得る
|
212
250
|
private Square getSquare(int x, int y) {
|
213
|
-
for(
|
251
|
+
for(Square s : squareList) {
|
214
|
-
if(
|
252
|
+
if(s.x == x && s.y == y) return s;
|
215
253
|
}
|
216
254
|
return null;
|
217
255
|
}
|
@@ -226,17 +264,15 @@
|
|
226
264
|
g.drawString("ゴール", 50*9+5, 13);
|
227
265
|
|
228
266
|
//各マス
|
229
|
-
for(int i=0; i<squares.length; i++) {
|
230
|
-
|
267
|
+
for(Square s : squareList) s.draw(g);
|
231
|
-
}
|
232
268
|
|
233
269
|
//点線
|
234
|
-
DotLineDrawer dotLineDrawer = new DotLineDrawer(5
|
270
|
+
DotLineDrawer dotLineDrawer = new DotLineDrawer(5);
|
235
|
-
dotLineDrawer.setStart(
|
271
|
+
dotLineDrawer.setStart(squareList.get(0).getPoint(Square.Direction.CENTER));
|
236
|
-
for(int i=1; i<
|
272
|
+
for(int i=1; i<squareList.size()-1; i++) {
|
237
|
-
dotLineDrawer.draw(g,
|
273
|
+
dotLineDrawer.draw(g, squareList.get(i).getPoint(Square.Direction.CENTER));
|
238
274
|
}
|
239
|
-
dotLineDrawer.draw(g,
|
275
|
+
dotLineDrawer.draw(g, squareList.get(squareList.size()-1).getPoint(Square.Direction.EAST)); //最後はマスの右端まで
|
240
276
|
}
|
241
277
|
}
|
242
278
|
}
|
1
getSquare 修正
answer
CHANGED
@@ -210,7 +210,10 @@
|
|
210
210
|
}
|
211
211
|
//x,y指定から Square を得る
|
212
212
|
private Square getSquare(int x, int y) {
|
213
|
+
for(int i=0; i<POINTS.length; i+=2) {
|
214
|
+
if(POINTS[i] == x && POINTS[i+1] == y) return squares[i/2];
|
215
|
+
}
|
213
|
-
return
|
216
|
+
return null;
|
214
217
|
}
|
215
218
|
|
216
219
|
public void paintComponent(Graphics g) {
|