目录
基于 Java 的葫芦娃大战妖精 1
1 项目介绍 1
1.1 项目简介 1
1.2 运行方式 2
1.3 实现效果 3
对局结束后显示提示信息 6
2 设计思想 6
2.1 类的设计 6
3 实现细节 7
3.1 图形界面 7
3.2 网络通信 8
3.3 游戏流程控制和用户交互 11
3.4 战斗逻辑 12
3.5 回放功能 14
4 总结 16
4.1 一点优点 16
4.2 一点反思 16
4.3 可改进的地方 16
1 项目介绍
1.1 项目简介
本项目使用 Java 语言编程,运用图形框架 JavaFX,结合网络编程(C/S 架构),实现可供多名玩家在线匹配的 1v1 联机游戏《葫芦娃大战妖精》。
游戏规则:
1.
玩家首先要输入运行服务器的主机 IP 地址与服务器连接,在成功连接服务器后可以通过鼠标点击选择:
1)匹配玩家:选择当前已连接服务器的某一玩家 id(最小为 0)并发送对战邀请,如果对方同意则可以直接进入游戏;相应的,在接受其他玩家发出的对战邀请后也可以直接进入游戏。
2)战斗回放:选择某一用于记录战局的*.xml 文件(文件名为对局时间)可以读取文件内容,并按文件中记录的内容进行战斗回放。
3)退出游戏
在成功匹配玩家后,游戏在 59 的二维空间战场上进行,分为葫芦娃阵营和妖精阵营。游戏开始时葫芦娃阵营(包含七兄弟、老爷爷和穿山甲)与妖精阵营(包括蛇精、蝎子精和小喽啰等)以特定阵型在左右两侧分列站队。玩家可以用键盘的“1”-“9”键选中对应编号的游戏角色;使用"W", “S”, ”A", "D"键控制角色进行上,下,左,右方向的移动;使用“J”键进行攻击(仅能攻击人物朝向的相邻位置的角色),使敌方角色掉血;人物上方的红色血条显示人物剩余血量,血量为 0 时角色死亡,当某一方生物全部死亡时,游戏结束,对局过程将保存到文件中,同时有弹窗提示对局结果。
在进行战斗回放时,会跳出文件选择对话框,选择记录对局过程的
.xml 文件即可进行战斗回放。*.xml 文件通常以时间命名,如提交版本中录制的对局:target/2021-01-02 11_34_46.xml
注:需要使用鼠标进行功能选择,并没有添加使用按键的空格键开始对局,"L"键进行战斗回放的交互方式。本文来自:http://www.biyezuopin.vip/onews.asp?id=16768
1.2 运行方式
Tip:CalabashServer 类和 Main 类中都有 main 函数,分别是服务器和客户端的入口。
先运行服务器,可以直接运行 CalabashServer 中的 main 函数,也可以将 pom.xml 文件中的 artifactId 改为 CalabashServer,将 mainClass 修改为 sample.CalabashServer 后打包成 CalabashServer-1.0.jar 后直接运行 target 目录下的 jar 包。即如下修改:
CalabashServer

sample.CalabashServer


成功运行服务器后,可以在不同的主机上运行客户端,即运行 target 目录下的 jar 包 CalabashWar-1.0.jar。
(生成 CalabashWar-1.0.jar:将 pom.xml 文件中的 artifactId 改为 CalabashWar,将 mainClass 修改为 sample.Main 后执行 mvn package 指令)
(因为 pom.xml 文件的后期修改失误,提交版本中 target 目录下名字为 CalabashServer-1.0.jar 和 CalabashWar-1.0.jar 其实对应的都是客户端的 jar 包,即指定主类为 Main 的 jar 包)

package sample;import java.io.File;
import java.lang.reflect.Array;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;import javax.xml.transform.TransformerException;import java.util.Arrays;
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;
import javafx.scene.image.ImageView;
import javafx.scene.image.Image;
import javafx.scene.layout.Pane;
import javafx.application.Platform;
import javafx.scene.control.Label;
import javafx.scene.control.TextInputDialog;
import javafx.scene.input.MouseEvent;
import javafx.scene.input.KeyEvent;
import javafx.scene.input.KeyCode;
import javafx.scene.control.Alert;
import javafx.scene.control.Button;
import javafx.scene.control.ButtonType;
import javafx.scene.control.ChoiceDialog;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.stage.FileChooser;
import javafx.stage.StageStyle;public class Main extends Application {// connectint myID;// 自己的idint matchPlayerID = -1;// 想匹配的玩家IDint enemyID = -1;//boolean started = false;String serverIP;// 服务器ip地址List<Player> players = new ArrayList<>();// 当前与服务器连接的可匹配玩家// UIPane canvas = new Pane();Stage stage = new Stage();Scene scene = new Scene(canvas, Attributes.width, Attributes.height);double mouseX;double mouseY;CalabashClient calabashClient;Battle battle = new Battle();List<ImageView> picsList;ArrayList<ImageView> pics = new ArrayList<>();ArrayList<ImageView> picsDead = new ArrayList<>();ArrayList<Label> labels = new ArrayList<>();AtomicBoolean playing = new AtomicBoolean(false);@Overridepublic void init() throws Exception {Attributes.init();}// step1:连接服务器void connectServer(int flag) {TextInputDialog dialog = new TextInputDialog(Attributes.localServerIP);dialog.setTitle("连接服务器");if (flag == 0) {dialog.setHeaderText("输入服务器IP地址后,按“确定”键连接服务器");} else {dialog.setHeaderText("服务器连接失败! 请检查服务器是否正在运行及服务器IP地址是否正确后重新输入");}dialog.setContentText("服务器IP地址:");Optional<String> result = dialog.showAndWait();if (result.isPresent()) {serverIP = result.get();calabashClient = new CalabashClient(this);if (calabashClient.connect(serverIP)) {startInterface();} else {connectServer(1);}}}// step2:选择开始游戏or回放or退出public void startInterface() {// 背景ImageView start = new ImageView(Attributes.images.get(Attributes.START));start.setFitHeight(Attributes.height);start.setFitWidth(Attributes.width);canvas.getChildren().add(start);//开始游戏按钮ImageView startGame = new ImageView(Attributes.images.get(Attributes.STARTICON));startGame.setFitHeight(54);startGame.setFitWidth(175);Label startLabel = new Label("",startGame);startLabel.setLayoutX(350);startLabel.setLayoutY(550);startLabel.setOnMouseClicked((MouseEvent e)->{ matchPlayer(); });canvas.getChildren().add(startLabel);//退出按钮ImageView exitImage = new ImageView(Attributes.images.get(Attributes.EXITICON));exitImage.setFitHeight(54);exitImage.setFitWidth(175);Label exitLabel = new Label("",exitImage);exitLabel.setMaxSize(350,109);exitLabel.setLayoutX(950);exitLabel.setLayoutY(550);exitLabel.setOnMouseClicked((MouseEvent e)->{ System.exit(0); });canvas.getChildren().add(exitLabel);// 读取进度按钮ImageView loadfile = new ImageView(Attributes.images.get(Attributes.LOADICON));loadfile.setFitHeight(54);loadfile.setFitWidth(175);Label loadLabel = new Label("", loadfile);loadLabel.setLayoutX(650);loadLabel.setLayoutY(550);loadLabel.setOnMouseClicked((MouseEvent e) -> {try {loadProgress();} catch (InterruptedException e1) {// TODO Auto-generated catch blocke1.printStackTrace();}});canvas.getChildren().add(loadLabel);}// step3-1:选择开始游戏后匹配玩家void matchPlayer() {List<String> choices = new ArrayList<>();for (Player p : players) {System.out.println(p.id);choices.add(Integer.toString(p.id));}String defaultPlayer;if (choices.size() > 0)defaultPlayer = choices.get(0);elsedefaultPlayer = "--";ChoiceDialog<String> dialog = new ChoiceDialog<>(defaultPlayer, choices);dialog.setTitle("匹配玩家");dialog.setHeaderText("选择当前在线玩家进行战斗吧!若想刷新新玩家请点击“取消”后再按“START“");dialog.setContentText("请选择想匹配的玩家id:");Optional<String> result = dialog.showAndWait();if (result.isPresent() && result.get() != "--") {matchPlayerID = Integer.parseInt(result.get());InviteMessage message = new InviteMessage(myID, matchPlayerID);calabashClient.send(message);/** enemyID=matchPlayerID; started=true;*/}if (started == true)enterBattle();// The Java 8 way to get the response value (with lambda expression).// result.ifPresent(letter -> System.out.println("Your choice: " + letter));}//void processInvitation(int playerID) {Alert alert = new Alert(Alert.AlertType.CONFIRMATION);alert.setTitle("玩家邀请");alert.setHeaderText("玩家" + Integer.toString(playerID) + "邀请您加入战斗");alert.setContentText("是否同意邀请?");Optional<ButtonType> result = alert.showAndWait();if (result.get() == ButtonType.OK) {enemyID = playerID;battle = new Battle();battle.setCamp(Camp.MONSTER);started = true;enterBattle();ReplyMessage r = new ReplyMessage(myID, playerID, 1);calabashClient.send(r);} else {ReplyMessage r = new ReplyMessage(myID, playerID, 0);calabashClient.send(r);}}void invitationRefused() {Alert alert = new Alert(Alert.AlertType.INFORMATION);alert.setTitle("匹配失败");alert.setHeaderText(null);alert.setContentText("玩家" + Integer.toString(matchPlayerID) + "拒绝了您的邀请,请重新匹配!");alert.showAndWait();}int xToPixel(int x) {// 地图格X坐标转换为像素横坐标return Attributes.mapLeft + x * Attributes.gridWidth;}int yToPixel(int y) {// 地图格Y坐标转换为像素纵坐标return Attributes.mapTop + y * Attributes.gridHeight;}void moveRole(int id,int x,int y){//角色图片labels.get(id).setLayoutX(xToPixel(x));labels.get(id).setLayoutY(yToPixel(y));//血量labels.get(id + Attributes.hpoffset).setLayoutX(xToPixel(x));labels.get(id + Attributes.hpoffset).setLayoutY(yToPixel(y)-3);//本地记录移动动作battle.gameprogress.writeIn(ActionType.MOVE, id + " " + x + " " + y);}void waitStart() {// 等待其他玩家进入后开局ImageView start = new ImageView(Attributes.images.get(Attributes.START));start.setFitHeight(Attributes.height);start.setFitWidth(Attributes.width);canvas.getChildren().add(start);// calabashClient.connect(Attributes.serverIP);enterBattle();}////*** Runs the specified {@link Runnable} on the JavaFX application thread and* waits for completion.** @param action the {@link Runnable} to run* @throws NullPointerException if {@code action} is {@code null}*/static void runAndWait(Runnable action) {if (action == null)throw new NullPointerException("action");// run synchronously on JavaFX threadif (Platform.isFxApplicationThread()) {action.run();return;}// queue on JavaFX thread and wait for completionfinal CountDownLatch doneLatch = new CountDownLatch(1);Platform.runLater(() -> {try {action.run();// new Thread(action).start();} finally {doneLatch.countDown();}});try {doneLatch.await();} catch (InterruptedException e) {// ignore exception}}/void loadProgress() throws InterruptedException {FileChooser chooser = new FileChooser();chooser.getExtensionFilters().addAll(new FileChooser.ExtensionFilter("Xml Files", "*.xml"));File file = chooser.showOpenDialog(stage);if (file != null) {Playback autoplay = new Playback(file.getPath(), this);// autoplay.run();//A版本:Thread t1 = new Thread(autoplay);t1.start();// t1.join();// startInterface();System.out.println("回退");// runAndWait(autoplay);// final CountDownLatch doneLatch = new CountDownLatch(1);// try {// new Thread(autoplay).start();// } finally {// doneLatch.countDown();// startInterface();// System.out.println("回到主界面");// }}// while (true) {//     if (playing.get() == false) {//         startInterface();//         System.out.println("回到主界面");//         break;//     }// }}void decorateStage() {labels.clear();pics.clear();picsDead.clear();// 显示地图ImageView map = new ImageView(Attributes.images.get(Attributes.MAP));map.setFitHeight(Attributes.height);map.setFitWidth(Attributes.width);canvas.getChildren().add(map);// 加载角色图片picsList = Arrays.asList(new ImageView(Attributes.images.get(Attributes.CALABASH1)),new ImageView(Attributes.images.get(Attributes.CALABASH2)),new ImageView(Attributes.images.get(Attributes.CALABASH3)),new ImageView(Attributes.images.get(Attributes.CALABASH4)),new ImageView(Attributes.images.get(Attributes.CALABASH5)),new ImageView(Attributes.images.get(Attributes.CALABASH6)),new ImageView(Attributes.images.get(Attributes.CALABASH7)),new ImageView(Attributes.images.get(Attributes.GRANDPA)),new ImageView(Attributes.images.get(Attributes.PANGOLIN)),new ImageView(Attributes.images.get(Attributes.SCORPION)),new ImageView(Attributes.images.get(Attributes.SNAKE)),new ImageView(Attributes.images.get(Attributes.MINION3)),new ImageView(Attributes.images.get(Attributes.MINION4)),new ImageView(Attributes.images.get(Attributes.MINION5)),new ImageView(Attributes.images.get(Attributes.MINION6)),new ImageView(Attributes.images.get(Attributes.MINION7)),new ImageView(Attributes.images.get(Attributes.MINION8)),new ImageView(Attributes.images.get(Attributes.MINION9)));pics.addAll(picsList);///List<ImageView> picsListDead = Arrays.asList(new ImageView(Attributes.images.get(Attributes.CALABASH1_DEAD)),new ImageView(Attributes.images.get(Attributes.CALABASH2_DEAD)),new ImageView(Attributes.images.get(Attributes.CALABASH3_DEAD)),new ImageView(Attributes.images.get(Attributes.CALABASH4_DEAD)),new ImageView(Attributes.images.get(Attributes.CALABASH5_DEAD)),new ImageView(Attributes.images.get(Attributes.CALABASH6_DEAD)),new ImageView(Attributes.images.get(Attributes.CALABASH7_DEAD)),new ImageView(Attributes.images.get(Attributes.GRANDPA_DEAD)),new ImageView(Attributes.images.get(Attributes.PANGOLIN_DEAD)),new ImageView(Attributes.images.get(Attributes.SCORPION_DEAD)),new ImageView(Attributes.images.get(Attributes.SNAKE_DEAD)),new ImageView(Attributes.images.get(Attributes.MINION_DEAD)),new ImageView(Attributes.images.get(Attributes.MINION_DEAD)),new ImageView(Attributes.images.get(Attributes.MINION_DEAD)),new ImageView(Attributes.images.get(Attributes.MINION_DEAD)),new ImageView(Attributes.images.get(Attributes.MINION_DEAD)),new ImageView(Attributes.images.get(Attributes.MINION_DEAD)),new ImageView(Attributes.images.get(Attributes.MINION_DEAD)));// ArrayList<ImageView> picsDead=new ArrayList<>();picsDead.addAll(picsListDead);for (int i = 0; i < 2 * Attributes.rolesNum; i++) {pics.get(i).setFitWidth(100);pics.get(i).setFitHeight(100);picsDead.get(i).setFitHeight(100);picsDead.get(i).setFitWidth(100);}// 人物的显示for (int i = 0; i < 2 * Attributes.rolesNum; i++) {Label label = new Label("", pics.get(i));label.setLayoutX(Attributes.mapLeft + battle.roles.get(i).curX.get() * Attributes.gridWidth);label.setLayoutY(Attributes.mapTop + battle.roles.get(i).curY.get() * Attributes.gridHeight);labels.add(label);canvas.getChildren().add(label);}// 血量条的显示for (int i = 0; i < 2 * Attributes.rolesNum; i++) {battle.hpbars.get(i).setBar(battle.roles.get(i));Label labelbar = new Label("", battle.hpbars.get(i));labelbar.setLayoutX(Attributes.mapLeft + battle.roles.get(i).curX.get() * Attributes.gridWidth);labelbar.setLayoutY(Attributes.mapTop + battle.roles.get(i).curY.get() * Attributes.gridHeight - 3);labels.add(labelbar);canvas.getChildren().add(labelbar);}System.out.println("show 地图");}public void enterBattle() {decorateStage();battle.enemyId = enemyID;if (battle.myCamp == Camp.MONSTER)battle.selected = 9;elsebattle.selected = 0;// 响应键盘,控制角色移动和攻击scene.setOnKeyPressed(new EventHandler<KeyEvent>() {@Overridepublic void handle(KeyEvent event) {int selected = battle.selected;String key = event.getText();if (key.length() > 0 && key.charAt(0) >= '1' && key.charAt(0) <= '9') {selected = key.charAt(0) - '1';if (battle.myCamp == Camp.MONSTER)selected += 9;battle.selected = selected;System.out.println(selected);}if (battle.roles.get(selected).alive == false)return;if (key.equals("a")) {battle.roles.get(selected).move(Direction.LEFT);} else if (key.equals("d")) {battle.roles.get(selected).move(Direction.RIGHT);} else if (key.equals("w")) {battle.roles.get(selected).move(Direction.UP);} else if (key.equals("s")) {battle.roles.get(selected).move(Direction.DOWN);} else if (key.equals("j")) {Direction dir = Direction.RIGHT;if (battle.roles.get(selected).camp == Camp.MONSTER)dir = Direction.LEFT;if (battle.roles.get(selected).healer == false) {int atkid = battle.roles.get(selected).useGnrAtk(dir);AttackMessage message = new AttackMessage(enemyID, selected, dir);battle.gameprogress.writeIn(ActionType.GNRATK, selected + " " + battle.dir2str(dir));calabashClient.send(message);if (atkid != -1) {System.out.println("攻击" + atkid + "血量为" + battle.roles.get(atkid).HP);if (battle.roles.get(atkid).alive == false) {battle.enemyDeadCount++;setDead(atkid);if (battle.enemyDeadCount == Attributes.rolesNum) {gameOver(true);}}}} else {// 治愈者无攻击能力,按j使用的是治愈术int healid = battle.roles.get(selected).useHealing(dir);AttackMessage message = new AttackMessage(enemyID, selected, dir);battle.gameprogress.writeIn(ActionType.HEAL, selected + " " + battle.dir2str(dir));calabashClient.send(message);if (healid != -1) {System.out.println("治愈" + healid + "血量为" + battle.roles.get(healid).HP);}}}int x = battle.roles.get(selected).curX.get();int y = battle.roles.get(selected).curY.get();moveRole(selected, x, y);//向服务器发送移动消息RoleMoveMessage message=new RoleMoveMessage(enemyID,selected,x,y);calabashClient.send(message);}});}// step3-3:游戏结束void gameOver(boolean winFlag) {try {battle.gameprogress.saveFile();} catch (TransformerException e) {// TODO Auto-generated catch blocke.printStackTrace();}Alert alert = new Alert(Alert.AlertType.INFORMATION);alert.setTitle("对战结果");alert.setHeaderText(null);if (winFlag) {alert.setContentText("恭喜您,取得胜利!");} else {alert.setContentText("很遗憾,对局失败...");}labels.clear();pics.clear();picsDead.clear();started = false;alert.showAndWait();startInterface();}void setDead(int roleID) {// labels.get(roleID).setGraphic(picsDead.get(roleID));labels.get(roleID).setVisible(false);labels.get(roleID).setManaged(false);labels.get(roleID + Attributes.hpoffset).setVisible(false);labels.get(roleID + Attributes.hpoffset).setManaged(false);}@Overridepublic void start(Stage primaryStage) throws Exception {// Parent root = FXMLLoader.load(getClass().getResource("sample.fxml"));primaryStage.setTitle("Calabash VS Monster");primaryStage.setScene(scene);primaryStage.show();this.stage = primaryStage;canvas.setOnMousePressed((MouseEvent e) -> {mouseX = e.getSceneX();mouseY = e.getSceneY();});canvas.setOnMouseDragged((MouseEvent e) -> {primaryStage.setX(e.getScreenX() - mouseX);primaryStage.setY(e.getScreenY() - mouseY);});startInterface();connectServer(0);}public static void main(String[] args) {launch(args);}
}









基于JavaFX实现的葫芦娃大战妖精游戏设计相关推荐

  1. 基于android平台的24点游戏设计与实现需求分析,基于Android平台的24点游戏设计与实现需求分析_毕业设计论文.doc...

    基于Android平台的24点游戏设计与实现 摘要 随着移动设备的普及以及移动设备的硬件的提升,移动设备的功能越来越完善,移动设备的系统平台也日渐火热起来.目前国内最常见的移动开发平台有Symbian ...

  2. 基于Java实现的Android拼图游戏设计

    资源下载地址:https://download.csdn.net/download/sheziqiong/85638665 基于Java实现的Android拼图游戏设计 游戏效果 一.Android ...

  3. 【java毕业设计】基于java+swing+GUI的连连看游戏设计与实现(毕业论文+程序源码)——连连看游戏

    基于java+swing+GUI的连连看游戏设计与实现(毕业论文+程序源码) 大家好,今天给大家介绍基于java+swing+GUI的连连看游戏设计与实现,文章末尾附有本毕业设计的论文和源码下载地址哦 ...

  4. java毕业设计——基于java+J2ME的贪吃蛇游戏设计与实现(毕业论文+程序源码)——贪吃蛇游戏

    基于java+J2ME的贪吃蛇游戏设计与实现(毕业论文+程序源码) 大家好,今天给大家介绍基于java+J2ME的贪吃蛇游戏设计与实现,文章末尾附有本毕业设计的论文和源码下载地址哦.需要下载开题报告P ...

  5. 基于Unity3D的体素沙盒游戏设计与实现(上)

    基于Unity3D的体素沙盒游戏设计与实现 摘    要 随着计算机硬件和软件技术的逐步发展,世界游戏开发行业也在日益壮大,涌现出不少优秀的作品,逐渐成为各国文化创意领域一张闪亮的名片.本文以全球知名 ...

  6. 基于python的游戏设计与实现-基于Python的网络中国象棋游戏设计与实现

    基于Python的网络中国象棋游戏设计与实现 摘要中国象棋是一种家喻户晓的棋类游戏,随着互联网时代的到来,人们的娱乐方式也逐渐向PC端和移动端上发展.本文将传统的中国象棋游戏和当下的互联网技术结合作为 ...

  7. java 2048游戏_JAVA2048游戏 本课程设计是基于java语言的2048小游戏设计 联合开发网 - pudn.com...

    JAVA2048游戏 所属分类:游戏 开发工具:Java 文件大小:789KB 下载次数:4 上传日期:2020-11-23 10:57:11 上 传 者:滴滴滴大萌 说明:  本课程设计是基于jav ...

  8. 【java毕业设计】基于java+Eclipse的飞机大战游戏设计与实现(毕业论文+程序源码)——飞机大战游戏

    基于java+Eclipse的飞机大战游戏设计与实现(毕业论文+程序源码) 大家好,今天给大家介绍基于java+Eclipse的飞机大战游戏设计与实现,文章末尾附有本毕业设计的论文和源码下载地址哦. ...

  9. android 飞机源码,基于安卓Android平台的飞机游戏设计与实现毕业论文+项目源码...

    摘   要 本课题是基于Android平台开发的飞机游戏,本游戏主要是针对现实生活中比较忙碌并且没有自己业余生活的人开发的,随着社会的发展,人们的生活也越来越快,压力也在不断的加大,反而没有了自己的休 ...

  10. 基于QTGUI图像界面的空战游戏设计

    基于图形界面的空战游戏 设计内容设计一个基于图形界面的空战游戏,使用 qt 的 GUI 框架下图为最终的游戏过程截图 设计目标(功能介绍) 加载界面 主窗口可伸缩 提供菜单界面 背景音乐(可切换) 游 ...

最新文章

  1. [实变函数]6 微分与不定积分
  2. Android 让View 和 ViewGroup 同时响应点击或者长按事件
  3. VCG(VisualCodeGrepper)安装使用教程
  4. 看你知道不知道之-制作数据字典
  5. c++MMMMM:oo
  6. stl vector 函数_在C ++ STL中使用vector :: begin()和vector :: end()函数打印矢量的所有元素...
  7. [js] 如何按回车自动提交表单
  8. 如何获取url中的参数并传递给iframe中的报表
  9. Mint-UI 报错提示缺少“raf.js / vue-lazyload / vue-popup” - 解决办法
  10. 对while((pid = waitpid(-1, stat, WNOHANG)) 0)不懂的地方,现在懂了
  11. WPF-14:绑定中数据模型必须为public问题
  12. webApplicationContext 与servletContext
  13. 使用Python全栈打造淘宝客微信机器人(2)!功能太强大了
  14. 线性渐变与径向渐变与重复渐变
  15. 吃土豆_nyoj_234(动态规划).java
  16. 关于计算机网络海明Hamming Code校验码, CRC及奇偶码校验
  17. 做产品与做项目的区别
  18. 《PPT思维》第一课:PPT基础思维
  19. echarts将x轴展示在图标上方
  20. 判断两个IP地址(ipv4)是否在同一个网段

热门文章

  1. [经典论文分享] Decision Transformer: Reinforcement Learning via Sequence Modeling
  2. 虚幻引擎4控制台变量和命令
  3. 最新的 CocoaPods 的使用教程 上传podspec
  4. 22.3 MIDI 和音乐
  5. 超分辨率技术AI人工智能老照片修复自动人像脑补照片高清重建人脸模糊图片变清晰软件
  6. html+css基础入门学习教程之HTML 样式
  7. Android N for Developers(API概览)
  8. 等了两年半!计算机专硕重大改革!不再只是电子信息了!
  9. 内存取证工具Volatility学习
  10. (笔记)Spring实战_征服数据库(5)_Spring与Java持久化API