英文:
Is there a way to reload my JFrame game other than using setVisible() to true and false?
问题
这是您要翻译的内容:
So the goal here is essentially to create a basic text-based roguelike game. I'm fairly new to java, so I'm sure you'll find tons of stuff to be improved with my program. The biggest thing I have is I don't know of a good way to update the screen so it accurately displays the player's position. What I am currently using is setVisible(false)
and setVisible(true)
to completely reload the program, which is fine for now for the purposes of development and at least ensuring things are working. However, the time has come for where that no longer does what I need it, so my question is essentially how do I reload it each time an arrow key is pressed (that's the input for moving the player).
I have experimented with repaint() with nothing to show for it as I could not get it to do anything. Any help would be greatly appreciated!
Here is the code as it is:
import java.awt.*;
import javax.swing.JFrame;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.*;
public class DisplayGraphics extends Canvas{
// 全局游戏变量
int screenW = 1024;
int screenH = 768;
static JFrame f = null;
static int playerX = 0;
static int playerY = 0;
static String[][] map = new String[80][36];
public void paint(Graphics g) {
for (int x=0;x<map.length;x++) {
for (int y=0;y<map[x].length;y++) {
if (x==playerX&& y==playerY) map[x][y] = "@";
else map[x][y] = ".";
}
}
for (int x=0;x<map.length;x++) {
for (int y=0;y<map[x].length;y++) {
g.drawString(map[x][y], (11+(8*x)), (13*y)+14);
}
}
g.drawString("HEALTH:", 10, 545);
}
public static void main(String[] args) {
// 定义玩家变量
DisplayGraphics m=new DisplayGraphics();
f=new JFrame();
f.add(m);
f.setSize(840,610);
// 获取键盘输入
f.addKeyListener(new KeyAdapter() {
public void keyPressed(KeyEvent e) {
int keyCode = e.getKeyCode();
if (keyCode == KeyEvent.VK_UP) {
System.out.println("Up Arrrow-Key is pressed!");
playerY--;
System.out.println(playerY);
f.setVisible(false);
f.setVisible(true);
}
else if (keyCode == KeyEvent.VK_DOWN) {
System.out.println("Down Arrrow-Key is pressed!");
playerY++;
System.out.println(playerY);
f.setVisible(false);
f.setVisible(true);
}
else if (keyCode == KeyEvent.VK_LEFT) {
System.out.println("Left Arrrow-Key is pressed!");
playerX--;
System.out.println(playerX);
f.setVisible(false);
f.setVisible(true);
}
else if (keyCode == KeyEvent.VK_RIGHT) {
System.out.println("Right Arrrow-Key is pressed!");
playerX++;
System.out.println(playerX);
f.setVisible(false);
f.setVisible(true);
}
}
});
f.setVisible(true);
}
public void actionPerformed(KeyEvent event) {
f.repaint();
}
}
请告诉我如果还有其他需要翻译的内容。
英文:
So the goal here is essentially to create a basic text-based roguelike game. I'm fairly new to java, so I'm sure you'll find tons of stuff to be improved with my program. The biggest thing I have is I don't know of a good way to update the screen so it accurately displays the player's position. What I am currently using is setVisible(false)
and setVisible(true)
to completely reload the program, which is fine for now for the purposes of development and at least ensuring things are working. However, the time has come for where that no longer does what I need it, so my question is essentially how do I reload it each time an arrow key is pressed (that's the input for moving the player).
I have experimented with repaint() with nothing to show for it as I could not get it to do anything. Any help would be greatly appreciated!
Here is the code as it is:
import java.awt.*;
import javax.swing.JFrame;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.*;
public class DisplayGraphics extends Canvas{
// Global game variables
int screenW = 1024;
int screenH = 768;
static JFrame f = null;
static int playerX = 0;
static int playerY = 0;
static String[][] map = new String[80][36];
// public void makeMap(String[][] map) {
//
// }
public void paint(Graphics g) {
for (int x=0;x<map.length;x++) {
for (int y=0;y<map[x].length;y++) {
if (x==playerX&& y==playerY) map[x][y] = "@";
else map[x][y] = ".";
}
}
for (int x=0;x<map.length;x++) {
for (int y=0;y<map[x].length;y++) {
g.drawString(map[x][y], (11+(8*x)), (13*y)+14);
}
}
g.drawString("HEALTH:", 10, 545);
}
public static void main(String[] args) {
// DEFINE PLAYER VARIABLES
DisplayGraphics m=new DisplayGraphics();
f=new JFrame();
f.add(m);
f.setSize(840,610);
//we get the keyboard input
f.addKeyListener(new KeyAdapter() {
public void keyPressed(KeyEvent e) {
int keyCode = e.getKeyCode();
if (keyCode == KeyEvent.VK_UP) {
System.out.println("Up Arrrow-Key is pressed!");
playerY--;
System.out.println(playerY);
f.setVisible(false);
f.setVisible(true);
}
else if (keyCode == KeyEvent.VK_DOWN) {
System.out.println("Down Arrrow-Key is pressed!");
playerY++;
System.out.println(playerY);
f.setVisible(false);
f.setVisible(true); }
else if (keyCode == KeyEvent.VK_LEFT) {
System.out.println("Left Arrrow-Key is pressed!");
playerX--;
System.out.println(playerX);
f.setVisible(false);
f.setVisible(true);
}
else if (keyCode == KeyEvent.VK_RIGHT) {
System.out.println("Right Arrrow-Key is pressed!");
playerX++;
System.out.println(playerX);
f.setVisible(false);
f.setVisible(true);
}
}
});
f.setVisible(true);
}
public void actionPerformed(KeyEvent event) {
f.repaint();
}
}
答案1
得分: 1
Your code produced an interesting game field. I'm impressed that you're just learning.
I took your idea and created the following GUI.
I started the player in the center of the map. I'm representing the player as a blue circle.
Oracle has a helpful tutorial, Creating a GUI With Swing. Skip the Learning Swing with the NetBeans IDE section. Pay particular attention to the Performing Custom Painting section.
The first thing I did was create a game model. I made the map a java.awt.Dimension
specifying the width and height of the map. The drawing JPanel
dimensions are based on the map dimensions. I specified the player position with a java.awt.Point
, which holds an X and Y int
.
You can add one or more monsters or obstacles the same way, by defining them as a Point
.
Next, I created the JFrame
and a drawing JPanel
. I used key bindings rather than a key listener. Yes, the code looks more complicated. The advantage is that key bindings continue to work when the drawing JPanel
doesn't have focus. I added the WASD keys as a bonus.
Drawing the player is a rather simple math equation. I draw the circle based on the center point, so I have to adjust the drawing coordinates in the drawOval
.
Here's the complete runnable code. I made the additional classes inner classes so I could post the code as one block. You should separate the classes into different files. Good luck expanding your game.
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Point;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import javax.swing.AbstractAction;
import javax.swing.ActionMap;
import javax.swing.InputMap;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.KeyStroke;
import javax.swing.SwingUtilities;
public class DisplayGraphics implements Runnable {
public static void main(String[] args) {
SwingUtilities.invokeLater(new DisplayGraphics());
}
private final DisplayModel model;
private final DrawingPanel drawingPanel;
public DisplayGraphics() {
this.model = new DisplayModel();
this.drawingPanel = new DrawingPanel(model);
}
@Override
public void run() {
JFrame frame = new JFrame("Display Graphics");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(drawingPanel, BorderLayout.CENTER);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
public class DrawingPanel extends JPanel {
private static final long serialVersionUID = 1L;
private final int playerWidth, margin;
private final DisplayModel model;
public DrawingPanel(DisplayModel model) {
this.model = model;
this.margin = 10;
this.playerWidth = 16;
int totalWidth = 2 * margin + (model.getMap().width + 1) * playerWidth;
int totalHeight = 2 * margin + (model.getMap().height + 1) * playerWidth;
this.setPreferredSize(new Dimension(totalWidth, totalHeight);
setKeyBindings();
}
private void setKeyBindings() {
InputMap inputMap = getInputMap(JPanel.WHEN_IN_FOCUSED_WINDOW);
ActionMap actionMap = getActionMap();
inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_UP, 0), "up");
inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_DOWN, 0), "down");
inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_LEFT, 0), "left");
inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_RIGHT, 0), "right");
inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_W, 0), "up");
inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_S, 0), "down");
inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_A, 0), "left");
inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_D, 0), "right");
actionMap.put("up", new AbstractAction() {
private static final long serialVersionUID = 1L;
@Override
public void actionPerformed(ActionEvent event) {
model.incrementPlayerPositionY(-1);
repaint();
}
});
actionMap.put("down", new AbstractAction() {
private static final long serialVersionUID = 1L;
@Override
public void actionPerformed(ActionEvent event) {
model.incrementPlayerPositionY(+1);
repaint();
}
});
actionMap.put("left", new AbstractAction() {
private static final long serialVersionUID = 1L;
@Override
public void actionPerformed(ActionEvent event) {
model.incrementPlayerPositionX(-1);
repaint();
}
});
actionMap.put("right", new AbstractAction() {
private static final long serialVersionUID = 1L;
@Override
public void actionPerformed(ActionEvent event) {
model.incrementPlayerPositionX(+1);
repaint();
}
});
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Point p = model.getPlayerPosition();
int halfWidth = playerWidth / 2;
int x = margin + halfWidth + p.x * playerWidth;
int y = margin + halfWidth + p.y * playerWidth;
g.setColor(Color.blue);
g.fillOval(x - halfWidth, y - halfWidth, playerWidth, playerWidth);
}
}
public class DisplayModel {
private Point playerPosition;
private final Dimension map;
public DisplayModel() {
this.map = new Dimension(40, 30);
this.playerPosition = new Point(map.width / 2, map.height / 2);
}
public void incrementPlayerPositionX(int increment) {
playerPosition.x += increment;
if (playerPosition.x < 0) {
playerPosition.x = 0;
}
if (playerPosition.x > map.width) {
playerPosition.x = map.width;
}
}
public void incrementPlayerPositionY(int increment) {
playerPosition.y += increment;
if (playerPosition.y < 0) {
playerPosition.y = 0;
}
if (playerPosition.y > map.height) {
playerPosition.y = map.height;
}
}
public Point getPlayerPosition() {
return playerPosition;
}
public Dimension getMap() {
return map;
}
}
}
英文:
Your code produced an interesting game field. I'm impressed that you're just learning.
I took your idea and created the following GUI.
I started the player in the center of the map. I'm representing the player as a blue circle.
Oracle has a helpful tutorial, Creating a GUI With Swing. Skip the Learning Swing with the NetBeans IDE section. Pay particular attention to the Performing Custom Painting section.
The first thing I did was create a game model. I made the map a java.awt.Dimension
specifying the width and height of the map. The drawing JPanel
dimensions are based on the map dimensions. I specified the player position with a java.awt.Point
, which holds an X and Y int
.
You can add one or more monsters or obstacles the same way, by defining them as a Point
.
Next, I created the JFrame
and a drawing JPanel
. I used key bindings rather than a key listener. Yes, the code looks more complicated. The advantage is that key bindings continue to work when the drawing JPanel
doesn't have focus. I added the WASD keys as a bonus.
Drawing the player is a rather simple math equation. I draw the circle based on the center point, so I have to adjust the drawing coordinates in the drawOval
.
Here's the complete runnable code. I made the additional classes inner classes so I could post the code as one block. You should separate the classes into different files. Good luck expanding your game.
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Point;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import javax.swing.AbstractAction;
import javax.swing.ActionMap;
import javax.swing.InputMap;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.KeyStroke;
import javax.swing.SwingUtilities;
public class DisplayGraphics implements Runnable {
public static void main(String[] args) {
SwingUtilities.invokeLater(new DisplayGraphics());
}
private final DisplayModel model;
private final DrawingPanel drawingPanel;
public DisplayGraphics() {
this.model = new DisplayModel();
this.drawingPanel = new DrawingPanel(model);
}
@Override
public void run() {
JFrame frame = new JFrame("Display Graphics");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(drawingPanel, BorderLayout.CENTER);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
public class DrawingPanel extends JPanel {
private static final long serialVersionUID = 1L;
private final int playerWidth, margin;
private final DisplayModel model;
public DrawingPanel(DisplayModel model) {
this.model = model;
this.margin = 10;
this.playerWidth = 16;
int totalWidth = 2 * margin + (model.getMap().width + 1) * playerWidth;
int totalHeight = 2 * margin + (model.getMap().height + 1) * playerWidth;
this.setPreferredSize(new Dimension(totalWidth, totalHeight));
setKeyBindings();
}
private void setKeyBindings() {
InputMap inputMap = getInputMap(JPanel.WHEN_IN_FOCUSED_WINDOW);
ActionMap actionMap = getActionMap();
inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_UP, 0), "up");
inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_DOWN, 0), "down");
inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_LEFT, 0), "left");
inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_RIGHT, 0), "right");
inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_W, 0), "up");
inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_S, 0), "down");
inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_A, 0), "left");
inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_D, 0), "right");
actionMap.put("up", new AbstractAction() {
private static final long serialVersionUID = 1L;
@Override
public void actionPerformed(ActionEvent event) {
model.incrementPlayerPositionY(-1);
repaint();
}
});
actionMap.put("down", new AbstractAction() {
private static final long serialVersionUID = 1L;
@Override
public void actionPerformed(ActionEvent event) {
model.incrementPlayerPositionY(+1);
repaint();
}
});
actionMap.put("left", new AbstractAction() {
private static final long serialVersionUID = 1L;
@Override
public void actionPerformed(ActionEvent event) {
model.incrementPlayerPositionX(-1);
repaint();
}
});
actionMap.put("right", new AbstractAction() {
private static final long serialVersionUID = 1L;
@Override
public void actionPerformed(ActionEvent event) {
model.incrementPlayerPositionX(+1);
repaint();
}
});
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Point p = model.getPlayerPosition();
int halfWidth = playerWidth / 2;
int x = margin + halfWidth + p.x * playerWidth;
int y = margin + halfWidth + p.y * playerWidth;
g.setColor(Color.blue);
g.fillOval(x - halfWidth, y - halfWidth, playerWidth, playerWidth);
}
}
public class DisplayModel {
private Point playerPosition;
private final Dimension map;
public DisplayModel() {
this.map = new Dimension(40, 30);
this.playerPosition = new Point(map.width / 2, map.height / 2);
}
public void incrementPlayerPositionX(int increment) {
playerPosition.x += increment;
if (playerPosition.x < 0) {
playerPosition.x = 0;
}
if (playerPosition.x > map.width) {
playerPosition.x = map.width;
}
}
public void incrementPlayerPositionY(int increment) {
playerPosition.y += increment;
if (playerPosition.y < 0) {
playerPosition.y = 0;
}
if (playerPosition.y > map.height) {
playerPosition.y = map.height;
}
}
public Point getPlayerPosition() {
return playerPosition;
}
public Dimension getMap() {
return map;
}
}
}
答案2
得分: 1
以下是代码的中文翻译部分:
例如,首先从面向对象编程(OOP)类开始,这里首先创建一个Player类,该类包含自己的位置、符号和健康值(0至100)。一个简单的示例如下:
public class Player {
private int x;
private int y;
private int health;
private String symbol;
public Player() {
// 如果需要,可以创建无参数构造函数
}
public Player(int x, int y, int health, String symbol) {
this.x = x;
this.y = y;
this.health = health;
this.symbol = symbol;
}
public int getX() {
return x;
}
public void setX(int x) {
this.x = x;
}
public int getY() {
return y;
}
public void setY(int y) {
this.y = y;
}
public int getHealth() {
return health;
}
public void setHealth(int health) {
this.health = health;
}
public void setSymbol(String symbol) {
this.symbol = symbol;
}
public String getSymbol() {
return symbol;
}
}
这只是一个简单的“POJO”(Plain Old Java Object),具有一些字段、构造函数和一些getter和setter方法。没有太复杂的内容。
我将创建其他对象,比如一个表示地图以及地图可能包含的其他实体的对象,或者玩家可能与之交互的对象。出于简单起见,我不会在这里介绍这些对象,但我会展示一个用于显示和更改Player位置的示例Swing GUI:
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.GridBagLayout;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import javax.swing.*;
@SuppressWarnings("serial")
public class DisplayGraphicsPanel extends JPanel {
// 这部分跳过翻译,因为它包含了一些GUI组件的初始化和事件处理。
// ...
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> {
// 这部分跳过翻译,因为它包含了GUI的初始化和显示。
// ...
});
}
上面的代码使用一个JPanel,其中包含一个2D数组的其他JPanel单元格网格,并使用Key Bindings来捕捉箭头按键并将其用于移动Player。Key Bindings比KeyListener更好用,链接中的教程会解释得很好。简而言之,我已将每个箭头键与一个操作绑定在一起,该操作更改Player对象的x或y字段,然后使用这些值来移动在JPanel网格中显示的JLabel。
英文:
For example, I would first start with OOP classes, here starting with a Player class, one that holds its own position, a symbol and its own health value, 0 to 100. A simple example could look like so:
public class Player {
private int x;
private int y;
private int health;
private String symbol;
public Player() {
// no-arg constructor if needed
}
public Player(int x, int y, int health, String symbol) {
this.x = x;
this.y = y;
this.health = health;
this.symbol = symbol;
}
public int getX() {
return x;
}
public void setX(int x) {
this.x = x;
}
public int getY() {
return y;
}
public void setY(int y) {
this.y = y;
}
public int getHealth() {
return health;
}
public void setHealth(int health) {
this.health = health;
}
public void setSymbol(String symbol) {
this.symbol = symbol;
}
public String getSymbol() {
return symbol;
}
}
This is nothing more than a simple "POJO" or "Plain Old Java Object, one with a few fields, constructors and some getters and setters. Nothing fancy.
I'd create other objects, such as an object to represent the map and any other entities that the map might hold or that the player might interact with. I will dispense with this for now for simplicity, but will show a sample Swing GUI for displaying and changing the location of a Player:
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.GridBagLayout;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import javax.swing.*;
@SuppressWarnings("serial")
public class DisplayGraphicsPanel extends JPanel {
public static final int MAX_X = 80;
public static final int MAX_Y = 36;
private static final Dimension CELL_SIZE = new Dimension(15, 17);
private Player player = new Player(0, 0, 100, "@");
private JPanel gridHolderPanel = new JPanel(new GridLayout(MAX_Y, MAX_X, 1, 1));
private JPanel[][] panelGrid = new JPanel[MAX_Y][MAX_X];
private JLabel playerLabel;
private JLabel healthLabel = new JLabel("100%");
private int condition = WHEN_IN_FOCUSED_WINDOW;
private InputMap inputMap = getInputMap(condition);
private ActionMap actionMap = getActionMap();
public DisplayGraphicsPanel() {
playerLabel = new JLabel(player.getSymbol());
gridHolderPanel.setBackground(Color.BLACK);
gridHolderPanel.setBorder(BorderFactory.createLineBorder(Color.BLACK));
for (int y = 0; y < MAX_Y; y++) {
for (int x = 0; x < MAX_X; x++) {
JPanel panel = new JPanel();
panel.setBackground(Color.WHITE);
panel.setPreferredSize(CELL_SIZE);
panel.setLayout(new GridBagLayout());
panelGrid[y][x] = panel;
gridHolderPanel.add(panel);
}
}
panelGrid[0][0].add(playerLabel);
JPanel statusPanel = new JPanel();
statusPanel.add(new JLabel("Health:"));
statusPanel.add(Box.createHorizontalStrut(5));
statusPanel.add(healthLabel);
setLayout(new BorderLayout());
add(gridHolderPanel);
add(statusPanel, BorderLayout.PAGE_END);
putIntoMaps(KeyStroke.getKeyStroke(KeyEvent.VK_DOWN, 0), 0, 1);
putIntoMaps(KeyStroke.getKeyStroke(KeyEvent.VK_UP, 0), 0, -1);
putIntoMaps(KeyStroke.getKeyStroke(KeyEvent.VK_LEFT, 0), -1, 0);
putIntoMaps(KeyStroke.getKeyStroke(KeyEvent.VK_RIGHT, 0), 1, 0);
}
private void putIntoMaps(KeyStroke kStroke, int xDir, int yDir) {
inputMap.put(kStroke, kStroke.toString());
actionMap.put(kStroke.toString(), new MoveAction(xDir, yDir));
}
private class MoveAction extends AbstractAction {
private int xDir;
private int yDir;
public MoveAction(int xDir, int yDir) {
this.xDir = xDir;
this.yDir = yDir;
}
@Override
public void actionPerformed(ActionEvent e) {
int playerX = player.getX();
playerX += xDir;
// make sure we don't go out of bounds
playerX = Math.max(0, playerX);
playerX = Math.min(playerX, MAX_X);
player.setX(playerX);
int playerY = player.getY();
playerY += yDir;
playerY = Math.max(0, playerY);
playerY = Math.min(playerY, MAX_Y);
player.setY(playerY);
int health = player.getHealth();
health += Math.random() > 0.5 ? 4 : -4;
health = Math.min(100, health);
player.setHealth(health);
healthLabel.setText(String.format("%02d%%", player.getHealth()));
panelGrid[playerY][playerX].add(playerLabel);
gridHolderPanel.revalidate();
gridHolderPanel.repaint();
}
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> {
DisplayGraphicsPanel mainPanel = new DisplayGraphicsPanel();
JFrame frame = new JFrame("GUI");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(mainPanel);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
});
}
}
This class uses a JPanel that holds a grid of other JPanel cells in a 2D array, and uses Key Bindings to capture arrow keystrokes and use them to move the player. Key Bindings are much better to use than a KeyListener, and the tutorial (in the link) will explain it well. Briefly, I have bound each of the arrow keys with an action, one that changes the x or y field of the player object, and then I use those values to move a JLabel that is displayed within the JPanel grid.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论