Java實現(xiàn)經(jīng)典游戲推箱子的示例代碼
前言
《推箱子》推箱子是一個古老的游戲,目的是在訓(xùn)練你的邏輯思考能力。在一個狹小的倉庫中,要求把木箱放到指定的位置,稍不小心就會出現(xiàn)箱子無法移動或者通道被堵住的情況,所以需要巧妙的利用有限的空間和通道,合理安排移動的次序和位置,才能順利的完成任務(wù)。
游戲是用java語言實現(xiàn),采用了swing技術(shù)進(jìn)行了界面化處理,設(shè)計思路用了面向?qū)ο笏枷搿?/p>
主要需求
控制搬運工上下左右移動,來將箱子推到指定地點
主要設(shè)計
1、游戲面板生成顯示
2、地圖生成算法
3、人物移動算法
4、播放背景音樂
5、箱子移動算法
6、全部箱子移動到指定位置,才算游戲過關(guān)
功能截圖
游戲開始

移動效果

游戲過關(guān)

代碼實現(xiàn)
核心類
public class GameFrame extends JFrame implements
ActionListener, MouseListener, KeyListener {// 實現(xiàn)動作事件監(jiān)聽器、鼠標(biāo)事件監(jiān)聽器、鍵盤事件監(jiān)聽器
// 當(dāng)前的關(guān)卡數(shù),默認(rèn)為第一關(guān),從1開始計數(shù)
private int grade = 1;
// row,column記載人的位置,分別表示二維數(shù)組中的行號和列號,即map[row][column]確定人的位置
private int row = 7, column = 7;
// leftX,leftY記載左上角圖片的位置,避免圖片從(0,0)坐標(biāo)開始,因為是圖片填充,從(0,0)開始不行
private int leftX = 50, leftY = 50;
// 記載地圖的總共有多少行、多少列
private int mapRow = 0, mapColumn = 0;
// 記載屏幕窗口的寬度和高度
private int width = 0, height = 0;
private boolean acceptKey = true;
// 程序所需要用到的圖片
private Image pics[] = null;// 圖片數(shù)據(jù)
private byte[][] map = null;// 地圖數(shù)據(jù)
private ArrayList list = new ArrayList();
private SoundPlayerUtil soundPlayer;// 播放聲音工具類
/* 常量,即游戲中的資源 */
private final static int WALL = 1;// 墻
private final static int BOX = 2;// 箱子
private final static int BOX_ON_END = 3;// 放到目的地的箱子
private final static int END = 4;// 目的地
private final static int MAN_DOWN = 5;// 向下的人
private final static int MAN_LEFT = 6;// 向左的人
private final static int MAN_RIGHT = 7;// 向右的人
private final static int MAN_UP = 8;// 向上的人
private final static int GRASS = 9;// 通道
private final static int MAN_DOWN_ON_END = 10;// 站在目的地向下的人
private final static int MAN_LEFT_ON_END = 11;// 站在目的地向左的人
private final static int MAN_RIGHT_ON_END = 12;// 站在目的地向右的人
private final static int MAN_UP_ON_END = 13;// 站在目的地向上的人
private final static int MOVE_PIXEL = 30;// 表示每次移動30像素
/**
* 在構(gòu)造方法GameFrame0中,調(diào)用initMap()法來初始化本關(guān)grade游戲地圖,清空悔棋信
* 息列表list,同時播放MIDI背景音樂。
*/
public GameFrame() {
// 游戲窗口的一些基本設(shè)置
setTitle("推箱子游戲");
setSize(600, 600);
setVisible(true);
setLocation(300, 20);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
Container contentPane = getContentPane();
contentPane.setLayout(null);
contentPane.setBackground(Color.black);
// 其他設(shè)置,初始化窗口的寬度和高度賦值給width和height
this.width = getWidth();
this.height = getHeight();
// 初始化圖片資源
getPics();
// 初始化地圖數(shù)據(jù)
initMap();
// 注冊事件監(jiān)聽器
setFocusable(true);
addKeyListener(this);
addMouseListener(this);
// 播放音樂
initSound();
}
/**
* initMap()方法的作用是初始化本關(guān)grade 游戲地圖,清空悔棋信息列表list。 調(diào)用
* getMapSizeAndPosition(方法獲取游戲區(qū)域大小及顯示游戲的左上角位置( leftX, leftY )。
*/
public void initMap() {
// 獲取當(dāng)前關(guān)卡的地圖數(shù)據(jù)
map = MapFactory.getMap(grade);
// 清除上一關(guān)保存的回退地圖數(shù)據(jù),即清空list集合的內(nèi)容
list.clear();
// 初始化地圖行列數(shù)和左上角起始坐標(biāo)位置
getMapSizeAndPosition();
// 獲取角色的坐標(biāo)位置
getManPosition();
}
/**
* getManPosition()方法的作用是獲取工人的當(dāng)前位置(row,column)。
*/
public void getManPosition() {
// 即遍歷地圖數(shù)組map中存在那個值等于MANXXX(MAN_DOWN表示向下的人;MAN_UP表示向上的人)的情況,即表示該位置是人站立的位置,這個由地圖數(shù)據(jù)掃描得出
for (int i = 0; i < map.length; i++) {
for (int j = 0; j < map[0].length; j++) {
if (map[i][j] == MAN_DOWN || map[i][j] == MAN_DOWN_ON_END
|| map[i][j] == MAN_UP || map[i][j] == MAN_UP_ON_END
|| map[i][j] == MAN_LEFT || map[i][j] == MAN_LEFT_ON_END
|| map[i][j] == MAN_RIGHT || map[i][j] == MAN_RIGHT) {
// 保存人的位置,i表示第幾行,j表示第幾列,而且是從0開始的
this.row = i;
this.column = j;
break;
}
}
}
}
/**
* getMapSizeAndPosition()方法用來獲取游戲區(qū)域大小及顯示游戲的左上角位置( lefX, leftY )。
*/
private void getMapSizeAndPosition() {
// 初始化mapRow和mapColumn,表示地圖的行列數(shù)
this.mapRow = map.length;
this.mapColumn = map[0].length;
// 初始化leftX和leftY,即計算左上角的位置,
this.leftX = (width - map[0].length * MOVE_PIXEL) / 2;
this.leftY = (height - map.length * MOVE_PIXEL) / 2;
}
/**
* getPics()方法用來加載要顯示的圖片
*/
public void getPics() {
// 創(chuàng)建長度為13的數(shù)組,即有十三張圖片
pics = new Image[13];
// 然后循環(huán)將每張圖片讀取保存到pics數(shù)組中
for (int i = 0; i < 13; i++) {
pics[i] = Toolkit.getDefaultToolkit().getImage("src\\images\\pic_" + (i + 1) + ".png");
}
}
/**
* 初始化播放的音樂
*/
public void initSound() {
// 調(diào)用SoundPlayerUtil類中的方法播放音樂
soundPlayer = new SoundPlayerUtil();
soundPlayer.loadSound("src\\sounds\\music.wav");
soundPlayer.playSound(true);// 循環(huán)播放
}
/**
* grassOrEnd()方法判斷人所在的位置是通道GRASS還是目的地END
*
* @param man
* @return
*/
public byte grassOrEnd(byte man) {
if (man == MAN_DOWN_ON_END || man == MAN_LEFT_ON_END || man == MAN_RIGHT_ON_END || man == MAN_UP_ON_END) {
return END;
}
return GRASS;
}
/**
* 人物向上移動
*/
private void moveUp() {
// 如果上一位是WALL,則不能移動
if (map[row - 1][column] == WALL) {
return;
}
// 如果上一位是BOX或BOX_ON_END,需要考慮上一位的上一位是什么情況
if (map[row - 1][column] == BOX || map[row - 1][column] == BOX_ON_END) {
// 那么就需要考慮上一位的上一位情況,若上上一位是END或GRASS,則向上一步,其他情況不用處理
if (map[row - 2][column] == END || map[row - 2][column] == GRASS) {
// 要保留當(dāng)前信息,以便回退上一步
Map currMap = new Map(row, column, map);
list.add(currMap);
byte boxTemp = (byte) ((byte) map[row - 2][column] == END ? BOX_ON_END : BOX);
byte manTemp = (byte) (map[row - 1][column] == BOX ? MAN_UP : MAN_UP_ON_END);
// 箱子變成temp,箱子往前移動一步
map[row - 2][column] = boxTemp;
// 人變成MAN_UP,往上走一步
map[row - 1][column] = manTemp;
// 將人剛才站的地方變成GRASS或者END
map[row][column] = grassOrEnd(map[row][column]);
// 人離開后修改人的坐標(biāo)
row--;
}
} else {
// 上一位為GRASS或END,無需考慮上上一步,其他情況不用處理
if (map[row - 1][column] == GRASS || map[row - 1][column] == END) {
// 保留當(dāng)前這一步的信息,以便回退上一步
Map currMap = new Map(row, column, map);
list.add(currMap);
byte temp = (byte) (map[row - 1][column] == END ? MAN_UP_ON_END : MAN_UP);
// 人變成temp,人往上走一步
map[row - 1][column] = temp;
// 人剛才站的地方變成GRASS或者END
map[row][column] = grassOrEnd(map[row][column]);
// 人離開后修改人的坐標(biāo)
row--;
}
}
}
/**
* 人物向下移動,其中(row,column)是當(dāng)前角色站的位置,而map[row,column]表示當(dāng)前角色
*/
private void moveDown() {
// 如果下一位是WALL,則不能移動
// 所以map[row+1][column]表示當(dāng)前角色的下一步,也就是下一關(guān)圖像塊
if (map[row + 1][column] == WALL) {
return;
}
// 如果下一位是箱子BOX或放到目的地的箱子BOX_ON_END(即如果下一位是箱子,而不管是什么類型的箱子,都可以推動箱子),需要考慮下位的下一位是什么情況
if (map[row + 1][column] == BOX || map[row + 1][column] == BOX_ON_END) {
// 那么就需要考慮下一位的下一位情況(即箱子的下一位是什么,決定著箱子是否可以向前移動),若下下一位是目的地END或通道GRASS,則表示箱子可以向下移動一步,其他情況不用處理
// map[row+2][column]表示箱子的下一步是什么
if (map[row + 2][column] == END || map[row + 2][column] == GRASS) {
// 下面的代碼就是箱子向前移動一步,人移動原來箱子的位置
// 要保留當(dāng)前人和地圖信息,以便回退下一步
Map currMap = new Map(row, column, map);
list.add(currMap);
// 判斷箱子的下一步是否是目的地,如果是目的地,那么箱子的下一步就應(yīng)該變成BOX_ON_END(放在目的地的箱子),如果不是目的地那應(yīng)該還只是普通箱子BOX
byte boxTemp = (byte) ((byte) map[row + 2][column] == END ? BOX_ON_END : BOX);
// 判斷人的下一步是否是箱子
byte manTemp = (byte) (map[row + 1][column] == BOX ? MAN_DOWN : MAN_DOWN_ON_END);
// 箱子變成temp,箱子往下移動一步
map[row + 2][column] = boxTemp;
// 人變成MAN_UP,往下走一步
map[row + 1][column] = manTemp;
// 將人剛才站的地方變成GRASS或者END
map[row][column] = grassOrEnd(map[row][column]);
// 人離開后修改人的坐標(biāo)
row++;
}
} else {
// 執(zhí)行到這里,表示人的下一步不是箱子,那么要么是通道要么是終點
// 下一位為GRASS或END,無需考慮下下一步,其他情況不用處理
if (map[row + 1][column] == GRASS || map[row + 1][column] == END) {
// 保留當(dāng)前這一步的信息,以便回退下一步
Map currMap = new Map(row, column, map);
list.add(currMap);
byte temp = (byte) (map[row + 1][column] == END ? MAN_DOWN_ON_END : MAN_DOWN);
// 人變成temp,人往下走一步
map[row + 1][column] = temp;
// 人剛才站的地方變成GRASS或者END
map[row][column] = grassOrEnd(map[row][column]);
// 人離開后修改人的坐標(biāo)
row++;
}
}
}
/**
* 人物向左移動
*/
private void moveLeft() {
// 如果左一位是WALL,則不能移動
if (map[row][column - 1] == WALL) {
return;
}
// 如果左一位是BOX或BOX_ON_END,需要考慮左一位的左一位是什么情況
if (map[row][column - 1] == BOX || map[row][column - 1] == BOX_ON_END) {
// 那么就需要考慮左一位的左一位情況,若左左一位是END或GRASS,則向左一步,其他情況不用處理
if (map[row][column - 2] == END || map[row][column - 2] == GRASS) {
// 要保留當(dāng)前信息,以便回退左一步
Map currMap = new Map(row, column, map);
list.add(currMap);
byte boxTemp = (byte) ((byte) map[row][column - 2] == END ? BOX_ON_END : BOX);
byte manTemp = (byte) (map[row][column - 1] == BOX ? MAN_LEFT : MAN_LEFT_ON_END);
// 箱子變成temp,箱子往前移動一步
map[row][column - 2] = boxTemp;
// 人變成MAN_UP,往左走一步
map[row][column - 1] = manTemp;
// 將人剛才站的地方變成GRASS或者END
map[row][column] = grassOrEnd(map[row][column]);
// 人離開后修改人的坐標(biāo)
column--;
}
} else {
// 左一位為GRASS或END,無需考慮左左一步,其他情況不用處理
if (map[row][column - 1] == GRASS || map[row][column - 1] == END) {
// 保留當(dāng)前這一步的信息,以便回退左一步
Map currMap = new Map(row, column, map);
list.add(currMap);
byte temp = (byte) (map[row][column - 1] == END ? MAN_LEFT_ON_END : MAN_LEFT);
// 人變成temp,人往左走一步
map[row][column - 1] = temp;
// 人剛才站的地方變成GRASS或者END
map[row][column] = grassOrEnd(map[row][column]);
// 人離開后修改人的坐標(biāo)
column--;
}
}
}
/**
* 人物向右移動
*/
private void moveRight() {
// 如果右一位是WALL,則不能移動
if (map[row][column + 1] == WALL) {
return;
}
// 如果右一位是BOX或BOX_ON_END,需要考慮右位的右一位是什么情況
if (map[row][column + 1] == BOX || map[row][column + 1] == BOX_ON_END) {
// 那么就需要考慮右一位的右一位情況,若右右一位是END或GRASS,則向右一步,其他情況不用處理
if (map[row][column + 2] == END || map[row][column + 2] == GRASS) {
// 要保留當(dāng)前信息,以便回退右一步
Map currMap = new Map(row, column, map);
list.add(currMap);
byte boxTemp = (byte) ((byte) map[row][column + 2] == END ? BOX_ON_END : BOX);
byte manTemp = (byte) (map[row][column + 1] == BOX ? MAN_RIGHT : MAN_RIGHT_ON_END);
// 箱子變成temp,箱子往右移動一步
map[row][column + 2] = boxTemp;
// 人變成MAN_UP,往右走一步
map[row][column + 1] = manTemp;
// 將人剛才站的地方變成GRASS或者END
map[row][column] = grassOrEnd(map[row][column]);
// 人離開后修改人的坐標(biāo)
column++;
}
} else {
// 右一位為GRASS或END,無需考慮右右一步,其他情況不用處理
if (map[row][column + 1] == GRASS || map[row][column + 1] == END) {
// 保留當(dāng)前這一步的信息,以便回退右一步
Map currMap = new Map(row, column, map);
list.add(currMap);
byte temp = (byte) (map[row][column + 1] == END ? MAN_RIGHT_ON_END : MAN_RIGHT);
// 人變成temp,人往右走一步
map[row][column + 1] = temp;
// 人剛才站的地方變成GRASS或者END
map[row][column] = grassOrEnd(map[row][column]);
// 人離開后修改人的坐標(biāo)
column++;
}
}
}
/**
* 驗證玩家是否過關(guān),如果有目的地END值或人直接站在目的地則沒有成功
*
* @return 如果已經(jīng)通關(guān)則返回true,否則返回false
*/
public boolean isFinished() {
for (int i = 0; i < mapRow; i++) {
for (int j = 0; j < mapColumn; j++) {
if (map[i][j] == END || map[i][j] == MAN_DOWN_ON_END || map[i][j] == MAN_UP_ON_END || map[i][j] == MAN_LEFT_ON_END || map[i][j] == MAN_RIGHT_ON_END) {
return false;
}
}
}
return true;
}
// 使用雙緩沖技術(shù)解決動畫閃爍問題
private Image iBuffer;
private Graphics gBuffer;
/**
* 重寫繪制整個游戲區(qū)域的圖形
*
* @param g
*/
@Override
public void paint(Graphics g) {
if (iBuffer == null) {
iBuffer = createImage(width, height);
gBuffer = iBuffer.getGraphics();
}
// 清空屏幕原來的繪畫
gBuffer.setColor(getBackground());
gBuffer.fillRect(0, 0, width, height);
for (int i = 0; i < mapRow; i++) {
for (int j = 0; j < mapColumn; j++) {
// 畫出地圖,i表示行數(shù),j表示列數(shù)
if (map[i][j] != 0) {
// 這里要減1是因為圖片的名稱序號不對應(yīng),應(yīng)該從0開始,但是從1開始的
gBuffer.drawImage(pics[map[i][j] - 1], leftX + j * MOVE_PIXEL, leftY + i * MOVE_PIXEL, 30, 30, this);
}
}
}
gBuffer.setColor(Color.RED);
gBuffer.setFont(new Font("楷體_2312", Font.BOLD, 30));
gBuffer.drawString("現(xiàn)在是第", 150, 140);
gBuffer.drawString(String.valueOf(grade), 310, 140);
gBuffer.drawString("關(guān)", 360, 140);
g.drawImage(iBuffer, 0, 0, this);
/* 下面的代碼是未使用雙緩沖技術(shù)會導(dǎo)致動畫閃爍的代碼 */
/*g.clearRect(0, 0, width, height);
for (int i = 0; i < mapRow; i++) {
for (int j = 0; j < mapColumn; j++) {
// 畫出地圖,i表示行數(shù),j表示列數(shù)
if (map[i][j] != 0) {
// 這里要減1是因為圖片的名稱序號不對應(yīng),應(yīng)該從0開始,但是從1開始的
g.drawImage(pics[map[i][j] - 1], leftX + j * MOVE_PIXEL, leftY + i * MOVE_PIXEL, 30, 30, this);
}
}
}
g.setColor(Color.RED);
g.setFont(new Font("楷體_2312", Font.BOLD, 30));
g.drawString("現(xiàn)在是第", 150, 140);
g.drawString(String.valueOf(grade), 310, 140);
g.drawString("關(guān)", 360, 140);*/
}
@Override
public void actionPerformed(ActionEvent e) {
}
@Override
public void keyTyped(KeyEvent e) {
}
@Override
public void keyPressed(KeyEvent e) {
// 當(dāng)按鍵盤上的按鍵時觸發(fā)的事件
switch (e.getKeyCode()) {
case KeyEvent.VK_UP:// 上方向鍵
moveUp();// 向上移動
break;
case KeyEvent.VK_DOWN:// 下方向鍵
moveDown();// 向下移動
break;
case KeyEvent.VK_LEFT:// 左方向鍵
moveLeft();// 向左移動
break;
case KeyEvent.VK_RIGHT:// 右方向鍵
moveRight();// 向右移動
break;
}
// 然后重新繪制界面
repaint();
// 在移動完成后可能已經(jīng)通關(guān),所以需要判斷是否通關(guān)
if (isFinished()) {
// 禁用按鍵
acceptKey = false;
// 判斷是否是最后一關(guān),如果是則直接提示,如果不是則詢問是否要進(jìn)入下一關(guān)
if (grade == MapFactory.getCount()) {
JOptionPane.showMessageDialog(this, "恭喜通過最后一關(guān)!");
} else {
// 提示進(jìn)入下一關(guān)
String msg = "恭喜通過第" + grade + "關(guān)?。?!\n是否要進(jìn)入下一關(guān)?";
int choice = JOptionPane.showConfirmDialog(null, msg, "過關(guān)", JOptionPane.YES_NO_OPTION);
if (choice == 1) {
System.exit(0);
} else if (choice == 0) {
// 進(jìn)入下一關(guān)
acceptKey = true;
nextGrade();
}
}
}
}
@Override
public void keyReleased(KeyEvent e) {
}
@Override
public void mouseClicked(MouseEvent e) {
// MouseEvent.BUTTON3表示鼠標(biāo)右鍵
if (e.getButton() == MouseEvent.BUTTON3) {
undo();
}
}
@Override
public void mousePressed(MouseEvent e) {
}
@Override
public void mouseReleased(MouseEvent e) {
}
@Override
public void mouseEntered(MouseEvent e) {
}
@Override
public void mouseExited(MouseEvent e) {
}
/**
* 返回當(dāng)前人的位置用getManX()方法和getManY()方法
*
* @return
*/
public int getManX() {
return row;
}
public int getManY() {
return column;
}
/**
* 返回當(dāng)前關(guān)卡數(shù)
*
* @return
*/
public int getGrade() {
return grade;
}
/**
* 返回當(dāng)前關(guān)卡的地圖信息
*
* @return
*/
public byte[][] getMap() {
return MapFactory.getMap(grade);
}
/**
* 顯示提示信息對話框
*
* @param str
*/
public void displayToast(String str) {
JOptionPane.showMessageDialog(null, str, "提示", JOptionPane.ERROR_MESSAGE);
}
/**
* 撤銷移動操作
*/
public void undo() {
if (acceptKey) {
if (list.size() > 0) {
// 如果要撤銷,必須要走過
// 考慮用棧更合適
Map priorMap = (Map) list.get(list.size() - 1);
this.map = priorMap.getMap();
this.row = priorMap.getManX();
this.column = priorMap.getManY();
repaint();// 重新畫圖
list.remove(list.size() - 1);
} else {
displayToast("不能再撤銷了!");
}
} else {
displayToast("此關(guān)已完成,不能撤銷!");
}
}
/**
* 實現(xiàn)下一關(guān)的初始化,并且調(diào)用repaint()方法顯示游戲界面
*/
public void nextGrade() {
// 初始化下一關(guān)的數(shù)據(jù)
if (grade >= MapFactory.getCount()) {
displayToast("恭喜你完成所有關(guān)卡!");
acceptKey = false;
} else {
// 關(guān)卡數(shù)加1
grade++;
// 初始化下一關(guān)的地圖數(shù)據(jù)
initMap();
// 重新繪制畫面
repaint();
acceptKey = true;
}
}
/**
* 實現(xiàn)上一關(guān)初始化并且調(diào)用repaint()發(fā)顯示游戲界面
*/
public void priorGrade() {
grade--;
acceptKey = true;
if (grade < 0) {
grade = 0;
}
initMap();
repaint();
}
}聲音播放類
public class SoundPlayerUtil {
public File file;
public AudioInputStream stream;
public AudioFormat format;
DataLine.Info info;
Clip clip;
/**
* 加載聲音文件,支持wav、mp3等聲音文件
*
* @param filePath 聲音文件的路徑
*/
public void loadSound(String filePath) {
file = new File(filePath);
try {
stream = AudioSystem.getAudioInputStream(file);
} catch (UnsupportedAudioFileException | IOException e) {
e.printStackTrace();
}
format = stream.getFormat();
}
/**
* 播放音樂
*
* @param isLoop 表示是否循環(huán)播放音樂,如果傳入的是true則表示循環(huán)播放
*/
public void playSound(boolean isLoop) {
info = new DataLine.Info(Clip.class, format);
try {
clip = (Clip) AudioSystem.getLine(info);
clip.open(stream);
} catch (LineUnavailableException | IOException e) {
e.printStackTrace();
}
if (isLoop) {
clip.loop(Clip.LOOP_CONTINUOUSLY);// 添加該句代碼可以循環(huán)播放
}
clip.start();
}
}總結(jié)
通過此次的《推箱子》游戲?qū)崿F(xiàn),讓我對swing的相關(guān)知識有了進(jìn)一步的了解,對java這門語言也有了比以前更深刻的認(rèn)識。
java的一些基本語法,比如數(shù)據(jù)類型、運算符、程序流程控制和數(shù)組等,理解更加透徹。java最核心的核心就是面向?qū)ο笏枷?,對于這一個概念,終于悟到了一些。
以上就是Java實現(xiàn)經(jīng)典游戲推箱子的示例代碼的詳細(xì)內(nèi)容,更多關(guān)于Java推箱子的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
SpringData JPA中@OneToMany和@ManyToOne的用法詳解
這篇文章主要介紹了SpringData JPA中@OneToMany和@ManyToOne的用法詳解,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2021-10-10
為什么程序中突然多了 200 個 Dubbo-thread 線程的說明
這篇文章主要介紹了為什么程序中突然多了 200 個 Dubbo-thread 線程的說明,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-09-09
MyBatis中基于別名typeAliases的設(shè)置
這篇文章主要介紹了MyBatis中基于別名typeAliases的設(shè)置,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2021-07-07
springboot新建項目jdk只有17/21,無法選中1.8解決辦法
最近博主也有創(chuàng)建springboot項目,發(fā)現(xiàn)了IntelliJ IDEA在通過Spring Initilizer初始化項目的時候已經(jīng)沒有java8版本的選項了,這里給大家總結(jié)下,這篇文章主要給大家介紹了springboot新建項目jdk只有17/21,無法選中1.8的解決辦法,需要的朋友可以參考下2023-12-12
java HttpURLConnection 發(fā)送文件和字符串信息
這篇文章主要介紹了java HttpURLConnection 發(fā)送文件和字符串信息的相關(guān)資料,需要的朋友可以參考下2017-06-06

