java實現(xiàn)2048游戲源代碼
本文實例為大家分享了java實現(xiàn)2048游戲源代碼,供大家參考,具體內(nèi)容如下
一.主要功能:
1、游戲初始化:新建游戲4×4的16宮格畫布,隨機(jī)格子上生成2或者4兩個數(shù)字
2、格子的移動:先判斷能否移動,移動后判斷能否合并,合并后改變格子顏色和數(shù)字
3、新格子的生成:移動一次,就在剩余的空格子中隨機(jī)生成一個2或者4
4、判贏:16宮格中合并出了“2048”則為游戲勝利
5、判輸:16宮格中沒有剩余空格子且不能再向任何方向移動則為游戲失敗
二.項目的主要結(jié)構(gòu):

在項目2018游戲中,有4個源文件,此外,還有3個.png和兩個.wav格式的音樂文件。一個音樂是按鍵移動的聲音,另外一個是碰撞后的消除的聲音。然后游戲的最高分保存是在Recording源文件中,之后附上所需的圖片文件和音樂文件:
來了來了.



三.代碼
1、Game.java
package shixun;
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JFrame;
import javax.swing.JLabel;
public class Game extends JFrame {
private static final long serialVersionUID = 1L;
public static void main(String[] args) {
Game UI = new Game();
UI.IntUI();
}
// 用于存放數(shù)據(jù)的數(shù)組,構(gòu)成游戲4*4界面的數(shù)值
private int Numbers[][] = new int[4][4] ;
private void IntUI() {
this.setTitle("2048小游戲");
this.setLocation(450, 100);
this.setSize(400, 500);
this.setLayout(null);
// 開始游戲按鈕
ImageIcon imgicon = new ImageIcon("res/start.png");
JButton bt = new JButton(imgicon);
bt.setFocusable(false);
bt.setBorderPainted(false);
bt.setFocusPainted(false);
bt.setContentAreaFilled(false);
bt.setBounds(5, 10, 120, 30);// 設(shè)置按鈕的x,y坐標(biāo)位置和寬度與高度
this.add(bt);
//后退一步按鈕
ImageIcon backicon = new ImageIcon("res/backicon.png");
JButton back = new JButton(backicon);
back.setFocusable(false);
back.setBorderPainted(false);
back.setFocusPainted(false);
back.setContentAreaFilled(false);
back.setBounds(270, 10, 120, 30);// 設(shè)置按鈕的x,y坐標(biāo)位置和寬度與高度
this.add(back);
// 關(guān)于按鈕
ImageIcon imgicon2 = new ImageIcon("res/about.png");
JButton about = new JButton(imgicon2);
about.setFocusable(false);
about.setBorderPainted(false);
about.setFocusPainted(false);
about.setContentAreaFilled(false);
about.setBounds(160, 10, 70, 30);
this.add(about);
// 分?jǐn)?shù)顯示
JLabel lb = new JLabel("分?jǐn)?shù):0");
lb.setBounds(40, 45, 120, 30);
lb.setFont(new Font("幼圓", Font.CENTER_BASELINE, 18));
lb.setForeground(new Color(0x000000));
this.add(lb);
//最高分?jǐn)?shù)
Recorder.getRecording();
int maxscore = Recorder.getMaxscore_2048();
JLabel M=new JLabel("最高分:0");
M.setBounds(150,45,120,30);
M.setFont(new Font("幼圓", Font.CENTER_BASELINE, 18));
M.setForeground(new Color(0x000000));
this.add(M);
//靜音
JCheckBox isSoundBox=new JCheckBox("靜音");
isSoundBox.setBounds(290, 45, 120, 30);
isSoundBox.setFont(new Font("幼圓", Font.CENTER_BASELINE, 18));
isSoundBox.setFocusable(false);
isSoundBox.setBorderPainted(false);
isSoundBox.setFocusPainted(false);
isSoundBox.setContentAreaFilled(false);
this.add(isSoundBox);
this.setDefaultCloseOperation(3);
this.setResizable(false);
this.setVisible(true);// 顯示界面
// 創(chuàng)建事件處理類
MyListener cl = new MyListener(this,Numbers,lb,M, bt, about,back,isSoundBox);
bt.addActionListener(cl);
about.addActionListener(cl);
back.addActionListener(cl);
isSoundBox.addActionListener(cl);
this.addKeyListener(cl);
}
// 重寫窗體
@Override
public void paint(Graphics g) {
super.paint(g);
g.setColor(new Color(0xBBADA0));
g.fillRoundRect(15, 110, 370, 370, 15, 15);// 大矩形框
g.setColor(new Color(0xCDC1B4));
for (int i = 0; i < 4; i++) {
for (int j = 0; j < 4; j++) {
g.fillRoundRect(25 + i * 90, 120 + j * 90, 80, 80, 15, 15);// 小矩形框
}
}
// 調(diào)整數(shù)字的位置并上色
for (int i = 0; i < 4; i++) {
for (int j = 0; j < 4; j++) {
if (Numbers[j][i] != 0) {
int FontSize = 30;
int MoveX = 0, MoveY = 0;
switch (Numbers[j][i]) {
case 2:
g.setColor(new Color(0xeee4da));
FontSize = 30;
MoveX = 0;
MoveY = 0;
break;
case 4:
g.setColor(new Color(0xede0c8));
FontSize = 30;
MoveX = 0;
MoveY = 0;
break;
case 8:
g.setColor(new Color(0xf2b179));
FontSize = 30;
MoveX = 0;
MoveY = 0;
break;
case 16:
g.setColor(new Color(0xf59563));
FontSize = 29;
MoveX = -5;
MoveY = 0;
break;
case 32:
g.setColor(new Color(0xf67c5f));
FontSize = 29;
MoveX = -5;
MoveY = 0;
break;
case 64:
g.setColor(new Color(0xf65e3b));
FontSize = 29;
MoveX = -5;
MoveY = 0;
break;
case 128:
g.setColor(new Color(0xedcf72));
FontSize = 28;
MoveX = -10;
MoveY = 0;
break;
case 256:
g.setColor(new Color(0xedcc61));
FontSize = 28;
MoveX = -10;
MoveY = 0;
break;
case 512:
g.setColor(new Color(0xedc850));
FontSize = 28;
MoveX = -10;
MoveY = 0;
break;
case 1024:
g.setColor(new Color(0xedc53f));
FontSize = 27;
MoveX = -15;
MoveY = 0;
break;
case 2048:
g.setColor(new Color(0xedc22e));
FontSize = 27;
MoveX = -15;
MoveY = 0;
break;
default:
g.setColor(new Color(0x000000));
break;
}
g.fillRoundRect(25 + i * 90, 120 + j * 90, 80, 80, 15, 15);// 小矩形框上色
g.setColor(new Color(0x000000));
g.setFont(new Font("Kristen ITC", Font.PLAIN, FontSize));
g.drawString(Numbers[j][i] + "", 25 + i * 90 + 30 + MoveX,
120 + j * 90 + 50 + MoveY);
}
}
}
}
}
2、MyListener.java
package shixun;
import java.awt.Component;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.util.Arrays;
import java.util.Random;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
public class MyListener extends KeyAdapter implements ActionListener {
/**
* KevinWu
*/
private Game UI;// 界面對象
private int Numbers[][];// 存放數(shù)據(jù)的數(shù)組
private Random rand = new Random();
private int BackUp[][]= new int[4][4];//用于備份數(shù)組,供回退時使用
private int BackUp2[][]= new int[4][4];//用于備份數(shù)組,供起死回生時使用
public JLabel lb;
public JLabel M;
int score = 0;
int maxscore=Recorder.getMaxscore_2048();
int tempscore,tempscore2;//記錄回退isWin的分?jǐn)?shù)值
public JButton bt,about,back;
public JCheckBox isSoundBox;
private boolean isWin=false,relive=false,hasBack=false,isSound=true;
public MyListener(Game UI, int Numbers[][], JLabel lb,JLabel M ,JButton bt,JButton about,JButton back,JCheckBox isSoundBox) {
this.UI = UI;
this.Numbers = Numbers;
this.lb = lb;
this.bt=bt;
this.about=about;
this.back=back;
this.isSoundBox=isSoundBox;
this.M=M;
}
@Override
public void actionPerformed(ActionEvent e) {
// TODO Auto-generated method stub
if(e.getSource() ==bt ){
isWin=false;
for (int i = 0; i < 4; i++)
for (int j = 0; j < 4; j++)
Numbers[i][j] = 0;
score = 0;// 保證每次重置游戲都是0分開始
lb.setText("分?jǐn)?shù):" + score);
M.setText("最高分:"+maxscore);
int r1 = rand.nextInt(4);
int r2 = rand.nextInt(4);
int c1 = rand.nextInt(4);
int c2 = rand.nextInt(4);
while (r1 == r2 && c1 == c2) {
r2 = rand.nextInt(4);
c2 = rand.nextInt(4);
}
// 生成數(shù)字(2或者4)
int value1 = rand.nextInt(2) * 2 + 2;
int value2 = rand.nextInt(2) * 2 + 2;
// 把數(shù)字存進(jìn)對應(yīng)的位置
Numbers[r1][c1] = value1;
Numbers[r2][c2] = value2;
UI.paint(UI.getGraphics());
}
else if(e.getSource()==about){
JOptionPane.showMessageDialog(UI, "游戲規(guī)則:\n"
+ "開始時棋盤內(nèi)隨機(jī)出現(xiàn)兩個數(shù)字,出現(xiàn)的數(shù)字僅可能為2或4\n"
+ "玩家可以選擇上下左右四個方向,若棋盤內(nèi)的數(shù)字出現(xiàn)位移或合并,視為有效移動\n"
+ "玩家選擇的方向上若有相同的數(shù)字則合并,每次有效移動可以同時合并,但不可以連續(xù)合并\n"
+ "合并所得的所有新生成數(shù)字想加即為該步的有效得分\n"
+ "玩家選擇的方向行或列前方有空格則出現(xiàn)位移\n"
+ "每有效移動一步,棋盤的空位(無數(shù)字處)隨機(jī)出現(xiàn)一個數(shù)字(依然可能為2或4)\n"
+ "棋盤被數(shù)字填滿,無法進(jìn)行有效移動,判負(fù),游戲結(jié)束\n"
+ "棋盤上出現(xiàn)2048,判勝,游戲結(jié)束。\n"
);
}
else if(e.getSource()==back&&hasBack==false){
hasBack=true;
if(relive==false){
score=tempscore;
lb.setText("分?jǐn)?shù):" + score);
for(int i=0;i<BackUp.length;i++){
Numbers[i]=Arrays.copyOf(BackUp[i], BackUp[i].length);
}
}
else{
score=tempscore2;
lb.setText("分?jǐn)?shù):" + score);
for(int i=0;i<BackUp2.length;i++){
Numbers[i]=Arrays.copyOf(BackUp2[i], BackUp2[i].length);
}
relive=false;
}
UI.paint(UI.getGraphics());
}
else if(e.getSource().equals(isSoundBox)){
if (isSoundBox.isSelected())
isSound=false;
else
isSound=true;
}
}
// 鍵盤監(jiān)聽
public void keyPressed(KeyEvent event) {
int Counter = 0;// 計算器,判斷是否移動了
int NumCounter = 0;// 用于統(tǒng)計整個大方框中數(shù)字的個數(shù),判斷是否已滿
int NumNearCounter = 0;// 用于統(tǒng)計相鄰格子數(shù)字相同的個數(shù)
/*
* 方向鍵鍵值:左:37上:38右:39下:40
*/
hasBack = false;
if (BackUp != null || BackUp.length != 0) {
tempscore2 = tempscore;// 先把分?jǐn)?shù)備份好
// 下面的for循環(huán)調(diào)用java.util.Arrays.copyOf()方法復(fù)制數(shù)組,實現(xiàn)備份
for (int i = 0; i < BackUp.length; i++) {
BackUp2[i] = Arrays.copyOf(BackUp[i], BackUp[i].length);
}
}
tempscore = score;// 先把分?jǐn)?shù)備份好
// 下面的for循環(huán)調(diào)用java.util.Arrays.copyOf()方法復(fù)制數(shù)組,實現(xiàn)備份
for (int i = 0; i < Numbers.length; i++) {
BackUp[i] = Arrays.copyOf(Numbers[i], Numbers[i].length);
}
if (isWin == false) {
switch (event.getKeyCode()) {
case 37:
// 向左移動
if (isSound == true)
new PlaySound("move.wav").start();
for (int h = 0; h < 4; h++)
for (int l = 0; l < 4; l++)
if (Numbers[h][l] != 0) {
int temp = Numbers[h][l];
int pre = l - 1;
while (pre >= 0 && Numbers[h][pre] == 0) {
Numbers[h][pre] = temp;
Numbers[h][pre + 1] = 0;
pre--;
Counter++;
}
}
for (int h = 0; h < 4; h++)
for (int l = 0; l < 4; l++)
if (l + 1 < 4
&& (Numbers[h][l] == Numbers[h][l + 1])
&& (Numbers[h][l] != 0 || Numbers[h][l + 1] != 0)) {
if (isSound == true)
new PlaySound("merge.wav").start();
Numbers[h][l] = Numbers[h][l] + Numbers[h][l + 1];
Numbers[h][l + 1] = 0;
Counter++;
score += Numbers[h][l];
if (Numbers[h][l] == 2048) {
isWin = true;
}
}
for (int h = 0; h < 4; h++)
for (int l = 0; l < 4; l++)
if (Numbers[h][l] != 0) {
int temp = Numbers[h][l];
int pre = l - 1;
while (pre >= 0 && Numbers[h][pre] == 0) {
Numbers[h][pre] = temp;
Numbers[h][pre + 1] = 0;
pre--;
Counter++;
}
}
break;
case 39:// 向右移動
if (isSound == true)
new PlaySound("move.wav").start();
for (int h = 3; h >= 0; h--)
for (int l = 3; l >= 0; l--)
if (Numbers[h][l] != 0) {
int temp = Numbers[h][l];
int pre = l + 1;
while (pre <= 3 && Numbers[h][pre] == 0) {
Numbers[h][pre] = temp;
Numbers[h][pre - 1] = 0;
pre++;
Counter++;
}
}
for (int h = 3; h >= 0; h--)
for (int l = 3; l >= 0; l--)
if (l + 1 < 4
&& (Numbers[h][l] == Numbers[h][l + 1])
&& (Numbers[h][l] != 0 || Numbers[h][l + 1] != 0)) {
if (isSound == true)
new PlaySound("merge.wav").start();
Numbers[h][l + 1] = Numbers[h][l]
+ Numbers[h][l + 1];
Numbers[h][l] = 0;
Counter++;
score += Numbers[h][l + 1];
if (Numbers[h][l + 1] == 2048) {
isWin = true;
}
}
for (int h = 3; h >= 0; h--)
for (int l = 3; l >= 0; l--)
if (Numbers[h][l] != 0) {
int temp = Numbers[h][l];
int pre = l + 1;
while (pre <= 3 && Numbers[h][pre] == 0) {
Numbers[h][pre] = temp;
Numbers[h][pre - 1] = 0;
pre++;
Counter++;
}
}
break;
case 38:
//向上移動
if (isSound == true)
new PlaySound("move.wav").start();
for (int l = 0; l < 4; l++)
for (int h = 0; h < 4; h++)
if (Numbers[h][l] != 0) {
int temp = Numbers[h][l];
int pre = h - 1;
while (pre >= 0 && Numbers[pre][l] == 0) {
Numbers[pre][l] = temp;
Numbers[pre + 1][l] = 0;
pre--;
Counter++;
}
}
for (int l = 0; l < 4; l++)
for (int h = 0; h < 4; h++)
if (h + 1 < 4
&& (Numbers[h][l] == Numbers[h + 1][l])
&& (Numbers[h][l] != 0 || Numbers[h + 1][l] != 0)) {
if (isSound == true)
new PlaySound("merge.wav").start();
Numbers[h][l] = Numbers[h][l] + Numbers[h + 1][l];
Numbers[h + 1][l] = 0;
Counter++;
score += Numbers[h][l];
if (Numbers[h][l] == 2048) {
isWin = true;
}
}
for (int l = 0; l < 4; l++)
for (int h = 0; h < 4; h++)
if (Numbers[h][l] != 0) {
int temp = Numbers[h][l];
int pre = h - 1;
while (pre >= 0 && Numbers[pre][l] == 0) {
Numbers[pre][l] = temp;
Numbers[pre + 1][l] = 0;
pre--;
Counter++;
}
}
break;
case 40:
// 向下移動
if (isSound == true)
new PlaySound("move.wav").start();
for (int l = 3; l >= 0; l--)
for (int h = 3; h >= 0; h--)
if (Numbers[h][l] != 0) {
int temp = Numbers[h][l];
int pre = h + 1;
while (pre <= 3 && Numbers[pre][l] == 0) {
Numbers[pre][l] = temp;
Numbers[pre - 1][l] = 0;
pre++;
Counter++;
}
}
for (int l = 3; l >= 0; l--)
for (int h = 3; h >= 0; h--)
if (h + 1 < 4
&& (Numbers[h][l] == Numbers[h + 1][l])
&& (Numbers[h][l] != 0 || Numbers[h + 1][l] != 0)) {
if (isSound == true)
new PlaySound("merge.wav").start();
Numbers[h + 1][l] = Numbers[h][l]
+ Numbers[h + 1][l];
Numbers[h][l] = 0;
Counter++;
score += Numbers[h + 1][l];
if (Numbers[h + 1][l] == 2048) {
isWin = true;
}
}
for (int l = 0; l < 4; l++)
for (int h = 0; h < 4; h++)
if (Numbers[h][l] != 0) {
int temp = Numbers[h][l];
int pre = h - 1;
while (pre >= 0 && Numbers[pre][l] == 0) {
Numbers[pre][l] = temp;
Numbers[pre + 1][l] = 0;
pre--;
Counter++;
}
}
break;
case 40:
// 向下移動
if (isSound == true)
new PlaySound("move.wav").start();
for (int l = 3; l >= 0; l--)
for (int h = 3; h >= 0; h--)
if (Numbers[h][l] != 0) {
int temp = Numbers[h][l];
int pre = h + 1;
while (pre <= 3 && Numbers[pre][l] == 0) {
Numbers[pre][l] = temp;
Numbers[pre - 1][l] = 0;
pre++;
Counter++;
}
}
for (int l = 3; l >= 0; l--)
for (int h = 3; h >= 0; h--)
if (h + 1 < 4
&& (Numbers[h][l] == Numbers[h + 1][l])
&& (Numbers[h][l] != 0 || Numbers[h + 1][l] != 0)) {
if (isSound == true)
new PlaySound("merge.wav").start();
Numbers[h + 1][l] = Numbers[h][l]
+ Numbers[h + 1][l];
Numbers[h][l] = 0;
Counter++;
score += Numbers[h + 1][l];
if (Numbers[h + 1][l] == 2048) {
isWin = true;
}
}
for (int l = 3; l >= 0; l--)
for (int h = 3; h >= 0; h--)
if (Numbers[h][l] != 0) {
int temp = Numbers[h][l];
int pre = h + 1;
while (pre <= 3 && Numbers[pre][l] == 0) {
Numbers[pre][l] = temp;
Numbers[pre - 1][l] = 0;
pre++;
Counter++;
}
}
break;
default:break;
}
if(maxscore<=score) {
maxscore=score;
Recorder.setMaxscore(maxscore);
Recorder.keepRecording();
}
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
if (Numbers[i][j] == Numbers[i][j + 1]
&& Numbers[i][j] != 0) {
NumNearCounter++;
}
if (Numbers[i][j] == Numbers[i + 1][j]
&& Numbers[i][j] != 0) {
NumNearCounter++;
}
if (Numbers[3][j] == Numbers[3][j + 1]
&& Numbers[3][j] != 0) {
NumNearCounter++;
}
if (Numbers[i][3] == Numbers[i + 1][3]
&& Numbers[i][3] != 0) {
NumNearCounter++;
}
}
}
for (int i = 0; i < 4; i++) {
for (int j = 0; j < 4; j++) {
if (Numbers[i][j] != 0) {
NumCounter++;
}
}
}
if (Counter > 0) {
lb.setText("分?jǐn)?shù):" + score);
M.setText("最高分:"+maxscore);
int r1 = rand.nextInt(4);
int c1 = rand.nextInt(4);
while (Numbers[r1][c1] != 0) {
r1 = rand.nextInt(4);
c1 = rand.nextInt(4);
}
int value1 = rand.nextInt(2) * 2 + 2;
Numbers[r1][c1] = value1;
}
if (isWin == true){
UI.paint(UI.getGraphics());
JOptionPane.showMessageDialog(UI, "恭喜你贏了!\n您的最終得分為:" + score);
}
if (NumCounter == 16 && NumNearCounter == 0) {
relive = true;
JOptionPane.showMessageDialog(UI, "沒地方可以合并咯!!"
+ "\n很遺憾,您輸了~>_<~" + "\n悄悄告訴你,游戲有起死回生功能哦,不信你“退一步”試試?"
+ "\n說不定能扭轉(zhuǎn)乾坤捏 (^_~)");
}
UI.paint(UI.getGraphics());
}
}
}
3、PlaySound.java
package shixun;
import java.io.File;
import java.io.IOException;
import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.DataLine;
import javax.sound.sampled.SourceDataLine;
//播放聲音的線程
public class PlaySound extends Thread {
private String filename;
public PlaySound(String wavfile) {
filename = "res/" + wavfile;
}
public void run() {
File soundFile = new File(filename);
AudioInputStream audioInputStream = null;
try {
audioInputStream = AudioSystem.getAudioInputStream(soundFile);
} catch (Exception e1) {
e1.printStackTrace();
return;
}
AudioFormat format = audioInputStream.getFormat();
SourceDataLine auline = null;
DataLine.Info info = new DataLine.Info(SourceDataLine.class, format);
try {
auline = (SourceDataLine) AudioSystem.getLine(info);
auline.open(format);
} catch (Exception e) {
e.printStackTrace();
return;
}
auline.start();
int nBytesRead = 0;
// 這是緩沖
byte[] abData = new byte[512];
try {
while (nBytesRead != -1) {
nBytesRead = audioInputStream.read(abData, 0, abData.length);
if (nBytesRead >= 0)
auline.write(abData, 0, nBytesRead);
}
} catch (IOException e) {
e.printStackTrace();
return;
} finally {
auline.drain();
auline.close();
}
}
}
4、Recorder.java
package shixun;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
public class Recorder {
private static int maxscore_2048=0;
public static int getMaxscore_2048() {
// TODO Auto-generated method stub
return maxscore_2048;
}
public static void setMaxscore(int maxscore_2048) {
// TODO Auto-generated method stub
Recorder.maxscore_2048=maxscore_2048;
}
private static FileReader fr=null;
private static BufferedReader br=null;
private static FileWriter fw=null;
private static BufferedWriter bw=null;
//從文件中讀取,記錄
public static void getRecording()
{
boolean flag =false;//判斷文件是否新建
try {
File f=new File("src/myRecording.txt");
if(f.exists())
{
fr=new FileReader(f);
br=new BufferedReader(fr);
String n=br.readLine();
maxscore_2048=Integer.parseInt(n);
}
else {
flag=f.createNewFile();
}
}
catch(Exception e) {
e.printStackTrace();
}
finally {
try {
if(!flag) {
br.close();
fr.close();
}
}catch(Exception e2) {
e2.printStackTrace();
}
}
}
//保存最高分記錄
public static void keepRecording()
{
try {
File f=new File("src/myRecording.txt");
fw=new FileWriter(f);
bw=new BufferedWriter(fw);
bw.write(maxscore_2048+"\r\n");
}catch(IOException e) {
e.printStackTrace();
}
finally {
try {
bw.close();
fw.close();
}
catch(IOException e) {
e.printStackTrace();
}
}
}
}
四.游戲截圖


更多有趣的經(jīng)典小游戲?qū)崿F(xiàn)專題,分享給大家:
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
Java 批量獲取地址間距離工具(支持中轉(zhuǎn)站)
本文主要介紹了Java批量獲取地址間距離,獲取兩個地址間距離,實現(xiàn)方式比較多,具有一定的參考價值,感興趣的小伙伴們可以參考一下2021-07-07
MyBatisPlus+Spring實現(xiàn)聲明式事務(wù)的方法實現(xiàn)
本文主要介紹了MyBatisPlus+Spring實現(xiàn)聲明式事務(wù)的方法實現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2024-07-07
Spring+quartz實現(xiàn)定時發(fā)送郵件功能實例
spring提供的定時發(fā)送郵件功能一直深受廣大web開發(fā)者的喜愛,這篇文章主要介紹了Spring+quartz實現(xiàn)定時發(fā)送郵件功能實例,有興趣的可以了解一下。2017-03-03
關(guān)于SpringBoot整合Canal數(shù)據(jù)同步的問題
大家都知道canal是阿里巴巴旗下的一款開源工具,純java開發(fā),支持mysql數(shù)據(jù)庫,本文給大家介紹SpringBoot整合Canal數(shù)據(jù)同步的問題,需要的朋友可以參考下2022-03-03
jmeter實現(xiàn)接口關(guān)聯(lián)的兩種方式(正則表達(dá)式提取器和json提取器)
Jmeter用于接口測試時,后一個接口經(jīng)常需要用到前一次接口返回的結(jié)果,本文主要介紹了jmeter實現(xiàn)接口關(guān)聯(lián)的兩種方式,感興趣的小伙伴們可以參考一下2021-11-11

