jsp网络五子棋论文_第1页
jsp网络五子棋论文_第2页
jsp网络五子棋论文_第3页
jsp网络五子棋论文_第4页
jsp网络五子棋论文_第5页
已阅读5页,还剩71页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

绪论1.1课题研究背景 现在人们压力日益增大,人们需要劳逸结合也获得更高的工作效率,工作之余的娱乐对每一个人来说都是必不可少的放松方式。五子棋游戏简单易学同时具有很大奥妙性,也非常富有趣味性与消遣性。在经过不断发展后,五子棋已经成为棋盘娱乐的重要的组成部分,它能够开发智力、增强思维能力,是人们休闲娱乐的不二的选择。而网络互动娱乐是近几年迅速发展起来的新的娱乐形式,成为IT产业中增长最快的娱乐形式之一。 网络五子棋游戏很多是使用Java语言开发的一款游戏。它使用SOCKET建立连接,多线程处理数据,这些特点使这款游戏无论是客户端还是服务器的实现都相对容易。1.2选题的前提和目的随着计算机网络技术的不断发展,网络游戏已经成为最具潜力的热点领域。各种各样的游戏使人眼花缭乱,而特别是其中一些休闲益智类的棋牌游戏,集娱乐性、趣味性、益智性和互动性于一体,拥有很大的用户。棋类游戏能锻炼人的思维,起到修身养性的作用。五子棋游戏可以分为两类:一类是单机版五子棋游戏,另一类是网络五子棋游戏。随着计算机网络和JAVA技术的不断发展,使用Java开发网络五子棋游戏将是一个实用性很强的毕业设计项目。网络五子棋游戏的总体功能是要设计出具有精美界面的,具备人工智能的,支持网络对弈的五子棋游戏。本系统最终的目的是建立一个有具体规则的网络五子棋平台,使两台不同计算机的使用者通过网络连接,达到网络对弈的目的。1.3五子棋简要介绍五子棋相传起源于四千多年前的尧帝时期,比围棋的历史还要悠久,可能早在“尧造围棋”之前,民间就已有五子棋游戏。有关早期五子棋的文史资料与围棋有相似之处,因为古代五子棋的棋具与围棋是完全相同的。在上古的神话传说中有“女娲造人,伏羲做棋”一说,《增山海经》中记载:“休舆之山有石焉,名曰帝台之棋,五色而文状鹑卵。”李善注引三国魏邯郸淳《艺经》中曰:“棋局,纵横各十七道,合二百八十九道,白黑棋子,各一百五十枚”。这段虽没明讲是何种棋类,但至少知道远古就以漂亮的石头为棋子。因而规则简单的五子棋也可能出自当时,并是用石子作棋子。亦有传说,五子棋最初流行于少数民族地区,以后渐渐演变成围棋并在炎黄子孙后代中遍及开来。在古代,五子棋棋具虽然与围棋相类同,但是下法却是完全不同的。正如《辞海》中所言,五子棋是“棋类游戏,棋具与围棋相同,两人对局,轮流下子,先将五子连成一行者为胜”。1.4主要完成内容本课题为了分析了五子棋规则及技巧,以及研究客户端界面的布局,决定用Java开发五子棋游戏。主要完成客户端界面设计和网络对战2个功能模块。客户端负责收集用户的信息和界面维护,以及错误处理;服务器的建立以及对战用户的基本信息和两个对战用户的棋盘信息,判断输赢。2JAVA开发环境2.1JAVA开发工具Java的开发工具很多,比如JBuilder、Eclipse、NetBeansIDE、JCreator等等,不同的工具可能对开发不同的程序有针对的优势。我选择Eclipse进行编写,我们说一下Eclipse的优势。★Eclipse是一种具有可扩展的开放源代码IDE。Eclipse可以在同一IDE中集成了来自不同供应商的工具,并实现了工具之间的相互操作,从而显著简化了项目工作流程。★Eclipse框架的灵活性来自于它的扩展点。在XML中定义的已知接口,并充当插件的耦合点。扩展点的范围包括从简单字符串,到一个Java类的描述。★Eclipse的最大特点是它能接受由Java开发者自己编写的开放源代码插件。2.2Java简介 Java是一种简单的、分布式的、面向对象的、可移植、解释的、安全的的多线程语言。它以其平台无关性、硬件结构无关性、强安全性、面向对象、语言简洁的特点,在网络编程语言中占据了无可比拟的优势,成为实现电子商务系统的首选语言。2.3Java的起源和发展 Java是Sun公司在1995年推出的新兴的编程语言,它是一种跨平台的、应用于当前高速发展的网络的编程语言。在编程语言中,可认为Basic语言促使了C语言的出现,C语言促进了C++的出现,而C++又促使了Java语言的出现。 自从Java正式推出后,以它特有的优势迅速发展,经过几年的发展,Java已经在软件开发等领域占有很大的市场。Java分为三种:J2SE、J2EE和J2ME。J2SE是Java平台标准版[3],主要应用于桌面程序和Java小应用程序开发;J2EE主要用于企业级开发和大型网站的开发;J2ME主要用于手机等移动设备程序的开发。2.4Java特点★平台无关性Java的平台无关性能让这种软件在每个平台上都能正常地运行,就是"只要写一次程序,在任何地方、任何时间该程序永远都能够运行"。Java解释器生成与体系无关的字节码指令,这些指令对应于Java虚拟机里表示,Java解释器得到字节码后,对它进行转换,只要安装Java运行系统,Java就可以在任何处理器上运行。 ★简单性 Java语言是一种面向对象的语言,它通过提供最基本的方法来完成指定的任务,开发者只要知道一些概念就能够编写一些应用程序。★多线程 设计Java的多线程,是为了满足人们对创建交互式网上程序的需要。用Java编写出来的应用程序可以同时执行很多任务。多线程机制使应用程序可以并行执行,而且同步机制保证了对共享数据的正确操作。★健壮性 Java语言被病毒感染和破坏得最少。Java丢弃了难学和危险的指针功能,而大部分病毒程序常用的方法就是通过巧妙地运用地址变量如指针来获取计算机的资源,从而使程序不安全。★面向对象语言 Java的设计集中于对象及其接口,它提供了简单的类机制以及动态的接口模型。对象中封装它的状态变量和相应的方法,实现了模块化和信息的隐藏;而类则是提供对象的原型,并且通过继承的机制,子类可以使用父类所提供的方法,以实现代码的复用。 ★自动内存管理也可以说自动内存管理是Java健壮性的体现,内存管理是很多种应用程序内的很关键因素。在网络上的其他地方读取大量的数据,之后把该数据写入硬盘上的数据库内,一般的设计就是把数据读入内存中的某些集合内,对这些数据执行某些操作,之后把数据写入数据库。在数据写入数据库后,在下一批处理之前,临时存储数据的集合必须清空旧数据,或被删除后再建。这种操作可能执行很多次,很多语言要手工清空或删除集合数据结构。Java的自动内存管理[4]正好解决这一点,它使程序员不用再为内存管理写大量的代码。2.5JavaSocket网络编程简介2.5.1JavaSocket网络编程基础网络编程,简单的理解就是两台计算机相互通信。其基本模型就是客户机/服务器模型,也就是通信双方中的一方必须提供一个固定的端口,而另一方则只需要知道这个端口,并去建立两者之间的联系,然后完成数据交换。这里提供固定位置的一方通常称为服务器,而建立联系的一方通常称为客户端[5]。基于客户机/服务器的Socket通信模型如下图所示:接收服务结果向服务器发出服务请求向服务器发送连接请求将处理结果反馈给客户端解释并处理请求信息接收用户请求信息阻塞,等待建立连接在Socket上监听客户端请求在制定服务器端公认的地址和端口服务器端创建Socket对象创建Socket对象客户端建立连接请求信息反馈信息接收服务结果向服务器发出服务请求向服务器发送连接请求将处理结果反馈给客户端解释并处理请求信息接收用户请求信息阻塞,等待建立连接在Socket上监听客户端请求在制定服务器端公认的地址和端口服务器端创建Socket对象创建Socket对象客户端建立连接请求信息反馈信息图2.3.1-1基于客户机/服务器的Socket通信模型图 Java为这个模型的实现提供了简化的Socket编程接口。在程序中只要导入java.io包就可以方便的使用java的Socket编程接口。Java中Socket通信模型如下图所示:ServerSocketss(port#)ServerSocketss(port#)ss.accept()//等待连接ServerOutputStreamInputStreamss.close()OutputStreamInputStreams.close()Sockets(host,port#)//请求连接服务器Client图2.3.1-2Java中的Socket编程模型图2.5.2Socket编程的实现Socket类表示了系统的IP地址和端口号的结合,可以理解为客户端或者服务器端的一个特殊对象。它包含两个处理流的方法,一个是getInputStream(),另一个是getOutputStream(),分别用来获得网络的输入流和输出流。构造Socket对象的代码如下: Sockets=newSocket(IP,port); IP,port分别为服务器端的IP地址和服务器端的端口号。 ServerSocket类是一个专门建立Socket服务器的类,它可以用服务器需要使用的端口号作为参数来创建ServerSocket对象。示例代码如下: ServerSocketss=newServerSocket(TCP_PORT); 当一个客户端程序建立一个Socket连接,所连接的端口号为对应TCP_PORT时,服务器对象ss便响应这个连接,在用上述ss对象调用accept()创建一个代表服务器的Socket对象。创建后服务器便可以利用这个Socket对象与客户端进行数据交换。示例代码如下: SocketclientSocket=ss.accept();在本系统的实现过程中,在支持网络对弈的服务器类的定义中需要使用ServerSocket类来响应多个客户端的连接请求。能够同时建立多个服务器,玩家可以选择不同的服务器参与游戏。2.6Java图形编程Java中的Graphics类是一个工具类,用来绘图和显示格式化文本,Graphics类是在java.awt包中声明的。在Java程序中绘图必须在一个窗口或者是一个容器中进行,绘图窗体经常被设计为一个组件容器。显示格式化文本和绘图是调用Graphics类的drawXX()方法完成的,例如drawString(String)等等。绘图采用的坐标系[6]是原点在左上角,纵轴向下以像素为单位的坐标系。 3系统需求分析3.1用户需求分析根据老师提出的要求,我们把系统的用户分为两类:普通用户、系统管理员用户,下面是我们对两种用户的需求进行的分析:3.1.1普通用户需求根据分析,普通用户具有的功能:(1)用户登录:用户根据自己的密码登录本系统。(2)棋局回放:用户根据自己的需求回放自己以前下过的棋局。(3)玩五子棋:用户在点击playgame后会进入游戏界面玩游戏。(4)悔棋功能:在下棋过程中,用户根据自己的需求,选择悔棋。(5)更改密码:用户可以根据自己的需求更改自己的密码。3.1.2系级管理员需求系统管理员是本系统的最高权限的管理员,他不仅具有普通用户的各种功能,还具有他独有的功能一下是系统管理员所具备的功能:(1)用户登录:用户根据自己的密码登录本系统。(2)棋局回放:用户根据自己的需求回放自己以前下过的棋局。(3)玩五子棋:用户在点击playgame后会进入游戏界面玩游戏。(4)悔棋功能:在下棋过程中,用户根据自己的需求,选择悔棋。(5)更改密码:用户可以根据自己的需求更改自己的密码。(6)管理普通用户:可以对普通用户进行添加和删除。3.1.3系统用例图图3-1-3系统用例图图3-1-3系统用例图 3.2五子棋对弈系统的数据流图数据流图(DataFlowDiagram):简称DFD,它从数据传递和加工角度,以图形方式来表达系统的逻辑功能、数据在系统内部的逻辑流向和逻辑变换过程,是结构化系统分析方法的主要表达工具及用于表示软件模型的一种图示方法。下面简要介绍部分需求的数据流图:3.2.1用户登录数据流图(DFD)在用户登录过程当中,用户输入的信息经过加工处理后,通过对数据库的查询后返回给程序该用户的权限,数据流图(图3-1)如下:用户用户接受用户信息处理信息输入信息查询信息用户信息表(UserInfo)用户产生查询结果权限信息权限信息图3-1用户登录数据流图3.2.2用户界面显示数据流图(DFD)知道用户权限后,通过查询用户游戏信息,显示用户游戏信息。数据流图(图3-2)如下:用户用户接受权限信息处理信息用户每次游戏信息(UserDish)产生结果用户权限查询信息游戏信息游戏信息图3-2普通用户数据显示数据流图4系统的总体设计根据玩家的需求分析,本系统的实现主要用到如下几个类: ★ChessServer:主要用于玩家相关信息的传递。 ★ChessClient:主要用于玩家信息的初始化。 ★NetClient:主要用于实现连接网络玩家,通过此类玩家发送自己的游戏状态以及接收并进行处理从服务器传递过来的信息。 ★ChessPad:主要用于绘制棋盘及棋子。4.1网络编程的模式和选取网络编程模式主要分成两类:一种是基于C/S(客户机/服务器)模式,另一种是B/S(浏览器/服务器)式;C/S程序具有好的交互性,功能强大,但是客户端必须安装客户端软件,限制了其应用;B/S模式下要求客户端具有浏览器,但浏览器在安全方面有一些限制,交互性与功能有一些限制网络五子棋系统应用,所以一般的网络五子棋游戏都选用了C/S模式进行实现,使用TCP/IP方式利用Socket通过传输层提供服务。在Socket工作中,用ClientSocket类建立客户端连接,用ServerSocket类建立服务器端连接,这两个组件分别用来操纵客户端和服务器端的Socket对象进行连接和传输数据。在通信过程中,服务器端应用程序先启动,然后等待客户端的连接请求。在另外一台计算机上启动客户端应用程序,同时输入服务器端Socket地址和端口号进行选择服务器,找到服务器后就向服务器端发请求连接服务器端,允许连接后即向客户端Socket收到Accept信号。客户端和服务器端就正式建立起了后,就可以分别调用TserveRsocket和TClientSocket的Socket属性和客户端进行数据传输。客户端和服务器端Socket组件必须设置相同的端口号。4.2主要类与其作用4.2.1服务器类服务器类用于接收客户端的连接,并为每个客户端在服务器端启动唯一的守护线程,线程主要功能是接收客户端发送过来的消息并做出相应的处理。客户端发送到服务器端的主要消息有两部分:一部分是客户端发送给服务器端需要服务器端进行处理的,如客户端发送过的连接信息、客户端改名信息、客户端断开连接信息等;另一部分是客户端发送给服务器端需要服务端转发给其他客户端的消息,如客户端给游戏另一方发送的棋盘状态数据、聊天信息等。服务器类的主要对象如表4.2.1-1:表4.2.1-1服务器主要对象功能对象名称功能TCP_PORT:服务器端用于建立套接字的端口号,为了可靠的用户连接,因此在服务器端定义了此端口号为TCP的,主要用于建立服务器端与客户端的TCP连接。UDP_PORT:服务器端用于向客户端转发数据需要绑定的用户数据报套接字的端口号,玩家发送给服务器需要转发的消息时,服务器端的DatagramSocket就是使用此端口号建立的UDP连接。ClientDataHash:用于保存客户端套接字和IP套接字地址的哈希表,服务器可以通过发送消息的客户端Socket得到其IP套接字地址,将消息转发出去。ClientNameHash:用于保存客户端套接字和客户端当前名字的哈希表,同样是为了转发客户端消息的。ChessPeerHash:用于保存每一对开局玩家信息的哈希表,表中键是服务方,值是客户方,每一对玩家需要交换的如棋盘状态数据,倒计时信息大都依赖于此哈希表来实现。服务器类使用状况如下图:接受玩家接受玩家处理消息显示状态转发消息服务器端图4.2.1-1服务器类用况图4.2.2客户端主类游戏客户端的主要功能是为了初始化和组织用户界面,并且定义了各个按钮的功能。游戏客户端的主要对象如下如表4.2.2-1:表4.2.2-1客户端对象功能对象名称功能isGameConnected 用于判定玩家是否与服务器连接。isChess 用于判定玩家是否已经在开局游戏中。isServer 用于判定在此局开局游戏中,当前玩家是不是服务方,即主方。isClient 用于判定在此局开局游戏中,当前玩家是不是客户方,即次方。ShiCi 该类的对象,用于在玩家启动时动态地显示五子棋诗的信息。Sing 类该的对象,用于为客户端启动音乐功能。游戏客户端使用状况如下图:界面组织界面组织游戏控制信息交换玩家输入游戏玩家图4.2.2-1游戏客户端用况图4.2.3客户端副类客户端副类的主要功能是当前玩家与其他玩家进行对弈时,网络客户端处理需要发送和接收的消息。客户端副类的主要对象如表4.2.3-1:表4.2.3-1网络端对象功能对象名称功能r随机函数类的对象,用于为每个客户端启动时,为每一个客户端随机分配一个端口号,玩家使用此端口号来接收信息。time当前玩家方的时间信息。初始化时间为3分钟。otherTime当前开局游戏中对方的时间信息。初始时间为3分钟。客户端副类类用况图如下:网络对战玩家网络对战玩家发送消息聊天消息更名消息建立游戏消息连接消息加入消息退出消息处理消息退出消息玩家退出棋盘状态玩家列表倒计时图4.2.3-1客户端副类用况图4.2.4棋盘类棋盘类的主要功能是绘制玩家的棋盘状态与棋子信息。棋盘类的主要对象如表4.2.4-1:表4.2.4-1棋盘对象功能对象名称功能board[][] 玩家所维护的棋盘二维数组。结果为1表示(x,y)位置为黑子,结果为2表示(x,y)位置为白子。withComputer 玩家与电脑对弈的标志。如果当前玩家是与电脑对弈,此变量值为真;否则为假。isMouseEnable 以此变量来控制在网络对弈的双方中,当前玩家是否处于可以落子状态。因为网络对弈要求当一玩家下完后,对方才能落子,因此当此变量为真时,玩家可以落子;当此变 量为假时,玩家不可以落子。isRegretEnable 判断当前的悔棋按钮是否可用。为真时,玩家可以悔棋;为假时,玩家不可以悔棋。isFull判断当前的棋盘是否已经下满,当棋盘下满后,分别给游戏双方一个提示,然后进行清盘操作。棋盘类用况如下图:先手判断先手判断落子绘制棋盘胜负判断玩家图4.2.4-1棋盘类用况图5系统模块的详细设计5.2客户端界面设计 游戏客户端主要用于玩家信息的初始化,玩家的操作状态的定义,包括结构组织游戏客户端的界面,实现定义游戏控制按钮,完成定义键盘的事件。 主要方法: ★launchFrame()方法用在启动玩家客户端时,为用户发送连接服务器信息,并且加载背景音乐等。 ★actionPerformed(ActionEvente)方法用于客户端玩家单击控制按钮的功能的实现。该方法主要用来实现玩家修改名字、创建游戏、我要参赛、系统设置等各个按钮的功能。 ★keyPressed(KeyEvente)方法用于实现聊天功能,当玩家输入聊天信息到输入框中后,按回车键可以发送消息。此事件中主要处理了两个行为,一是当玩家选择某玩家进行私聊时的处理,二是当用户选择所有人进行公聊时的处理。客户端类如图5.2-1:图5.2-1游戏客户端类类图5.3客户端网络设计 网络客户端主要用于接收和发送服务器消息。 主要方法如下: ★connect(String,int)用于服务器的连接。第一个参数是要连接的服务器的IP地址,第二个参数是连该服务器的端口号。玩家用此方法连接上服务器,玩家启动一个线程用来接收服务器发送过来的消息。 ★restart()用于游戏重新开始,在此方法中要求将重新初始化信息,并且进行棋盘清理操作。 ★send(int,String)用于发送此玩家的消息状态给服务器。第一个参数是消息类型,第二个参数是消息内容。消息类型有如下几种如表5.3-1: 表5.3-1消息类型类型发送消息类型0代表修改客户端名字1代表客户端建立游戏2代表客户端加入游戏3代表向游戏对方通告客户端已加入4代表客户端放弃游戏5代表客户端对游戏对方发送过来的放弃操作进行断开6代表游戏一方向另一方发送棋盘状态7代表游戏一方向另一方发送时间信息 ★doMessage(DatagramPacket)用于接收从服务器端发送过来的消息。5.4棋盘类设计棋盘类主要用于绘制棋盘的。★paint(Graphics)方法用来绘制棋盘、棋盘的背景图片和棋子位置。因为采用了双缓冲技术,有效的消除加载图片时的窗口闪烁。★clearBoard()方法用于初始棋盘和一些变量的操作。★select()方法设置其按钮状态的。★isFull()方法用于判断当前棋盘是否已无法落子。如果当前棋盘已满,则通知玩家此局游戏流局。★judge(int,int,int)方法用于判断当前棋子落下时是否游戏胜负已分。如果游戏获胜,则方法返回真值;否则返回假值。棋盘类图如下所示:图5.4-1棋盘类类图5.5系统各模块之间的关系ChessServer类,ChessClient类,NetClient类,ChessPad类等类之间的交互实现了系统的主要功能。服务器端模块的实现,主要的类是ChessPad类和ChessClient类。ChessClient类实现了玩家单击按钮功能及界面的组织;ChessPad类用于绘制棋盘和玩家的落子位置。客户端主要用到的是这三个类:ChessServer类、ChessClient类和NetClient类。服务器类和客户端类用Socket编程实现的信息交换。其他功能都是在用户连接服务器后由游戏客户端类自动调用其类来实现的。各模块关系如下图所示:图5.5-1各模块关系图6系统演示6.1打开服务器端图6.1服务器端启动部分关键代码如下: publicServerThread(SocketclientSocket,HashtableclientDataHash, HashtableclientNameHash,HashtablechessPeerHash, ServerMsgPanelserver) { this.clientSocket=clientSocket; this.clientDataHash=clientDataHash; this.clientNameHash=clientNameHash; this.chessPeerHash=chessPeerHash; this.serverMsgPanel=server; }6.2棋盘的初始化图6.2棋盘的初始化我们可以看到,我们只有在连接起服务器之后,才能够进行游戏的初始化操作,否则;按钮是灰色的。6.3用户加入图6.3加入2个对战者从上图我们可以看到:一旦有人加入,那么服务器端会立即得到提示。6.4用户对战图6.4对战状态下的系统由上图我们可以看到,一旦初始化工作完成,那么对战系统就开始了工作;我们就可以在自己的电脑上看到2个窗口,分别是两个用户在对战。总结通过几个月的对软件系统的设计和实现,一个能够完成网络对弈的五子棋游戏基本实现。全部的总结工作,具体概括如下: 论文首先研究对比了网络五子棋游戏的具体优势,分析了C/S和B/S模式的各自的优缺点。对应系统的具体要求,构建了基于C/S模式的网络五子棋对战的基本设计。 采用了网络编程中的一种,Socket编程,分析了Socket通信的基本原理及实现。因此选择了TCP协议作为通讯方式,为了确保数据传输的高效性、实时性和安全性,对玩家信息的交换及聊天信息都采用的是UDP协议进行传输。 完成了网络五子棋对弈系统的总体的方案设计,以Java为编程语言基础,以Eclipse为五子棋游戏的开发工具,完成了系统各模块的设计,其中包括服务器模块、客户端模块以及美化界面方面的设计。 虽然网络五子棋这款游戏实现了基本的设计,但是需要改进的地方还有很多,我个人认为需要改进的地方有以下几点: 可以在游戏初始界面加入一个游戏大厅的列表,这样用户在进入游戏时可以选择可以看见的服务器列表,而省去了用户直接输入服务器的麻烦。 对游戏逻辑模块进行优化,进一步提高可扩展性,以适应将来新的需求和变化。致谢我不会忘记这难忘的几个月的时间。毕业论文的制作给了我难忘的回忆。在我徜徉书海查找资料的日子里,面对无数书本的罗列,最难忘的是每次找到资料时的激动和兴奋;亲手设计方案的时间里,记忆最深的是每一步小小思路实现时那幸福的心情;为了论文我曾赶稿到深夜,但看着亲手打出的一字一句,心里满满的只有喜悦毫无疲惫。这段旅程看似荆棘密布,实则蕴藏着无尽的宝藏。我从资料的收集中,掌握了很多网络编程方面的知识,让我对我所学过的知识有所巩固和提高,并且让我对当今JAVA对战游戏的发展有所了解。在整个过程中,我学到了新知识,增长了见识。在今后的日子里,我仍然要不断地充实自己,争取在所学领域有所作为。脚踏实地,认真严谨,实事求是的学习态度,不怕困难、坚持不懈、吃苦耐劳的精神是我在这次设计中最大的收益。我想这是一次意志的磨练,是对我实际能力的一次提升,也会对我未来的学习和工作有很大的帮助。在这次毕业设计中也使我们的同学关系更进一步了,同学之间互相帮助,有什么不懂的大家在一起商量,听听不同的看法对我们更好的理解知识,所以在这里非常感谢帮助我的同学。在此更要感谢我的导师和专业老师,是你们的细心指导和关怀,使我能够顺利的完成毕业论文。在我的学业和论文的研究工作中无不倾注着老师们辛勤的汗水和心血。老师的严谨治学态度、渊博的知识、无私的奉献精神使我深受启迪。从尊敬的导师身上,我不仅学到了扎实、宽广的专业知识,也学到了做人的道理。在此我要向我的导师致以最衷心的感谢和深深的敬意。最后再一次感谢所有在毕业设计中曾经帮助过我的良师益友和同学,以及在设计中被我引用或参考的论著的作者。参考文献[1].张海藩编著《软件工程导论》(第五版)[M]清华大学出版社2008[2]王小春编著《Pc游戏编程(人机博弈)》[M]重庆大学出版社2005[3]李宁等编著《JavaWeb开发技术大全》[M]清华大学出版社2009[4]贺松平编著《基于MVC模式的B/S架构的研究及应用》[M]武汉理工大学出版2004[5]耿祥义,张跃平编著《JSP实用教程》[M]清华大学出版社2003[6]吴其庆编著《Java程序设计实例教程》[M]冶金工业出版社,2006[7]冯博、应群:面向对象的Java网络编程。清华大学出版社,2004.11,P152-P155[8]孙更新等:Java毕业设计指南与项目实践,科学出版社,2008.03,P78-P88[9]单文仁:Java在我国的应用现状和发展趋势,科技成果纵横,2007.02,P132-P155[10]孙卫琴:JAVA面向对象编程,电子工业出版社,2006.07,P65-P69[11]朱福喜、黄昊著:Java项目开发与毕业设计指导,北京:清华大学出版社,2008.05,P54-P65[12]郭骅:Java网络编程中的若干问题,电子与电脑,2007.11,P36-P40[13]雨枫技术教程网:五子棋算法探讨,2009.09,P230-P235附录:关键代码服务器端packagecom.dikey.server;importjava.io.DataInputStream;importjava.io.DataOutputStream;importjava.io.IOException;import.Socket;importjava.util.Enumeration;importjava.util.Hashtable;importjava.util.StringTokenizer;publicclassServerThreadextendsThread{ SocketclientSocket;//保存客户端套接口信息 HashtableclientDataHash;//保存客户端端口与输出流对应的Hash HashtableclientNameHash;//保存客户端套接口和客户名对应的Hash HashtablechessPeerHash;//保存游戏创建者和游戏加入者对应的Hash ServerMsgPanelserverMsgPanel; booleanisClientClosed=false; publicServerThread(SocketclientSocket,HashtableclientDataHash, HashtableclientNameHash,HashtablechessPeerHash, ServerMsgPanelserver) { this.clientSocket=clientSocket; this.clientDataHash=clientDataHash; this.clientNameHash=clientNameHash; this.chessPeerHash=chessPeerHash; this.serverMsgPanel=server; } publicvoiddealWithMsg(StringmsgReceived) { StringclientName; StringpeerName; if(msgReceived.startsWith("/")) { if(msgReceived.equals("/list")) {//收到的信息为更新用户列表 Feedback(getUserList()); } elseif(msgReceived.startsWith("/creatgame[inchess]")) {//收到的信息为创建游戏 StringgameCreaterName=msgReceived.substring(20);//取得服务器名 synchronized(clientNameHash) {//将用户端口放到用户列表中 clientNameHash.put(clientSocket,msgReceived.substring(11)); } synchronized(chessPeerHash) {//将主机设置为等待状态 chessPeerHash.put(gameCreaterName,"wait"); } Feedback("/yourname"+clientNameHash.get(clientSocket)); sendGamePeerMsg(gameCreaterName,"/OK"); sendPublicMsg(getUserList()); } elseif(msgReceived.startsWith("/joingame")) {//收到的信息为加入游戏时 StringTokenizeruserTokens=newStringTokenizer(msgReceived,""); StringuserToken; StringgameCreatorName; StringgamePaticipantName; String[]playerNames={"0","0"}; intnameIndex=0; while(userTokens.hasMoreTokens()) { userToken=(String)userTokens.nextToken(""); if(nameIndex>=1&&nameIndex<=2) { playerNames[nameIndex-1]=userToken;//取得游戏者命 } nameIndex++; } gameCreatorName=playerNames[0]; gamePaticipantName=playerNames[1]; if(chessPeerHash.containsKey(gameCreatorName) &&chessPeerHash.get(gameCreatorName).equals("wait")) {//游戏已创建 synchronized(clientNameHash) {//增加游戏加入者的套接口与名称的对应 clientNameHash.put(clientSocket, ("[inchess]"+gamePaticipantName)); } synchronized(chessPeerHash) {//增加或修改游戏创建者与游戏加入者的名称的对应 chessPeerHash.put(gameCreatorName,gamePaticipantName); } sendPublicMsg(getUserList()); //发送信息给游戏加入者 sendGamePeerMsg(gamePaticipantName, ("/peer"+"[inchess]"+gameCreatorName)); //发送游戏给游戏创建者 sendGamePeerMsg(gameCreatorName, ("/peer"+"[inchess]"+gamePaticipantName)); } else {//若游戏未创建则拒绝加入游戏 sendGamePeerMsg(gamePaticipantName,"/reject"); try { closeClient(); } catch(Exceptionez) { ez.printStackTrace(); } } } elseif(msgReceived.startsWith("/[inchess]")) {//收到的信息为游戏中时 intfirstLocation=0,lastLocation; lastLocation=msgReceived.indexOf("",0); peerName=msgReceived.substring((firstLocation+1),lastLocation); msgReceived=msgReceived.substring((lastLocation+1)); if(sendGamePeerMsg(peerName,msgReceived)) { Feedback("/error"); } } elseif(msgReceived.startsWith("/giveup")) {//收到的信息为放弃游戏时 StringchessClientName=msgReceived.substring(8); if(chessPeerHash.containsKey(chessClientName) &&!((String)chessPeerHash.get(chessClientName)) .equals("wait")) {//胜利方为游戏加入者,发送胜利信息 sendGamePeerMsg((String)chessPeerHash.get(chessClientName), "/youwin"); synchronized(chessPeerHash) {//删除退出游戏的用户 chessPeerHash.remove(chessClientName); } } if(chessPeerHash.containsValue(chessClientName)) {//胜利方为游戏创建者,发送胜利信息 sendGamePeerMsg((String)getHashKey(chessPeerHash, chessClientName),"/youwin"); synchronized(chessPeerHash) {//删除退出游戏的用户 chessPeerHash.remove((String)getHashKey(chessPeerHash, chessClientName)); } } } else {//收到的信息为其它信息时 intlastLocation=msgReceived.indexOf("",0); if(lastLocation==-1) { Feedback("无效命令"); return; } } } else { msgReceived=clientNameHash.get(clientSocket)+">"+msgReceived; serverMsgPanel.msgTextArea.append(msgReceived+"\n"); sendPublicMsg(msgReceived); serverMsgPanel.msgTextArea.setCaretPosition(serverMsgPanel.msgTextArea.getText() .length()); } } //发送公开信息 publicvoidsendPublicMsg(StringpublicMsg) { synchronized(clientDataHash) { for(Enumerationenu=clientDataHash.elements();enu .hasMoreElements();) { DataOutputStreamoutputData=(DataOutputStream)enu.nextElement(); try { outputData.writeUTF(publicMsg); } catch(IOExceptiones) { es.printStackTrace(); } } } } //发送信息给指定的游戏中的用户 publicbooleansendGamePeerMsg(StringgamePeerTarget,StringgamePeerMsg) { for(Enumerationenu=clientDataHash.keys();enu.hasMoreElements();) {//遍历以取得游戏中的用户的套接口 SocketuserClient=(Socket)enu.nextElement(); if(gamePeerTarget.equals((String)clientNameHash.get(userClient)) &&!gamePeerTarget.equals((String)clientNameHash .get(clientSocket))) {//找到要发送信息的用户时 synchronized(clientDataHash) { //建立输出流 DataOutputStreampeerOutData=(DataOutputStream)clientDataHash .get(userClient); try { //发送信息 peerOutData.writeUTF(gamePeerMsg); } catch(IOExceptiones) { es.printStackTrace(); } } returnfalse; } } returntrue; } //发送反馈信息给连接到主机的人 publicvoidFeedback(StringfeedBackMsg) { synchronized(clientDataHash) { DataOutputStreamoutputData=(DataOutputStream)clientDataHash .get(clientSocket); try { outputData.writeUTF(feedBackMsg); } catch(Exceptioneb) { eb.printStackTrace(); } } } //取得用户列表 publicStringgetUserList() { StringuserList="/userlist"; for(Enumerationenu=clientNameHash.elements();enu.hasMoreElements();) { userList=userList+""+(String)enu.nextElement(); } returnuserList; } //根据value值从Hashtable中取得相应的key publicObjectgetHashKey(HashtabletargetHash,ObjecthashValue) { ObjecthashKey; for(Enumerationenu=targetHash.keys();enu.hasMoreElements();) { hashKey=(Object)enu.nextElement(); if(hashValue.equals((Object)targetHash.get(hashKey))) returnhashKey; } returnnull; } //刚连接到主机时执行的方法 publicvoidsendInitMsg() { sendPublicMsg(getUserList()); Feedback("/yourname"+(String)clientNameHash.get(clientSocket)); Feedback("Java五子棋客户端"); Feedback("/list--更新用户列表"); Feedback("/<username><talk>--私聊"); Feedback("注意:命令必须对所有用户发送"); } publicvoidcloseClient() { serverMsgPanel.msgTextArea.append("用户断开连接:"+clientSocket+"\n"); synchronized(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.get(clientSocket)), "tobeclosed"); } } synchronized(clientDataHash) {//删除客户数据 clientDataHash.remove(clientSocket); } synchronized(clientNameHash) {//删除客户数据 clientNameHash.remove(clientSocket); } sendPublicMsg(getUserList()); serverMsgPanel.statusLabel.setText("当前连接数:"+clientDataHash.size()); try { clientSocket.close(); } catch(IOExceptionexx) { exx.printStackTrace(); } isClientClosed=true; } publicvoidrun() { DataInputStreaminputData; synchronized(clientDataHash) { serverMsgPanel.statusLabel.setText("当前连接数:"+clientDataHash.size()); } try { //等待连接到主机的信息 inputData=newDataInputStream(clientSocket.getInputStream()); sendInitMsg(); while(true) { Stringmessage=inputData.readUTF(); dealWithMsg(message); } } catch(IOExceptionesx){} finally { if(!isClientClosed) { closeClient(); } } }}客户端packagecom.dikey.client;importjava.awt.*;importjava.awt.event.*;importjava.io.*;import.*;importjavax.swing.JTextField;publicclassWuZiQiPadextendsPanelimplementsMouseListener,ActionListener{ //鼠标是否能使用 publicbooleanisMouseEnabled=false; //是否胜利 publicbooleanisWinned=false; //是否在下棋中 publicbooleanisGaming=false; //棋子的x轴坐标位 publicintchessX_POS=-1; //棋子的y轴坐标位 publicintchessY_POS=-1; //棋子的颜色 publicintchessColor=1; //黑棋x轴坐标位数组 publicintchessBlack_XPOS[]=newint[200]; //黑棋y轴坐标位数组 publicintchessBlack_YPOS[]=newint[200]; //白棋x轴坐标位数组 publicintchessWhite_XPOS[]=newint[200]; //白棋y轴坐标位数组 publicintchessWhite_YPOS[]=newint[200]; //黑棋数量 publicintchessBlackCount=0; //白棋数量 publicintchessWhiteCount=0; //黑棋获胜次数 publicintchessBlackVicTimes=0; //白棋获胜次数 publicintchessWhiteVicTimes=0; //套接口 publicSocketchessSocket; publicDataInputStreaminputData; publicDataOutputStreamoutputData; publicStringchessSelfName=null; publicStringchessPeerName=null; publicStringhost=null; publicintport=4331; publicTextFieldstatusText=newTextField("请连接服务器!"); publicWuZiQiThreadfirThread=newWuZiQiThread(this); publicWuZiQiPad() { setSize(540,540); setLayout(null); setBackground(Color.pink); addMouseListener(this); add(statusText); statusText.setBounds(newRectangle(40,5,360,24)); statusText.setEditable(false); } //连接到主机 publicbooleanconnectServer(StringServerIP,intServerPort)throwsException { try { //取得主机端口 chessSocket=newSocket(ServerIP,ServerPort); //取得输入流 inputData=newDataInputStream(chessSocket.getInputStream()); //取得输出流 outputData=newDataOutputStream(chessSocket.getOutputStream()); firThread.start(); returntrue; } catch(IOExceptionex) { statusText.setText("连接失败!\n"); } returnfalse; } //设定胜利时的棋盘状态 publicvoidsetVicStatus(intvicChessColor) { //清空棋盘 this.removeAll(); //将黑棋的位置设置到零点 for(inti=0;i<=chessBlackCount;i++) { chessBlack_XPOS[i]=0; chessBlack_YPOS[i]=0; } //将白棋的位置设置到零点 for(inti=0;i<=chessWhiteCount;i++) { chessWhite_XPOS[i]=0; chessWhite_YPOS[i]=0; } //清空棋盘上的黑棋数 chessBlackCount=0; //清空棋盘上的白棋数 chessWhiteCount=0; add(statusText); statusText.setBounds(40,5,360,24); if(vicChessColor==1) {//黑棋胜 chessBlackVicTimes++; statusText.setText("黑方胜,黑:白"+chessBlackVicTimes+":"+chessWhiteVicTimes +",游戏重启,等待白方..."); } elseif(vicChessColor==-1) {//白棋胜 chessWhiteVicTimes++; statusText.setText("白方胜,黑:白"+chessBlackVicTimes+":"+chessWhiteVicTimes +",游戏重启,等待黑方..."); } } //取得指定棋子的位置 publicvoidsetLocation(intxPos,intyPos,intchessColor) { if(chessColor==1) {//棋子为黑棋时 chessBlack_XPOS[chessBlackCount]=xPos*20; chessBlack_YPOS[chessBlackCount]=yPos*20; chessBlackCount++; } elseif(chessColor==-1) {//棋子为白棋时 chessWhite_XPOS[chessWhiteCount]=xPos*20; chessWhite_YPOS[chessWhiteCount]=yPos*20; chessWhiteCount++; } } //判断当前状态是否为胜利状态 publicbooleancheckVicStatus(intxPos,intyPos,intchessColor) { intchessLinkedCount=1;//连接棋子数 intchessLinkedCompare=1;//用于比较是否要继续遍历一个棋子的相邻网格 intchessToCompareIndex=0;//要比较的棋子在数组中的索引位置 intcloseGrid=1;//相邻网格的位置 if(chessColor==1) {//黑棋时 chessLinkedCount=1;//将该棋子自身算入的话,初始连接数为1 //以下每对for循环语句为一组,因为下期的位置能位于中间而非两端 for(closeGrid=1;closeGrid<=4;closeGrid++) {//遍历相邻4个网格 for(chessToCompareIndex=0;chessToCompareIndex<=chessBlackCount;chessToCompareIndex++) {//遍历棋盘上所有黑棋子 if(((xPos+closeGrid)*20==chessBlack_XPOS[chessToCompareIndex]) &&((yPos*20)==chessBlack_YPOS[chessToCompareIndex])) {//判断当前下的棋子的右边4个棋子是否都为黑棋 chessLinkedCount=chessLinkedCount+1;//连接数加1 if(chessLinkedCount==5) {//五子相连时,胜利 returntrue; } } } if(chessLinkedCount==(chessLinkedCompare+1)){ chessLinkedCompare++; } else{//若中间有一个棋子非黑棋,则会进入此分支,此时无需再遍历 break; } } for(closeGrid=1;closeGrid<=4;closeGrid++) { for(chessToCompareIndex=0;chessToCompareIndex<=chessBlackCount;chessToCompareIndex++) { if(((xPos-closeGrid)*20==chessBlack_XPOS[chessToCompareIndex]) &&(yPos*20==chessBlack_YPOS[chessToCompareIndex])) {//判断当前下的棋子的左边4个棋子是否都为黑棋 chessLinkedCount++; if(chessLinkedCount==5) { returntrue; } } } if(chessLinkedCount==(chessLinkedCompare+1)){ chessLinkedCompare++; } else{ break; } } //进入新的一组for循环时要将连接数等重置 chessLinkedCount=1; chessLinkedCompare=1; for(closeGrid=1;closeGrid<=4;closeGrid++) { for(chessToCompareIndex=0;chessToCompareIndex<=chessBlackCount;chessToCompareIndex++) { if((xPos*20==chessBlack_XPOS[chessToCompareIndex]) &&((yPos+closeGrid)*20==chessBlack_YPOS[chessToCompareIndex])) {//判断当前下的棋子的上边4个棋子是否都为黑棋 chessLinkedCount++; if(chessLinkedCount==5) { returntrue; } } } if(chessLinkedCount==(chessLinkedCompare+1)){ chessLinkedCompare++; } else{ break; } } for(closeGrid=1;closeGrid<=4;closeGrid++) { for(chessToCompareIndex=0;chessToCompareIndex<=chessBlackCount;chessToCompareIndex++) { if((xPos*20==chessBlack_XPOS[chessToCompareIndex]) &&((yPos-closeGrid)*20==chessBlack_YPOS[chessToCompareIndex])) {//判断当前下的棋子的下边4个棋子是否都为黑棋 chessLinkedCount++; if(chessLinkedCount==5) { returntrue; } } } if(chessLinkedCount==(chessLinkedCompare+1)){ chessLinkedCompare++; } else{ break; } } chessLinkedCount=1; chessLinkedCompare=1; for(closeGrid=1;closeGrid<=4;closeGrid++) { for(chessToCompareIndex=0;chessToCompareIndex<=chessBlackCount;chessToCompareIndex++) { if(((xPos-closeGrid)*20==chessBlack_XPOS[chessToCompareIndex]) &&((yPos+closeGrid)*20==chessBlack_YPOS[chessToCompareIndex])) {//判断当前下的棋子的左上方向4个棋子是否都为黑棋 chessLinkedCount++; if(chessLinkedCount==5) { returntrue; } } } if(chessLinkedCount==(chessLinkedCompare+1)){ chessLinkedCompare++; } else{ break; } } for(closeGrid=1;closeGrid<=4;closeGrid++) { for(chessToCompareIndex=0;chessToCompareIndex<=chessBlackCount;chessToCompareIndex++) { if(((xPos+closeGrid)*20==chessBlack_XPOS[chessToCompareIndex]) &&((yPos-closeGrid)*20==chessBlack_YPOS[chessToCompareIndex])) {//判断当前下的棋子的右下方向4个棋子是否都为黑棋 chessLinkedCount++; if(chessLinkedCount==5) { returntrue; } } } if(chessLinkedCount==(chessLinkedCompare+1)){ chessLinkedCompare++; } else{ break; } } chessLinkedCount=1; chessLinkedCompare=1; for(closeGrid=1;closeGrid<=4;closeGrid++) { for(chessToCompareIndex=0;chessToCompareIndex<=chessBlackCount;chessToCompareIndex++) { if(((xPos+closeGrid)*20==chessBlack_XPOS[chessToCompareIndex]) &&((yPos+closeGrid)*20==chessBlack_YPOS[chessToCompareIndex])) {//判断当前下的棋子的右上方向4个棋子是否都为黑棋 chessLinkedCount++;

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论