局域网的象棋对战

说 明

本系统是一款基于Eclipse平台开发的局域网象棋对战游戏,采用Java GUI技术绘制界面,面向连接的Socket实现局域网联机,多线程同步用户信息数据。

系统分为服务器端和客户端,服务器端起到处理用户联网信息并转发数据的作用,客户端主要实现象棋对弈。

该象棋游戏界面友好,操作方便,能满足广大象棋爱好者的日常对弈需求。

目录

摘要................................................................ I Abstract........................................................... II

1引言 .............................................................. 1

1.1课题背景 ...................................................... 1

1.2中国象棋发展现状 .............................................. 1

2 开发环境与相关技术................................................ 1

2.1 Java语言 ..................................................... 1

2.2 开发工具 ...................................................... 2

2.3 技术 ........................................................ 3

2.3.1 面向对象设计 .............................................. 3

2.3.2 Java GUI技术 ............................................. 3

2.3.3 JAVA多线程技术 ........................................... 5

2.3.4 点对点通信 ................................................ 6

2.3.5 TCP/IP协议 ............................................... 7

3需求分析 .......................................................... 8

3.1 任务概述 ...................................................... 8

3.2 需求分析 ...................................................... 8

3.2.1 联机操作功能 .............................................. 8

3.2.2 象棋对弈功能 .............................................. 8

4总体设计 .......................................................... 9

4.1 系统结构图 .................................................... 9

4.2 类框架设计 .................................................... 9

4.2.1 服务器端 .................................................. 9

4.2.2 客户端 ................................................... 10

4.3 需要解决的问题 ............................................... 11

5系统实现 ......................................................... 13

5.1 棋盘设计 ..................................................... 13

5.2 规则制定 ..................................................... 16

5.2.1 规则说明 ................................................. 16

5.2.2 规则算法 ................................................. 17

6运行测试 ......................................................... 23

6.1 服务端 ....................................................... 23

6.2 客户端 ....................................................... 24

7 总结............................................................. 27

致谢............................................................... 27

参考文献........................................................... 27

基于局域网的中国象棋游戏

摘要:中国象棋具有悠久的历史。战国时期,已经有了关于象棋的正式记载,新中国建立之后,象棋进入了一个崭新的发展阶段。随着信息技术的发展,人民生活水平的不断提高。联网游戏作为一种娱乐手段,正以其独特的魅力吸引着越来越多的玩家。

为了满足广大象棋爱好者也可以享受到网络所带来的便利,本设计在当前局域网条件下实现了中国象棋的网络对战。鉴于局域网的特点和游戏本身的要求,本设计采用C/S架构来实现相互之间的通信。它主要包含以下几大模块:网络通信模块,图像绘制模块和规则设置模块。网络通信模块使得玩家之间可以方便迅速的建立起网络连接,从而实现联机对弈功能;图像绘制模块实现棋盘更新以及棋子动态表示等功能;规则设置模块用于约束玩家的走棋。在系统中我负责象棋部分的功能。

电脑游戏是计算机应用领域的一个重要主题,而当前网上最热门的休闲对战类游戏当属棋牌游戏。通过对象棋的数据结构,相关算法与网络联机,以及对网络对战平台系统的分析,设计成一套基于Java平台的棋牌类对战系统。

关键字:网络通信;联机对弈;图像绘制

Chinese chess game on LAN

Abstract:The Chinese chess has a long history. In the Warring States Period, there was a formal record about the chess already. After new China set up, the chess has entered a brand-new developing stage. With the development of information technology, peoples standard of living have improved constantly. On-line game as a means of entertainment has a unique charm to attract more and more players.

To meet chess lovers, this design has realized the Challenges of Chinese-chess between players under the current LAN environment. In view of the characteristics of local area networks and the requirements of the game itself, the design uses a two-tier C/S structure to achieve mutual communication. It contains the following major modules: the network communication module, image rendering module and the rules set up module. Network Communication Module allows gamers can quickly set up a convenient network connection in order to achieve an online game; image rendering module to update the board as well as functional pieces, such as the dynamic that; rules binding settings module for step-by-step player's game. I am responsible for chess part of the function in System.

Computer games is the field of computer applications as an important subject, and present the most popular casual online games war among board games. By the data structure, algorithms and network online, as well as the network platform for systematic analysis of the war, designed a set of Java platform based on the category Card battle system.

KeyWords: Network Communication; Online game; Image Rendering

1引言

1.1课题背景

中国象棋有着悠久的历史,通俗易懂,老少皆益;20世纪是信息的时代,随着计算机技术和经济的发展,计算机由商业逐渐走向家庭。象棋水平的发展是需要靠信息技术来推动的,国际象棋就是个很好的范例。然而,电脑在中国象棋上的运用还刚刚起步,尽管国内涌现出一大批中国象棋的专业网站和专业软件,但是由于缺乏必要的基础工作,电脑技术在中国象棋上的应用优势还无法体现出来。如果可以编译一种软件,方便象棋爱好者之间进行对弈,那对象棋的发展定会有推进作用。当前各种开发语言中,JAVA以自己的跨平台操作,简单,可移植性,面向对象,以接口实现多线程,动态等优点为大多人青睐。因此我选择了Java作为象棋对弈软件的开发语言。

1.2中国象棋发展现状

中国象棋发展至今已有二千三、四百年的历史了,早在战国时期就有正式记载,堪称中国的国粹。据统计,中国有2亿人会下象棋,这相当于平均6至7个人中就有1人会下,可见它有着广泛的群众基础。方寸之间包含天地玄机,人生哲理,使人越是细玩越觉其味悠然深远。简单的棋规,便捷的载体,使得他成为雅俗共赏的竞技项目。然而,如今中国象棋的发展前景却令人堪忧。导致这种现象的主要因素有:第一,就东亚地区,围棋的影响力胜于中国象棋。第二,中国象棋虽然在国内很受欢迎,但在世界舞台上名声却不如国际象棋那么响亮。之所以会存在这两个因素,都是因为在国际赛事上中国象棋的参赛选手大都是华人,而非华裔的选手又大都是业余选手,这无疑使比赛失去了竞争力,而围棋有韩国和日本的参与,国际象棋有全世界国家的加入。第三,进入了21世纪后,供人们娱乐活动的选择越来越多,中国象棋在年轻人的心中已开始渐渐失去魅力。

随着信息技术的不断发展,各种象棋软件的开发与应用应运而生,尤其是在网络方面的推广,使得中国象棋得到了很好的宣传,全面展示了中国象棋的风采、优点与特色,同时也让外国人认识到中国象棋这一我国的 “国粹”。想必在未来的几年随着中国象棋在各个领域的推广,必定会带来巨大的影响。

2 开发环境与相关技术

2.1 语言

Java是一种跨平台,适合于分布式计算环境的面向对象编程语言。其主要特点有:

(1) 平台无关性

平台无关性就是指 Java能运行于不同的平台。Java引进虚拟机原理,并运行于虚拟机,实现不同平台的Java接口之间。使用Java编写的程序能在世界范围内共享。Java的数据类型与机器无关,Java虚拟机(Java Virtual Machine)是建立在硬件和操作系统之上,实现 Java代码的解释执行功能,提供不同平台的接口。

(2) 安全性

Java的编程类似于C++,学习过C++的读者将很快能掌握Java的精髓。Java舍弃了C++

的指针对存储器地址的直接操作,程序运行时,内存由操作系统分配,这样可以避免病毒通过指针侵入系统。Java对程序提供了安全管理器,防止程序的非法访问。

(3) 面向对象

Java吸取了C++面向对象的概念,将数据封装的简洁性和便于维护性。类的封装性、继承性等有关对象的特性,使程序代码只需一次编译,然后通过上述特性到达反复利用。Java提供了众多的一般对象的类,通过继承即可使用父类的方法。

Java已有的类的功能强大,如输入输出类,进行普通输入输出和文件设计图形界面的常用部件,图形用户界面的设计上给程序员很大的方便。

(4) 简单性

Java舍弃C++的头文件,没有全局变量,这样能更好维护头文件,符合网络编程的要求。头文件中有全局变量的定义,这对可维护性和安全性都是不可取的。Java舍弃了C++的多重继承,引进了垃圾管理,避免在垃圾回收这一问题绞尽脑汁去设计。

(5) 多线程

多线程是Java的一大特点,能够在程序中实现多任务操作。传统的程序设计语言的程序只能单任务操作,效率非常低,例如程序往往在接收数据输入时被阻塞,只有等到程序获得数据后才能够继续运行。而多线程程序可以创建一个线程来进行输入输出操作,创建另一个线程在后台进行数据处理,输入输出的线程在接收数据时阻塞,而另一个线程仍然在运行。这样,多线程程序大大提高了运行的效率和处理能力。

2.2 工具

Eclipse是一个开放源代码的、基于 Java 的可扩展开发平台。就其本身而言,它只是一个框架和一组服务,用于通过插件组件构建开发环境。幸运的是,Eclipse 附带了一个标准的插件集,包括 Java 开发工具(Java Development Tools,JDT)。

虽然大多数用户很乐于将 Eclipse 当作Java IDE来使用,但Eclipse的目标不仅限于此。Eclipse还包括插件开发环境(Plug-in Development Environment,PDE),这个组件主要针对希望扩展Eclipse的软件开发人员,因为它允许他们构建与Eclipse环境无缝集成的工具。由于Eclipse中的每样东西都是插件,对于给Eclipse提供插件,以及给用户提供一致和统一的集成开发环境而言,所有工具开发人员都具有同等的发挥场所。

这种平等和一致性并不仅限于Java开发工具。尽管Eclipse是使用Java语言开发的,但它的用途并不限于Java语言;例如,支持诸如C/C++、COBOL和Eiffel等编程语言的插件已经可用,或预计会推出。Eclipse框架还可用来作为与软件开发无关的其他应用程序类型的基础,比如内容管理系统。

基于Eclipse的应用程序的突出例子是IBM的WebSphere Studio Workbench,它构成了 IBM Java开发工具系列的基础。例如,WebSphere Studio Application Developer添加了对JSP、servlet、EJB、XML、Web服务和数据库访问的支持。

Eclipse最初由OTI和IBM两家公司的IDE产品开发组创建,起始于1999年4月。IBM提供了最初的Eclipse代码基础,包括Platform、JDT和PDE。目前由IBM牵头,围绕着Eclipse项目已经发展成为了一个庞大的Eclipse联盟,有150多家软件公司参与到Eclipse项目中,其中包括Borland、Rational Software、Red Hat及Sybase等。

Eclipse是一个开发源码项目,它其实是Visual Age for Java的替代品,其界面跟先前的Visual Age for Java差不多,但由于其开放源码,任何人都可以免费得到,并可以在此基础上开发各自的插件,因此越来越受人们关注。近期还有包括Oracle在内的许多大公司也纷纷加入了该项目,并宣称Eclipse将来能成为可进行任何语言开发的IDE集大成者,使用者只需下载各种语言的插件即可。

2.3 技术

2.3.1 面向对象设计

面向对象的程序设计(简称OOP)是一种目前比较提倡的程序设计方法。它的基本思想是把定义的数据集对数据的相关操作包装成一个新的类型即对象(Object)。

面向对象方法的基本观点是:客观世界是由对象组成的,每个对象都有自己的内部状态和运动规律,不同对象彼此之间通过消息相互联系和相互作用。软件结构应该与所要解决的问题一致,而不是与某种方法一致。面向对象方法强调的是对客观世界的洞察力,而洞察力不但取决于所用的方法,更依赖知识和经验的积累。

面向对象程序设计方法模拟人类习惯的解题方法,用对象分解取代功能分解,也就是把程序分解成许多对象,不同对象之间通过发送消息向对方提出服务请求,接受消息的对象主动完成指定功能,程序中的所有对象分工协作,共同完成整个程序的功能。面向对象程序设计方法的提出,是对软件开发的一场革命,它代表了计算机程序设计的新颖思维的方法,是目前解决软件开发面临的困难的最有希望、最有前途的方法之一。

2.3.2 Java GUI技术

AWT(Abstract Window Tools),抽象窗口工具类。

GUI(Graphic User Interface),图形化的用户接口。

构造图形界面的步骤:

(1) 选择一个容器

(2) 设置容器的布局管理器

(3) 向容器添加组件

(4) 事件的监听

容器(Container):用于管理其他的组件的对象,组件必须放到容器里。

JFrame,这是一个最顶层的窗体容器,所有其他的组件必须放在顶层容器里。

JDialog,对话框容器,他要依附于其父组件,他不是一个顶层容器。

JPanel,他不是顶层容器,必须放在顶层容器中,任何一个容器都有add()方法,Panel面板是透明的(默认)。

布局管理器:

FlowLayout,流式布局管。Panel的默认布局管理就是FlowLayout。

BorderLayout,按方位进行布局管理,(North,South,East,West,Center)不明确指定,就会默认加载在中间(Center),add(Component comp,String place)这个方法是在指定的位置添加组件。

GridLayout,网格布局,通过行列、间距,来用网格分割,把组件放入网格中,先行后列摆放组件。

CardLayout,卡片布局,面板重叠放置。

GridBogLayout,组件可以跨行跨列的网格布局。

组件:

JButton :按钮 JTextField:单行文本域

JTextArea:多行文本区 JScrollPane:滚动窗体

JComboBox:下拉选择框 RadioButton:单选按钮

JCheckBox:多选按钮 JLabel:标签

JPasswordField:密码输入框 JMenuBar:菜单条

JMenu:菜单 JMenuItem:菜单项

JPopupMenu:弹出式菜单 JSlider:滑动条

JSplitPane:分隔面板 JFileChooser:文件选择器

JColorChooser:颜色选择器

事件的监听----模型

事件对象

事件源————————〉事件处理者

图2-1事件监听模型

这就是事件模型的机制(图2-1),也就是由事件源对象发送一个消息(事件对象),然后事件处理者调用相应的方法处理事件。

事件对象继承自EventObject类,并可以通过getSource()方法获得事件源对象,当然需要在构造事件对象时将事件源对象传入,来区分是哪个事件源发出的事件,所以要用事件对象作为参数。

在Java的图形编程中,所有动作(事件)都已经提供了相应的事件对象和事件监听接口,例如:实现窗口的关闭按钮,点击关闭按钮会发出相应的事件对象,相应的调用监听器中实现好的方法。

自定义组件监听器如图2-2:

Button=new Button("close")

Button.addActionListener(this)

条目监听器如图2-3:

图2-2 自定义组件监听器 图2-3 条目监听器

鼠标监听器如图2-4:

图2-4 鼠标监听器

窗口监听器如图2-5:

2.3.3 JAVA多线程技术

关于线程的几个概念: 图2-5 窗口监听器

进程:正在执行的一个独立的程序,对于单CPU来说,进程在宏观上是并发的,但在微观上是串发的。

线程:在一个进程内部的“可以并发执行的多个函数”,一个进程中可有多个线程。 对于进程,每一个进程都是独占数据空间的,(是一个程序的执行流程)。而对于线程,它生活在进程内部,它们共享进程空间,线程是由操作系统(OS)来维护的。

线程三要素:CPU资源,执行代码Code,数据存储空间Data。

在JAVA中,来创建一个线程有两种方式可以选取择:

一种方法是将类声明为 Thread 的子类。该子类应重写 Thread 类的 run 方法。

如: class ThreadA extends Thread {

} Private String name; Public ThreadA(String name) { this.name = name; } Public void run() { } //具体的代码

使用:

Thread a = new ThreadA(a); //创建一个线程

a.start();//启动一个线程

创建线程的另一种方法是声明实现 Runnable 接口的类。该类然后实现 run 方法。然后可以分配该类的实例,在创建 Thread 时作为一个参数来传递。

如: class ThreadB implements Runnable {

. . . .

} Public void run() { } //具体的代码

使用:

Runnable r = new ThreadB(); //创建一个Runnable的实例 r

Thread b = new Thread(r); //使用一个Runnable的实例来创建一个线程b

b.start(); //启动一个线程

实现Runnable 接口的类不是一个线程类,只能是用它去构造一个线程对象。 在JAVA中,线程也是一个类(Thread),实际的线程就是一个对象。

线程状态转换,如图2-6所示:

对象对象

图2-6 线程状态转换

2.3.4 点对点通信

从OSI参考模型的应用层来看,可认为网络是由工作站和服务器组成的,但从传输层和网络层的角度看,工作站和服务器没有本质的区别,它们都是连接到网络上的一台机器,都可以用网络地址或名称来代替。它们之间的通信就是所谓的点对点通信,也叫对等通信。在局域网上,点点通信意味着两个工作站可以直接对话而不用经过文件服务器中转。

通信的基础是套接口(Socket),一个套接口是通讯的一端。socket通常也称作“套接字”,用于描述IP地址和端口,是一个通信链的句柄。应用程序通常通过“套接字”向网络发出请求或者应答网络请求。

Socket实质上提供了进程通信的端点。进程通信之前,双方首先必须各自创建一个端点,

否则是没有办法建立联系并相互通信的。正如打电话之前,双方必须各自拥有一台电话机一样。在网间网内部,每一个socket用一个半相关描述(协议,本地地址,本地端口)。一个完整的socket有一个本地唯一的socket号,由系统分配。最重要的是,socket是面向客户/服务器模型而设计的,针对客户和服务器程序提供不同的socket系统调用。客户随机申请一个socket(相当于一个想打电话的人可以在任何一台入网电话上拨号呼叫),系统为之分配一个socket号;服务器拥有全局公认的socket,任何客户都可以向它发出连接请求和信息请求(相当于一个被呼叫的电话拥有一个呼叫方知道的电话号码)。socket利用客户/服务器模式巧妙地解决了进程之间建立通信连接的问题。

服务器socket半相关为全局所公认非常重要。假如通信双方没有任何一方的socket固定,就好比打电话的双方彼此不知道对方的电话号码,要通话是不可能。在这一端上你可以找到与其对应的一个名字,一个正在被使用的套接口都有它的类型和与其相关的进程。套接口存在于通讯域中。通讯域是为了处理一般的线程通过套接口通讯而引进的一种抽象概念。套接口通常和同一个域中的套接口交换数据(数据交换也可能穿越域的界限,但这时一定要执行某种解释程序)。Windows Sockets规范支持单一的通讯域,即Internet域。各种进程使用这个域互相之间用Internet协议来进行通讯。

局域网中工作站之间的通信程序的开发一般通过四种途径:第一种是通过改造网络原有通信软件来实现。但这种改造必须以对该软件充分了解为基础,否则改造后很难保证不影响网络的整体性能,甚至会造成系统运行不可靠,而改造后的通信质量不一定理想。第二种是利用Novell网本身的网络协议IPX/SPX来实现,由于这种方法开发比较麻烦,采用的并不多。第三种是通过NetBIOS功能调用来实现,NetBIOS是PC LAN的通信接口标准,广泛适用于多种微机网络,使得以它为基础的设计和应用开发可移植性好。它不依赖于任何网络硬件,是一个介于网络硬件和用户应用程序之间的接口协议。其通信原理是:两个要进行通信的工作站通过名字建立一个虚电路,然后向相应的虚电路号发送或接收信息,这样通过虚电路实现了两个工作站之间的对等通信。利用NetBIOS实现工作站之间的实时通信,功能比较强,编程实现比较容易,所以应用比较广泛。第四种是通过TCP/IP协议来实现。

2.3.5 TCP/IP协议

TCP协议(Transmission Control Protocol 传输控制协议)是一种流传输控制协议,它提供可靠的、有序的、双向的、面向连接的数据传输,是一种面向连接的协议。

TCP协议是一种端对端的协议,使用TCP没有任何广播或类似的概念,要用TCP协议与另一台计算机通信,两台机之间必须像打电话一样连接在一起,每一端都为通话做好准备。

TCP协议每发送一个数据包都将会收到一个确认信息,这种发送/应答模式是提供可靠的协议的唯一方法:你必须让对方知道你是否收到了数据。当然,这也会造成一些性能损失,人们为了改善系统效率不高的状况,引入了“捎带确认(piggybacking)”的方法。TCP协议之所以是全双工的就是因为这个“捎带确认”信息,因为它允许双方同时发送数据。这是通过在当前的数据包中携带以前收到的数据的确认信息方式实现的,从提高网络利用率的角度看,这比单纯发送一个通知对方“信息已收到”的数据包要好得多。最后,还有一个批量确认的概念:即一次确认一个以上的数据包,表示“我收到了包括这个数据包在内的全部数据包”。

在IP协议中,我们处理的单个数据包是一个更大的数据报的一部分,一个TCP段就是一个单个的TCP数据包。TCP是一个数据流,因此,除了“连接”之外,没有任何需要真正担心的其它概念。最大报文段长度(MSS)是在连接的时候协商的,但是,它总是在不断地改变。默认的最大报文段长度是536字节,这是576字节(IP协议保证的最小数据包长度)减去用于IP头的20个字节和用于TCP头的20个字节以后的长度。TCP协议要设法避免在IP级别上的分段。因此,TCP协议总是从536字节开始的。TCP/IP协议的核心部分是传输层协议(TCP、UDP),网络层协议(IP)和物理接口层,这三层通常是在操作系统内核中实现。因此用户一般不涉及,编程时,编程界面有两种形式:一、是由内核直接提供的系统调用;二、使用以库函数方式提供的各种函数。前者为核内实现,后者为核外实现。用户服务要通过核外的应用程序才能实现,所以要使用套接字(socket)来实现。

3需求分析

3.1 任务概述

中国象棋具有悠久的历史,象棋的爱好者更是数不胜数,远在战国时代,象棋便在贵族阶层中广为流传,早期的象棋是象征着当时战斗场面的游戏,后来这种观念慢慢改变,成为人们休闲娱乐中不可缺少的一部分。而如今的人们忙于工作,很少有时间静下心来享受象棋对弈的乐趣,因此电脑版象棋、手机版象棋便开始受到人们的关注。

基于局域网的象棋游戏,可以极大的方便玩家快速建立并进入一个象棋的对弈平台,玩家通过对走棋的思考和对全局的掌控,在游戏之余,又可以锻炼思考和判断的能力,可谓一种很好的寓教于乐方式。同时象棋对弈过程需要玩家耐心的操作,其观察力,耐心、专注力都有很好的培养,此外,通过与高水平玩家的对战,可以提高自己的技术,在思考中不断提高自己。

3.2 需求分析 3.2.1 联机操作功能

由于基于Java平台的局域网联机对战游戏,联机功能自然是重中之重,必须要有服务器作为支持。当服务器启动之后,客户端连接到服务器,服务器接受并处理来至客户端的操作信息,经过相应判断和处理后,选择性的向客户端发送相应的反馈消息,保证信息传输的正确性,可靠性。

3.2.2 象棋对弈功能

当两个客户端通过局域网连接到一起之后,双方将进行象棋对弈。由于基于PC来实现游戏客户端,所以游戏是通过鼠标点击来进行,鼠标点击选中棋子,然后点击该棋子需要移动的目标位置。象棋具有其特有的规则,为了保证游戏能够按照正确的规则进行下去,必须要在客户端对玩家的着子点进行合法性判断,只有符合一定规则的走棋才能够实现,并且通过服务器传输给对方玩家。同时,客户端程序需要对棋局的胜负进行判断,当一方胜利后给出胜利提示信息。

4总体设计

4.1 功能结构图

图4-1系统结构图

服务器端:指定端口号,启动服务器后等待客户端的连接,若没有客户连接,则一直处于等待状态。待客户端连接到服务器端,则显示在线的用户列表,若客户端发送信息过来,服务器经过相应的处理后转发给相应的客户端。 客户端:启动客户端后指定统一的主机IP地址,以确定同一服务器。然后输入自己的昵称和端口号,便可以选择想挑战的在线用户进行对弈。

4.2 类结构设计 4.2.1 服务器端

服务器端类图设计如图4-2所示。

4-2 服务器端类图

Server类:实现服务器端界面初始化,各个按钮的相应操作。 ServerThread类:用于接收客户端的连接,并为每一个连接分配一个服务器代理线程。 ServerAgentThread:主要用于接收客户端传来的信息,并将该信息转发给对应的另一客户端。服务器为所有客户端都分配了一个该类线程实例,单独为特定客户端进行服务。同时每一个服务器代理线程都有能惟一标识其的名称。

4.2.2 客户端

客户端类图设计如图4-3所示。

4-3 客户端类图

QiPan类:棋盘类除了完成绘制棋盘的作用,同时还负责下棋逻辑的处理。 GuiZe类:定义象棋走棋规则。

ClientAgentThread类:要用于接收服务器传来的消息,并根据不同的消息进行相应的业QiZi类:用于定义象棋的基本属性。

XiangQi类:初始化客户端组件,让用户通过运行该类连接服务器,并通过在该类的窗

务处理。

体中与其他玩家进行对弈。

4.3 需要解决的问题

服务器端要求:

(1)手动制定服务器端口号,并且端口号只能是0-65535的整数。 (2)可以支持多人同时在线,并实时刷新在线用户列表。 (3)玩家昵称不能同名,否则无法登陆。

客户端要求:

(1)通过设置主机IP及端口号登录到服务器。

(2)可以显示当前在线的其他用户。

(3)可以从在线用户列表中选择玩家进行去挑战。 (4)可以接受或拒绝挑战。

(5)如果对方正在与其他玩家对弈中,则应给出相应的提示信息。 (6)棋子样式采用最普通的象棋,即棋子黑色,字为红色和白色。 (7)棋盘界面初始化。

(8)棋子走棋规则,输赢判定。

以下内容为本人独立实现

5系统实现

5.1 棋盘设计

棋子活动的场所,叫作“棋盘”。在长方形的平面上,绘有九条平行的竖线和十条平行

的横线相交组成,共有九十个交叉点,棋子就摆在交叉点上。中间部分,也就是棋盘的第五,第六两横线之间末画竖线的空白地带称为“河界”。两端的中间,也就是两端第四条到第六条竖线之间的正方形部位,以斜交叉线构成“米”字方格的地方,叫作“九宫”(它恰好有九个交叉点)。

棋盘类主要作用为棋盘的绘制,选棋走棋的判断,吃棋的实现和以及胜负的判定等。 本系统中棋盘,棋子的绘制是通过锁定坐标,绘制相应线条实现,而非用图片加载的方(1) 棋盘绘制

式得到。棋盘绘制在程序中表现为调用QiPan类中paint()方法,首先是绘制一个矩形框架,然后分别绘制9 × 10网格线,最后在棋盘中间写入“楚河汉界”四字。 public void paint(Graphics g1) {

Graphics2D g = (Graphics2D) g1;// 获得Graphics2D对象 g.setRenderingHint(RenderingHints.KEY_ANTIALIASING,

RenderingHints.VALUE_ANTIALIAS_ON);// 打开抗锯齿

Color c = g.getColor();// 获得画笔颜色

g.setColor(XiangQi.bgColor);// 将画笔设为背景色 g.fill3DRect(60, 30, 580, 630, false);// 绘制一个矩形棋盘 g.setColor(Color.black);// 画笔颜色设为黑 }

g.drawLine(110, 80, 110, 620);// 绘制左边界线 g.drawLine(590, 80, 590, 620);// 绘制右线

g.drawLine(i, 80, i, 320);//上面部分 g.drawLine(i, 380, i, 620);//下面部分

for (int i = 110; i

g.drawLine(110, i, 590, i);

for (int i = 80; i

}

g.drawLine(290, 80, 410, 200);// 绘制两边的斜线 g.drawLine(290, 200, 410, 80); g.drawLine(290, 500, 410, 620); g.drawLine(290, 620, 410, 500); g.setColor(Color.black); g.setFont(font1);

Font font1 = new Font("宋体", Font.BOLD, 50);// 设置字体 g.drawString("楚 河", 170, 365);// 绘制楚河汉界

g.drawString("漢 界", 400, 365); g.setFont(font);// 设置字体 }

Font font = new Font("宋体", Font.BOLD, 30);

以上代码执行之后棋盘初步模型便已完成,接下来调用smallLine()方法对棋盘上的

public void smallLine(Graphics2D g, int i, int j) { int x = 110 + 60 * i;// 计算坐标 int y = 80 + 60 * j;

if (i > 0) {// 绘制左上方的标志 g.drawLine(x - 3, y - 3, x - 20, y - 3); }

if (i

if (i > 0) {// 绘制左下方的标志 g.drawLine(x - 3, y + 3, x - 20, y + 3); }

if (i

g.drawLine(x + 3, y + 3, x + 3, y + 20); g.drawLine(x - 3, y + 3, x - 3, y + 20); g.drawLine(x + 3, y - 3, x + 3, y - 20); g.drawLine(x - 3, y - 3, x - 3, y - 20);

标记点进行绘制。

}

棋盘绘制完成之后就是棋子的绘制,该实现通过双重循环,调用fillOval()方法绘制

而成。

for (int i = 0; i

for (int j = 0; j

if (this.qiZi[i][j].getFocus() != false) {// 选中棋子

g.setColor(XiangQi.focusbg);// 选中后的背景色

g.fillOval(110 + i * 60 - 25, 80 + j * 60 - 25, 50,

状态

50);// 绘制该棋子起点(110,80)棋子半径(25)

g.setColor(XiangQi.focuschar);// 字符的颜色 } else {

g.fillOval(110 + i * 60 - 25, 80 + j * 60 - 25, 50,

50);// 绘制该棋子

g.setColor(qiZi[i][j].getColor());// 设置画笔颜色 }

g.drawString(qiZi[i][j].getName(), 110 + i * 60 - 15,

}

80 + j * 60 + 10);// 绘字

g.setColor(Color.black);// 设为黑色 }

(2) 选棋走棋的实现

在棋盘中,当玩家通过鼠标选择己方棋子在棋盘上走招或吃掉对方棋子,这一过程是通过getPos()方法和noFocus()方法实现的。前者获取鼠标在棋盘上点击的坐标位子,后者则是判断棋子归属以及对选中棋子的高亮处理。

pos[0] = Math.round((float) (x - 110)) / 60; // round()加0.5

取整

getPos()方法可以获得棋子的坐标,同时限制棋子只能是在棋盘中移动。

public int[] getPos(MouseEvent e) { // 获得事件发生坐标

int[] pos = new int[2];

pos[0] = -1; pos[1] = -1;

Point p = e.getPoint();// 获得事件发生的坐标点 double x = p.getX(); double y = p.getY();

if (Math.abs((x - 110) % 60)

} else if (Math.abs((x - 110) % 60) >= 35) { }

if (Math.abs((y - 80) % 60)

return pos;

pos[1] = Math.round((float) (y - 80)) / 60; pos[1] = Math.round((float) (y - 80)) / 60 + 1; pos[0] = Math.round((float) (x - 110)) / 60 + 1;

}

} else if (Math.abs((y - 80) % 60) >= 35) {

调用noFocus()方法判断玩家点击棋子是否为己方棋子,如果是则高亮显示。

public void noFocus(int i, int j) {// 判断棋子颜色并聚焦

if (this.qiZi[i][j] != null)// 如果该位置有棋子 {

if (this.xq.color == 0)// 如果是红方 {

if

(this.qiZi[i][j].getColor().equals(XiangQi.color1))// 如果棋子是红色 {

this.qiZi[i][j].setFocus(true);// 将该棋子设为选中状态 focus = true;// 将focus设为true startI = i;// 保存该坐标点

}

startJ = j;

} else// 如果是白方 {

if

(this.qiZi[i][j].getColor().equals(XiangQi.color2))// 如果该棋子是白色 {

}

}

}

}

this.qiZi[i][j].setFocus(true);// 将该棋子设为选中状态 focus = true;// 将focus设为true startI = i;// 保存该坐标点 startJ = j;

(3) 吃棋和胜负的判定

吃棋表现为一方棋占用另外一方的坐标位子,胜负判定则是己方的“将”或“帅”被对方吃掉就认定为失败。程序中的体现则是让被吃掉的棋子设置为空,并且再调用paint()对棋盘重画。

qiZi[endI][endJ] = qiZi[startI][startJ];// 吃掉该棋子 qiZi[startI][startJ] = null;// 将原来的位置设为空 this.xq.repaint();// 重绘

JOptionPane.showMessageDialog(this.xq, "恭喜您,您获胜了", "提示",

JOptionPane.INFORMATION_MESSAGE);// 给出获胜信息

5.2 规则制定 5.2.1 规则说明

在对局时,由执红棋的一方先走,双方轮流各走一步,直至分出胜负为止。轮到走棋的

一方,将某个棋子从一个交叉点到另一个交叉点,或者吃掉对方棋子而占领交叉点,都算走了一步。双方各走一步,成为一回合。

任何棋子在走动时,如果一方棋子可以到达的位置有对方的棋子,就可以把对方棋子拿出棋盘(称为吃子)而换上自己的棋子。只有炮的“吃子”方式与它的走法不同:它和对方棋子之间必须隔一个子(无论是自己的还是对方的),具备此条件才能"吃掉"人家。一定要注意,中隔一个棋子,这个棋子俗称“炮架子”。

一方的棋子攻击对方的将(帅),并且在下一步能把它吃掉,俗称“将军”。被“将军”的一方必须立即“应将”,即用自卫的步法曲化解被“将军”的状态。如果被“将军”而无法“应将”,就算被“将死”,输掉本局。轮到走棋的一方将(帅)虽没被对方“将军”,却被禁在一个位置上无路可走,同时己方其他棋子也都不能动,就算被“困死”,同样输掉本局。

以下为棋子规则:

(1) 将(帅):将和帅是棋中的首脑,是双方竭力争夺的目标。它只能在“九宫”之内活动,可上可下,可左可右,每次走动只能按竖线和横线走动一格。江河帅不能在同一竖线上直接面对,否则判走方输棋。

(2) 士(仕):士(仕)是将(帅)的贴身保镖,它也只能在“九宫”内走动。它的行棋路径只能是“九宫”内的斜线。

(3) 象(相):象(相)的主要作用是防守,保护自己的将(帅)。它的走法是每次循对角线走两格。俗称“象走田”。象(相)的活动范围限于“河界”以内的本方阵地,不能过河,且如果它走的“田”字中央有一个棋子的时候,就不能走,俗称“塞象眼”。

(4) 车:车在象棋中威力最大,无论横线、竖线均可行走,只要无子阻拦,部署不受限制。因此一车可以控制十七个点,故有“一车十子寒”之称。

(5) 炮:炮在不吃子的时候,走动与车完全相同。

(6) 马:马在走动的方法是一直一斜,即先横着或竖着走一格,然后再斜着走一个对角线,俗称“马走日”。马一次可走的选择点可以达到四周的八个点。故有“八面威风”之说。如果在要去得方向有别的棋子挡住,马就无法走过去,俗称“蹩马腿”。

(7) 卒(兵):兵(卒)在未过河前,只能向前一步步走,过河以后,除不能后退外,允许左右移动,但也只能一次一步,即使这样,兵(卒)的威力也大大增强,故有“过河的卒子顶半个车”之说。

5.2.2 规则算法

马走日字,相飞田字,七种棋子,七种不同的走法,映射到程序中来,必须有一个方法来约束其行动。本系统中的运用bool型canMove (int startI,int startJ,int endI,int endJ,String name)函数来设置规则约束,当用户点击拿起棋子,在再次点击目的地时程序将根据canMove的name参数调用相应方法来判断着法是否可行,不可行返回false,反之返回true。canMove()的参数startI和startJ为原棋子坐标,endI和endJ为目的坐标,name为棋子名称,默认返回值为true。

(1) 将或帅:

移动范围:九宫格范围

移动规则:每一步只可以水平或垂直移动一点。

public void jiang(int maxI, int minI, int maxJ, int minJ, int startI,

int startJ, int endI, int endJ) {// 对"帥"、"將"的处理

int a = maxI - minI;

int b = maxJ - minJ;// 获得X,Y坐标的差

if ((a == 1 && b == 0) || (a == 0 && b == 1)) {// 如果走的是一小格 if (startJ > 4)// 如果是下方的将

{

if (endJ

{

canMove = false;// 不可以走

}

} } else {// 如果是上方的将 if (endJ > 2)// 如果越界 { canMove = false;// 不可以走 } } if (endI > 5 || endI

移动规则:每一步只能沿对角线移动一点。

public void shi(int maxI, int minI, int maxJ, int minJ, int startI,

int startJ, int endI, int endJ) {

int a = maxI - minI;

int b = maxJ - minJ;// 获得X,Y坐标的差

if (a == 1 && b == 1)// 如果是小斜线

{

if (startJ > 4)// 如果是下方的士

{

if (endJ

canMove = false;// 如果下方的士越界,不可以走

}

} else {// 如果是上方的仕

if (endJ > 2) {

canMove = false;// 如果上方的仕越界,不可以走

}

}

if (endI > 5 || endI

{

canMove = false;

}

} else {// 如果不是小斜线

canMove = false;// 不可以走

}

}

(3) 象:

移动范围:河界的一侧。

移动规则:每一步只可沿对角线方向移动两点,另外,在移动的过程中不能够穿越障碍。

public void xiang1(int maxI, int minI, int maxJ, int minJ, int startI, int startJ, int endI, int endJ) {// 对"相"的处理

int a = maxI - minI;

int b = maxJ - minJ;// 获得X,Y坐标的差

if (a == 2 && b == 2)// 如果是"田"字

{

if (endJ > 4)// 如果过河了

{

canMove = false;// 不可以走

}

if (qiZi[(maxI + minI) / 2][(maxJ + minJ) / 2] != null)

// 如果"田"字中间有棋子

{

canMove = false;// 不可以走

}

} else {

canMove = false;// 如果不是"田"字,不可以走

}

}

(4) 车:

移动范围:任何位置

移动规则:可以水平或垂直方向移动到任意个无阻碍的点。 public void ju(int maxI, int minI, int maxJ, int minJ) {// 对"車"的处理方法 if (maxI == minI)// 走竖线 { for (j = minJ + 1; j

{ canMove = false;// 不可以走棋 } } (5) 炮:

移动范围:任何位置

移动规则:移动起来和车很相似,但它必须跳过一个棋子来吃掉对方的一个棋子。 public void pao(int maxI, int minI, int maxJ, int minJ, int startI,

int startJ, int endI, int endJ) {// 对"炮"、"砲"的处理

if (maxI == minI)// 如果走的竖线

{

if (qiZi[endI][endJ] != null)// 如果终点有棋子

{

int count = 0;//计间隔的棋子数

for (j = minJ + 1; j

if (qiZi[minI][j] != null)// 判断起点与终点之间有几个棋子 {

count++;

}

}

if (count != 1) {// 如果不止一个棋子

canMove = false;// 不可以走

}

} else if (qiZi[endI][endJ] == null)// 如果终点没有棋子

{

for (j = minJ + 1; j

if (qiZi[minI][j] != null)// 如果起止点之间有棋子

{

canMove = false;// 不可以走

break;

}

}

}

} else if (maxJ == minJ)// 如果走的是横线

{

if (qiZi[endI][endJ] != null)// 如果终点有棋子

{

int count = 0;

for (i = minI + 1; i

if (qiZi[i][minJ] != null)// 判断起点与终点之间有几个棋子 {

count++;

}

}

if (count != 1)// 如果不止一个棋子

{

canMove = false;// 不可以走

}

} else if (qiZi[endI][endJ] == null)// 如果终点没有棋子

{

for (i = minI + 1; i

if (qiZi[i][minJ] != null)// 如果起止点之间有棋子

{

canMove = false;// 不可以走

break;

}

}

}

} else if (maxJ != minJ && maxI != minI) {

// 如果走的既不是竖线,也不是横线,则不可以走

canMove = false;

}

}

(6) 马:

移动范围:任何位置

移动规则:每一步只可以水平或垂直移动一点,再按对角线方面向左或者右移动。另外,在移动的过程中不能够穿越障碍。

public void ma(int maxI, int minI, int maxJ, int minJ, int startI, int startJ, int endI, int endJ) {// 对"馬"的处理方法

int a = maxI - minI;

int b = maxJ - minJ;// 获得两坐标点之间的差

if (a == 1 && b == 2)// 如果是竖着的"日"字

{

if (startJ > endJ)// 如果是从下向上走

{

if (qiZi[startI][startJ - 1] != null)// 如果马腿处有棋子 {

canMove = false;// 不可以走

}

} else {// 如果是从上往下走

if (qiZi[startI][startJ + 1] != null)// 如果马腿处有棋子 {

canMove = false;// 不可以走

}

}

} else if (a == 2 && b == 1)// 如果是横着的"日"

{

if (startI > endI)// 如果是从右往左走

{

if (qiZi[startI - 1][startJ] != null)// 如果马腿处有棋子 {

canMove = false;// 不可以走

}

} else {// 如果是从左往右走

if (qiZi[startI + 1][startJ] != null)// 如果马腿处有棋子 {

canMove = false;// 不可以走

}

}

} else if (!((a == 2 && b == 1) || (a == 1 && b == 2)))

// 如果不时"日"字

{

canMove = false;// 不可以走

}

}

(7) 兵:

移动范围:任何位置

移动规则:每步只能向前移动一点。过河以后,它便增加了向左右移动的能力,兵不允许向后移动。

public void bing(int maxI, int minI, int maxJ, int minJ, int startI, int startJ, int endI, int endJ) {// 对"兵"的处理

if (startJ

{

if (startI != endI)// 如果不是向前走,横左边变化

{

canMove = false;// 不可以走

}

if (endJ - startJ != 1)// 如果走的不是一格

{

canMove = false;// 不可以走

}

} else {// 如果已经过河

if (startI == endI) {// 如果走的是竖线,横坐标相同

if (endJ - startJ != 1)// 如果走的不是一格

{

canMove = false;// 不可以走

}

} else if (startJ == endJ) {// 如果走的是横线

if (maxI - minI != 1) {// 如果走的不是一格

canMove = false;// 不可以走

}

} else if (startI != endI && startJ != endJ) {

// 如果走的既不是竖线,也不是横线,则不可以走

canMove = false;

}

}

}

6运行测试

6.1 服务端

(1) 端口限制测试,端口只能输入0-65535之间的整数,其他输入一律无效。如图6-1所示。

6-1 服务器端端口限制测试

(2) 服务器列表显示在线玩家IP地址以及玩家昵称测试。如图6-2所示。

6-2 显示在线用户列表

6.2 客户端

(1) 昵称测试,默认情况下不允许同名玩家出现。例服务端显示已经有play1玩家登陆,如果再有play1的玩家登陆则提示重名信息。如图6-3所示。

图6-3 昵称测试

(2) 玩家挑战测试,play1在下拉列表中选择play3进行对弈,并发出相应的提示信息。如图 6-4所示。

图6-4 玩家挑战测试

(3) 繁忙测试,当一方玩家正在对弈中,其他玩家无法向其挑战。例玩家play1与play3对弈中,玩家play2无法向玩家play1或play3发起挑战。如图6-5所示。

图6-5繁忙测试

(4) 胜负判定测试,当玩家的“将”或“帅”被吃掉,则判定该玩家失败,弹出相应的失败消息提示框,同时另外一方显示胜利。例玩家play1与play3的对弈结果。如图6-6所示。

图6-6 胜负判定

2011届软件工程专业毕业设计(论文)

7 总结

本程序设计实现了基本于Java平台的局域网象棋对弈游戏的简单开发,具有一定的可玩性,可作为工作之余的休闲娱乐游戏。虽然在开发过程中经常遇到许多技术困难,但是经过查阅相关资料和调试排错解决了绝大部分的问题。

由于技术水平有限,仅仅实现了象棋对弈游戏的基本功能,能够实现局域网的人人对战,程序做的还不够完善,功能单一,比较简单,但我相信,随着时间的推移、个人水平的增长,一定能重写一个比较完善的象棋对弈游戏。

中国象棋在棋牌类游戏中非常经典,它对于如何走棋的判断、对蹩脚马和塞眼象的判断,这些算法的设计比较复杂。网络通信方面的数据传输和识别,视图的更新和重绘都是本系统设计的重点。通过这段时间的学习,进一步加深了Java的学习,巩固了以前的一些基础知识。虽然程序不是十分完美,但是看着自己的努力的成果,还是感到非常欣慰。

致谢

经过一个学期的努力学习和工作,我的象棋对弈游戏在老师和同学的帮助下终于开发完成了!在这个项目的开发过程中,我深深地体会到了软件开发人员应具备的素质和肩负的责任,同时也深深感受到了集体的温暖和团结的力量。

在这里,首先我要衷心地感谢我的导师——老师给予我的指导和帮助,使我在系统的设计和实现中少走了不少的弯路。在导师的指导下,我的系统一点,一点的开发,功能一步,一步的实现。她严谨的治学态度,循循善诱的教导方式给我留下了深刻的印象。其次,我还要感谢同学的真诚帮助,他们在关键的时候给予我莫大的帮助,让我深深感受到了团结合作的力量。最后,在这里请允许我向所有帮助我的老师和同学表示最真诚的谢意!

参考文献

[1]张思民,梁维娜.Java程序设计实践教程[M].北京:清华大学出版社,2006.8

[2]朱福喜,唐晓军.Java程序设计技巧与开发实例[M].北京:人民邮电出版社, 2007.6

[3]刘新.java开发技术大全[M].北京:清华大学出版社,2009,2

[4]赵文靖.Java程序设计基础与上机指导[M].北京:清华大学出版社,2006

[5]杨昭编.二级Java语言程序设计教程[M].北京:中国水利水电出版社,2006

[6]Rogers Cadenhead. Java编程入门经典.梅兴文译.第4版.北京:人民邮电出版社,2007

[7]Bruce Eckel. Thinking In Java[M].北京:机械工业出版社,2007

[8]陈轶,姚晓昆.Java程序设计实验指导[M].北京:清华大学出版社,2006

[9]吴其庆.Java程序设计实例教程[M].北京:冶金工业出版社,2006

[10]葛维蒲.象棋入门(修订本)[M].上海:上海辞书出版社,2008

[11]黄少龙.象棋入门[M].成都:成都时代出版社,2007

第27页 共27页

说 明

本系统是一款基于Eclipse平台开发的局域网象棋对战游戏,采用Java GUI技术绘制界面,面向连接的Socket实现局域网联机,多线程同步用户信息数据。

系统分为服务器端和客户端,服务器端起到处理用户联网信息并转发数据的作用,客户端主要实现象棋对弈。

该象棋游戏界面友好,操作方便,能满足广大象棋爱好者的日常对弈需求。

目录

摘要................................................................ I Abstract........................................................... II

1引言 .............................................................. 1

1.1课题背景 ...................................................... 1

1.2中国象棋发展现状 .............................................. 1

2 开发环境与相关技术................................................ 1

2.1 Java语言 ..................................................... 1

2.2 开发工具 ...................................................... 2

2.3 技术 ........................................................ 3

2.3.1 面向对象设计 .............................................. 3

2.3.2 Java GUI技术 ............................................. 3

2.3.3 JAVA多线程技术 ........................................... 5

2.3.4 点对点通信 ................................................ 6

2.3.5 TCP/IP协议 ............................................... 7

3需求分析 .......................................................... 8

3.1 任务概述 ...................................................... 8

3.2 需求分析 ...................................................... 8

3.2.1 联机操作功能 .............................................. 8

3.2.2 象棋对弈功能 .............................................. 8

4总体设计 .......................................................... 9

4.1 系统结构图 .................................................... 9

4.2 类框架设计 .................................................... 9

4.2.1 服务器端 .................................................. 9

4.2.2 客户端 ................................................... 10

4.3 需要解决的问题 ............................................... 11

5系统实现 ......................................................... 13

5.1 棋盘设计 ..................................................... 13

5.2 规则制定 ..................................................... 16

5.2.1 规则说明 ................................................. 16

5.2.2 规则算法 ................................................. 17

6运行测试 ......................................................... 23

6.1 服务端 ....................................................... 23

6.2 客户端 ....................................................... 24

7 总结............................................................. 27

致谢............................................................... 27

参考文献........................................................... 27

基于局域网的中国象棋游戏

摘要:中国象棋具有悠久的历史。战国时期,已经有了关于象棋的正式记载,新中国建立之后,象棋进入了一个崭新的发展阶段。随着信息技术的发展,人民生活水平的不断提高。联网游戏作为一种娱乐手段,正以其独特的魅力吸引着越来越多的玩家。

为了满足广大象棋爱好者也可以享受到网络所带来的便利,本设计在当前局域网条件下实现了中国象棋的网络对战。鉴于局域网的特点和游戏本身的要求,本设计采用C/S架构来实现相互之间的通信。它主要包含以下几大模块:网络通信模块,图像绘制模块和规则设置模块。网络通信模块使得玩家之间可以方便迅速的建立起网络连接,从而实现联机对弈功能;图像绘制模块实现棋盘更新以及棋子动态表示等功能;规则设置模块用于约束玩家的走棋。在系统中我负责象棋部分的功能。

电脑游戏是计算机应用领域的一个重要主题,而当前网上最热门的休闲对战类游戏当属棋牌游戏。通过对象棋的数据结构,相关算法与网络联机,以及对网络对战平台系统的分析,设计成一套基于Java平台的棋牌类对战系统。

关键字:网络通信;联机对弈;图像绘制

Chinese chess game on LAN

Abstract:The Chinese chess has a long history. In the Warring States Period, there was a formal record about the chess already. After new China set up, the chess has entered a brand-new developing stage. With the development of information technology, peoples standard of living have improved constantly. On-line game as a means of entertainment has a unique charm to attract more and more players.

To meet chess lovers, this design has realized the Challenges of Chinese-chess between players under the current LAN environment. In view of the characteristics of local area networks and the requirements of the game itself, the design uses a two-tier C/S structure to achieve mutual communication. It contains the following major modules: the network communication module, image rendering module and the rules set up module. Network Communication Module allows gamers can quickly set up a convenient network connection in order to achieve an online game; image rendering module to update the board as well as functional pieces, such as the dynamic that; rules binding settings module for step-by-step player's game. I am responsible for chess part of the function in System.

Computer games is the field of computer applications as an important subject, and present the most popular casual online games war among board games. By the data structure, algorithms and network online, as well as the network platform for systematic analysis of the war, designed a set of Java platform based on the category Card battle system.

KeyWords: Network Communication; Online game; Image Rendering

1引言

1.1课题背景

中国象棋有着悠久的历史,通俗易懂,老少皆益;20世纪是信息的时代,随着计算机技术和经济的发展,计算机由商业逐渐走向家庭。象棋水平的发展是需要靠信息技术来推动的,国际象棋就是个很好的范例。然而,电脑在中国象棋上的运用还刚刚起步,尽管国内涌现出一大批中国象棋的专业网站和专业软件,但是由于缺乏必要的基础工作,电脑技术在中国象棋上的应用优势还无法体现出来。如果可以编译一种软件,方便象棋爱好者之间进行对弈,那对象棋的发展定会有推进作用。当前各种开发语言中,JAVA以自己的跨平台操作,简单,可移植性,面向对象,以接口实现多线程,动态等优点为大多人青睐。因此我选择了Java作为象棋对弈软件的开发语言。

1.2中国象棋发展现状

中国象棋发展至今已有二千三、四百年的历史了,早在战国时期就有正式记载,堪称中国的国粹。据统计,中国有2亿人会下象棋,这相当于平均6至7个人中就有1人会下,可见它有着广泛的群众基础。方寸之间包含天地玄机,人生哲理,使人越是细玩越觉其味悠然深远。简单的棋规,便捷的载体,使得他成为雅俗共赏的竞技项目。然而,如今中国象棋的发展前景却令人堪忧。导致这种现象的主要因素有:第一,就东亚地区,围棋的影响力胜于中国象棋。第二,中国象棋虽然在国内很受欢迎,但在世界舞台上名声却不如国际象棋那么响亮。之所以会存在这两个因素,都是因为在国际赛事上中国象棋的参赛选手大都是华人,而非华裔的选手又大都是业余选手,这无疑使比赛失去了竞争力,而围棋有韩国和日本的参与,国际象棋有全世界国家的加入。第三,进入了21世纪后,供人们娱乐活动的选择越来越多,中国象棋在年轻人的心中已开始渐渐失去魅力。

随着信息技术的不断发展,各种象棋软件的开发与应用应运而生,尤其是在网络方面的推广,使得中国象棋得到了很好的宣传,全面展示了中国象棋的风采、优点与特色,同时也让外国人认识到中国象棋这一我国的 “国粹”。想必在未来的几年随着中国象棋在各个领域的推广,必定会带来巨大的影响。

2 开发环境与相关技术

2.1 语言

Java是一种跨平台,适合于分布式计算环境的面向对象编程语言。其主要特点有:

(1) 平台无关性

平台无关性就是指 Java能运行于不同的平台。Java引进虚拟机原理,并运行于虚拟机,实现不同平台的Java接口之间。使用Java编写的程序能在世界范围内共享。Java的数据类型与机器无关,Java虚拟机(Java Virtual Machine)是建立在硬件和操作系统之上,实现 Java代码的解释执行功能,提供不同平台的接口。

(2) 安全性

Java的编程类似于C++,学习过C++的读者将很快能掌握Java的精髓。Java舍弃了C++

的指针对存储器地址的直接操作,程序运行时,内存由操作系统分配,这样可以避免病毒通过指针侵入系统。Java对程序提供了安全管理器,防止程序的非法访问。

(3) 面向对象

Java吸取了C++面向对象的概念,将数据封装的简洁性和便于维护性。类的封装性、继承性等有关对象的特性,使程序代码只需一次编译,然后通过上述特性到达反复利用。Java提供了众多的一般对象的类,通过继承即可使用父类的方法。

Java已有的类的功能强大,如输入输出类,进行普通输入输出和文件设计图形界面的常用部件,图形用户界面的设计上给程序员很大的方便。

(4) 简单性

Java舍弃C++的头文件,没有全局变量,这样能更好维护头文件,符合网络编程的要求。头文件中有全局变量的定义,这对可维护性和安全性都是不可取的。Java舍弃了C++的多重继承,引进了垃圾管理,避免在垃圾回收这一问题绞尽脑汁去设计。

(5) 多线程

多线程是Java的一大特点,能够在程序中实现多任务操作。传统的程序设计语言的程序只能单任务操作,效率非常低,例如程序往往在接收数据输入时被阻塞,只有等到程序获得数据后才能够继续运行。而多线程程序可以创建一个线程来进行输入输出操作,创建另一个线程在后台进行数据处理,输入输出的线程在接收数据时阻塞,而另一个线程仍然在运行。这样,多线程程序大大提高了运行的效率和处理能力。

2.2 工具

Eclipse是一个开放源代码的、基于 Java 的可扩展开发平台。就其本身而言,它只是一个框架和一组服务,用于通过插件组件构建开发环境。幸运的是,Eclipse 附带了一个标准的插件集,包括 Java 开发工具(Java Development Tools,JDT)。

虽然大多数用户很乐于将 Eclipse 当作Java IDE来使用,但Eclipse的目标不仅限于此。Eclipse还包括插件开发环境(Plug-in Development Environment,PDE),这个组件主要针对希望扩展Eclipse的软件开发人员,因为它允许他们构建与Eclipse环境无缝集成的工具。由于Eclipse中的每样东西都是插件,对于给Eclipse提供插件,以及给用户提供一致和统一的集成开发环境而言,所有工具开发人员都具有同等的发挥场所。

这种平等和一致性并不仅限于Java开发工具。尽管Eclipse是使用Java语言开发的,但它的用途并不限于Java语言;例如,支持诸如C/C++、COBOL和Eiffel等编程语言的插件已经可用,或预计会推出。Eclipse框架还可用来作为与软件开发无关的其他应用程序类型的基础,比如内容管理系统。

基于Eclipse的应用程序的突出例子是IBM的WebSphere Studio Workbench,它构成了 IBM Java开发工具系列的基础。例如,WebSphere Studio Application Developer添加了对JSP、servlet、EJB、XML、Web服务和数据库访问的支持。

Eclipse最初由OTI和IBM两家公司的IDE产品开发组创建,起始于1999年4月。IBM提供了最初的Eclipse代码基础,包括Platform、JDT和PDE。目前由IBM牵头,围绕着Eclipse项目已经发展成为了一个庞大的Eclipse联盟,有150多家软件公司参与到Eclipse项目中,其中包括Borland、Rational Software、Red Hat及Sybase等。

Eclipse是一个开发源码项目,它其实是Visual Age for Java的替代品,其界面跟先前的Visual Age for Java差不多,但由于其开放源码,任何人都可以免费得到,并可以在此基础上开发各自的插件,因此越来越受人们关注。近期还有包括Oracle在内的许多大公司也纷纷加入了该项目,并宣称Eclipse将来能成为可进行任何语言开发的IDE集大成者,使用者只需下载各种语言的插件即可。

2.3 技术

2.3.1 面向对象设计

面向对象的程序设计(简称OOP)是一种目前比较提倡的程序设计方法。它的基本思想是把定义的数据集对数据的相关操作包装成一个新的类型即对象(Object)。

面向对象方法的基本观点是:客观世界是由对象组成的,每个对象都有自己的内部状态和运动规律,不同对象彼此之间通过消息相互联系和相互作用。软件结构应该与所要解决的问题一致,而不是与某种方法一致。面向对象方法强调的是对客观世界的洞察力,而洞察力不但取决于所用的方法,更依赖知识和经验的积累。

面向对象程序设计方法模拟人类习惯的解题方法,用对象分解取代功能分解,也就是把程序分解成许多对象,不同对象之间通过发送消息向对方提出服务请求,接受消息的对象主动完成指定功能,程序中的所有对象分工协作,共同完成整个程序的功能。面向对象程序设计方法的提出,是对软件开发的一场革命,它代表了计算机程序设计的新颖思维的方法,是目前解决软件开发面临的困难的最有希望、最有前途的方法之一。

2.3.2 Java GUI技术

AWT(Abstract Window Tools),抽象窗口工具类。

GUI(Graphic User Interface),图形化的用户接口。

构造图形界面的步骤:

(1) 选择一个容器

(2) 设置容器的布局管理器

(3) 向容器添加组件

(4) 事件的监听

容器(Container):用于管理其他的组件的对象,组件必须放到容器里。

JFrame,这是一个最顶层的窗体容器,所有其他的组件必须放在顶层容器里。

JDialog,对话框容器,他要依附于其父组件,他不是一个顶层容器。

JPanel,他不是顶层容器,必须放在顶层容器中,任何一个容器都有add()方法,Panel面板是透明的(默认)。

布局管理器:

FlowLayout,流式布局管。Panel的默认布局管理就是FlowLayout。

BorderLayout,按方位进行布局管理,(North,South,East,West,Center)不明确指定,就会默认加载在中间(Center),add(Component comp,String place)这个方法是在指定的位置添加组件。

GridLayout,网格布局,通过行列、间距,来用网格分割,把组件放入网格中,先行后列摆放组件。

CardLayout,卡片布局,面板重叠放置。

GridBogLayout,组件可以跨行跨列的网格布局。

组件:

JButton :按钮 JTextField:单行文本域

JTextArea:多行文本区 JScrollPane:滚动窗体

JComboBox:下拉选择框 RadioButton:单选按钮

JCheckBox:多选按钮 JLabel:标签

JPasswordField:密码输入框 JMenuBar:菜单条

JMenu:菜单 JMenuItem:菜单项

JPopupMenu:弹出式菜单 JSlider:滑动条

JSplitPane:分隔面板 JFileChooser:文件选择器

JColorChooser:颜色选择器

事件的监听----模型

事件对象

事件源————————〉事件处理者

图2-1事件监听模型

这就是事件模型的机制(图2-1),也就是由事件源对象发送一个消息(事件对象),然后事件处理者调用相应的方法处理事件。

事件对象继承自EventObject类,并可以通过getSource()方法获得事件源对象,当然需要在构造事件对象时将事件源对象传入,来区分是哪个事件源发出的事件,所以要用事件对象作为参数。

在Java的图形编程中,所有动作(事件)都已经提供了相应的事件对象和事件监听接口,例如:实现窗口的关闭按钮,点击关闭按钮会发出相应的事件对象,相应的调用监听器中实现好的方法。

自定义组件监听器如图2-2:

Button=new Button("close")

Button.addActionListener(this)

条目监听器如图2-3:

图2-2 自定义组件监听器 图2-3 条目监听器

鼠标监听器如图2-4:

图2-4 鼠标监听器

窗口监听器如图2-5:

2.3.3 JAVA多线程技术

关于线程的几个概念: 图2-5 窗口监听器

进程:正在执行的一个独立的程序,对于单CPU来说,进程在宏观上是并发的,但在微观上是串发的。

线程:在一个进程内部的“可以并发执行的多个函数”,一个进程中可有多个线程。 对于进程,每一个进程都是独占数据空间的,(是一个程序的执行流程)。而对于线程,它生活在进程内部,它们共享进程空间,线程是由操作系统(OS)来维护的。

线程三要素:CPU资源,执行代码Code,数据存储空间Data。

在JAVA中,来创建一个线程有两种方式可以选取择:

一种方法是将类声明为 Thread 的子类。该子类应重写 Thread 类的 run 方法。

如: class ThreadA extends Thread {

} Private String name; Public ThreadA(String name) { this.name = name; } Public void run() { } //具体的代码

使用:

Thread a = new ThreadA(a); //创建一个线程

a.start();//启动一个线程

创建线程的另一种方法是声明实现 Runnable 接口的类。该类然后实现 run 方法。然后可以分配该类的实例,在创建 Thread 时作为一个参数来传递。

如: class ThreadB implements Runnable {

. . . .

} Public void run() { } //具体的代码

使用:

Runnable r = new ThreadB(); //创建一个Runnable的实例 r

Thread b = new Thread(r); //使用一个Runnable的实例来创建一个线程b

b.start(); //启动一个线程

实现Runnable 接口的类不是一个线程类,只能是用它去构造一个线程对象。 在JAVA中,线程也是一个类(Thread),实际的线程就是一个对象。

线程状态转换,如图2-6所示:

对象对象

图2-6 线程状态转换

2.3.4 点对点通信

从OSI参考模型的应用层来看,可认为网络是由工作站和服务器组成的,但从传输层和网络层的角度看,工作站和服务器没有本质的区别,它们都是连接到网络上的一台机器,都可以用网络地址或名称来代替。它们之间的通信就是所谓的点对点通信,也叫对等通信。在局域网上,点点通信意味着两个工作站可以直接对话而不用经过文件服务器中转。

通信的基础是套接口(Socket),一个套接口是通讯的一端。socket通常也称作“套接字”,用于描述IP地址和端口,是一个通信链的句柄。应用程序通常通过“套接字”向网络发出请求或者应答网络请求。

Socket实质上提供了进程通信的端点。进程通信之前,双方首先必须各自创建一个端点,

否则是没有办法建立联系并相互通信的。正如打电话之前,双方必须各自拥有一台电话机一样。在网间网内部,每一个socket用一个半相关描述(协议,本地地址,本地端口)。一个完整的socket有一个本地唯一的socket号,由系统分配。最重要的是,socket是面向客户/服务器模型而设计的,针对客户和服务器程序提供不同的socket系统调用。客户随机申请一个socket(相当于一个想打电话的人可以在任何一台入网电话上拨号呼叫),系统为之分配一个socket号;服务器拥有全局公认的socket,任何客户都可以向它发出连接请求和信息请求(相当于一个被呼叫的电话拥有一个呼叫方知道的电话号码)。socket利用客户/服务器模式巧妙地解决了进程之间建立通信连接的问题。

服务器socket半相关为全局所公认非常重要。假如通信双方没有任何一方的socket固定,就好比打电话的双方彼此不知道对方的电话号码,要通话是不可能。在这一端上你可以找到与其对应的一个名字,一个正在被使用的套接口都有它的类型和与其相关的进程。套接口存在于通讯域中。通讯域是为了处理一般的线程通过套接口通讯而引进的一种抽象概念。套接口通常和同一个域中的套接口交换数据(数据交换也可能穿越域的界限,但这时一定要执行某种解释程序)。Windows Sockets规范支持单一的通讯域,即Internet域。各种进程使用这个域互相之间用Internet协议来进行通讯。

局域网中工作站之间的通信程序的开发一般通过四种途径:第一种是通过改造网络原有通信软件来实现。但这种改造必须以对该软件充分了解为基础,否则改造后很难保证不影响网络的整体性能,甚至会造成系统运行不可靠,而改造后的通信质量不一定理想。第二种是利用Novell网本身的网络协议IPX/SPX来实现,由于这种方法开发比较麻烦,采用的并不多。第三种是通过NetBIOS功能调用来实现,NetBIOS是PC LAN的通信接口标准,广泛适用于多种微机网络,使得以它为基础的设计和应用开发可移植性好。它不依赖于任何网络硬件,是一个介于网络硬件和用户应用程序之间的接口协议。其通信原理是:两个要进行通信的工作站通过名字建立一个虚电路,然后向相应的虚电路号发送或接收信息,这样通过虚电路实现了两个工作站之间的对等通信。利用NetBIOS实现工作站之间的实时通信,功能比较强,编程实现比较容易,所以应用比较广泛。第四种是通过TCP/IP协议来实现。

2.3.5 TCP/IP协议

TCP协议(Transmission Control Protocol 传输控制协议)是一种流传输控制协议,它提供可靠的、有序的、双向的、面向连接的数据传输,是一种面向连接的协议。

TCP协议是一种端对端的协议,使用TCP没有任何广播或类似的概念,要用TCP协议与另一台计算机通信,两台机之间必须像打电话一样连接在一起,每一端都为通话做好准备。

TCP协议每发送一个数据包都将会收到一个确认信息,这种发送/应答模式是提供可靠的协议的唯一方法:你必须让对方知道你是否收到了数据。当然,这也会造成一些性能损失,人们为了改善系统效率不高的状况,引入了“捎带确认(piggybacking)”的方法。TCP协议之所以是全双工的就是因为这个“捎带确认”信息,因为它允许双方同时发送数据。这是通过在当前的数据包中携带以前收到的数据的确认信息方式实现的,从提高网络利用率的角度看,这比单纯发送一个通知对方“信息已收到”的数据包要好得多。最后,还有一个批量确认的概念:即一次确认一个以上的数据包,表示“我收到了包括这个数据包在内的全部数据包”。

在IP协议中,我们处理的单个数据包是一个更大的数据报的一部分,一个TCP段就是一个单个的TCP数据包。TCP是一个数据流,因此,除了“连接”之外,没有任何需要真正担心的其它概念。最大报文段长度(MSS)是在连接的时候协商的,但是,它总是在不断地改变。默认的最大报文段长度是536字节,这是576字节(IP协议保证的最小数据包长度)减去用于IP头的20个字节和用于TCP头的20个字节以后的长度。TCP协议要设法避免在IP级别上的分段。因此,TCP协议总是从536字节开始的。TCP/IP协议的核心部分是传输层协议(TCP、UDP),网络层协议(IP)和物理接口层,这三层通常是在操作系统内核中实现。因此用户一般不涉及,编程时,编程界面有两种形式:一、是由内核直接提供的系统调用;二、使用以库函数方式提供的各种函数。前者为核内实现,后者为核外实现。用户服务要通过核外的应用程序才能实现,所以要使用套接字(socket)来实现。

3需求分析

3.1 任务概述

中国象棋具有悠久的历史,象棋的爱好者更是数不胜数,远在战国时代,象棋便在贵族阶层中广为流传,早期的象棋是象征着当时战斗场面的游戏,后来这种观念慢慢改变,成为人们休闲娱乐中不可缺少的一部分。而如今的人们忙于工作,很少有时间静下心来享受象棋对弈的乐趣,因此电脑版象棋、手机版象棋便开始受到人们的关注。

基于局域网的象棋游戏,可以极大的方便玩家快速建立并进入一个象棋的对弈平台,玩家通过对走棋的思考和对全局的掌控,在游戏之余,又可以锻炼思考和判断的能力,可谓一种很好的寓教于乐方式。同时象棋对弈过程需要玩家耐心的操作,其观察力,耐心、专注力都有很好的培养,此外,通过与高水平玩家的对战,可以提高自己的技术,在思考中不断提高自己。

3.2 需求分析 3.2.1 联机操作功能

由于基于Java平台的局域网联机对战游戏,联机功能自然是重中之重,必须要有服务器作为支持。当服务器启动之后,客户端连接到服务器,服务器接受并处理来至客户端的操作信息,经过相应判断和处理后,选择性的向客户端发送相应的反馈消息,保证信息传输的正确性,可靠性。

3.2.2 象棋对弈功能

当两个客户端通过局域网连接到一起之后,双方将进行象棋对弈。由于基于PC来实现游戏客户端,所以游戏是通过鼠标点击来进行,鼠标点击选中棋子,然后点击该棋子需要移动的目标位置。象棋具有其特有的规则,为了保证游戏能够按照正确的规则进行下去,必须要在客户端对玩家的着子点进行合法性判断,只有符合一定规则的走棋才能够实现,并且通过服务器传输给对方玩家。同时,客户端程序需要对棋局的胜负进行判断,当一方胜利后给出胜利提示信息。

4总体设计

4.1 功能结构图

图4-1系统结构图

服务器端:指定端口号,启动服务器后等待客户端的连接,若没有客户连接,则一直处于等待状态。待客户端连接到服务器端,则显示在线的用户列表,若客户端发送信息过来,服务器经过相应的处理后转发给相应的客户端。 客户端:启动客户端后指定统一的主机IP地址,以确定同一服务器。然后输入自己的昵称和端口号,便可以选择想挑战的在线用户进行对弈。

4.2 类结构设计 4.2.1 服务器端

服务器端类图设计如图4-2所示。

4-2 服务器端类图

Server类:实现服务器端界面初始化,各个按钮的相应操作。 ServerThread类:用于接收客户端的连接,并为每一个连接分配一个服务器代理线程。 ServerAgentThread:主要用于接收客户端传来的信息,并将该信息转发给对应的另一客户端。服务器为所有客户端都分配了一个该类线程实例,单独为特定客户端进行服务。同时每一个服务器代理线程都有能惟一标识其的名称。

4.2.2 客户端

客户端类图设计如图4-3所示。

4-3 客户端类图

QiPan类:棋盘类除了完成绘制棋盘的作用,同时还负责下棋逻辑的处理。 GuiZe类:定义象棋走棋规则。

ClientAgentThread类:要用于接收服务器传来的消息,并根据不同的消息进行相应的业QiZi类:用于定义象棋的基本属性。

XiangQi类:初始化客户端组件,让用户通过运行该类连接服务器,并通过在该类的窗

务处理。

体中与其他玩家进行对弈。

4.3 需要解决的问题

服务器端要求:

(1)手动制定服务器端口号,并且端口号只能是0-65535的整数。 (2)可以支持多人同时在线,并实时刷新在线用户列表。 (3)玩家昵称不能同名,否则无法登陆。

客户端要求:

(1)通过设置主机IP及端口号登录到服务器。

(2)可以显示当前在线的其他用户。

(3)可以从在线用户列表中选择玩家进行去挑战。 (4)可以接受或拒绝挑战。

(5)如果对方正在与其他玩家对弈中,则应给出相应的提示信息。 (6)棋子样式采用最普通的象棋,即棋子黑色,字为红色和白色。 (7)棋盘界面初始化。

(8)棋子走棋规则,输赢判定。

以下内容为本人独立实现

5系统实现

5.1 棋盘设计

棋子活动的场所,叫作“棋盘”。在长方形的平面上,绘有九条平行的竖线和十条平行

的横线相交组成,共有九十个交叉点,棋子就摆在交叉点上。中间部分,也就是棋盘的第五,第六两横线之间末画竖线的空白地带称为“河界”。两端的中间,也就是两端第四条到第六条竖线之间的正方形部位,以斜交叉线构成“米”字方格的地方,叫作“九宫”(它恰好有九个交叉点)。

棋盘类主要作用为棋盘的绘制,选棋走棋的判断,吃棋的实现和以及胜负的判定等。 本系统中棋盘,棋子的绘制是通过锁定坐标,绘制相应线条实现,而非用图片加载的方(1) 棋盘绘制

式得到。棋盘绘制在程序中表现为调用QiPan类中paint()方法,首先是绘制一个矩形框架,然后分别绘制9 × 10网格线,最后在棋盘中间写入“楚河汉界”四字。 public void paint(Graphics g1) {

Graphics2D g = (Graphics2D) g1;// 获得Graphics2D对象 g.setRenderingHint(RenderingHints.KEY_ANTIALIASING,

RenderingHints.VALUE_ANTIALIAS_ON);// 打开抗锯齿

Color c = g.getColor();// 获得画笔颜色

g.setColor(XiangQi.bgColor);// 将画笔设为背景色 g.fill3DRect(60, 30, 580, 630, false);// 绘制一个矩形棋盘 g.setColor(Color.black);// 画笔颜色设为黑 }

g.drawLine(110, 80, 110, 620);// 绘制左边界线 g.drawLine(590, 80, 590, 620);// 绘制右线

g.drawLine(i, 80, i, 320);//上面部分 g.drawLine(i, 380, i, 620);//下面部分

for (int i = 110; i

g.drawLine(110, i, 590, i);

for (int i = 80; i

}

g.drawLine(290, 80, 410, 200);// 绘制两边的斜线 g.drawLine(290, 200, 410, 80); g.drawLine(290, 500, 410, 620); g.drawLine(290, 620, 410, 500); g.setColor(Color.black); g.setFont(font1);

Font font1 = new Font("宋体", Font.BOLD, 50);// 设置字体 g.drawString("楚 河", 170, 365);// 绘制楚河汉界

g.drawString("漢 界", 400, 365); g.setFont(font);// 设置字体 }

Font font = new Font("宋体", Font.BOLD, 30);

以上代码执行之后棋盘初步模型便已完成,接下来调用smallLine()方法对棋盘上的

public void smallLine(Graphics2D g, int i, int j) { int x = 110 + 60 * i;// 计算坐标 int y = 80 + 60 * j;

if (i > 0) {// 绘制左上方的标志 g.drawLine(x - 3, y - 3, x - 20, y - 3); }

if (i

if (i > 0) {// 绘制左下方的标志 g.drawLine(x - 3, y + 3, x - 20, y + 3); }

if (i

g.drawLine(x + 3, y + 3, x + 3, y + 20); g.drawLine(x - 3, y + 3, x - 3, y + 20); g.drawLine(x + 3, y - 3, x + 3, y - 20); g.drawLine(x - 3, y - 3, x - 3, y - 20);

标记点进行绘制。

}

棋盘绘制完成之后就是棋子的绘制,该实现通过双重循环,调用fillOval()方法绘制

而成。

for (int i = 0; i

for (int j = 0; j

if (this.qiZi[i][j].getFocus() != false) {// 选中棋子

g.setColor(XiangQi.focusbg);// 选中后的背景色

g.fillOval(110 + i * 60 - 25, 80 + j * 60 - 25, 50,

状态

50);// 绘制该棋子起点(110,80)棋子半径(25)

g.setColor(XiangQi.focuschar);// 字符的颜色 } else {

g.fillOval(110 + i * 60 - 25, 80 + j * 60 - 25, 50,

50);// 绘制该棋子

g.setColor(qiZi[i][j].getColor());// 设置画笔颜色 }

g.drawString(qiZi[i][j].getName(), 110 + i * 60 - 15,

}

80 + j * 60 + 10);// 绘字

g.setColor(Color.black);// 设为黑色 }

(2) 选棋走棋的实现

在棋盘中,当玩家通过鼠标选择己方棋子在棋盘上走招或吃掉对方棋子,这一过程是通过getPos()方法和noFocus()方法实现的。前者获取鼠标在棋盘上点击的坐标位子,后者则是判断棋子归属以及对选中棋子的高亮处理。

pos[0] = Math.round((float) (x - 110)) / 60; // round()加0.5

取整

getPos()方法可以获得棋子的坐标,同时限制棋子只能是在棋盘中移动。

public int[] getPos(MouseEvent e) { // 获得事件发生坐标

int[] pos = new int[2];

pos[0] = -1; pos[1] = -1;

Point p = e.getPoint();// 获得事件发生的坐标点 double x = p.getX(); double y = p.getY();

if (Math.abs((x - 110) % 60)

} else if (Math.abs((x - 110) % 60) >= 35) { }

if (Math.abs((y - 80) % 60)

return pos;

pos[1] = Math.round((float) (y - 80)) / 60; pos[1] = Math.round((float) (y - 80)) / 60 + 1; pos[0] = Math.round((float) (x - 110)) / 60 + 1;

}

} else if (Math.abs((y - 80) % 60) >= 35) {

调用noFocus()方法判断玩家点击棋子是否为己方棋子,如果是则高亮显示。

public void noFocus(int i, int j) {// 判断棋子颜色并聚焦

if (this.qiZi[i][j] != null)// 如果该位置有棋子 {

if (this.xq.color == 0)// 如果是红方 {

if

(this.qiZi[i][j].getColor().equals(XiangQi.color1))// 如果棋子是红色 {

this.qiZi[i][j].setFocus(true);// 将该棋子设为选中状态 focus = true;// 将focus设为true startI = i;// 保存该坐标点

}

startJ = j;

} else// 如果是白方 {

if

(this.qiZi[i][j].getColor().equals(XiangQi.color2))// 如果该棋子是白色 {

}

}

}

}

this.qiZi[i][j].setFocus(true);// 将该棋子设为选中状态 focus = true;// 将focus设为true startI = i;// 保存该坐标点 startJ = j;

(3) 吃棋和胜负的判定

吃棋表现为一方棋占用另外一方的坐标位子,胜负判定则是己方的“将”或“帅”被对方吃掉就认定为失败。程序中的体现则是让被吃掉的棋子设置为空,并且再调用paint()对棋盘重画。

qiZi[endI][endJ] = qiZi[startI][startJ];// 吃掉该棋子 qiZi[startI][startJ] = null;// 将原来的位置设为空 this.xq.repaint();// 重绘

JOptionPane.showMessageDialog(this.xq, "恭喜您,您获胜了", "提示",

JOptionPane.INFORMATION_MESSAGE);// 给出获胜信息

5.2 规则制定 5.2.1 规则说明

在对局时,由执红棋的一方先走,双方轮流各走一步,直至分出胜负为止。轮到走棋的

一方,将某个棋子从一个交叉点到另一个交叉点,或者吃掉对方棋子而占领交叉点,都算走了一步。双方各走一步,成为一回合。

任何棋子在走动时,如果一方棋子可以到达的位置有对方的棋子,就可以把对方棋子拿出棋盘(称为吃子)而换上自己的棋子。只有炮的“吃子”方式与它的走法不同:它和对方棋子之间必须隔一个子(无论是自己的还是对方的),具备此条件才能"吃掉"人家。一定要注意,中隔一个棋子,这个棋子俗称“炮架子”。

一方的棋子攻击对方的将(帅),并且在下一步能把它吃掉,俗称“将军”。被“将军”的一方必须立即“应将”,即用自卫的步法曲化解被“将军”的状态。如果被“将军”而无法“应将”,就算被“将死”,输掉本局。轮到走棋的一方将(帅)虽没被对方“将军”,却被禁在一个位置上无路可走,同时己方其他棋子也都不能动,就算被“困死”,同样输掉本局。

以下为棋子规则:

(1) 将(帅):将和帅是棋中的首脑,是双方竭力争夺的目标。它只能在“九宫”之内活动,可上可下,可左可右,每次走动只能按竖线和横线走动一格。江河帅不能在同一竖线上直接面对,否则判走方输棋。

(2) 士(仕):士(仕)是将(帅)的贴身保镖,它也只能在“九宫”内走动。它的行棋路径只能是“九宫”内的斜线。

(3) 象(相):象(相)的主要作用是防守,保护自己的将(帅)。它的走法是每次循对角线走两格。俗称“象走田”。象(相)的活动范围限于“河界”以内的本方阵地,不能过河,且如果它走的“田”字中央有一个棋子的时候,就不能走,俗称“塞象眼”。

(4) 车:车在象棋中威力最大,无论横线、竖线均可行走,只要无子阻拦,部署不受限制。因此一车可以控制十七个点,故有“一车十子寒”之称。

(5) 炮:炮在不吃子的时候,走动与车完全相同。

(6) 马:马在走动的方法是一直一斜,即先横着或竖着走一格,然后再斜着走一个对角线,俗称“马走日”。马一次可走的选择点可以达到四周的八个点。故有“八面威风”之说。如果在要去得方向有别的棋子挡住,马就无法走过去,俗称“蹩马腿”。

(7) 卒(兵):兵(卒)在未过河前,只能向前一步步走,过河以后,除不能后退外,允许左右移动,但也只能一次一步,即使这样,兵(卒)的威力也大大增强,故有“过河的卒子顶半个车”之说。

5.2.2 规则算法

马走日字,相飞田字,七种棋子,七种不同的走法,映射到程序中来,必须有一个方法来约束其行动。本系统中的运用bool型canMove (int startI,int startJ,int endI,int endJ,String name)函数来设置规则约束,当用户点击拿起棋子,在再次点击目的地时程序将根据canMove的name参数调用相应方法来判断着法是否可行,不可行返回false,反之返回true。canMove()的参数startI和startJ为原棋子坐标,endI和endJ为目的坐标,name为棋子名称,默认返回值为true。

(1) 将或帅:

移动范围:九宫格范围

移动规则:每一步只可以水平或垂直移动一点。

public void jiang(int maxI, int minI, int maxJ, int minJ, int startI,

int startJ, int endI, int endJ) {// 对"帥"、"將"的处理

int a = maxI - minI;

int b = maxJ - minJ;// 获得X,Y坐标的差

if ((a == 1 && b == 0) || (a == 0 && b == 1)) {// 如果走的是一小格 if (startJ > 4)// 如果是下方的将

{

if (endJ

{

canMove = false;// 不可以走

}

} } else {// 如果是上方的将 if (endJ > 2)// 如果越界 { canMove = false;// 不可以走 } } if (endI > 5 || endI

移动规则:每一步只能沿对角线移动一点。

public void shi(int maxI, int minI, int maxJ, int minJ, int startI,

int startJ, int endI, int endJ) {

int a = maxI - minI;

int b = maxJ - minJ;// 获得X,Y坐标的差

if (a == 1 && b == 1)// 如果是小斜线

{

if (startJ > 4)// 如果是下方的士

{

if (endJ

canMove = false;// 如果下方的士越界,不可以走

}

} else {// 如果是上方的仕

if (endJ > 2) {

canMove = false;// 如果上方的仕越界,不可以走

}

}

if (endI > 5 || endI

{

canMove = false;

}

} else {// 如果不是小斜线

canMove = false;// 不可以走

}

}

(3) 象:

移动范围:河界的一侧。

移动规则:每一步只可沿对角线方向移动两点,另外,在移动的过程中不能够穿越障碍。

public void xiang1(int maxI, int minI, int maxJ, int minJ, int startI, int startJ, int endI, int endJ) {// 对"相"的处理

int a = maxI - minI;

int b = maxJ - minJ;// 获得X,Y坐标的差

if (a == 2 && b == 2)// 如果是"田"字

{

if (endJ > 4)// 如果过河了

{

canMove = false;// 不可以走

}

if (qiZi[(maxI + minI) / 2][(maxJ + minJ) / 2] != null)

// 如果"田"字中间有棋子

{

canMove = false;// 不可以走

}

} else {

canMove = false;// 如果不是"田"字,不可以走

}

}

(4) 车:

移动范围:任何位置

移动规则:可以水平或垂直方向移动到任意个无阻碍的点。 public void ju(int maxI, int minI, int maxJ, int minJ) {// 对"車"的处理方法 if (maxI == minI)// 走竖线 { for (j = minJ + 1; j

{ canMove = false;// 不可以走棋 } } (5) 炮:

移动范围:任何位置

移动规则:移动起来和车很相似,但它必须跳过一个棋子来吃掉对方的一个棋子。 public void pao(int maxI, int minI, int maxJ, int minJ, int startI,

int startJ, int endI, int endJ) {// 对"炮"、"砲"的处理

if (maxI == minI)// 如果走的竖线

{

if (qiZi[endI][endJ] != null)// 如果终点有棋子

{

int count = 0;//计间隔的棋子数

for (j = minJ + 1; j

if (qiZi[minI][j] != null)// 判断起点与终点之间有几个棋子 {

count++;

}

}

if (count != 1) {// 如果不止一个棋子

canMove = false;// 不可以走

}

} else if (qiZi[endI][endJ] == null)// 如果终点没有棋子

{

for (j = minJ + 1; j

if (qiZi[minI][j] != null)// 如果起止点之间有棋子

{

canMove = false;// 不可以走

break;

}

}

}

} else if (maxJ == minJ)// 如果走的是横线

{

if (qiZi[endI][endJ] != null)// 如果终点有棋子

{

int count = 0;

for (i = minI + 1; i

if (qiZi[i][minJ] != null)// 判断起点与终点之间有几个棋子 {

count++;

}

}

if (count != 1)// 如果不止一个棋子

{

canMove = false;// 不可以走

}

} else if (qiZi[endI][endJ] == null)// 如果终点没有棋子

{

for (i = minI + 1; i

if (qiZi[i][minJ] != null)// 如果起止点之间有棋子

{

canMove = false;// 不可以走

break;

}

}

}

} else if (maxJ != minJ && maxI != minI) {

// 如果走的既不是竖线,也不是横线,则不可以走

canMove = false;

}

}

(6) 马:

移动范围:任何位置

移动规则:每一步只可以水平或垂直移动一点,再按对角线方面向左或者右移动。另外,在移动的过程中不能够穿越障碍。

public void ma(int maxI, int minI, int maxJ, int minJ, int startI, int startJ, int endI, int endJ) {// 对"馬"的处理方法

int a = maxI - minI;

int b = maxJ - minJ;// 获得两坐标点之间的差

if (a == 1 && b == 2)// 如果是竖着的"日"字

{

if (startJ > endJ)// 如果是从下向上走

{

if (qiZi[startI][startJ - 1] != null)// 如果马腿处有棋子 {

canMove = false;// 不可以走

}

} else {// 如果是从上往下走

if (qiZi[startI][startJ + 1] != null)// 如果马腿处有棋子 {

canMove = false;// 不可以走

}

}

} else if (a == 2 && b == 1)// 如果是横着的"日"

{

if (startI > endI)// 如果是从右往左走

{

if (qiZi[startI - 1][startJ] != null)// 如果马腿处有棋子 {

canMove = false;// 不可以走

}

} else {// 如果是从左往右走

if (qiZi[startI + 1][startJ] != null)// 如果马腿处有棋子 {

canMove = false;// 不可以走

}

}

} else if (!((a == 2 && b == 1) || (a == 1 && b == 2)))

// 如果不时"日"字

{

canMove = false;// 不可以走

}

}

(7) 兵:

移动范围:任何位置

移动规则:每步只能向前移动一点。过河以后,它便增加了向左右移动的能力,兵不允许向后移动。

public void bing(int maxI, int minI, int maxJ, int minJ, int startI, int startJ, int endI, int endJ) {// 对"兵"的处理

if (startJ

{

if (startI != endI)// 如果不是向前走,横左边变化

{

canMove = false;// 不可以走

}

if (endJ - startJ != 1)// 如果走的不是一格

{

canMove = false;// 不可以走

}

} else {// 如果已经过河

if (startI == endI) {// 如果走的是竖线,横坐标相同

if (endJ - startJ != 1)// 如果走的不是一格

{

canMove = false;// 不可以走

}

} else if (startJ == endJ) {// 如果走的是横线

if (maxI - minI != 1) {// 如果走的不是一格

canMove = false;// 不可以走

}

} else if (startI != endI && startJ != endJ) {

// 如果走的既不是竖线,也不是横线,则不可以走

canMove = false;

}

}

}

6运行测试

6.1 服务端

(1) 端口限制测试,端口只能输入0-65535之间的整数,其他输入一律无效。如图6-1所示。

6-1 服务器端端口限制测试

(2) 服务器列表显示在线玩家IP地址以及玩家昵称测试。如图6-2所示。

6-2 显示在线用户列表

6.2 客户端

(1) 昵称测试,默认情况下不允许同名玩家出现。例服务端显示已经有play1玩家登陆,如果再有play1的玩家登陆则提示重名信息。如图6-3所示。

图6-3 昵称测试

(2) 玩家挑战测试,play1在下拉列表中选择play3进行对弈,并发出相应的提示信息。如图 6-4所示。

图6-4 玩家挑战测试

(3) 繁忙测试,当一方玩家正在对弈中,其他玩家无法向其挑战。例玩家play1与play3对弈中,玩家play2无法向玩家play1或play3发起挑战。如图6-5所示。

图6-5繁忙测试

(4) 胜负判定测试,当玩家的“将”或“帅”被吃掉,则判定该玩家失败,弹出相应的失败消息提示框,同时另外一方显示胜利。例玩家play1与play3的对弈结果。如图6-6所示。

图6-6 胜负判定

2011届软件工程专业毕业设计(论文)

7 总结

本程序设计实现了基本于Java平台的局域网象棋对弈游戏的简单开发,具有一定的可玩性,可作为工作之余的休闲娱乐游戏。虽然在开发过程中经常遇到许多技术困难,但是经过查阅相关资料和调试排错解决了绝大部分的问题。

由于技术水平有限,仅仅实现了象棋对弈游戏的基本功能,能够实现局域网的人人对战,程序做的还不够完善,功能单一,比较简单,但我相信,随着时间的推移、个人水平的增长,一定能重写一个比较完善的象棋对弈游戏。

中国象棋在棋牌类游戏中非常经典,它对于如何走棋的判断、对蹩脚马和塞眼象的判断,这些算法的设计比较复杂。网络通信方面的数据传输和识别,视图的更新和重绘都是本系统设计的重点。通过这段时间的学习,进一步加深了Java的学习,巩固了以前的一些基础知识。虽然程序不是十分完美,但是看着自己的努力的成果,还是感到非常欣慰。

致谢

经过一个学期的努力学习和工作,我的象棋对弈游戏在老师和同学的帮助下终于开发完成了!在这个项目的开发过程中,我深深地体会到了软件开发人员应具备的素质和肩负的责任,同时也深深感受到了集体的温暖和团结的力量。

在这里,首先我要衷心地感谢我的导师——老师给予我的指导和帮助,使我在系统的设计和实现中少走了不少的弯路。在导师的指导下,我的系统一点,一点的开发,功能一步,一步的实现。她严谨的治学态度,循循善诱的教导方式给我留下了深刻的印象。其次,我还要感谢同学的真诚帮助,他们在关键的时候给予我莫大的帮助,让我深深感受到了团结合作的力量。最后,在这里请允许我向所有帮助我的老师和同学表示最真诚的谢意!

参考文献

[1]张思民,梁维娜.Java程序设计实践教程[M].北京:清华大学出版社,2006.8

[2]朱福喜,唐晓军.Java程序设计技巧与开发实例[M].北京:人民邮电出版社, 2007.6

[3]刘新.java开发技术大全[M].北京:清华大学出版社,2009,2

[4]赵文靖.Java程序设计基础与上机指导[M].北京:清华大学出版社,2006

[5]杨昭编.二级Java语言程序设计教程[M].北京:中国水利水电出版社,2006

[6]Rogers Cadenhead. Java编程入门经典.梅兴文译.第4版.北京:人民邮电出版社,2007

[7]Bruce Eckel. Thinking In Java[M].北京:机械工业出版社,2007

[8]陈轶,姚晓昆.Java程序设计实验指导[M].北京:清华大学出版社,2006

[9]吴其庆.Java程序设计实例教程[M].北京:冶金工业出版社,2006

[10]葛维蒲.象棋入门(修订本)[M].上海:上海辞书出版社,2008

[11]黄少龙.象棋入门[M].成都:成都时代出版社,2007

第27页 共27页


相关内容

  • 3中国象棋网络对战软件设计说明书
  • 中国象棋网络对战 软件设计说明书 吴刚 学号:201242238 12级信息工程2班 2014年12月10号 1绪论........................................................................错误!未定义书签. 1.1项目开发的背景 ...

  • 基于MFC的对战象棋设计与实现毕业论文
  • 毕业设计说明书 学生姓名 学院 学 号 计算机科学与技术学院 软件工程 基于MFC的 对战象棋设计与实现 专 业 题 目 指导教师 (姓 名) (专业技术职称/学位) 年 月 毕业论文独创性声明 本人郑重声明: 本论文是我个人在导师指导下进行的研究工作及取得的研究成果.本论文除引文外所有实验.数据和 ...

  • N多毕业设计题目
  • 基于Ajax技术的WEB应用的设计 又快到毕业的时候了,大家该准备做毕业设计了.大学问问特意收集了一些毕业设计(论文)的题目,供大家选择. VB售楼管理系统 VB无纸化考试系统 VB小区物业管理系统 VB航空公司管理信息系统 VB计算机机房管理系统 VB房地产评估系统VB+SQL2000 VB光盘信 ...

  • 计算机常用1端口一览表
  • 计算机常用端口一览表 1 传输控制协议端口服务多路开关选择器 2 compressnet 管理实用程序 3 压缩进程 5 远程作业登录 7 回显(Echo) 9 丢弃 11 在线用户 13 时间 15 netstat 17 每日引用 18 消息发送协议 19 字符发生器 20 文件传输协议(默认数据 ...

  • 2016年年中工会工作检查
  • 2016年年中工会工作检查 2016年,公司工会在公司的正确领导下,在行政的大力支持下,各项工作紧扣公司安全生产.经营管理.工程建设和精神文明建设工作,不断深化民主管理,认真履行工会职能,维护职工合法权益,强化群众安全监督,通过开展经常性的职工教育.劳动竞赛.厂务公开.文体活动等,不断激励广大职工为 ...

  • 2011年机关办公室工作计划
  • 2011年,办公室要紧紧围绕反腐倡廉和委局工作大局,以贯彻落实"四个文件"精神为契机,按照加强县级纪检监察机关建设和建设学习型政党的要求,以建设"学习率先型.文化丰富型.作风务实型.工作效能型"机关为目标,认真学习贯彻中央和省市纪委全会精神,全面完成各项目标任 ...

  • 小学发展规划
  • 教育是一项系统工程,学校教育又是教育的主阵地,需要从小学开始就奠定学校教育的扎实基础。因而,贯彻中共中央和上海市委关于制定十五计划建议的要求,进一步落实全国、市和区教育工作会议精神,围绕实现静安精品教育区的目标,开创新世纪全面推进素质教育的新局面,必须切实制订好学校发展规划。 一、制订规划的基础 本 ...

  • 智能机器人的发展与展望
  • 智能机器人的发展与展望 关键词:智能机器人.人工智能.感知.决策 摘要:本文首先介绍了机器人的起源.历史发展,然后对当代智能机器人的三大要素进行分析,并提出存在的主要问题和面临的挑战,最后对智能机器人的未来进行展望,就未来机器人如何发展的问题提出了自己的看法. 引言:从1954年美国戴沃尔最早提出了 ...

  • 在集团运输安全生产大会上的发言材料
  • 去年以来,江村站作为集团公司安全文化建设五个试点单位之一,按照集团公司"高标准.讲科学.不懈怠.严管理.建机制.强基础"的安全工作基本要求和总体思路以及<集团公司安全文化建设三年规划>部署,坚持以创建"和谐班组"活动为载体,深入推进安全文化建设,促 ...