版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
1、编号:计算机网络课程设计说明书题 目:网络对弈程序设计系 别:计算机科学与工程学院 专 业:计算机科学与技术学生姓名:学 号:指导教师: 王虎寅 2013年3月20日目 录1 设计任务及目标11.1 开发背景以及设计目标11.2设计任务12 需求分析22.1系统需求22.2用户需求2服务端需求2客户端需求2技术上可行性分析32.3.系统运行环境43 总体设计43.1系统结构设计43.2服务器设计53.3客户端设计73.4棋类设计84 详细设计94.1 服务器9服务器主类的设计开发9服务器线程的设计开发134.2 客户端234.3棋盘以及规则265软件实现以及使用说明465.1服务器运行使用及测
2、试4652 客户端运行使用及测试496总结536.1任务完成情况536.2特色与不足53特色53不足536.3所遇到的问题536.4体会547 参考文献551 设计任务及目标1.1开发背景以及设计目标五子棋有着悠久的历史,五子棋爱好者更是不计其数,但是由于人们工作地点,时间的限制,生活节奏的加快,人们之间的交流越来越少,面对面下五子棋的机会更是少了很多,那种面对面的下棋的方式已经不再适应人们的生活,但网络给了人们一个交流的平台,因此人们开始转向网络五子棋。网络五子棋有很多优点,通过网络五子棋,对弈双方可以是网络上任意两个五子棋的爱好者,甚至从不认识。网络五子棋让对弈的范围更加的广泛,让玩家可以
3、与更多的五子棋爱好者切磋棋艺。所以我此次网络课程设计综合运用计算机网络、JAVA语言程序设计、网络编程等课程知识;从需求分析入手,系统地掌握计算机网络编程初级技术,独立、合理地完成网络五子棋对弈程序设计任务。设计目标主要包括:(1)实现需求分析阶段所要求的服务器端以及客户端的功能。(2)游戏界面朴素美观。(3)棋子样式采用传统样式,黑色和白色。(4)客户端的信息交流完全通过服务器传递完成。1.2设计任务完成一个网络五子棋对弈程序设计工作。根据自身多年来进行网络对弈的经验,以及了解,对网络五子棋对弈的设计进行需求分析。根根设计目标以及需求分析对五子棋游戏界面总体规划和设计,游戏界面设计好以后进行
4、服务器端和客户端的规划设计,最后进行棋盘以及棋子的设计。设计阶段要进行服务器端框架设计与业务代码开发,客户端框架设计与业务代码的开发,棋子以及棋盘类的设计开发,规则类的设计开发等。2 需求分析2.1系统需求(1) 满足客户端连接到服务器的基本要求。(2) 服务器满足记录客户端游戏动作的基本要求。(3) 满足服务器实时获得客户端游戏状态的基本要求。2.2用户需求2.2.1服务端需求(1)可以有一个显示服务器状态的界面,用于记录各个客户端的连接状态。服务器是用于连接各个客户端的通信,如果独立地创建一个直观的服务器,将有力地显示客户端的每个状态,直观地向用户反应各类信息。(2)可以支持多人同时在线。
5、一个服务器能够你能够接受来自其他多个客户端的请求,提供相应的响应服务,是网络对弈的基本要求。(3)可以显示在线用户的信息。显示在线用户的信息,比如主机名,IP地址,以及连接断的状态,有利于用户随时监控客户端的通信状态。(4)不允许玩家同名。不允许客户端同名即是不允许客户端的端口号相同,如果相同,将会造成游戏登陆用户的管理混乱。(5)服务器界面节约大方。服务器是用于监控客户端的连接情况,没用必要做得繁杂,用户只需要直观的状态显示,所以我们的服务器不需要设计太多按钮,只需要有显示服务器状态,关闭服务器,清空列表的按钮,方便用户操作。2.2.2客户端需求(1) 能够通过主机IP及端口号登陆到服务器。
6、(2) 可以显示当前所有用户。游戏客户端应设计一个可以显示当前 所有在线用户的列表,有助于用户随意选择玩家挑战。(3) 可以从在线用户列表中选择玩家进行挑战。(4) 可以创建以及接受挑战。(5) 如果对方正在与其他玩家对弈,则应给出相应提示。(6) 五子棋规则一定要严密。其中五子棋游戏的规则如下:Ø 棋盘,棋子:a) 棋盘为十五路,正中一点为“天元”,周围四点为小星。b) 棋子分黑白两色,黑子113枚,白子112枚,共225枚。Ø 比赛规则:a) 黑先白后,从天元开始落子。然后执白棋的一方在黑棋周围的交叉点上落子,白第二着棋应布在自己河界的一侧。此后,执黑方在以天元为中心的
7、25个交叉点的范围内布盘面的第三着棋。b) 最先在横向,竖向,斜向形成连续的相同色五个棋子的一方为胜。c) 黑棋禁手判负,白棋无禁手。黑棋禁手包括“三三”,“四四”,“长连”。黑方只能“四三”胜。所谓禁手,是指黑方一子落下同时形成两个或两个以上的活三,冲四及长连禁手。长连禁手是指黑方形成六个或六个以上的连续棋子。d) 双方均不能形成五连为和棋。e) 对局中拔子,中途退场均判为负。f) 五连与禁手同时形成,先五为胜。因黑方已形成五连,故禁手失效,黑方胜。g) 黑方禁手形成时,白方应立即指出禁手点,黑方即负。若白方继续应子,则黑方禁手不成立。h) 高段位职业比赛的特殊规定:“三手可交换”:黑下完第
8、手,执白者可提出交换。即执白方变为执黑方。“五手两打法”:执黑下第五手时,必须下两手棋,执白者从这两手棋中任选一步。i) 本文所论述的联机五子棋系统就是依照这种方式进行的。2.2.3技术上可行性分析对需求分析阶段的结果进行总结,对软件的可行性分析如下:(1) 网络对弈需要两个客户端进行通信,而利用服务器的线程开发,进行中间中介连接正好可以完成。(2) 五子棋的规则虽然严密,但是通过各种情况分析,然后将每个情况分析设计出来。(3) 本系统的设计运行环境只用到MyEclipse的编程软件,无需借用到其它的软件,比较容易实现。2.3.系统运行环境系统运行环境:MyEclipse6.63 总体设计3.
9、1系统结构设计该游戏主要分为服务器端与客户端两部分。服务器端的功能主要是建立与客户端的连接,监控客户端的连接及断开的状态,接收客户端发送的信息以及向客户端发送信息。客户端的功能主要是连接服务器端,创建游戏用户,创建游戏,加入游戏,选择玩家挑战,向服务器发送信息,接收服务器端发送来的信息。其具体的功能模块如图所示:网络五子棋服务器端客户端启动服务器维护在线用户信息接收客户端信息向客户端发送信息连接服务器创建游戏选择玩家挑战向服务器发送信息接收服务器传来的信息3.2服务器设计服务器的设计主要分为服务器主界面,服务器线程,服务器主机面板三个部分。服务器主界面的设计主要包括界面大小,界面背景,界面上的
10、按钮,比如清空列表,服务器状态,关闭服务器的设计,以及启动对客户端的监听,启动服务器线程。服务器线程的设计主要包括接受多个客户端的连接,接受客户端信息,向客户端发送信息。服务器主机面板的设计主要包括客户端信息板的设计,包括板的大小,背景颜色。其具体的功能模块如图所示:服务器端服务器主界面服务器线程服务器主机面板监听客户端启动服务器线程清空,显示,关闭服务器信息接收客户端信息向客户端发送信息信息板的显示3.3客户端设计客户端的设计主要分为客户端界面,客户端线程两部分。客户端界面的设计主要包括客户端界面大小,背景颜色,主要按钮:创建游戏,加入游戏,连接到服务器,放弃游戏,退出游戏的设计以及它们对应
11、事件的处理。客户端线程的设计主要包括连接到服务器,向服务器发送信息,接受服务器信息的设计以及它们对应的事件处理,比如收到服务器发送来的游戏胜利,信息错误,信息有效等的处理。其具体功能模块如图所示:客户端客户端界面客户端线程创建游戏加入游戏连接到游戏连接到服务器向服务器发送信息放弃游戏退出游戏接收服务器信息3.4棋类设计五子棋类的设计主要分为棋盘,棋子,五子棋动作线程,规则四部分。棋盘的设计主要包括画棋子,捕获下棋事件,画网络棋盘。棋子的设计包括黑棋以及白旗的设计,其中有大小,颜色,所属棋盘的设计。五子棋动作线程的设计包括处理捕获下棋信息,发送当前下棋信息,这一部分的设计是五子棋类设计的重点。规
12、则的设包括取得指定棋子的位置,判断当前棋子是否取得胜利,当前棋子各个方向的判断,当前所要下的棋子是否越界。五子棋棋盘棋子画棋子捕获下棋事件黑棋白棋五子棋线程画网络棋盘处理捕获的下棋信息发送当前下棋信息规则方向判断胜利判断越界判断4 详细设计4.1 服务器4.1.1服务器主类的设计开发服务器主类即服务器端的运行类,用户通过运行该类进入服务器的主界面。其中包括创建服务器端用到的控件以及声明用到的对象引用,完成对控件的初始化:设置窗体的标题,图标,大小以及可见性,将各个控件添加到各面板的相应位置FIRServer.java类:/ 服务器界面类public class FIRServer extend
13、s Frame implements ActionListenerJButton clearMsgButton = new JButton("清空列表");JButton serverStatusButton = new JButton("服务器状态");JButton closeServerButton = new JButton("关闭服务器");Panel buttonPanel = new Panel();ServerMsgPanel serverMsgPanel = new ServerMsgPanel();ServerSo
14、cket serverSocket;Hashtable clientDataHash = new Hashtable(50); /将客户端套接口和输出流绑定Hashtable clientNameHash = new Hashtable(50); /将客户端套接口和客户名绑定Hashtable chessPeerHash = new Hashtable(50); /将游戏创建者和游戏加入者绑定public FIRServer()super("Java 五子棋服务器");setBackground(Color.LIGHT_GRAY);buttonPanel.setLayout
15、(new FlowLayout();clearMsgButton.setSize(60, 25);buttonPanel.add(clearMsgButton);clearMsgButton.addActionListener(this);serverStatusButton.setSize(75, 25);buttonPanel.add(serverStatusButton);serverStatusButton.addActionListener(this);closeServerButton.setSize(75, 25);buttonPanel.add(closeServerButto
16、n);closeServerButton.addActionListener(this);add(serverMsgPanel, BorderLayout.CENTER);add(buttonPanel, BorderLayout.SOUTH);addWindowListener(new WindowAdapter()public void windowClosing(WindowEvent e)System.exit(0););pack();setVisible(true);setSize(400, 400);setResizable(false);validate();trycreateS
17、erver(4331, serverMsgPanel);catch (Exception e)e.printStackTrace();/ 用指定端口和面板创建服务器public void createServer(int port, ServerMsgPanel serverMsgPanel) throws IOExceptionSocket clientSocket; / 客户端套接口long clientAccessNumber = 1; / 连接到主机的客户数量this.serverMsgPanel = serverMsgPanel; / 设定当前主机tryserverSocket =
18、new ServerSocket(port);serverMsgPanel.msgTextArea.setText("服务器启动于:"+ InetAddress.getLocalHost() + ":" /djr+ serverSocket.getLocalPort() + "n");while (true)/ 监听客户端套接口的信息clientSocket = serverSocket.accept();serverMsgPanel.msgTextArea.append("已连接用户:" + clientSock
19、et + "n");/ 建立客户端输出流DataOutputStream outputData = new DataOutputStream(clientSocket.getOutputStream();/ 将客户端套接口和输出流绑定clientDataHash.put(clientSocket, outputData);/ 将客户端套接口和客户名绑定clientNameHash.put(clientSocket, ("新玩家" + clientAccessNumber+);/ 创建并运行服务器端线程FIRServerThread thread = ne
20、w FIRServerThread(clientSocket,clientDataHash, clientNameHash, chessPeerHash, serverMsgPanel);thread.start();catch (IOException ex)ex.printStackTrace();public void actionPerformed(ActionEvent e)if (e.getSource() = clearMsgButton) / 清空服务器信息serverMsgPanel.msgTextArea.setText("");if (e.getSou
21、rce() = serverStatusButton) / 显示服务器信息tryserverMsgPanel.msgTextArea.append("服务器信息:"+ InetAddress.getLocalHost() + ":"+ serverSocket.getLocalPort() + "n");catch (Exception ee)ee.printStackTrace();if (e.getSource() = closeServerButton) / 关闭服务器System.exit(0);public static v
22、oid main(String args)FIRServer firServer = new FIRServer();4.1.2服务器线程的设计开发服务器线程是服务器启动后创建并启动的第一个线程,该线程主要用于接收客户端的连接,并未每个连接分配一个服务器代理线程。服务器代理线程主要用于接收客户端传来的消息,并将该消息转发给另一个客户端。服务器为所有客户端都分配了一个该类线程实例,单独为特定客户端进行服务。同时每一个服务器代理线程都有能唯一标识的名称。FIRServerThead.java类:public class FIRServerThread extends ThreadSocket cl
23、ientSocket; / 保存客户端套接口信息Hashtable clientDataHash; / 保存客户端端口与输出流对应的HashHashtable clientNameHash; / 保存客户端套接口和客户名对应的HashHashtable chessPeerHash; / 保存游戏创建者和游戏加入者对应的HashServerMsgPanel serverMsgPanel;boolean isClientClosed = false;public FIRServerThread(Socket clientSocket, Hashtable clientDataHash,Hashta
24、ble clientNameHash, Hashtable chessPeerHash,ServerMsgPanel server)this.clientSocket = clientSocket;this.clientDataHash = clientDataHash;this.clientNameHash = clientNameHash;this.chessPeerHash = chessPeerHash;this.serverMsgPanel = server;public void dealWithMsg(String msgReceived)String clientName;St
25、ring peerName;if (msgReceived.startsWith("/")if (msgReceived.equals("/list") / 收到的信息为更新用户列表Feedback(getUserList();else if (msgReceived.startsWith("/creatgame inchess") / 收到的信息为创建游戏String gameCreaterName = msgReceived.substring(20); /取得服务器名synchronized (clientNameHash) /
26、 将用户端口放到用户列表中clientNameHash.put(clientSocket, msgReceived.substring(11);synchronized (chessPeerHash) / 将主机设置为等待状态chessPeerHash.put(gameCreaterName, "wait");Feedback("/yourname " + clientNameHash.get(clientSocket);sendGamePeerMsg(gameCreaterName, "/OK");sendPublicMsg(get
27、UserList();else if (msgReceived.startsWith("/joingame ") / 收到的信息为加入游戏时StringTokenizer userTokens = new StringTokenizer(msgReceived, " ");String userToken;String gameCreatorName;String gamePaticipantName;String playerNames = "0", "0" ;int nameIndex = 0;while (u
28、serTokens.hasMoreTokens()userToken = (String) userTokens.nextToken(" ");if (nameIndex >= 1 && nameIndex <= 2)playerNamesnameIndex - 1 = userToken; / 取得游戏者命nameIndex+;gameCreatorName = playerNames0;gamePaticipantName = playerNames1;if (chessPeerHash.containsKey(gameCreatorName
29、)&& chessPeerHash.get(gameCreatorName).equals("wait") / 游戏已创建synchronized (clientNameHash) / 增加游戏加入者的套接口与名称的对应clientNameHash.put(clientSocket,("inchess" + gamePaticipantName);synchronized (chessPeerHash) / 增加或修改游戏创建者与游戏加入者的名称的对应chessPeerHash.put(gameCreatorName, gamePatic
30、ipantName);sendPublicMsg(getUserList();/ 发送信息给游戏加入者sendGamePeerMsg(gamePaticipantName,("/peer " + "inchess" + gameCreatorName);/ 发送游戏给游戏创建者sendGamePeerMsg(gameCreatorName,("/peer " + "inchess" + gamePaticipantName);else / 若游戏未创建则拒绝加入游戏sendGamePeerMsg(gamePatic
31、ipantName, "/reject");trycloseClient();catch (Exception ez)ez.printStackTrace();else if (msgReceived.startsWith("/inchess") / 收到的信息为游戏中时int firstLocation = 0, lastLocation;lastLocation = msgReceived.indexOf(" ", 0);peerName = msgReceived.substring(firstLocation + 1), la
32、stLocation);msgReceived = msgReceived.substring(lastLocation + 1);if (sendGamePeerMsg(peerName, msgReceived)Feedback("/error");else if (msgReceived.startsWith("/giveup ") / 收到的信息为放弃游戏时String chessClientName = msgReceived.substring(8);if (chessPeerHash.containsKey(chessClientName)
33、&& !(String) chessPeerHash.get(chessClientName).equals("wait") / 胜利方为游戏加入者,发送胜利信息sendGamePeerMsg(String) chessPeerHash.get(chessClientName),"/youwin");synchronized (chessPeerHash) / 删除退出游戏的用户chessPeerHash.remove(chessClientName);if (chessPeerHash.containsValue(chessClient
34、Name) / 胜利方为游戏创建者,发送胜利信息sendGamePeerMsg(String) getHashKey(chessPeerHash,chessClientName), "/youwin");synchronized (chessPeerHash)/ 删除退出游戏的用户chessPeerHash.remove(String) getHashKey(chessPeerHash,chessClientName);else / 收到的信息为其它信息时int lastLocation = msgReceived.indexOf(" ", 0);if
35、(lastLocation = -1)Feedback("无效命令");return;elsemsgReceived = clientNameHash.get(clientSocket) + ">" + msgReceived;serverMsgPanel.msgTextArea.append(msgReceived + "n");sendPublicMsg(msgReceived);serverMsgPanel.msgTextArea.setCaretPosition(serverMsgPanel.msgTextArea.ge
36、tText().length();/ 发送公开信息public void sendPublicMsg(String publicMsg)synchronized (clientDataHash)for (Enumeration enu = clientDataHash.elements(); enu.hasMoreElements();)DataOutputStream outputData = (DataOutputStream) enu.nextElement();tryoutputData.writeUTF(publicMsg);catch (IOException es)es.prin
37、tStackTrace();/ 发送信息给指定的游戏中的用户public boolean sendGamePeerMsg(String gamePeerTarget, String gamePeerMsg)for (Enumeration enu = clientDataHash.keys(); enu.hasMoreElements();) / 遍历以取得游戏中的用户的套接口Socket userClient = (Socket) enu.nextElement();if (gamePeerTarget.equals(String) clientNameHash.get(userClient
38、)&& !gamePeerTarget.equals(String) clientNameHash.get(clientSocket) / 找到要发送信息的用户时synchronized (clientDataHash)/ 建立输出流DataOutputStream peerOutData = (DataOutputStream) clientDataHash.get(userClient);try/ 发送信息peerOutData.writeUTF(gamePeerMsg);catch (IOException es)es.printStackTrace();return f
39、alse;return true;/ 发送反馈信息给连接到主机的人public void Feedback(String feedBackMsg)synchronized (clientDataHash)DataOutputStream outputData = (DataOutputStream) clientDataHash.get(clientSocket);tryoutputData.writeUTF(feedBackMsg);catch (Exception eb)eb.printStackTrace();/ 取得用户列表public String getUserList()Stri
40、ng userList = "/userlist"for (Enumeration enu = clientNameHash.elements(); enu.hasMoreElements();)userList = userList + " " + (String) enu.nextElement();return userList;/ 根据value值从Hashtable中取得相应的keypublic Object getHashKey(Hashtable targetHash, Object hashValue)Object hashKey;for
41、 (Enumeration enu = targetHash.keys(); enu.hasMoreElements();)hashKey = (Object) enu.nextElement();if (hashValue.equals(Object) targetHash.get(hashKey)return hashKey;return null;/ 刚连接到主机时执行的方法public void sendInitMsg()sendPublicMsg(getUserList();Feedback("/yourname " + (String) clientNameHa
42、sh.get(clientSocket);Feedback("Java 五子棋客户端");Feedback("/list -更新用户列表");Feedback("/<username> <talk> -私聊");Feedback("注意:命令必须对所有用户发送");public void closeClient()serverMsgPanel.msgTextArea.append("用户断开连接:" + clientSocket + "n");sync
43、hronized (chessPeerHash) /如果是游戏客户端主机if (chessPeerHash.containsKey(clientNameHash.get(clientSocket)chessPeerHash.remove(String) clientNameHash.get(clientSocket);if (chessPeerHash.containsValue(clientNameHash.get(clientSocket)chessPeerHash.put(String) getHashKey(chessPeerHash,(String) clientNameHash.g
44、et(clientSocket),"tobeclosed");synchronized (clientDataHash) / 删除客户数据clientDataHash.remove(clientSocket);synchronized (clientNameHash) / 删除客户数据clientNameHash.remove(clientSocket);sendPublicMsg(getUserList();serverMsgPanel.statusLabel.setText("当前连接数:" + clientDataHash.size();trycl
45、ientSocket.close();catch (IOException exx)exx.printStackTrace();isClientClosed = true;public void run()DataInputStream inputData;synchronized (clientDataHash)serverMsgPanel.statusLabel.setText("当前连接数:" + clientDataHash.size();try/ 等待连接到主机的信息inputData = new DataInputStream(clientSocket.getI
46、nputStream();sendInitMsg();while (true)String message = inputData.readUTF();dealWithMsg(message);catch (IOException esx)finallyif (!isClientClosed)closeClient();4.2 客户端客户端主类即客户端的运行类,用户通过运行该类连接服务器,也是通过在该类的窗体中与其他玩家对弈。FIRClientThread.java类:public class FIRClientThread extends Threadpublic FIRClient fir
47、Client;public FIRClientThread(FIRClient firClient)this.firClient = firClient;public void dealWithMsg(String msgReceived)if (msgReceived.startsWith("/userlist ") / 若取得的信息为用户列表StringTokenizer userToken = new StringTokenizer(msgReceived, " ");int userNumber = 0;/ 清空客户端用户列表firClient.
48、userListPad.userList.removeAll();/ 清空客户端用户下拉框firClient.userInputPad.userChoice.removeAll();/ 给客户端用户下拉框添加一个选项firClient.userInputPad.userChoice.addItem("所有用户");while (userToken.hasMoreTokens() / 当收到的用户信息列表中存在数据时String user = (String) userToken.nextToken(" "); / 取得用户信息if (userNumber
49、 > 0 && !user.startsWith("inchess") / 用户信息有效时firClient.userListPad.userList.add(user);/ 将用户信息添加到用户列表中firClient.userInputPad.userChoice.addItem(user); / 将用户信息添加到用户下拉框中userNumber+;firClient.userInputPad.userChoice.setSelectedIndex(0);/ 下拉框默认选中所有人else if (msgReceived.startsWith(&qu
50、ot;/yourname ") / 收到的信息为用户本名时firClient.chessClientName = msgReceived.substring(10); / 取得用户本名firClient.setTitle("Java 五子棋客户端 " + "用户名:"+ firClient.chessClientName); / 设置程序Frame的标题else if (msgReceived.equals("/reject") / 收到的信息为拒绝用户时tryfirClient.firPad.statusText.setT
51、ext("不能加入游戏!");firClient.userControlPad.cancelButton.setEnabled(false);firClient.userControlPad.joinButton.setEnabled(true);firClient.userControlPad.createButton.setEnabled(true);catch (Exception ef).setText("Cannot close!");firClient.userControlPad.joinButton.setEnabled(true);else if (msgReceived.startsWith("/peer ") / 收到信息为游戏中的等待时firClient.firPad.chessPeerName = msgReceived.substring(6);if (firClient.isCreator) / 若用户为游戏建立者firClient.firPad.chessColor = 1; / 设定其为黑棋先
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 施工现场闸机设置标准
- 施工现场施工防高空坠物制度
- 阅读启迪心灵小学生的成长之路
- 母婴用品销售中的用户体验优化策略汇报
- 清明节扫墓应急预案
- 预防为主早期小儿肺炎识别与护理措施
- DB4415T 55-2025香芋南瓜-紫云英-香芋南瓜轮作生产技术规程
- 交通监控项目工程合同
- 上海市大数据中心计算机信息系统集成合同
- 个人小额信贷合同范本
- 渠道管理就这样做
- 大客户销售这样说这样做
- 精装修样板房房屋使用说明
- 乔迁新居结婚典礼主持词
- 小学四年级数学竞赛试题(附答案)
- 鲁科版高中化学必修2全册教案
- 《病理学基础》知识考核试题题库与答案
- 人口分布 高一地理下学期人教版 必修第二册
- 部编版六年级下册语文第3单元习作例文+习作PPT
- 四年级上册英语试题-Module 9 Unit 1 What happened to your head--外研社(一起)(含答案)
- 子宫内膜异位症诊疗指南
评论
0/150
提交评论