网站导航网学 原创论文 原创专题 网站设计 最新系统 原创论文 论文降重 发表论文 论文发表 UI设计定制 论文答辩PPT格式排版 期刊发表 论文专题
返回网学首页
网学原创论文
最新论文 推荐专题 热门论文 论文专题
当前位置: 网学 > 交易代码 > 课程设计 > 正文

J2ME基于手机平台的智能客户端游戏设计

论文降重修改服务、格式排版等 获取论文 论文降重及排版 论文发表 相关服务
J2ME基于手机平台的智能客户端游戏设计  J2ME手机游戏设计 GCF联网技术更多更新更免费论文网,专业毕业设计论文,课程设计源代码,上机实习报告,实验报告请点击www.lwfree.cn
基于手机平台的智能客户端游戏设计
 
 
摘  要
 
本文主要研究基于手机平台的智能游戏程序客户端设计及手机客户端与PC服务器间的互联。通过选用J2ME作为手机游戏客户端的开发平台,利用GCF联网技术,本文设计了选择游戏种类的通讯协议,以及针对多种麻将的特点设计了摸牌,出牌及和牌等麻将游戏的通讯协议。通过该协议,实现了基于MIDP手机平台与PC服务器的连接,客户端的游戏规则判断由服务器完成。
在游戏客户端的功能模块实现上,本文将游戏客户端分为系统初始化模块,网络互联模块,图形界面的绘制及按键响应处理模块和游戏的逻辑处理模块。系统初始化模块用来实现程序运行主界面,用户可以选择多种麻将进行游戏;网络互联模块实现了与PC端的无线连接,根据相应的通讯协议进行数据包的发送与接收;客户图形界面的绘制及按键响应处理模块实现了客户端的绘制以及按键响应处理;游戏的逻辑处理模块实现了麻将游戏的逻辑处理。
 
关键词:J2ME、手机游戏、网络互联、知识库、通讯协议
 
Smart Client Game Design Based On Mobile Phone
 
ABSTRACT
 
This paper is mainly about the research of the smart client game design based on mobile phone and mobile phone network with PC server. By using J2ME as mobile phone game’s client-development platform, and also using GCF networking technologies, we design the communications protocol of choosing the type of games and the communications protocol about getting  a cart, and win. By Using the protocol, the connection of MIDP mobile phone platforms and PC server connectivity has been realized, then the rules of the game is judged by the server.
In the implement of the game client's functional modules, the paper will divide the game client into system initialization module, networking module, the user interface design module, key press answer module, and game logic module. system initialization module realizes the game’s main flame, users can choose different kinds of mahjong to play; networking module realizes the wireless network connection between mobile phone client and PC server, the client sends or gets the data package according to the communications protocol; key press answer module realizes the drawing of the client and the handle of key press answer; game logic module realizes the handle of mahjong logic.
KEYWORDS: J2ME, mobile game, networking, game knowledge databases
基于手机平台的智能客户端游戏设计
 
 
摘  要
 
本文主要研究基于手机平台的智能游戏程序客户端设计及手机客户端与PC服务器间的互联。通过选用J2ME作为手机游戏客户端的开发平台,利用GCF联网技术,本文设计了选择游戏种类的通讯协议,以及针对多种麻将的特点设计了摸牌,出牌及和牌等麻将游戏的通讯协议。通过该协议,实现了基于MIDP手机平台与PC服务器的连接,客户端的游戏规则判断由服务器完成。
在游戏客户端的功能模块实现上,本文将游戏客户端分为系统初始化模块,网络互联模块,图形界面的绘制及按键响应处理模块和游戏的逻辑处理模块。系统初始化模块用来实现程序运行主界面,用户可以选择多种麻将进行游戏;网络互联模块实现了与PC端的无线连接,根据相应的通讯协议进行数据包的发送与接收;客户图形界面的绘制及按键响应处理模块实现了客户端的绘制以及按键响应处理;游戏的逻辑处理模块实现了麻将游戏的逻辑处理。
 
关键词:J2ME、手机游戏、网络互联、知识库、通讯协议
 
Smart Client Game Design Based On Mobile Phone
 
ABSTRACT
 
This paper is mainly about the research of the smart client game design based on mobile phone and mobile phone network with PC server. By using J2ME as mobile phone game’s client-development platform, and also using GCF networking technologies, we design the communications protocol of choosing the type of games and the communications protocol about getting  a cart, and win. By Using the protocol, the connection of MIDP mobile phone platforms and PC server connectivity has been realized, then the rules of the game is judged by the server.
In the implement of the game client's functional modules, the paper will divide the game client into system initialization module, networking module, the user interface design module, key press answer module, and game logic module. system initialization module realizes the game’s main flame, users can choose different kinds of mahjong to play; networking module realizes the wireless network connection between mobile phone client and PC server, the client sends or gets the data package according to the communications protocol; key press answer module realizes the drawing of the client and the handle of key press answer; game logic module realizes the handle of mahjong logic.
KEYWORDS: J2ME, mobile game, networking, game knowledge databases
基于手机平台的智能客户端游戏设计
 
 
摘  要
 
本文主要研究基于手机平台的智能游戏程序客户端设计及手机客户端与PC服务器间的互联。通过选用J2ME作为手机游戏客户端的开发平台,利用GCF联网技术,本文设计了选择游戏种类的通讯协议,以及针对多种麻将的特点设计了摸牌,出牌及和牌等麻将游戏的通讯协议。通过该协议,实现了基于MIDP手机平台与PC服务器的连接,客户端的游戏规则判断由服务器完成。
在游戏客户端的功能模块实现上,本文将游戏客户端分为系统初始化模块,网络互联模块,图形界面的绘制及按键响应处理模块和游戏的逻辑处理模块。系统初始化模块用来实现程序运行主界面,用户可以选择多种麻将进行游戏;网络互联模块实现了与PC端的无线连接,根据相应的通讯协议进行数据包的发送与接收;客户图形界面的绘制及按键响应处理模块实现了客户端的绘制以及按键响应处理;游戏的逻辑处理模块实现了麻将游戏的逻辑处理。
 
关键词:J2ME、手机游戏、网络互联、知识库、通讯协议
 
Smart Client Game Design Based On Mobile Phone
 
ABSTRACT
 
This paper is mainly about the research of the smart client game design based on mobile phone and mobile phone network with PC server. By using J2ME as mobile phone game’s client-development platform, and also using GCF networking technologies, we design the communications protocol of choosing the type of games and the communications protocol about getting  a cart, and win. By Using the protocol, the connection of MIDP mobile phone platforms and PC server connectivity has been realized, then the rules of the game is judged by the server.
In the implement of the game client's functional modules, the paper will divide the game client into system initialization module, networking module, the user interface design module, key press answer module, and game logic module. system initialization module realizes the game’s main flame, users can choose different kinds of mahjong to play; networking module realizes the wireless network connection between mobile phone client and PC server, the client sends or gets the data package according to the communications protocol; key press answer module realizes the drawing of the client and the handle of key press answer; game logic module realizes the handle of mahjong logic.
KEYWORDS: J2ME, mobile game, networking, game knowledge databases
 

目   录
第一章 引言. 8
1.1 研究背景. 8
1.2 国内外的研究现状. 8
1.3 为何选择J2ME 9
1.4 J2ME的体系结构. 10
1.4.1 J2ME总体结构概览... 10
1.4.2 Configuration与Profile. 11
1.5 本文研究的目标和内容. 12
第二章 J2ME手机游戏系统设计. 14
2.1 本程序需解决的有关技术问题. 14
2.2 系统总框架. 14
2.4 系统功能模块设计. 20
2.4.1 麻将属性... 20
2.4.2 程序初始化... 20
2.4.3 网络传输... 21
2.4.4 主游戏模块... 21
第三章 客户端游戏与PC机互连. 24
3.1 J2ME网络. 24
3.1.1 通用连接框架... 24
3.1.2 InputStream和OutputStream.. 24
3.1.3 GCF支持的协议... 25
3.2 socket网络通讯原理及实现方式. 25
3.2.1 socket网络通讯原理... 25
3.2.2 socket实现方式... 25
3.3 手机游戏的通讯协议. 26
第四章 客户端游戏与知识库的接口. 28
4.1 知识库的基本原理. 28
4.2 知识库在游戏中的运用. 28
4.3 客户端游戏规则调用. 29
第五章 总结和展望. 30
致 谢. 31
参考文献. 32
附  录(核心代码). 34
基于手机平台的智能客户端游戏设计
第一章 引言
1.1 研究背景
游戏作为日常休闲的娱乐活动,历经了电视游戏、电脑单机游戏、电脑网络游戏这几个阶段。现在,游戏作为一个产业,可以看出游戏市场有着非常庞大的需求。而手机游戏的出现,也给游戏市场带来了新的活力,由于娱乐时不受时间和地点的限制,手机游戏在中国的火爆的时刻已经来临。
从全球范围来讲,游戏已经走上了高科技的数字路线,电子游戏产品已经深入普通大众,而在这庞大的游戏市场中,手机游戏将凭借着其硬件基础“手机”可移动,方便携带的特性,在与传统电脑游戏与电视游戏竞争中占有一席之地,而在与掌机游戏的竞争中,其又具有可通讯性,应用范围广的优势又显现了出来。因此随着手机产品的不断更新,以及技术的不断发展,手机游戏的市场将更为光明。
中国手机游戏市场在未来几年内在市场收入上有大幅提高,考虑到国内手机及互联网环境的影响,预计到2008年时,J2ME与BREW游戏将成为手机游戏市场中收入最多的一个模块,现在收入最多的是手机单机游戏,以及日益火爆的手机网络游戏。
知识库已被广泛应用于金融系统,大型企业系统等领域,而游戏知识库目前正处于发展初期。利用游戏知识库,可以很好的实现对游戏规则的处理。一旦开发出一款游戏,对于开发其他同类游戏,只需对游戏规则作一些变换就可以完成对整个游戏的开发。利用游戏知识库,可以快速地开发多款游戏,大大地缩短了游戏开发周期,游戏知识库的应用在将来很有前景。
1.2 国内外的研究现状
手机游戏按手机平台分类,可分为J2ME、BREW、Unija、Symbian等几种手机游戏。而当前应用最为广泛的当属J2ME平台和BREW平台。
J2ME平台继承了Java语言的特性,如平台无关性,安全性,面向对象,分布式,健壮性等。Java引进了虚拟机原理,并运行于虚拟机,实现不同平台之间的Java接口[1]。使用Java编写的程序能在世界范围内共享,Java的数据类型与机器无关;在安全性方面,Java的编程类似C++,但舍弃了C++的指针对存储器地址的直接操作,程序运行时,内存由操作系统分配,这样可以避免病毒通过指针入侵系统。它提供了安全管理器,防止程序的非法访问;同时,Java是一门面向对象语言,Java吸收了C++面向对象的概念,将数据封装于类中,实现了程序的简洁性和便于维护性,使程序代码可以只需一次编译就可反复利用;Java建立在TCP/IP网络平台上,提供了用HTTP和FTP协议传送和接收信息的库函数,使用其相关技术可以十分方便的构建分布式应用系统;在健壮性方面,Java致力与检查程序在编译和运行时的错误,并自动回收内存,减少了内存出错的可能性。Java取消了C语言的结构、指针、#define语句、多重继承、goto语句、操作符、重载等不易被掌握的特性,提供垃圾收集器自动回收不用的内存空间[2]。
BREW是Binary Runtime Environment for Wireless(无线二进制运行环境)的缩写,是美国高通公司为无线数据应用程序开发和执行提供的通用接口平台。BREW提供一个高效、低成本、可扩展和熟悉的应用程序执行环境,着重开发可无缝植入任何实际手持设备的应用程序[3]。BREW能够在运营商端进行有效的计费。它提供了完备的应用认证与管理,能够确保一个用户下载的程序只能为该客户所使用,从而有效地防止应用软件的非法复制与盗版现象[4]。而Java平台上大部分的应用是只需要一次付清下载费用就可以无限运行的离线应用,BREW平台的这两个特性是Java平台所不具有的。但业界对此也有质疑,由于BREW支持手机具有一定的局限性,而Java则可以被所有手机使用,因此很多开发商更喜欢把热情投向Java。
1.3 为何选择J2ME
Java目前有三个版本,分别应用于不同的领域。它们是J2SE、J2EE和J2ME。其中J2SE,即Java平台标准版,被应用最广泛,也是J2ME和J2EE的基础,被广泛应用于桌面电脑应用,一般用于开发桌面软件。J2EE,即Java平台企业版,被广泛应用于服务器上包括JSP,SERVLET,EJB以及目前炙手可热的WEB SERVICE等技术。J2ME,即Java平台微型版,被使用在资源受限,小型消费性电子设备上如电视机顶盒,无线电话,掌上电脑等[5]。
 

移动设备的繁荣发展,造成了五花八门的厂商与品种异常广泛的设备。例如两种设备也许具有相同的功能,但是实现的方法可能会有相当大的区别,例如对PDA和手持电话来说都具有显示的功能,但屏幕的实际尺寸却有很大的区别,支持的色深也不相同。重复的开发工作以及移植的不便性使得开发成本与开发难度不断提高,这就使得设备厂商要求拥有一个统一的开发平台。
面向这个问题Sun提出的J2ME的解决方法具有的优势有,从程序员的层面看Java语言简单易学,而且功能强大,减小学习该技术的梯度。而且大量的已有的Java程序员可以平滑的过渡到J2ME编程中来,为其提供大量的人力支持。从Java平台来说,天生的对移植性良好的支持,以及Java平台的整体解决方案,即与J2SE,J2EE的协作可以建立端对端的Java解决方案[6]。
1.4 J2ME的体系结构
1.4.1 J2ME总体结构概览
J2ME其作为一个可以与J2EE、J2SE相提并论的平台,是在1999年的Javaone大会上提出的。随着时间的推移与技术逐渐地成熟,其平台本身的构架也逐渐演变。如图1.1所示,给出了J2ME一个总体的构架[7]。






KVM





JVM





CLDC





MIDP





CDC





Foundation Profile图1.1 J2ME总体框架
JVM和KVM分别表示Java虚拟机,J2ME可以用两种不同的虚拟机,针对不同的内存大小,取用不同的虚拟机,大于2M的内存的电子设备,可以用JVM虚拟机,128KB到512KB内存的电子设备,可以用KVM虚拟机。在它上一层是配置,再上一层就是简表。配置是提供支持最大范围设备的最小的平台。简表是针对特定的设备提供相应的开发包集合。
1.4.2 Configuration与Profile
J2ME使用配置(Configuration)和简表(Profile)定制Java运行时环境(JRE)。作为一个完整的JRE,J2ME由配置和简表组成,配置决定了使用的JVM,而简表通过添加特定于域的类来定义应用程序。
配置将基本运行时环境定义为一组核心类和一个运行在特定类型设备上的特定JVM。设备的配置为这些设备定义了一个基本的J2ME运行环境,其中包括虚拟机和核心的Java类库。可以把配置理解为一个针对某一种设备的最小的Java平台。其中包括满足该族设备的JVM(虚拟机)功能的最小子集和针对该族设备的Java类库的最小集合。要注意的是,配置主要针对的是系统级的特性,如基本的Java语言的特性,虚拟机的特性,以及系统级的Java核心类库等[8]。
J2ME配置(Configuration)包括两种,分别是连接设备配置(CDC)和连接受限设备配置(CLDC)。正如前面提到过的,配置分别针对的是某一族系的设备。J2ME所支持的设备主要分为两种,分别通过CDC和CLDC支持。CLDC设备通常有160KB到512KB的可用内存,并使用电池。它们还使用不一致的、小带宽的无线网络连接,可能没有用户界面。CLDC设备使用KJava虚拟机(KVM)实现,KVM是JVM的一种缩减版本。CLDC设备包括寻呼机、个人数字助理、无线电话、专用终端和128KB到512KB内存的手持消费性电子设备。CDC设备使用32位架构,至少有2MB内存,实现了具有完整功能的JVM。CDC设备包括数字机顶盒、家用电器、导航系统、购物终端和智能电话。
简表(Profile)定义应用程序。特别地,它向J2ME配置中添加特定于域的类,定义设备的某种作用。简表是构建在配置层之上的一层类库。它比配置的针对性更强。它提供配置层中所缺失的功能以支持特定的设备。这些功能包括对UI、对持续性存储的支持等。简表层提供了应用程序级的接口,应用程序就建立在简表层。上一个配置可能会有好几个简表(也就是说一个设备可以支持多个简表)。请注意简表针对的更特定的设备,从功能划分的角度来说也是如此。例如,针对某些移动设备,可能会定义一个SMS简表以提供收发短消息的功能。这种功能就只能定义在简表中,而不能定义在配置中,因为短消息这种功能是只针对手机等移动设备的[9]。SUN共定义了7种简表。它们是Foundation Profile,Game Profile,Mobile Information Device Profile,PDA Profile,Personal Profile,Personal Basis Profile和RMI Profile。
这里,手机游戏是使用Mobile Information Device Profile(MIDP),Connected Limited Device Configuration(CLDC)。
1.5 本文研究的目标和内容
本文讲述了手机游戏开发的现状,以及相关的开发平台。同时讲述了J2ME的开发概要,以及麻将应用在J2ME平台上的系统设计。同时,考虑到手机平台的处理能力和内存资源有限,本文采用了知识库来解决这个问题。即通过网络,把处理过程复杂的事件都放到服务器端进行。同时,这样也可以轻易实现规则的转变,可以轻易的把杭州麻将该写成广州麻将。甚至,还可以把麻将改成红五等网络休闲游戏。
网络互联一直是一个热门的话题,无论从PC机还是手机等嵌入式设备。由于互联网造就了知识经济,信息时代的到来,使全球经济出现新一轮的增长,可见互联的重要作用。游戏作为一种娱乐活动,再没有比互动更加有意义的事了,网络游戏的盛行正因为如此。同样,实现手机游戏网络互联,是未来手机游戏发展的趋势,也是手机游戏赢利的增长点。
知识库已被广泛应用于金融系统,大型企业系统等领域,而游戏知识库目前正处于发展初期。利用游戏知识库,可以很好的实现对游戏规则的处理。一旦开发出一款游戏,对于开发其他同类游戏,只需对游戏规则作一些变换就可以完成对整个游戏的开发。利用游戏知识库,可以快速地开发多款游戏,大大地缩短了游戏开发周期,游戏知识库的应用在将来很有前景。
本课题通过研究两种麻将(杭州麻将,广州麻将)之间的共性和区别,构造一个游戏知识库,通过游戏知识库中规则的改变以实现不同麻将游戏。就杭州麻将来说,它是通过抓牌、吃牌、碰牌、杠牌等方式,使手中的牌按照相关规定的牌型条件和牌,其中在比赛前选定一张牌为“财神”(若这张牌为“财神”,那么这张牌可以替代任何牌,“财神”是随机选择的)。杭州麻将游戏的目的在于将手中的十四张牌凑成四组顺子或刻子,即可和牌。
而广州麻将跟杭州麻将的区别就是没有财神,对于广州麻将,由于其没有财神,所以跟杭州麻将的和牌规则是不一样的。
因此,本文采用游戏知识库中的产生式规则来实现和牌的规则判断,通过已有出牌的事实,到游戏知识库中进行匹配,找出相应的规则进行推理。
本文将探讨如何利用游戏知识库在开发原有的杭州麻将的前提下,快速开发出广州麻将。最后,对本文进行了总结,对手机游戏开发、手机游戏行业进行了展望。
 

第二章 J2ME手机游戏系统设计
2.1 本程序需解决的有关技术问题
本游戏程序是在手机平台上运行的游戏。由于手机操作系统是一种嵌入式操作系统,在嵌入式操作系统上运行的系统对于精度要求相对比较高,绘图事件、按键事件都会以极高的频率在后台等待响应,若有丝毫的差别都将很容易导致程序在运行不久后可能出现严重错误,甚至死循环。因此,其逻辑设计应当相当严谨,需将所有可能发生的事件及意外情况考虑在设计中。
2.2 系统总框架
本系统采用Eclipse3.1作为集成开发工具,Eclipse作为IBM投资的一个开源IDE,功能丝毫不比JBuilder差,迄今为止,它已是J2SE,J2ME,J2EE开发的有力支持者[10]。然后本文采用SUN公司的WTK2.2工具来把程序打包成JAR文件,因为SUN公司打包的JAR版本在所有手机上都是可以运行的[11]。
本程序采用的Profile是midp2.0,Configuration是CLDC1.0。游戏力求图形界面尽量美观,虽然是休闲类游戏,但是整体布局以及界面的美观性也是一个好游戏必备的因素。本程序启动后,系统会提示你是否进行联网,如图2.1所示(根据SUN公司的规定,出于安全性的考虑,手机游戏如果需要联网,都会对用户进行提示,提示用户是否需要联网,以确保手机系统的稳定以及用户信息的安全性)。
 
图2.1 系统提示是否联网
根据用户的选择,本文把游戏分为单机版和网络版两个版本。如果用户不想进行联网,那么游戏执行单机版,如果用户想要进行联网,那么游戏就执行网络版。进入游戏后,界面上方是一张麻将图像作为LOGO,下方是一个让用户选择不同功能的表单框,根据按键响应做出不同的按键处理,根据选择的不同表单选项,执行不同的操作。如图2.2所示。
 
图2.2 初始化界面
初始化后,系统总框架如图2.3所示。






游戏主入口表单





启动游戏





帮助说明





退出





选择游戏图2.3 系统总框架
根据不同的选择,系统可以进入启动游戏、选择游戏、帮助说明、退出四个模块。系统进入启动游戏功能模块,游戏启动;系统进入选择游戏功能模块,玩家可以选择杭州麻将或者广州麻将;系统进入帮助说明模块,出现一个带Exit键的Form,该Form只有一张图片,该图片提示了用户如何进行按键操作,如图2.4所示;系统进入退出模块,退出该游戏,游戏没有启动。
 
图2.4 帮助图片
下面是启动游戏后的笼统的系统设计,如图2.5所示。






启动游戏





初始化





玩家一(人)





玩家二(电脑)





玩家三(电脑)





玩家四(电脑)图2.5 系统总体运行情况
这样对游戏就有个总体的方向,然后再落实到细节处,对游戏再进行详细的系统设计:可以看到,以上流程图出现了死循环,其实循环的出口就是和牌。而且,循环不是一成不变的,当玩家有吃,或者有碰的时候就要进行跳转,下面给出了玩家一(人)具体的流程框图,如图2.6所示。
 

图2.6 玩家一(人)流程图
启动游戏,然后进行初始化,然后由庄家先出牌,接着按顺时针的顺序拿牌,出牌。对于玩家一的流程,首先在初始化的时候判断是否是庄家,如果是,那就首先出牌,如果不是,继续监听是否该轮到玩家一拿牌了,如果是,那就由玩家一拿牌,不是,那就由玩家一继续监听是否有吃碰杠,有的话,就提示玩家一是否要执行。玩家一一直处于一种监听状态,首先监听是否是他拿牌了,其次监听是否有吃碰杠,根据得到不同的动作,玩家一再进行操作,比如拿牌,或者进行吃碰杠。然后再在拿到牌以后判断是否能和牌,如果有的话那就进行提示,没有的话就出牌。最后,若玩家能和牌了,再有系统提示是否要开始新一轮的游戏,如果开始新一轮的游戏的话,那么庄家就是赢家,如果按退出的话,那就关闭游戏。接下来是其他玩家(电脑)的流程图,如图2.7所示。
图2.7 电脑玩家流程图
由于让电脑玩家考虑是否应该和牌实现起来比较复杂,所以本文在功能实现上决定,放弃追求麻将的番数,一旦有和牌的机会,就让电脑玩家和牌,这样在人工智能上就实现起来就方便了很多。其他流程跟玩家一(人)完全一样。
2.4 系统功能模块设计
2.4.1 麻将属性
本文把麻将写成一个类,这样就有效地实现了封装,以方便调用。属性分别是花色和点数,另外包括以下两种情况,一是财神,本文把它的值定义为-1;二是白板,本文把它替代为原财神,这是杭州麻将的规则。
2.4.2 程序初始化
在MID设备上运行的Java程序被称为MIDlet。这些MIDlet在底层CLDC的支持下,通过MIDP中提供的包获得更多的功能(其中包括UI、网络、永续性存储等)。MIDlet可以直接使用MIDP本身提供的类库以及MIDP从CLDC中继承的那部分API。MIDlet程序的运行是由startApp(),pauseApp()和destroyApp()这3个方法控制的。它们都在Javax.microedition.midlet.MIDlet中定义,所有的MIDlet都必须实现这3个方法[12]。
程序初始化主要是针对J2ME运行机制作出的一些处理。初始化MIDlet时,必须写上三个方法:startApp(),pauseApp(),destroyApp()。startApp()方法具体实现如下:
public void startApp() {
             Display.getDisplay(this).setCurrent(form);
             conn = new Connection(this); // 初始化网络
      }
表示将在游戏启动时运行Form表单,同时进行网络的初始化操作。
J2ME用户界面编程分为高级UI编程和低级UI编程。Screen类属于高级图形用户界面组件,Canvas是低级图形用户界面组件[13]。在同一时刻,只能有唯一一个Screen或者Canvas类的子类显示在屏幕上,可以调用Display的setCurrent()的方法来将前一个画面替换掉,必须自行将前一个画面的状态保留起来,并自己控制整个程序画面的切换[14]。Form表单是属于Screen的派生类,它是属于高级图形用户界面组件,然后再用Command类对按键进行监听。运行表单后,这样就可以进行不同的按键选择了。
2.4.3 网络传输
网络的传输本文用两个类来实现。第一个类进行网络连接初始化,第二个类是客户端对服务器端进行发包收包操作,并进行响应的包解析。
2.4.4 主游戏模块
主游戏模块是整个程序的核心,它继承了Canvas类,是低级用户界面组件,用Keypress进行按键响应[15]。如图2.8所示,是主游戏启动后的界面。
 
图2.8 游戏启动后界面
在上述体系结构的基础上,主要分为以下几个模块:初始化游戏模块、绘画机制模块、检测吃碰杠模块、和牌模块、电脑玩家出牌模块。
2.4.5 初始化游戏模块
初始化游戏需要作以下工作:首先是财神的选定,本文采用随机的方法来选定财神,然后是庄家的选定,本文这样规定庄家,如果是第一局,就规定玩家一(人)是庄家,如果不是第一局的话,那么就由上一局是赢家的那家作为庄家。然后对四家发牌,采用随机发牌;最后是对四家手上的牌进行排序,初始化完毕。
2.4.6 绘画机制模块
绘画机制在整个程序中起到很重要的一块,在游戏设计中尤为重要。绘画模块大致可以分为两个模块:第一是初始化模块,第二是运行时模块。当游戏启动时,本文把画布设成全屏模式,加载一些图片,画出财神,以及一些为了美观作的修饰,等等,这些都是初始化模块需要做的工作;在运行时模块中,本文必须在run()函数中调用repaint()函数,以便能够在每次执行其他操作后进行刷新或者重画。比如,每次取了牌,必须得将手中的牌刷新一次,有人打出了牌,也得重新画一次,遇到吃,碰,杠,和,或者提示,都得进行绘画。
2.4.7 检测吃碰杠模块
本文分别用三个函数eat(),bump(),gang()来检测吃、碰、杠。本文根据花色相同,点数相连来进行吃的检测;根据花色相同,点数相同来进行碰的检测;当然如果有四张牌点数花色都一样的话那就是杠了。
2.4.8 和牌模块
和牌模块算是整个游戏设计中的一个难点,本文采用列举的方法把各种和牌的模式归纳性的罗列了出来。可以把和牌大致分为以下两类:一类是特殊的,一类是普通的。
特殊的一类是七对子,即手中的14张牌都是一对一对的,总共七对(当然,也可以用财神替代)。这种牌如果和了的话就是四番。
普通的一类就是平时和的那种牌,即多个顺子,一副对。这种和牌可以考虑从对里面入手,可以分两种情况:一种是有对的,一种是没对的。如果有对的话,那可以把对子拿出来进行判断剩下的牌是否都是一顺一顺的(可以用一张财神来抵消任何一顺差一张牌的类型)。如果没有对的话,那就要看有没有财神,如果没的话,直接返回,表示不能和,如果有的话,可以用财神跟任何一张牌来搭配充当一对,然后对剩下的牌进行判断,是否都是一顺一顺的。
2.4.9 电脑玩家出牌模块
电脑出牌涉及到人工智能方面的问题,由于人工智能并非本文研究的课题,所以只简单地实现了电脑出牌的人工智能。本文采用积分的方法来实现,对于每一张牌,都会赋予不同的积分,然后对于积分最小的牌,就认为该牌最没有价值,最后将该牌打出。
具体赋予该牌的积分规则如下:根据牌值的大小赋予不同的值,越是中心牌,那么积分越大,但是不超过5分;如果是财神的话,赋予50分;如果是一顺的话,那么该顺子的每张牌都赋予20分;如果是相邻的牌或者是一对的话,那每张牌赋予10分,如果是相间的话,那每张牌赋予5分。最后再根据积分的大小
 

来决定哪张牌该是打出的牌。
第三章 客户端游戏与PC机互连
3.1 J2ME网络
3.1.1 通用连接框架
由于小型计算设备缺乏完整地处理和存储信息的能力,所以J2ME提出了通用连接框架(Generic Connection Framework,GCF),用来连接网络。通过GCF,可以用来连接服务器端,利用后台处理系统处理和存储数据的能力。
可以使用GCF中描述的Connector类建立网络连接。可以使用Connector类来访问七个GCF连接接口之一。GCF连接接口为网络操作提供了基本的体系结构,并且为编写网络代码提供了独立的网络协议。使用GCF连接接口同样可以忽略底层的网络协议。Connection接口是最基本的连接,可以用于打开或者关闭一个连接[16]。在程序的实现过程中,本文用下列一段代码实现:
String url= "socket://192.168.0.41:10001";
SocketConnection sc = null;
sc = (SocketConnection) Connector.open(url);
这样就打开了Connection。
3.1.2 InputStream和OutputStream
InputStream类定义了一个打开的连接读取数据的基本接口。首先打开一个连接,再创建从InputStream类派生来的合适的类实例。InputStream主要的方法是read()方法和close()方法。其中read()方法可以从打开的连接中读取多个字节,将读取的字节存储到作为参数传给read()方法的数组或者字符串中。而close()方法则用来终止输入流,但是并不是关闭连接。您很少需要调用close()方法,因为当InputStream的实例超出命名空间时就会自动关闭这个输入流。但是,调用close()方法释放资源是一种好习惯。
OutputStream类定义了一个往一个打开的连接中写数据的基本接口。首先打开一个连接,然后再创建从OutputStream类派生来的合适的类的实例。然后调用OutputStream类的一个方法往连接中写数据。在OutputStream类中,主要的方法是write()和close()。其中write()方法是将数组或者字符串中的元素写到输出流中[17]。而OutputStream的close()方法和InputStream的close()方法功能基本一样,不再重复讲述。
3.1.3 GCF支持的协议
GCF支持三种网络通信协议,分别是超文本传输协议(Hypertext Transfer Protocol,HTTP)、文件传输协议(File Transfer Protocol,FTP)和套接字协议(Socket)。这里,本文采用套接字(Socket)协议来进行与服务器端进行联网[18]。
3.2 socket网络通讯原理及实现方式
3.2.1 socket网络通讯原理
Socket是在Unix中被首先提出的,被广泛应用于Internet程序设计中。Socket是与远程计算机的端口的连接,并且使用HTTP命令交换信息。HTTP命令可以使您的应用程序向一台远程计算机发送一个要求获得数据流的HTTP请求。返回时,远程计算机会发送一个HTTP应答作为对您的应用程序的应答。假设您的应用程序希望从一台远程计算机的特定文件存储器上接受一个数据流。首先您的应用程序应该打开与这台服务器上的端口的socket连接。接着应用程序发送GET命令和文件名作为HTTP请求的一部分。然后您的应用程序就能读取包含了远程服务器的HTTP应答的流。
3.2.2 socket实现方式
Java有两个socket类,Java.net.Socket和Java.net.ServerSocket很好的支持了TCP套接字。当编写与已有服务连接的客户软件时,应该使用Socket类。当编写绑定到本地端口,以提供服务的服务器软件时,应该使用ServerSocket类[19]。这与处理UDP的DatagramSocket类的工作方式不同-连接到服务器端的功能和从客户接受数据的功能在TCP下被分成了独立的类。
Socket类表示客户端套接字,它属于一台或两台机器的TCP通信端口之间的通信信道。套接字可以与本地系统的端口连接,从而无需另一台机器,但是多数网络软件包含的是两台机器。然而,TCP套接字不会在多于两台机器之间通信。如果需要这种功能,那么客户应该建立多个套接字连接,为每台机器建立一个连接。
ServerSocket类表示服务器端套接字,服务器套接字是一种特殊类型的套接字,被用来提供TCP服务。客户套接字绑定到本地机器上的任何空闲端口,并连接到特定的服务器端口和主机。服务器套接字的不同之处在于它们绑定到本地机器的特定端口,这样远程客户就可以定位服务。客户套接字连接只能连接到一台机器,而服务器套接字可以响应多个客户的请求。
服务器套接字的工作方式很简单-客户知道运行在某个特殊端口上的服务(通常是被人熟知的端口号,被用于特殊协议,但是服务器也可能在非标准端口号上运行)。它们建立连接,该连接在服务器内被接受。可以同时接受多个连接,或者服务器可以选择在某个给定的时刻只接受一个连接。连接被一旦接受,那么该连接就以Socket对象的形式,由一个普通的套接字来表示,一旦你掌握了Socket类,那么编写服务器软件就变得与编写客户软件一样简单了。服务器与客户的唯一差异在于,服务器使用ServerSocket对象绑定到某个特定端口。ServerSocket对象充当客户连接的工厂,你不必创建Socket类的实例。这些连接被设计成常见的套接字方式,所以你可以连接输入/输出过滤器流(或者甚至读取器和写入器)和这些连接。
3.3 手机游戏的通讯协议
手机游戏的通讯协议如表3.1所示。
 
 
 
 
 
 
 
表3.1 手机游戏的通讯协议





协议种类

协议标识

协议内容

备注


Check

001

标识,牌值,牌点数,打出的牌。

c->s,请求服务器进行吃碰杠检测。


Hu

002

标识,牌值,牌点数。

c->s,请求服务器进行和牌检测。


Think

003

标识,牌值,牌点数。

c->s,请求服务器决定该出的牌。


Rs_Check

004

标识,牌值,结果。

s->c,服务器发送核对的结果。


Rs_Hu

005

标识,牌值,结果。

s->c,服务器发送是否和牌的结果。


Rs_Think

006

标识,牌值,结果。

s->c,服务器发送电脑出牌的结果。
手机客户端采用Socket进行与PC服务器端进行网络互联,由于Socket编程是以发包的形式进行数据传送的,所以,本文必须对包的通讯协议进行定义,规范地定义数据包,可以使网络通讯相对比较稳定。如表3.1所示,对于不同的协议种类设置不同的协议内容,对于001协议,本文采用标识+牌值+牌点数+打出的牌的格式内容进行数据包的传递,由于Socket是建立在TCP上的通讯协议,所以其在客户端对数据包中内容的顺序与在服务器端收到的数据包中内容的顺序是一样的。
 

第四章 客户端游戏与知识库的接口
4.1 知识库的基本原理
什么是知识?知识是人们在长期的生活及社会实践中、科学研究及实验中积累起来的对客观世界的认识与经验,人们把实践中获得的信息关联在一起,就获得了知识[20]。信息之间有多种关联形式,其中用得最多的一种是如果……,则……所表示的关联形式,它反映了信息间的某种因果关系。知识库,就是知识的集合。
知识有如下特性。第一,知识的相对正确性,知识来自于人们对客观世界运动规律的正确认识,是从感性认识上升成为理性认识的高级思维劳动过程的结晶;第二,确定性与不确定性知识,知识可以由若干信息关联的结构来组织,其中,有的信息是精确的,有的信息是不精确的;第三,知识的可表示性、可利用性和可发展性,人类的历史,就是不断地积累知识和用知识创造文明的历史,为了使知识更加便于传播、学习,并使有用的知识得以让后人顺利继承,人们利用并发展了各种生动活泼的形式来记录、描述和表示知识[21]。
4.2 知识库在游戏中的运用
知识库已广泛用于其他领域,用于在游戏中的知识库本文把它叫做游戏知识库。游戏知识库具有如下特点:首先,知识库知识量大,内容丰富,各个知识之间存在松散联系;其次知识的不断更新;再次表达能力强,便于控制,有利于提高搜索和匹配的效率;最后,结构一致,有利于知识库的扩充、修改和一致性的检查等。
手机客户端由于其处理能力弱,所以本文尝试着把一些处理过程复杂的模型放到服务器端进行处理,也就是把规则放到服务器端进行处理。这样的话,手机客户端只要简单的实现视图模块的功能就可以了。这就大大减轻了手机处理的强度。
本文首先在服务器端对手机游戏规则知识库进行建库,对于游戏中和牌规则,吃碰杠规则,电脑出牌规则进行建库。当手机客户端游戏运行时需要进行规则判断时,可以通过与服务器联网,把相关的数据发给服务器端,让服务器端读取规则,然后进行规则的处理,在把相应的规则判断结果返回发送给客户端,这样客户端就不用再进行判断,而直接可以从服务器发回的数据中得到动作代码。根据动作代码去执行相应的动作。
4.3 客户端游戏规则调用
由于杭州麻将游戏跟广州麻将游戏打发一样,和牌规则不一样。杭州麻将的和牌规则与广州麻将的和牌规则的区别就是是否有财神,所以可以通过修改杭州麻将游戏知识库中的和牌规则,来迅速完成对广州麻将游戏的开发。甚至还可以利用游戏知识库来把杭州麻将修改为红五、三扣一等游戏。
通过通讯协议的方式,到服务器端知识库中进行规则的匹配,找出相应的游戏规则处理,通过服务器端返回的动作代码(action),客户端调用相应的动作相应函数,进行处理。
第五章 总结和展望
手机游戏市场正在加速发展,手机游戏是移动多媒体时代最有价值的应用。因为游戏是多媒体应用中集大成的业务,图像、音乐、互动都能在游戏中实现,能充分满足用户各方面的需求。在近几年,中国手机游戏的整个市场规模增长速度是相当快的。
在全球,手机游戏已经成为游戏市场中增长最快的部分。而在国内,2003年9月,随着中国移动百宝箱正式收费,国内手机游戏产业正式启动,用户增长十分迅速。短短几个月的时间里,手机游戏用户就增长到200万。可见目前手机市场是一个前景无限的网络游戏市场。
手机游戏在极短的时间内复制了电脑游戏的发展历程。起先流行的是一些单机作品,大多属于益智类的作品,操作简单、短小精悍、易于上手,对技术指标和显示屏要求都不高。此后,手机游戏经历了短信息服务游戏、WAP游戏,一直到现在正在流行的基于J2ME/BREW的游戏。与此同时,手机终端也进入了彩屏时代。更重要的是,随着2.5G和3G移动通信技术的发展,特别是3G的出现,移动带宽资源将全面拓展,语音、图像、视频将有机地结合起来,而手机游戏也将由单机迅速过渡到类似于电脑网络游戏的时代。而利用游戏知识库,智能地开发知识库,只要进行知识库的切换就可以实现多种游戏的切换,这样开发的效率就大大提高了。可以很好的满足广大手机游戏迷对多种游戏的需求。
与PC网络游戏相同,手机网络游戏的推出同样会造就一个全新的产业链,移动运营商、增值服务商(SP)、手机厂商等等,虽然在类似短信、彩信这样的业务中,这个产业链已具雏形,但手机网络游戏的推出必将把这个产业链更紧密地联系在一起。
 
致 谢
首先,应当感谢学院的领导给我们营造了良好的学习环境,以及对我们学业上的重视与关怀。特别是对本次毕业设计给予了大量人力、物力的支持。在这里尤其要感谢实验室的老师们,按时地为我们开发实验室。其次,也要感谢我签约的公司,群硕软件开发(上海)有限公司以及我的项目经理Samuel,在我需要返校做毕业设计的时候,得到了他们的谅解与支持。
在写毕业论文的时间里,我一直受到了计算机信息学院老师,同学,及父母和亲友的无私的关怀和帮助。借此机会,谨表示衷心的感谢。最要感谢的是我的导师、老师。在这段日子里,他们在各个方面都给予了我极大的帮助。在学习科研上,他们为我指明了研究的方向,并提供了最好的环境,给了我许多研究,探索和实践的机会,并鞭策我不断进步;在生活上,他们给予了我无微不至的关怀,帮我解决了很多后顾之忧,使我能够安心的进行学习和科研工作。在这段时间里,我获得了许多受用一生的东西。
总之,我在大学四年的学习中取得的各项成绩是各级领导与各位老师培养教育的结果。这使我受益终生。
【参考文献】
[1] Springer Berlin. Heidelberg.Level of Detail Modelling in a Computer Game Engine[J].Computer Science,2004,3166:451-454.
[2] Bruce Eckel. Thinking In Java[M]. 机械工业出版社, 2004. 25-106页.
[3] 卜佳俊. 深入BREW手机游戏开发[M].清华大学出版社, 2004. 5-14页.
[4] 李贺, 尹强国, 蒋亮. BREW技术开发与应用[M]. 机械工业出版社, 2006. 3-25页.
[5] David Flanagan. Java in a Nutshell, 5th Edition[M]. O'Reilly, 2002. 20-87页.
[6] 尚雷明, 关亚飞, 石必明. J2ME MIDP/J2EE应用集成中的通讯模式[J]. 安徽理工大学学报(自然科学版), 2004, 5:26-31.
[7] 李振军, 成良玉. 基于MIDP的Java手机游戏开发方法的分析与实现[J]. 计算机应用, 2004, 24(3):237-241.
[8] Bishop, L Eberly, D Whitted, T. Designing a PC Game Engine[J]. Computer Graphics and Applications, 1998,18(1):46-53.
[9] 仇宇. J2ME:信息设备的支持[J]. 中国计算机用户, June 2004:58.
[10] Steve Holzner. Eclipse [M]. O'Reilly. 2004, 102-165.
[11] Ulrich Kortenkamp, Dirk Materlik. Geometry teaching in wireless classroom environments using Java and J2ME[J]. Science of Computer Programming, 2004,53:71-85.
[12] Krikke. Samurai Romanesque, J2ME, and the battle for mobile cyberspace[J]. Computer Graphics and Applications, 2003,23(1):16-23.
[13] 郎锐, 孙方. J2ME手机程序Eclipse开发基础[M]. 机械工业出版社, 2006.57-84页.
[14] David Fox, Roman Verhosek. Micro Java Game Development[M]. Addison Wesley, 2002. 81-142.
[15] James Keogh. J2ME: The Complete Reference[M]. Brandon A. Nordin, 2003.98-145.
[16] Hassan Artail. A Multiplatform Methodology: Developing Mobile Device Applications[J].computer society,2005,4(2):92-96.
[17] Bruce Eckel. Thinking In Java[M]. 机械工业出版社,2004. 54-76页.
[18] 胡虚怀. 移动设备中基于MIDP2.0的2D游戏的开发[J]. 计算机工程与应用,2005,41(13):104-107.
[19] 魏冬健,高济. 基于J2ME平台的无线设备应用系统的开发[J]. 计算机应用研究,2002,19(10):146-148.
[20] 王永庆. 人工智能原理与方法[M]. 西安交通大学出版社, 2003.53-108页.
[21] 蔡瑞英, 李长河. 人工智能[M]. 武汉理工大学出版社, 2003. 14-62页.
 

附  录
一、麻将类:
public class majiang {
         int num = 0;
         int type = 0;
         boolean side;
         play_majiang pm;
         Image mahimage;
         public majiang(int n, int t, boolean s, play_majiang pm) {
                   this.pm = pm;
                   num = n;
                   type = t;
                   side = s;
                   if (n == pm.magic1 && t == pm.magic2) {
                            num = 7;
                            type = 3;
                   }
                   if (n == -1) {
                            num = pm.magic1;
                            type = pm.magic2;
                   }
         }
}
二、J2ME初始化程序:
/** Main method */
         public void startApp() {
                   Display.getDisplay(this).setCurrent(form);        
                   conn = new Connection(this); // 初始化网络
         }
         /** Handle pausing the MIDlet */
         public void pauseApp() {
         }
         /** Handle destroying the MIDlet */
         public void destroyApp(boolean unconditional) {
         }
         /** Quit the MIDlet */
         public static void quitApp() {
                   instance.destroyApp(true);
                   instance.notifyDestroyed();
                   instance = null;
         }
         public void startgame() {
                   pm = new play_majiang(this, winner, wei);
                   Display.getDisplay(this).setCurrent(pm);
         }
 
三、高级用户界面按键响应:
       // 进入帮助说明后的按键响应
         public void commandAction(Command c, Displayable d) {
                   if (c == exit) {
                            Display.getDisplay(midlet).setCurrent(this);
                   }
         }
public void keyPressed(int key) {
                   switch (getGameAction(key)) {
                  case Canvas.UP: {
                            if (choose > 1)
                                     choose--;
                            else
                                     choose = 3;
                   }
                            break;
                   case Canvas.DOWN: {
                            if (choose < 3)
                                     choose++;
                            else
                                     choose = 1;
                   }
                            break;
                   case Canvas.FIRE: {
                            if (choose == 1) {
                                     if (first) {
                                               midlet.startgame();
                                               first = false;
                                     } else {
                                               //把ff设成true
                                               midlet.pm.changeff();
                                               Display.getDisplay(midlet).setCurrent(midlet.pm);
                                     }
                            }
                            if (choose == 2) {
                                     Display.getDisplay(midlet).setCurrent(form);
                            }
                            if (choose == 3) {
                                      midlet.quitApp();
                            }
                   }
                            break;
                   case 0: {
                            switch (key) {
                            case Canvas.KEY_NUM2: {
                                     if (choose > 1)
                                               choose--;
                                     else
                                               choose = 3;
                            }
                                     break;
                            case Canvas.KEY_NUM8: {
                                     if (choose < 3)
                                               choose++;
                                     else
                                               choose = 1;
                            }
                                     break;
                            case Canvas.KEY_NUM5: {
                                     if (choose == 1) {
                                               if (first) {
                                                        midlet.startgame();
                                                        first = false;
                                               } else {
                                                        midlet.pm.changeff();
                                                        Display.getDisplay(midlet).setCurrent(midlet.pm);
                                               }
                                     }
                                     if (choose == 2) {
                                               Display.getDisplay(midlet).setCurrent(form);
                                     }
                                     if (choose == 3) {
                                               midlet.quitApp();
                                     }
                            }
                                     break;
                            }
                   }
                            break;
                   }
                   repaint();
         }}
 

一、连接服务器端代码:
1,客户端首先进行初始化:
public boolean initNet() {
                   try { // 打开两个连接(一个上一个下),并使它们联结
                            sc = (SocketConnection) Connector.open(url);
                            System.out.println("cnnect to server...");
                            io_is = sc.openInputStream();
                            io_os = sc.openOutputStream();                          
                            return true;
                   } catch (Exception e) {
                            netWork = false ;
                            System.out.println(e.getMessage() + "初始化网络错误");
                            return false;
                   }
         }
       2,与服务器端进行发包收包动作:
public void sendMessage(String str) {
                   try {
                            os.write(str.getBytes());
                            os.write("\r\n".getBytes());
                   } catch (IOException ioe) {
                            ioe.printStackTrace();
                   }
         }
        
public InputStream getMessage(){
                   try{
                            is.read();
                   }catch(Exception e){
                            System.out.println("null message");
                            e.printStackTrace();
                   }
                   return is;
         }
public synchronized void run() {
                   System.out.println("run send");
                   while (true) {
                            // If no client to deal, wait until one connects
                            if (message == null) {
                                     try {
                                               wait();
                                     } catch (InterruptedException e) {
                                     }
                            }
                            if (message == null) {
                                     break;
                            }
                            try {
                                     os.write(message.getBytes());
                                     os.write("\r\n".getBytes());
                            } catch (IOException ioe) {
                                     ioe.printStackTrace();
                            }
                            // Completed client handling, return handler to pool and
                            // mark for wait
                            message = null;
                   }
         }
二、运行游戏的代码:
public void run() {             
                            if (start1 && first) {
                                     System.out.println("start1 and first");
                                     Random rand = new Random();
                                     int count;
                                     for (int i = 0; i < 14; i++) {
                                               // 拿牌
                                               if (mah[0][0][i] == 0) {
                                                        // 随机取牌添加到最后
                                                        do {
                                                                 count = abs(rand.nextInt() % 136);
                                                        } while (initmah[count] == 0);
                                                        initmah[count] = 0;
                                                        if (count < 108) {
                                                                 mah[0][0][i] = count % 9 + 1;
                                                        } else {
                                                                 mah[0][0][i] = (count - 108) % 7 + 1;
                                                        }
                                                        mah[0][1][i] = count / 36;
                                                        if (mah[0][0][i] == magic1 && mah[0][1][i] == magic2) {
                                                                 mah[0][0][i] = -1;
                                                                 mah[0][1][i] = 0;
                                                        }
                                                        if (mah[0][0][i] == 7 && mah[0][1][i] == 3) {
                                                                 mah[0][0][i] = magic1;
                                                                 mah[0][1][i] = magic2;
                                                        }
                                                        mahcount--;
                                                        break;
                                               }
                                     }
                                     // 进行胡牌判断,还应该进行杠判断
                                     // 如果可以胡了的话,提示可以胡了
                                     winnum = win(0);
                                     if (winnum > 0) {
                                               eat1 = 6;
                                     }
                                     first = false;}
  • 上一篇资讯: 人事管理系统用户手册
  • 设为首页 | 加入收藏 | 网学首页 | 原创论文 | 计算机原创
    版权所有 网学网 [Myeducs.cn] 您电脑的分辨率是 像素
    Copyright 2008-2020 myeducs.Cn www.myeducs.Cn All Rights Reserved 湘ICP备09003080号 常年法律顾问:王律师