Форум программистов, компьютерный форум, киберфорум
Java
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.67/6: Рейтинг темы: голосов - 6, средняя оценка - 4.67
Модератор
Эксперт Java
 Аватар для alecss131
2852 / 1360 / 405
Регистрация: 11.08.2017
Сообщений: 4,342
Записей в блоге: 2

Покритикуйте код

20.02.2020, 12:16. Показов 1389. Ответов 10

Студворк — интернет-сервис помощи студентам
В продолжение моей прошлой темы. Накидал тут игрушку на swing 2048, воспользовался советом который дали другому пользователю. Раньше я уже писал эту игру на матлабе, сейчас вот переписал на джаве. Внешне мне нравится всё, кроме того что цифры не двигаются а телепортируются, то есть нету анимации. Такой вариант проще, но с анимацией будет еще красивее, только вот как это сделать не знаю (думаю код придется сильно переписать).
Прикладываю код классов
App
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
import java.awt.Color;
import java.awt.Point;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
 
public class App implements KeyListener, ActionListener, MouseListener, MouseMotionListener {
    private JFrame wnd = new JFrame("2048 Game");
    private Render render;
    private GameLogic game;
    private ResourceManager rm;
    private JButton newGame = new Button("New Game");
    private JButton exit = new CButton("x");
    private JButton minimize = new CButton("-");
    private JButton play = new Button("Continue");
    private int bestScore = 0;
    private JLabel bScore = new Board("BEST");
    private JLabel score = new Board("SCORE");
    private Point mouseDownCompCoords = null;
    
    public static void main(String[] args) {
        new App();
    }
    
    App() {
        rm = new ResourceManager();
        game = new GameLogic();
        render = new Render(rm, game.getGameField());
        newGame.setBounds(320, 102, 100, 25);
        exit.setLocation(5, 5);
        exit.addActionListener(this);
        exit.setActionCommand("Exit");
        minimize.setLocation(20, 5);
        minimize.addActionListener(this);
        minimize.setActionCommand("Minimize");
        bScore.setLocation(355, 20);
        score.setLocation(250, 20);
        render.setLocation(5, 150);
        newGame.setActionCommand("NewGame");
        newGame.addActionListener(this);
        play.setBounds(180, 270, 90, 25);
        play.setFocusable(false);
        play.setActionCommand("Continue");
        play.addActionListener(this);
        play.setVisible(false);
        render.setLayout(null);
        render.add(play);
        wnd.setUndecorated(true);
        wnd.setContentPane(new JLabel(rm.getBackGroud()));
        wnd.setBackground(new Color(0, 0, 0, 0));
        wnd.add(render);
        wnd.add(newGame);
        wnd.add(bScore);
        wnd.add(score);
        wnd.add(exit);
        wnd.add(minimize);
        wnd.setLayout(null);
        wnd.addKeyListener(this);
        wnd.addMouseListener(this);
        wnd.setOpacity(1f);
        wnd.addMouseMotionListener(this);
        wnd.setResizable(false);
        wnd.setBounds(200, 200, 460, 605);
        wnd.setIconImage(rm.getIcon());
        wnd.setVisible(true);
    }
 
    public void keyTyped(KeyEvent e) {}
 
    public void keyPressed(KeyEvent e) {
        if (!game.isGameOver() && !game.isWin()) {
            switch (e.getKeyCode()) {
            case KeyEvent.VK_LEFT: {
                game.moveLeft();
                break;
            }
            case KeyEvent.VK_RIGHT: {
                game.moveRight();
                break;
            }
            case KeyEvent.VK_UP: {
                game.moveUp();
                break;
            }
            case KeyEvent.VK_DOWN: {
                game.moveDown();
                break;
            }
            }
            render.renderImage(game.getGameField(), game.isGameOver(), game.isWin());
            score.setText("" + game.getScore());
            play.setVisible(game.isWin());
        }
    }
 
    public void keyReleased(KeyEvent e) {}
 
    public void actionPerformed(ActionEvent ae) {
        switch (ae.getActionCommand()) {
        case "NewGame" : {
            if (game.getScore()>bestScore && (game.isGameOver() || game.isWin())) {
                bestScore = game.getScore();
                bScore.setText("" + bestScore);
            }
            score.setText("0");
            game.clear();
            render.renderImage(game.getGameField(), game.isGameOver(), game.isWin());
            break;
        }
        case "Continue" : {
            game.setWin(false);
            play.setVisible(game.isWin());
            render.renderImage(game.getGameField(), game.isGameOver(), game.isWin());
            break;
        }
        case "Minimize" : {
            wnd.setState(JFrame.ICONIFIED);
            break;
        }
        case "Exit" : {
            System.exit(0);
        }
        }
    }
 
    public void mouseDragged(MouseEvent e) {
        Point currCoords = e.getLocationOnScreen();
        wnd.setLocation(currCoords.x - mouseDownCompCoords.x, currCoords.y - mouseDownCompCoords.y);
        wnd.setOpacity(0.5f);
    }
 
    public void mouseMoved(MouseEvent e) {}
 
    public void mouseClicked(MouseEvent e) {}
 
    public void mousePressed(MouseEvent e) {
        mouseDownCompCoords = e.getPoint();
    }
 
    public void mouseReleased(MouseEvent e) {
        mouseDownCompCoords = null;
        wnd.setOpacity(1f);
    }
 
    public void mouseEntered(MouseEvent e) {}
 
    public void mouseExited(MouseEvent e) {}
}

Board
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
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
 
import javax.swing.JLabel;
 
public class Board extends JLabel {
 
    private static final long serialVersionUID = 1L;
    private String label;
    
    Board(String label) {
        super("0");
        this.label = label;
        setSize(100, 50);
    }
    
    @Override
    protected void paintComponent(Graphics g) {
        Graphics2D g2d = (Graphics2D) g.create();
        g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
        g2d.setColor(new Color(188, 175, 161, 250));
        g2d.fillRoundRect(0, 0, 100, 50, 5, 5);
        g2d.fillRoundRect(0, 0, 100, 50, 5, 5);
        g2d.setColor(new Color(255, 255, 255, 255));
        g2d.setFont(new Font("Arial", Font.BOLD, 10));
        int w = g2d.getFontMetrics().stringWidth(label);
        g2d.drawString(label, (getSize().width-w)/2, 15);
        g2d.setFont(new Font("Arial", Font.BOLD, 20));
        w = g2d.getFontMetrics().stringWidth(getText());
        g2d.drawString(getText(), (getSize().width-w)/2, 40);
    }
}

Button
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
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import javax.swing.JButton;
 
public class Button extends JButton  implements MouseListener {
    private static final long serialVersionUID = 1L;
    private boolean onMouse = false;
    private boolean onClick = false;
    
    Button(String text) {
        super(text);
        setFocusable(false);
        setFocusPainted(false);
        setContentAreaFilled(false);
        setBorder(null);
        setBorderPainted(false);
        addMouseListener(this);
    }
    
    @Override
    protected void paintComponent(Graphics g) {
        Graphics2D g2d = (Graphics2D) g.create();
        g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
        g2d.setColor(new Color(255, 255, 255, 0));
        g2d.fillRect(0, 0, getWidth(), getHeight());
        g2d.setColor(new Color(144, 123, 102, 255));
        g2d.fillRoundRect(0, 0, getWidth(), getHeight(), 5, 5);
        g2d.setFont(new Font("Arial", Font.BOLD, 15));
        g2d.setColor(Color.white);
        String text = getText();
        int a = g2d.getFontMetrics().getAscent();
        int w = g2d.getFontMetrics().stringWidth(text);
        int h = g2d.getFontMetrics().getHeight();
        g2d.drawString(text, (getSize().width-w)/2, (getSize().height-h)/2+a);
        if (onMouse) {
            g2d.setColor(new Color(184, 163, 142, 120));
            g2d.fillRoundRect(0, 0, getWidth(), getHeight(), 5, 5);
        }
        if (onClick) {
            g2d.setColor(new Color(104, 83, 62, 120));
            g2d.fillRoundRect(0, 0, getWidth(), getHeight(), 5, 5);
        }
    }
    
    @Override
    public void mouseClicked(MouseEvent e) {}
    
    @Override
    public void mousePressed(MouseEvent e) {
        onClick = true;
    }
    
    @Override
    public void mouseReleased(MouseEvent e) {
        onClick = false;
        repaint();
    }
    
    @Override
    public void mouseEntered(MouseEvent e) {
        onMouse = true;
    }
    
    @Override
    public void mouseExited(MouseEvent e) {
        onMouse = false;
        repaint();
    }
}

CButtont
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
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import javax.swing.JButton;
 
public class CButton extends JButton  implements MouseListener {
    private static final long serialVersionUID = 1L;
    private boolean onMouse = false;
    private boolean onClick = false;
    private int s = 12;
    private Color color;
    private String type;
    
    CButton(String type) {
        setFocusable(false);
        setFocusPainted(false);
        setContentAreaFilled(false);
        setBorder(null);
        setBorderPainted(false);
        addMouseListener(this);
        setSize(s, s);
        this.type = type;
        switch (type) {
        case "x" : {
            color = new Color(246, 94, 56, 255);
            break;
        }
        case "-" : {
            color = new Color(250, 248, 0, 255);
            break;
        }
        default : {
            color = new Color(0, 240, 0, 255);
        }
        }
    }
    
    @Override
    protected void paintComponent(Graphics g) {
        Graphics2D g2d = (Graphics2D) g.create();
        g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
        g2d.setColor(new Color(255, 255, 255, 0));
        g2d.fillRect(0, 0, s, s);
        g2d.setColor(color);
        g2d.fillOval(0, 0, s, s);
        if (onMouse) {
            g2d.setColor(new Color(50, 50, 50, 100));
            if (type.equals("-")) {
                g2d.setFont(new Font("Arial", Font.BOLD, 15));
            } 
            g2d.drawString(type, 3, 10);
        }
        if (onClick) {
            g2d.setColor(new Color(104, 83, 62, 120));
            g2d.fillOval(0, 0, s, s);
        }
    }
    
    @Override
    public void mouseClicked(MouseEvent e) {}
    
    @Override
    public void mousePressed(MouseEvent e) {
        onClick = true;
    }
    
    @Override
    public void mouseReleased(MouseEvent e) {
        onClick = false;
        repaint();
    }
    
    @Override
    public void mouseEntered(MouseEvent e) {
        onMouse = true;
    }
    
    @Override
    public void mouseExited(MouseEvent e) {
        onMouse = false;
        repaint();
    }
}

GameLogic
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
import java.util.Random;
 
public class GameLogic {
    private int field[][];
    private int score;
    private boolean over;
    private int width;
    private int height;
    private int field2[][];
    private boolean win;
    private boolean cont;
    
    GameLogic() {
        this(4, 4);
    }
    
    GameLogic(int height, int width) {
        this.height = height;
        this.width = width;
        field = new int[height][width];
        addNumber(true);
        addNumber(true);
    }
    
    GameLogic(int[][] field, int score) {
        this.field = field;
        this.score = score;
    }
    
    public boolean isGameOver() {
        return over;
    }
    
    public int getScore() {
        return score;
    }
    
    public int[][] getGameField() {
        return field;
    }
    
    public boolean isWin() {
        return win;
    }
    
    public void setWin(boolean win) {
        this.win = win;
    }
    
    public void moveLeft() {
        field2 = copy2dArray(field);
        for (int i=0; i<height; i++) {
            for (int j=0; j<width; j++) {
                for (int k=0; k<width-1; k++) {
                    if (field[i][k]==0) {
                        field[i][k] = field[i][k+1];
                        field[i][k+1] = 0;
                    }
                }
            }
            for (int j=1; j<width; j++) {
                if (field[i][j-1]==field[i][j]) {
                    field[i][j-1] = field[i][j-1] + field[i][j];
                    score += field[i][j-1];
                    field[i][j] = 0;
                }
            }
            for (int j=0; j<width; j++) {
                for (int k=0; k<width-1; k++) {
                    if (field[i][k]==0) {
                        field[i][k] = field[i][k+1];
                        field[i][k+1] = 0;
                    }
                }
            }
        }
        addNumber(isChanged());
        checkWin();
        checkGameOver();
    }
    
    public void moveRight() {
        field2 = copy2dArray(field);
        for (int i=0; i<height; i++) {
            for (int j=0; j<width; j++) {
                for (int k=width-1; k>0; k--) {
                    if (field[i][k]==0) {
                        field[i][k] = field[i][k-1];
                        field[i][k-1] = 0;
                    }
                }
            }
            for (int j=width-1; j>0; j--) {
                if (field[i][j-1]==field[i][j]) {
                    field[i][j] = field[i][j-1] + field[i][j];
                    score += field[i][j];
                    field[i][j-1] = 0;
                }
            }
            for (int j=0; j<width; j++) {
                for (int k=width-1; k>0; k--) {
                    if (field[i][k]==0) {
                        field[i][k] = field[i][k-1];
                        field[i][k-1] = 0;
                    }
                }
            }
        }
        addNumber(isChanged());
        checkWin();
        checkGameOver();
    }
    
    public void moveUp() {
        field2 = copy2dArray(field);
        for (int i=0; i<height; i++) {
            for (int j=0; j<width; j++) {
                for (int k=0; k<width-1; k++) {
                    if (field[k][i]==0) {
                        field[k][i] = field[k+1][i];
                        field[k+1][i] = 0;
                    }
                }
            }
            for (int j=1; j<width; j++) {
                if (field[j-1][i]==field[j][i]) {
                    field[j-1][i] = field[j-1][i] + field[j][i];
                    score += field[j-1][i];
                    field[j][i] = 0;
                }
            }
            for (int j=0; j<width; j++) {
                for (int k=0; k<width-1; k++) {
                    if (field[k][i]==0) {
                        field[k][i] = field[k+1][i];
                        field[k+1][i] = 0;
                    }
                }
            }
        }
        addNumber(isChanged());
        checkWin();
        checkGameOver();
    }
    
    public void moveDown() {
        field2 = copy2dArray(field);
        for (int i=0; i<height; i++) {
            for (int j=0; j<width; j++) {
                for (int k=width-1; k>0; k--) {
                    if (field[k][i]==0) {
                        field[k][i] = field[k-1][i];
                        field[k-1][i] = 0;
                    }
                }
            }
            for (int j=width-1; j>0; j--) {
                if (field[j-1][i]==field[j][i]) {
                    field[j][i] = field[j-1][i] + field[j][i];
                    score += field[j][i];
                    field[j-1][i] = 0;
                }
            }
            for (int j=0; j<width; j++) {
                for (int k=width-1; k>0; k--) {
                    if (field[k][i]==0) {
                        field[k][i] = field[k-1][i];
                        field[k-1][i] = 0;
                    }
                }
            }
        }
        addNumber(isChanged());
        checkWin();
        checkGameOver();
    }
    
    public void clear() {
        score = 0;
        field = new int[height][width];
        win = false;
        over = false;
        cont = false;
        addNumber(true);
        addNumber(true);
    }
    
    private void addNumber(boolean add) {
        if (!over && hasEmptyCells() && add) {
            int number = getNumber();
            int x, y;
            do {
            x = new Random().nextInt(height);
            y = new Random().nextInt(width);
            if (field[x][y] == 0) {
                field[x][y] = number;
                break;
            }
            } while (field[x][y] != 0);
        }
    }
    
    private int getNumber() {
        switch (new Random().nextInt(100)%4) {
        case 0 : {
            return 2;
        }
        case 1 : { 
            return 4;
        }
        case 2 : {
            return 2;
        }
        case 3 : {
            return 2;
        }
        default :
            return 8;
        }
    }
    
    private void checkGameOver() {
        if (!hasEmptyCells()) {
            for (int i = 0; i < height; i++) {
                for (int j = 0; j < width - 1; j++) {
                    if ((field[i][j] == field[i][j + 1]) || (field[j][i] == field[j + 1][i])) {
                        return;
                    }
                }
            }
            over = true;
        }
    }
    
    private boolean hasEmptyCells() {
        for (int i = 0; i < height; i++) {
            for (int j = 0; j < width; j++) {
                if (field[i][j] == 0) {
                    return true;
                }
            }
        }
        return false;
    }
    
    private int[][] copy2dArray(int[][] in) {
        int out[][] = new int[height][width];
        for (int i=0; i<height; i++) {
            out[i] = in[i].clone();
        }
        return out;
    }
    
    private boolean isChanged() {
        for (int i = 0; i < height; i++) {
            for (int j = 0; j < width; j++) {
                if (field[i][j] != field2[i][j]) {
                    return true;
                }
            }
        }
        return false;
    }
    
    private void checkWin() {
        if (!cont) {
            for (int i = 0; i < height; i++) {
                for (int j = 0; j < width; j++) {
                    if (field[i][j] == 2048) {
                        win = true;
                        cont = true;
                    }
                }
            }
        }
    }
}

Render
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
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import javax.swing.JPanel;
 
public class Render extends JPanel {
 
    private static final long serialVersionUID = 1L;
    private ResourceManager resources;
    private int field[][];
    private boolean over;
    private boolean win;
 
    Render(ResourceManager manager, int field[][]) {
        super();
        this.field = field;
        resources = manager;
        setSize(resources.getFieldImage().getWidth(), resources.getFieldImage().getHeight());
    }
 
    public void renderImage(int field[][], boolean over, boolean win) {
        this.field = field;
        this.over = over;
        this.win = win;
        repaint();
    }
 
    @Override
    protected void paintComponent(Graphics g) {
        Graphics2D g2d = (Graphics2D) g.create();
        g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
        g2d.drawImage(resources.getFieldImage(), 0, 0, null);
        for (int i = 0; i < field.length; i++) {
            for (int j = 0; j < field[0].length; j++) {
                if (field[j][i] > 0) {
                    g2d.drawImage(resources.getNumberImage(field[j][i]), resources.getCoordinate(i),
                            resources.getCoordinate(j), null);
                }
            }
        }
        if (over) {
            g2d.setColor(new Color(235, 195, 20, 120));
            g2d.fillRect(0, 0, getSize().width, getSize().height);
            g2d.setColor(new Color(240, 90, 50, 255));
            g2d.setFont(new Font("Arial", Font.BOLD, 50));
            String text = "Game Over";
            int a = g2d.getFontMetrics().getAscent();
            int w = g2d.getFontMetrics().stringWidth(text);
            int h = g2d.getFontMetrics().getHeight();
            g2d.drawString(text, (getSize().width-w)/2, (getSize().height-h)/2+a);
        } else if (win) {
            g2d.setColor(new Color(235, 195, 20, 120));
            g2d.fillRect(0, 0, getSize().width, getSize().height);
            g2d.setColor(new Color(120, 110, 101, 255));
            g2d.setFont(new Font("Arial", Font.BOLD, 50));
            String text = "You Win";
            int a = g2d.getFontMetrics().getAscent();
            int w = g2d.getFontMetrics().stringWidth(text);
            int h = g2d.getFontMetrics().getHeight();
            g2d.drawString(text, (getSize().width-w)/2, (getSize().height-h)/2+a);
        }
    }
}

ResourceManager
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
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.RenderingHints;
import java.awt.image.BufferedImage;
import java.util.Random;
import javax.swing.ImageIcon;
 
public class ResourceManager {
    private int length;
    private BufferedImage[] images;
    private BufferedImage field;
    private BufferedImage backGround;
    private BufferedImage icon;
    private int width;
    private int height;
    private int max;
    private int numSize = 100;
    private int space = 10;
    private int rad = 5;
    private Color colors[] = {
            new Color(239, 229, 219, 255),
            new Color(238, 225, 201, 255),
            new Color(242, 179, 122, 255),
            new Color(245, 150, 99, 255),
            new Color(245, 127, 96, 255),
            new Color(246, 94, 56, 255),
            new Color(238, 208, 115, 255),
            new Color(238, 205, 97, 255),
            new Color(238, 201, 79, 255),
            new Color(238, 198, 61, 255),
            new Color(237, 197, 50, 255)};
    
    ResourceManager() {
        this(4, 4, 8192);
    }
    
    ResourceManager(int maxNumber) {
        this(4, 4, maxNumber);
    }
    
    ResourceManager(int height, int width) {
        this(height, width, 8192);
    }
    
    ResourceManager(int height, int width, int maxNumber) {
        this.height = height;
        this.width = width;
        max = maxNumber;
        length = log2(maxNumber);
        images = new BufferedImage[length];
        createGameField();
        createNubersImages();
        createBackGround();
        createIcon();
    }
    
    
    private int log2(int in) {
        return Integer.toBinaryString(in).length()-1;
    }
    
    public BufferedImage getFieldImage() {
        return field;
    }
    
    public ImageIcon getBackGroud() {
        return new ImageIcon(backGround);
    }
    
    public Image getIcon() {
        return icon;
    }
    
    public BufferedImage getNumberImage(int number) throws NumberFormatException {
        if (number > max) {
            throw new NumberFormatException("Out of range number exceprion");
        }
        return images[log2(number)-1];
    }
    
    public int getCoordinate(int i) {
        return (i+1)*space+i*numSize;
    }
    
    private void createGameField() {
        int fieldWidth = numSize * width + (width + 1) * space;
        int fieldHeight = numSize * height + (height + 1) * space;
        field = new BufferedImage(fieldWidth, fieldHeight, BufferedImage.TYPE_INT_ARGB);
        Graphics2D g2d = (Graphics2D) field.getGraphics();
        g2d.setColor(new Color(255, 255, 255, 0));
        g2d.fillRect(0, 0, fieldWidth, fieldHeight);
        g2d.setColor(new Color(188, 175, 161, 255));
        g2d.fillRoundRect(0, 0, fieldWidth, fieldHeight, 2*rad, 2*rad);
        g2d.setColor(new Color(206, 194, 181, 255));
        for (int i=0; i<width; i++) {
            for (int j=0; j<height; j++) {
                g2d.fillRoundRect(getCoordinate(i), getCoordinate(j), numSize, numSize, rad, rad);
            }
        }
    }
    
    private void createNubersImages() {
        int fontSize = 50;
        String text;
        int w;
        int h;
        int a;
        for (int i=0; i<length; i++) {
            images[i] = new BufferedImage(numSize, numSize, BufferedImage.TYPE_INT_ARGB);
            Graphics2D g2d = (Graphics2D) images[i].getGraphics();
            g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
            g2d.setColor(new Color(255, 255, 255, 0));
            g2d.fillRect(0, 0, numSize, numSize);
            if (i >= colors.length) {
                g2d.setColor(new Color(1, new Random().nextInt(256), new Random().nextInt(256), 
                        new Random().nextInt(256)));
            } else {
                g2d.setColor(colors[i]);
            }
            g2d.fillRoundRect(0, 0, numSize, numSize, rad, rad);
            if (i<2) {
                g2d.setColor(new Color(120, 110, 101, 255));
            } else {
                g2d.setColor(new Color(249, 246, 242, 255));
            }
            if (i>5 && i<9) {
                fontSize = 45;
            } else if (i>8 && i<12) {
                fontSize = 35;
            } else if (i>11){
                fontSize = 30;
            }
            g2d.setFont(new Font("Arial", Font.BOLD, fontSize));
            text = ((int)Math.pow(2, i+1))+"";
            a = g2d.getFontMetrics().getAscent();
            w = g2d.getFontMetrics().stringWidth(text);
            h = g2d.getFontMetrics().getHeight();
            g2d.drawString(text, (numSize-w)/2, (numSize-h)/2+a);
        }
    }
    
    private void createBackGround() {
        int w = 460;
        int h = 605;
        int r = 15;
        backGround = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB);
        Graphics2D g2d = (Graphics2D) backGround.getGraphics();
        g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
        g2d.setColor(new Color(255, 255, 255, 0));
        g2d.fillRect(0, 0, w, h);
        g2d.setColor(new Color(250, 248, 255, 250));
        g2d.fillRoundRect(0, 0, w, h, r, r);
        g2d.setColor(new Color(120, 110, 101, 250));
        g2d.setFont(new Font("Arial", Font.BOLD, 80));
        g2d.drawString("2048", 20, 80);
        g2d.setFont(new Font("Arial", Font.TRUETYPE_FONT, 15));
        String text = "Join the numbers and get to the";
        g2d.drawString(text, 20, 120);
        int tw = g2d.getFontMetrics().stringWidth(text);
        g2d.setFont(new Font("Arial", Font.BOLD, 15));
        g2d.drawString("2048 tile!", tw+23, 120);
    }
    
    private void createIcon() {
        icon = new BufferedImage(128, 128, BufferedImage.TYPE_INT_RGB);
        Graphics2D g2d = (Graphics2D) icon.getGraphics();
        g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
        g2d.setColor(new Color(237, 197, 0));
        g2d.fillRect(0, 0, 128, 128);
        g2d.setColor(new Color(255, 255, 255));
        g2d.setFont(new Font("Arial", Font.BOLD, 40));
        String text = "2048";
        int a = g2d.getFontMetrics().getAscent();
        int w = g2d.getFontMetrics().stringWidth(text);
        int h = g2d.getFontMetrics().getHeight();
        g2d.drawString(text, (128-w)/2, (128-h)/2+a);
    }
}

А так же приложу джарник (внутри 7z архива), мавен проект и скрин. Прошу не судить строго, эта игра написана за день.
Миниатюры
Покритикуйте код  
Вложения
Тип файла: 7z 2048-jar.7z (15.4 Кб, 5 просмотров)
Тип файла: 7z 2048-mvn.7z (4.9 Кб, 3 просмотров)
0
cpp_developer
Эксперт
20123 / 5690 / 1417
Регистрация: 09.04.2010
Сообщений: 22,546
Блог
20.02.2020, 12:16
Ответы с готовыми решениями:

Покритикуйте код
Добрый вечер. Выполнял одно тестовое задание (уже получил отрицательный ответ), буду рад, если скажите все ошибки, а также, как их можно...

Покритикуйте пожалуйста резюме Junior Java Developer
Пожалуйста скажите что стоит поправить. Если кому не сложно скиньте свои резюме с которыми вы устраивались. Резюме

Покритикуйте код
Всем привет. У меня есть обычный POJO-класс с полями и класс для работы с данной коллекцией объектов. Посоветуйте плс, как улучшить...

10
Эксперт Java
3639 / 2971 / 918
Регистрация: 05.07.2013
Сообщений: 14,220
20.02.2020, 12:31
Цитата Сообщение от alecss131 Посмотреть сообщение
switch (type) {
        case "x" : {
            color = new Color(246, 94, 56, 255);
            break;
        }
        case "-" : {
            color = new Color(250, 248, 0, 255);
            break;
        }
        default : {
            color = new Color(0, 240, 0, 255);
        }
        }
форматирование
Цитата Сообщение от alecss131 Посмотреть сообщение
CButton
чо такое CButton?
Почему конструктор без модификатора?
0
Модератор
Эксперт Java
 Аватар для alecss131
2852 / 1360 / 405
Регистрация: 11.08.2017
Сообщений: 4,342
Записей в блоге: 2
20.02.2020, 12:36  [ТС]
Цитата Сообщение от xoraxax Посмотреть сообщение
чо такое CButton?
это класс отвечающий за 2 круглые кнопки слева в углу (закрыть и свернуть окно), сокращение от CircleButton, полностью было лень писать)) Блин в названии спойлера буква t лишняя в конце
Цитата Сообщение от xoraxax Посмотреть сообщение
Почему конструктор без модификатора?
Вот это не понял
0
1552 / 918 / 193
Регистрация: 26.03.2010
Сообщений: 3,105
20.02.2020, 13:00
честно говоря, кроме форматирования, которое фиксится одним хоткеем в идее, особо нечего критиковать - логики мало очень )
0
Модератор
Эксперт Java
 Аватар для alecss131
2852 / 1360 / 405
Регистрация: 11.08.2017
Сообщений: 4,342
Записей в блоге: 2
24.02.2020, 11:57  [ТС]
Немного подредактировал код, небольшая реорганизация и оптимизация (теперь перерисовывает только если были изменения), а в одном месте (класс Board) было не пойми что с рисованием (не то что задумывалось). Прикладываю новый проект.
Собственно новый вопрос. Никто не посоветует как лучше всего реализовать анимацию движения плиток? А то они у меня сейчас телепортируются. Сколько не думал идей нету. Если каждую плитку превратить в объект то тогда вылезает проблема с обработкой ходов...
Вложения
Тип файла: 7z 2048.7z (6.4 Кб, 0 просмотров)
0
Эксперт PythonЭксперт Java
19530 / 11067 / 2931
Регистрация: 21.10.2017
Сообщений: 23,294
24.02.2020, 13:09
alecss131, ты лучше на гитхаб выкладывай, ага. Качать архив, распаковывать, куда-то это все импрортировать... Кому это надо?
0
Модератор
Эксперт Java
 Аватар для alecss131
2852 / 1360 / 405
Регистрация: 11.08.2017
Сообщений: 4,342
Записей в блоге: 2
24.02.2020, 13:22  [ТС]
iSmokeJC, вот https://github.com/loginmen/2048
0
528 / 263 / 70
Регистрация: 11.12.2016
Сообщений: 1,223
25.02.2020, 15:46
Цитата Сообщение от alecss131 Посмотреть сообщение
Никто не посоветует как лучше всего реализовать анимацию движения плиток?
Я бы посоветовал использовать JavaFX, там и анимации, как по мне, проще и CSS можно подключить. Понимаю что swing это не javafx (с первым опыта использования вообще не было) и прийдется много переписывать, но учитывая как быстро вы это написали я бы взялся. Плюс ко всему немного упорядочить код в процессе переписываня, чтобы не были такие большие конструктора, например сделать какого-то пославщика услуг визуализации (чтобы можно было поменять swing на javafx в одной строке), других поставщиков, спилей извне итд.. короче чтобы ваш главный класс занимался только делегированием других а не работой.
0
Модератор
Эксперт Java
 Аватар для alecss131
2852 / 1360 / 405
Регистрация: 11.08.2017
Сообщений: 4,342
Записей в блоге: 2
25.02.2020, 16:45  [ТС]
ViktorFX, JavaFX я уже пробовал и мне очень не понравилось, особенно использование css и xml файлов. Мне приятней и привычней писать интерфейс в коде, нежели в отдельных файлах. Еще javafx мне не понравился меньшей гибкостью, если в swing чтото не устраивает то можно без проблем переписать нужные методы и получить желаемое, то тут так не выйдет. Я уже пробовал переносить интерфейс с одного на другой, в итоге перенос вышел не точный, не полный и с кучей костылей.
Я в данный момент изучаю opengl и были идеи перенести туда, но имхо opengl больше подходит для 3д, в крайнем случае 2д игр где побольше активных действий. Но даже тут у меня нету идей как прикрутить анимацию к плиткам.
Конечно понимаю что для анимации надо менять логику игры, может даже полностью отказаться от матриц и заменить плитки с чисел на объекты, но тогда возникает проблема как организовать логику игры.
0
50 / 49 / 10
Регистрация: 27.05.2014
Сообщений: 232
26.02.2020, 00:18
Привет, тут уже был разговор про участок.

Java
1
2
3
4
5
6
7
8
9
10
11
12
13
switch (type) {
        case "x": {
            color = new Color(246, 94, 56, 255);
            break;
        }
        case "-": {
            color = new Color(250, 248, 0, 255);
            break;
        }
        default: {
            color = new Color(0, 240, 0, 255);
        }
    }
Если есть возможность, color вынести в именованные константы было бы получше.
0
Модератор
Эксперт Java
 Аватар для alecss131
2852 / 1360 / 405
Регистрация: 11.08.2017
Сообщений: 4,342
Записей в блоге: 2
26.04.2020, 23:31  [ТС]
Начал переписывать игру на opengl, вот ссылка на новый гит https://github.com/loginmen/2048-gl
Жду новую порцию критики нового кода. Только прошу учесть что это первая технодемка, реализовал почти все, кроме счета и лучшего счета, так как не так просто рисовать текст. Пока чисто порт со свинга. Хочу многое переписать получше, но пока без идей.
Картинки генерируются перед запуском игры в java awt коде а потом через цепочку промежуточных шагов грузятся в видеокарту. Что мне не очень нравится, но использовать готовые картинки тоже не хочу. Вот пример такой цепочки. Выходит так: buffered image -> byte array output stream -> byte array -> byte buffer -> byte buffer -> texture, в идеале хотелось бы так: buffered image -> byte array -> byte buffer -> texture. То есть выходит лишний прогон в стрим в виде байтов png а потом обратный декод в байты rgba, то есть последний byte buffer -> byte buffer выходит расшифровка png bytes -> rgba bytes.
Почему из buffered image можно вытащить массив интов (причем от 0 до 255) но нельзя вытащить массив байт? Просто выходит что значения от 0 до 255 занимают 4 байта вместо 1. Я в курсе что байт это знаковый тип которым по модулю не превосходит 127
Игровые клетки рисую используя инстансинг, массив текстур и геометрический шейдер и при перерисовке поля просто в буфере меняю массив из 16 значений поля. Хотя можно было бы просто рисовать в цикле каждую клетку но это не интересно.
По сути в opengl коде менять особо нечего, больше в правке и критике нуждается логика игры а не отрисовка
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
raxper
Эксперт
30234 / 6612 / 1498
Регистрация: 28.12.2010
Сообщений: 21,154
Блог
26.04.2020, 23:31
Помогаю со студенческими работами здесь

Покритикуйте код моего сокет сервера для игрового чата
С помощью пары уроков, сделал сервер для визуального чата, типа галактики знакомств. Интересны советы по упрощению и оптимизации. Там...

Многопоточность. Покритикуйте
ищем простые числа на заданном промежутке, задавая кол-во потоков, равномерно деля работу между ними. потоки должны стартовать...

Покритикуйте, пожалуйста
Написала свой пермутатор. Мне нравится. Но понимаю, конечно, что найдется много разных косяков. Большая просьба к опытным программистам,...

Покритикуйте новичка
Доброго всем времени суток! Самоучкой пытаюсь освоить Java, общение с опытными программистами или преподавателями недоступно. Остаётся...

Алгоритм: Трамвайные билеты. Покритикуйте
Привет, решение данной задачи на Java. Покритикуйте. package olympicexercises; import java.io.*; import java.util.*; import...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
11
Ответ Создать тему
Новые блоги и статьи
Установка Emscripten SDK (emsdk) и CMake на Windows для сборки C и C++ приложений в WebAssembly (Wasm)
8Observer8 30.01.2026
Чтобы скачать Emscripten SDK (emsdk) необходимо сначало скачать и уставить Git: Install for Windows. Следуйте стандартной процедуре установки Git через установщик. Система контроля версиями Git. . .
Подключение Box2D v3 к SDL3 для Android: физика и отрисовка коллайдеров
8Observer8 29.01.2026
Содержание блога Box2D - это библиотека для 2D физики для анимаций и игр. С её помощью можно определять были ли коллизии между конкретными объектами. Версия v3 была полностью переписана на Си, в. . .
Инструменты COM: Сохранение данный из VARIANT в файл и загрузка из файла в VARIANT
bedvit 28.01.2026
Сохранение базовых типов COM и массивов (одномерных или двухмерных) любой вложенности (деревья) в файл, с возможностью выбора алгоритмов сжатия и шифрования. Часть библиотеки BedvitCOM Использованы. . .
Загрузка PNG с альфа-каналом на SDL3 для Android: с помощью SDL_LoadPNG (без SDL3_image)
8Observer8 28.01.2026
Содержание блога SDL3 имеет собственные средства для загрузки и отображения PNG-файлов с альфа-каналом и базовой работы с ними. В этой инструкции используется функция SDL_LoadPNG(), которая. . .
Загрузка PNG с альфа-каналом на SDL3 для Android: с помощью SDL3_image
8Observer8 27.01.2026
Содержание блога SDL3_image - это библиотека для загрузки и работы с изображениями. Эта пошаговая инструкция покажет, как загрузить и вывести на экран смартфона картинку с альфа-каналом, то есть с. . .
Влияние грибов на сукцессию
anaschu 26.01.2026
Бифуркационные изменения массы гриба происходят тогда, когда мы уменьшаем массу компоста в 10 раз, а скорость прироста биомассы уменьшаем в три раза. Скорость прироста биомассы может уменьшаться за. . .
Воспроизведение звукового файла с помощью SDL3_mixer при касании экрана Android
8Observer8 26.01.2026
Содержание блога SDL3_mixer - это библиотека я для воспроизведения аудио. В отличие от инструкции по добавлению текста код по проигрыванию звука уже содержится в шаблоне примера. Нужно только. . .
Установка Android SDK, NDK, JDK, CMake и т.д.
8Observer8 25.01.2026
Содержание блога Перейдите по ссылке: https:/ / developer. android. com/ studio и в самом низу страницы кликните по архиву "commandlinetools-win-xxxxxx_latest. zip" Извлеките архив и вы увидите. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru