新書推薦:
《
画楼:《北洋画报》忆旧(年轮丛书)
》
售價:HK$
337.5
《
大国脊梁:漫画版
》
售價:HK$
80.2
《
跟着渤海小吏读历史:大唐气象(全三册)
》
售價:HK$
189.0
《
心智的构建:大脑如何创造我们的精神世界
》
售價:HK$
81.4
《
美国小史(揭秘“美国何以成为美国”,理解美国的经典入门读物)
》
售價:HK$
81.4
《
中国古代北方民族史丛书——东胡史
》
售價:HK$
87.8
《
巨人传(插图珍藏本)
》
售價:HK$
705.6
《
地下(村上春树沙林毒气事件的长篇纪实)
》
售價:HK$
76.7
|
編輯推薦: |
1)本书以五子棋游戏制作为背景,介绍使用Java语言进行软件开发的技术与技巧,内容包括单机版五子棋、网络五子棋、棋谱保存与回放、以及人机对战,本书可作为Java程序设计实训、Java课程设计课程的教材,也可以作为毕业设计或游戏编程爱好者的参考书;(2)本书在写作过程中,始终强调面向对象的编程思想,重点训练Java中的网络编程、数据库编程、界面编程、文件操作以及异常处理等;(3)教材以五子棋游戏制作为例,提高学生的学习兴趣,激发学生的学习积极性。
|
內容簡介: |
本书以五子棋游戏制作为例,介绍Java在开发应用软件中的各种技术,并体现面向对象的设计思想。内容包括单机版五子棋、下网络五子棋、下棋数据的保存以及人机对战等。书中对于Java中的输入输出、数据库、异常处理、网络编程以及界面编程等进行了比较深入的探讨。 本书可作为计算机相关专业Java课程设计、Java实训等课程的教材,也可作为学生毕业设计以及Java程序设计爱好者的参考书。
|
目錄:
|
目录
第1章单机版五子棋游戏1
1.1五子棋游戏窗口制作1
1.2创建棋盘类2
1.2.1准备图片2
1.2.2棋盘类的创建2
1.2.3显示棋盘3
1.3创建棋子类4
1.3.1棋子类4
1.3.2在棋盘上画出棋子6
1.4实现单击鼠标下棋6
1.5判断赢棋8
1.6实现工具栏上的功能11
1.7改变鼠标的形状13
1.8作业13第2章网络五子棋15
2.1服务器端界面制作16
2.2创建客户端界面17
2.2.1创建主窗口和棋盘17
2.2.2创建客户端界面右侧的3个类18
2.2.3创建客户端界面下方的控制面板类21
2.3实现连接主机按钮的功能22
2.3.1连接服务器获取用户名23
2.3.2将已经连接的客户端添加到用户列表中26
2.4实现加入游戏按钮的功能31
2.4.1客户端申请加入后对方选择同意或拒绝31
2.4.2完成猜棋并准备好下棋37
2.5实现下棋功能41
2.5.1客户端向服务器发送下棋消息41
2.5.2服务器接收消息并处理43
2.5.3客户端接收消息并处理43
2.6实现放弃游戏的功能45
2.6.1Command类添加常量46
2.6.2添加放弃游戏的响应代码46
2.6.3在Communication类中添加giveup
方法46
2.6.4服务器接收giveup命令并处理46
2.7加入计时功能47
2.7.1设计计时线程类47
2.7.2猜先后启动倒计时线程48
2.8完善关闭程序按钮的功能49
2.8.1在Command类中添加命令49
2.8.2客户端向服务器发送命令49
2.8.3服务器处理quit命令50
2.8.4客户端处理delete命令50
2.9作业51第3章下棋数据的保存52
3.1创建数据库52
3.1.1数据库设计52
3.1.2创建数据库53
3.2用户管理55
3.2.1数据库连接类55
3.2.2用户管理56
3.3用户注册和登录61
3.3.1准备工作62
3.3.2用户登录62
3.3.3用户注册67
3.4记录棋局和棋谱71
3.4.1记录棋局71
3.4.2记录棋谱77
3.5查询棋局和棋谱欣赏80
3.5.1查询棋局81
3.5.2棋谱欣赏85
3.6作业90第4章人机对战91
4.1准备工作91
4.1.1在主程序中添加复选框91
4.1.2在棋盘类中添加成员变量92
4.1.3棋盘类中添加方法以及修改已有的
方法92
4.2计算机智能下棋95
4.2.1处理棋盘类中的数据成员95
4.2.2五子棋的棋型与估值97
4.2.3创建估值类Evaluate100
4.2.4实现计算机智能下棋111
4.3极小极大搜索法提高下棋水平112
4.3.1极小极大算法与棋局的评价113
4.3.2极小极大算法的实现115
4.4AlphaBeta搜索方法124
4.4.1AlphaBeta搜索方法简介124
4.4.2AlphaBeta搜索方法实现125
4.5作业128
作业参考答案130
参考文献152
|
內容試閱:
|
前言 Java是目前使用最广泛的语言之一,对于软件开发人员,掌握Java语言基础以及拥有使用Java进行软件开发的能力是非常重要的,因此大多数与计算机相关的专业都开设了Java程序设计课程。Java程序设计是一门实践性很强的课程,仅仅掌握Java的基本语法知识,与利用Java进行软件开发还有很大的差距。掌握Java基本知识后,应该通过大量的编程实践,逐步提高利用Java进行软件开发的能力。本书以五子棋游戏制作为例,介绍利用Java进行软件开发的技术。五子棋游戏比较简单,是大家比较熟悉的游戏之一,因此选择五子棋游戏为例,有助于提高学习者的兴趣,易于跟着书中介绍的步骤,一步步将五子棋游戏制作出来。为了简单起见,本书中的五子棋程序不考虑禁手。本书由4章内容组成,包括单机版五子棋、网络五子棋、下棋数据的保存,以及人机对战;涉及的主要知识有异常处理、输入输出流、数据库编程、多线程和网络编程等。本书可作为计算机相关专业Java课程设计、Java实训等课程的教材,也可作为学生毕业设计和Java游戏程序爱好者的参考书。本书的所有程序都由作者亲自编写,并在JDK1.6环境下调试通过,数据库使用的是MySQL数据库。为了方便教师教学与学生学习,本书为使用本教材的教师提供PowerPoint电子教案,方便教师根据具体情况进行必要的修改,相关资源可以从清华大学出版社网站www.tup.com.cn下载。本书由宁淑荣、杨国兴主编,参加编写工作的还有庄凤娟、王国芳等。由于作者水平有限,书中难免有不妥之处,恳请广大读者批评指正。
作者2017年3月
第3章下棋数据的保存为了保存用户下棋的数据,用户必须先注册、登录服务器才能下棋。棋局结束后,将棋局保存在数据库中,将棋谱保存在数据文件中。将来可以根据用户名查询出该用户下过的所有棋局,可以选择其中的某一个棋局,将棋谱读出来回放。在这里我们使用的数据库是MySQL数据库。3.1创建数据库[1]3.1.1数据库设计为了保存用户信息和棋局信息,我们先创建一个数据库fiveChess,数据库中包含两个数据表user和game。user表用于保存用户信息,字段包括用户ID、姓名、密码、电子邮箱、级别和注册日期。user表结构如表3.1所示。表3.1user表结构字段名类型长度允许空备注useridINT否主键,自动增长userNameVARCHAR10否用户名passWordVARCHAR10否密码emailVARCHAR30否邮箱levelINT否级别regDateDate否注册日期game表用于保存棋局信息,字段包括用户ID、下棋日期、黑方、白方、赢棋方和记录棋谱的文件名。game表结构如表3.2所示。表3.2game表结构字段名类型长度允许空备注gameidINT否主键,自动增长gameDateDate否下棋日期playerBlackVARCHAR10否黑方playerWhiteVARCHAR10否白方winnerVARCHAR10否赢棋方manualFileNameVARCHAR100否记录棋谱的文件名3.1.2创建数据库首先创建工程NetFive。在后面的程序中还会设计很多类,因此我们建立3个包,将实现下棋功能的类放在five包中,与用户有关的类放在user包中,与棋局和棋谱有关的类放在game包中。首先建立five包,将第2章程序中的类全部移到five包中。为了在Java程序中操作数据库中的数据,需要配置数据库驱动程序JDBC。如果计算机中没有,可从MySQL网站上下载mysqlconnectorjava压缩文件,然后解压缩。在eclipse中右击工程名NetFive,在弹出的快捷菜单中选择build path | add external Archives菜单项,在JAR Selection对话框中找到上面解压缩的jar文件,如图3.1所示,单击打开按钮,将该文件导入到我们的工程中。图3.1JAR Selection对话框新建user包,在user包中新建类CreateDatabase,该类负责创建数据库fiveChess,以及数据库中的两个表user和game。代码如下: public class CreateDatabase {public static void mainString\[\] args {Connection conn=null;Statement stmt=null;try {Class.forName"com.mysql.jdbc.Driver";conn=DriverManager.getConnection"jdbc:mysql:localhost:3306","root","1234";stmt=conn.createStatement;}catch ClassNotFoundException e {e.printStackTrace;System.exit-1;}catch SQLException e {e.printStackTrace;try {conn.close;}catch SQLException e1 {e1.printStackTrace;System.exit-1;}}createDatabasestmt, "fiveChess";try {stmt.close;conn.close;}catch SQLException e {e.printStackTrace;}}public static void createDatabaseStatement stmt, String dbName{try {stmt.executeUpdate"create database " dbName;stmt.executeUpdate"use " dbName;String sql;sql="create table userid int auto_increment not null primary key," "name VARCHAR10 not null, " "password VARCHAR10 not null," "email VARCHAR30 not null," "level int not null," "regDate date not null";stmt.executeUpdatesql;sql="insert into username,password,email,level,regDate " "values''test1'', ''test1'',''test1@five.com'',1,''2016-01-22''";stmt.executeUpdatesql;sql="insert into username,password,email,level,regDate " "values''test2'', ''test2'',''test2@five.com'',1,''2016-01-22''";stmt.executeUpdatesql;sql="create table gameid int auto_increment not null primary key," "gameDate date not null, " "playerBlack VARCHAR10 not null, " "playerWhite VARCHAR10 not null, " "winner VARCHAR10 not null, " "manualFileName VARCHAR100 not null";stmt.executeUpdatesql;sql="insert into gamegameDate, playerBlack, playerwhite, winner,manualFileName"" values''2016-01-22'',''test1'',''test2'',''test2'',''game1201601221205.fiv''";stmt.executeUpdatesql;sql="insert into gamegameDate, playerBlack, playerwhite, winner,manualFileName"" values''2016-01-22'',''test1'',''test2'',''test1'',''game1201601221848.fiv''";stmt.executeUpdatesql;}catchSQLException e {e.printStackTrace;}}}在主方法中创建数据库连接Connection对象和Statement对象,然后调用createDatabase方法,创建数据库fiveChess,再创建user表,并向user表中插入两条记录,最后再创建game表,并向game表插入两条记录。给两个表分别插入两条记录是为了测试创建数据库和表的功能是否完善,实际中不必插入这些记录。运行CreateDatabase类,创建数据库和表,以后的程序是在这两个表的基础上实现的。创建好数据库之后,就不要再次运行CreateDatabase类了,以后如果需要初始化数据库,可以在这个类的基础上稍加修改。3.2用户管理为了实现用户注册和登录的功能,我们首先创建用户管理类,实现用户的添加和查找功能。3.2.1数据库连接类由于在后面的程序中经常要进行数据库连接操作,因此我们首先设计一个连接数据库的类DBConnection,将其放在user包中。代码如下: public class DBConnection {Connection conn=null;public DBConnection{try {Class.forName"com.mysql.jdbc.Driver";conn=DriverManager.getConnection"jdbc:mysql:localhost:3306fiveChess","root","1234";}catchClassNotFoundException e {e.printStackTrace;System.exit-1;}catchSQLException e {e.printStackTrace;ifconn!=null{try {conn.close;}catch SQLException e1 {e1.printStackTrace;System.exit-1;}}}}public Connection getConn {return conn;}}DBConnection类的代码也比较简单,在构造方法中创建Connection对象。其他类可以调用DBConnection类的getConn方法获得这个数据库连接对象。3.2.2用户管理[45]1. User类在user包中添加User类,因为在后面的注册程序中,需要在客户端与服务器之间传递User对象,因此User类要实现Serializable接口,代码如下。public class User implements Serializable {private static final long serialVersionUID=-8418444131403945274L;private String userName;private String passWord;private String email;private intlevel;private DateregDate;public UserString userName, String passWord, String email, int level, Date regDate {this.userName=userName;this.passWord=passWord;this.email=email;this.level=level;this.regDate=regDate;}public String getEmail {return email;}public void setEmailString email {this.email=email;}public String getPassWord {return passWord;}public void setPassWordString passWord {this.passWord=passWord;}public String getUserName {return userName;}public void setUserNameString userName {this.userName=userName;}public int getLevel {return level;}public void setLevelint level {this.level=level;}public Date getRegDate {return regDate;}public void setRegDateDate regDate {this.regDate=regDate;}public String toString{return userName ":" passWord ":" email ":" level ":" regDate;}}User类中的属性分别对应user表中的字段,这里,注册日期的类型Date是java.util.Date。添加toString方法是为了在测试程序时,方便输出User对象的信息。2. 用户管理类在user包中创建用户管理类UserDao,完成向user表添加用户以及在user表中根据用户名和密码查找用户,代码如下。public class UserDao {Connection conn=null;Statement st=null;PreparedStatement pstmt;ResultSet rs=null;public UserDao{conn=new DBConnection.getConn;}public boolean addUserUser user{String userName=user.getUserName;String passWord=user.getPassWord;String email=user.getEmail;int level=user.getLevel;Date regDate=user.getRegDate;try {st=conn.createStatement;rs=st.executeQuery"select from user where name=''" userName "''";ifrs.next{return false;}else{String sql="insert into useruserName,passWord,email,level,regDate" "values?,?,?,?,?";pstmt=conn.prepareStatementsql;pstmt.setString1,userName;pstmt.setString2, passWord;pstmt.setString3, email;pstmt.setInt4, level;pstmt.setDate5, new java.sql.DateregDate.getTime;pstmt.executeUpdate;return true;}}catch SQLException e {e.printStackTrace;return false;}finally{ifrs!=null{try {rs.close;} catch SQLException e {e.printStackTrace;}}ifst!=null{try {st.close;} catch SQLException e {e.printStackTrace;}}}}public User getUserString userName, String passWord {try {st=conn.createStatement;String sql="select from user where name=''" userName "'' and passWord=''" passWord "''";rs=st.executeQuerysql;ifrs.next{String email=rs.getString"email";int level=rs.getInt"level";Date regDate=rs.getDate"regDate";return new UseruserName,passWord,email,level,regDate;}else{return null;}}catch SQLException e {e.printStackTrace;return null;}finally{ifrs!=null{try {rs.close;} catch SQLException e {e.printStackTrace;}}ifst!=null{try {st.close;} catch SQLException e {e.printStackTrace;}}}}}addUserUser user方法向用户表添加一个用户。因为表中不允许有同名的用户,因此首先在用户表中查找和user同名的记录,如果找到,则不能添加,返回false。如果找不到,则将user对象代表的用户数据添加到用户表中,返回true。getUserString userName, String passWord方法在用户表中查找参数指定的用户名和密码对应的记录,如果找到,则由这条记录的数据创建User对象,并返回,如果找不到,则返回null。3. 测试用户类和用户管理类完成了User类和UserDao类之后,可以添加一个临时的测试类,测试UserDao类添加用户和查找用户的功能,例如下面的程序。public class Test {public static void mainString\[\] args {UserDao dao=new UserDao;User user=new User"test3","aaa","tetsts",1,new Date;ifdao.addUseruserSystem.out.println"添加成功!";elseSystem.out.println"添加失败!";User user2=dao.getUser"test3", "aaa";ifuser2!=null{System.out.println"找到该用户!";System.out.printlnuser2;}else{System.out.println"未找到该用户!";}
User user3=dao.getUser"test3", "dddd";ifuser3!=null{System.out.println"找到该用户!";}else{System.out.println"未找到该用户!";}}}根据测试结果,对照数据库中的user表,如果有不合理的地方,则需要修改User类或UserDao类,测试成功后,可将测试类Test删除。3.3用户注册和登录在客户端提供一个注册和登录界面,用户填好数据后向服务器发送注册或登录命令,服务器处理后,将处理结果通知客户端。运行界面如图3.2所示。图3.2注册和登录界面在客户端界面单击登录按钮,出现用户登录对话框,可以填写用户名和密码,单击登录按钮,向服务器发送login命令。如果用户还没有注册,可以单击注册按钮,在出现的用户注册对话框中输入相关信息后,单击注册按钮,向服务器发送register命令。客户端与服务器之间发送命令的流程如图3.3所示。图3.3注册登录流程注册时,客户端发送register命令,参数是User对象,服务器通过UserDao类向用户表添加记录。如果成功,则向客户端发送参数为true的register命令;如果失败,则向客户端发送参数为false的register命令。登录时,客户端发送login命令,参数是用户名和密码,服务器通过UserDao类从用户表中查找用户名和密码指定的记录,如果找到,则登录成功,向客户端发送参数为true的login命令;如果没找到,则登录失败,向客户端发送参数为false的login命令。3.3.1准备工作[45]1. Command类添加命令常量在Command类中添加下面两个命令常量:public static final String REGISTER="register";public static final String LOGIN="login"; 2. 修改PanelControl类将PanelControl类中的连接主机按钮改为登录按钮,即将connectButton改为loginButton,连接主机改为登录,然后将程序中的所有connectButton替换为loginButton。3. FiveClient类中添加方法由于在用户登录对话框类中要用到FiveClient类中的Communication属性c,而登录对话框类和FiveClient类不在一个包中,因此需要在FiveClient类中添加getC方法,以便在其他类中获取Communication对象,代码如下。public Communication getC{return c;}3.3.2用户登录[45]1. Communication类的登录方法由于连接服务器已经被登录代替了,因此可以删除FiveClient类中的connect方法。将Communication类中的connect方法改为login方法,代码如下: public boolean loginString ip, String userName, String passWord {try {s=new Socketip,FiveServer.TCP_PORT;dis=new DataInputStreams.getInputStream;dos=new DataOutputStreams.getOutputStream;dos.writeUTFCommand.LOGIN ":" userName ":" passWord;String msg=dis.readUTF;String\[\] words=msg.split":";ifwords\[0\].equalsCommand.LOGIN && words\[1\].equals"true"{fc.isConnected=true;new ReceaveThreads.start;fc.control.exitGameButton.setEnabledtrue;fc.control.loginButton.setEnabledfalse;fc.control.joinGameButton.setEnabledtrue;fc.control.cancelGameButton.setEnabledfalse;return true;}else{s.close;return false;}} catch UnknownHostException e {e.printStackTrace;} catch IOException e {ifs!=null{try {s.close;} catch IOException e1 {e1.printStackTrace;}}e.printStackTrace;}return false;}连接服务器后,向服务器发送login命令,然后等待服务器返回的结果。如果返回login: true,说明登录成功,为相关变量设置值,创建接收消息的线程并启动,设置按钮的状态;如果返回login: false,说明登录失败。2. 登录对话框在user包中创建登录对话框DialogLogin类,代码如下: public class DialogLogin extends JDialog implements ActionListener{JTextField tfUserName=new JTextField14;JTextField tfPassword=new JTextField14;JButton jbLogin=new JButton"登录";JButton jbRegister=new JButton"注册";JButton jbCancel=new JButton"取消";String ip;FiveClient fc;public DialogLoginWindow parent, String ip {superparent, "用户登录",Dialog.ModalityType.APPLICATION_MODAL;fc=FiveClient parent;this.ip=ip;createGUI;}public void actionPerformedActionEvent e {String str=e.getActionCommand;if "登录".equalsstr {String userName=tfUserName.getText;String passWord=tfPassword.getText;ifuserName==null||userName.isEmpty ||passWord==null||passWord.isEmpty{JOptionPane.showMessageDialogthis, "各项数据不能为空!";return;}else {iffc.getC.loginip, userName, passWord{JOptionPane.showMessageDialogthis, "登录成功!";this.dispose;}else{JOptionPane.showMessageDialogthis, "用户名或密码不符!";}}}else if "注册".equalsstr {DialogRegister rd=new DialogRegisterthis,ip;}else if"取消".equalsstr{this.dispose;}}public void createGUI {this.setLayoutnew BorderLayout;JPanel jpWest=new JPanel;JPanel jpCenter=new JPanel;JPanel jpSouth=new JPanel;jpWest.setLayoutnew GridLayout3, 1;jpCenter.setLayoutnew GridLayout3, 1;jpSouth.setLayoutnew FlowLayout;jpWest.addnew JLabel"用户名:";jpWest.addnew JLabel"密 码:";jpCenter.addtfUserName;jpCenter.addtfPassWord;this.addnew JPanel,BorderLayout.NORTH;this.addjpWest,BorderLayout.WEST;this.addjpCenter,BorderLayout.CENTER;jpSouth.addjbLogin;jpSouth.addjbRegister;jpSouth.addjbCancel;jbLogin.addActionListenerthis;jbRegister.addActionListenerthis;jbCancel.addActionListenerthis;this.addjpSouth,BorderLayout.SOUTH;this.setDefaultCloseOperationDISPOSE_ON_CLOSE;this.setLocation450,250;this.pack;this.setVisibletrue;}}由于对话框本身负责事件监听,因此DialogLogin类实现了ActionListener接口。为了便于看清程序的逻辑结构,我们将创建界面的代码放在了一个单独方法createGUI中。在构造方法中设置对话框的父窗口(由参数指定)、标题以及显示模式,然后调用createGUI方法创建对话框界面并显示。在actionPerformed方法中,处理3个按钮的单击事件。如果是登录按钮,则首先获取编辑框中的用户名和密码,如果用户名和密码都不为空,则调用Communication类中的login方法登录,如返回true,则登录成功,返回false,则登录失败。如果是注册按钮,则显示注册对话框,完成注册功能注册功能的实现稍后给出。如果是取消按钮,则使对话框消失。3. 显示登录对话框在fiveClient中修改登录按钮的监听程序段,显示登录对话框,代码如下: else ife.getSource==control.loginButton{c=new CommunicationFiveClient.this;DialogLogin dr=new DialogLoginFiveClient.this, FiveClient.this.control.inputIP.getText;}在创建DialogLogin对象时,要通过构造方法的参数指定对话框的父窗口和服务器的ip地址。4. 服务器处理login命令由于现在已经不需要服务器为用户起名了,因此可以删除服务器类的静态成员clientNameNum,然后修改startServer方法。修改后的代码如下: public void startServer{try {ss=new ServerSocketTCP_PORT;whiletrue{Socket s=ss.accept;InputStream is=s.getInputStream;OutputStream os=s.getOutputStream;DataInputStream dis=new DataInputStreamis;DataOutputStream dos=new DataOutputStreamos;String msg=dis.readUTF;String\[\] words=msg.split":";ifwords\[0\].equalsCommand.LOGIN{String userName=words\[1\];String passWord=words\[2\];UserDao ud=new UserDao;ifud.getUseruserName, passWord!=null{dos.writeUTFCommand.LOGIN ":true";clientNum;Client c=new ClientuserName, s;clients.addc;lStatus.setText"连接数" clientNum;taMessage.appends.getInetAddress.getHostAddress " " userName "\\n";tellNamec;addAllUserToMec;addMeToAllUserc;new ClientThreadc.start;}else{dos.writeUTFCommand.LOGIN":false";s.close;}}}} catchIOException e {e.printStackTrace;}}现在客户端连接服务器有注册和登录两个目的,因此服务器在接收到客户端连接时,要分别处理这两种情况。如果是login命令,则将用户名和密码取出,利用UserDao的getUser方法在user表中查找指定的用户,如果返回值不为空,则登录成功,向客户端发送登录成功的命令,然后进行相应的处理,创建接收该客户端命令的线程并启动。为了不改变以前的程序结构,我们仍通过tellName方法向客户端发送客户名,当然这个客户名就是客户端传过来的名字。如果登录失败,则向客户端发送登录失败的命令,然后将该Socket关闭。3.3.3用户注册与登录后就准备下棋不同,注册是一个相对独立的功能,因此对于注册功能,我们不使用Communication类与服务器通信,而是在注册对话框类中添加自己的Socket属性实现与服务器的连接。1. 注册对话框类在user包中创建注册对话框DialogRegister类,代码如下: public class DialogRegister extends JDialog implements ActionListener {JTextField tfUserName=new JTextField20;JTextField tfPassword=new JTextField20;JTextField tfRePassword=new JTextField20;JTextField tfEmail=new JTextField20;JButton jbRegister=new JButton"注册";JButton jbCancel=new JButton"取消";String ip;public DialogRegisterWindow parent, String ip {superparent, "用户注册", Dialog.ModalityType.APPLICATION_MODAL;this.ip=ip;createGUI;}public void actionPerformedActionEvent e {String str=e.getActionCommand;if "注册".equalsstr {String userName=tfUserName.getText;String passWord=tfPassWord.getText;String rePassWord=tfRePassWord.getText;String email=tfEmail.getText;ifuserName==null||userName.isEmpty || passWord==null||passWord.isEmpty || rePassWord==null||rePassWord.isEmpty || email==null||email.isEmpty{JOptionPane.showMessageDialogthis, "各项数据不能为空!";return;}if !passWord.equalsrePassWord {JOptionPane.showMessageDialogthis, "两次密码不一致!";return;}else {ifregisternew UseruserName,passWord,email,1,new Date{JOptionPane.showMessageDialogthis, "注册成功!";}else{JOptionPane.showMessageDialogthis, "注册失败!可能重名。";}}}else if"取消".equalsstr{this.dispose;}}public boolean registerUser u{Socket s=null;InputStream is=null;OutputStream os=null;DataInputStream dis=null;DataOutputStream dos=null;ObjectOutputStream oos=null;try {s=new Socketip, FiveServer.TCP_PORT;is=s.getInputStream;os=s.getOutputStream;dis=new DataInputStreamis;dos=new DataOutputStreamos;dos.writeUTFCommand.REGISTER;oos=new ObjectOutputStreamos;oos.writeObjectu;String msg=dis.readUTF;ifmsg.equalsCommand.REGISTER ":true"{return true;}else{return false;}} catchUnknownHostException e {e.printStackTrace;return false;} catchIOException e {e.printStackTrace;return false;}finally{try {oos.close;dos.close;dis.close;s.close;} catchIOException e {e.printStackTrace;}}}public void createGUI {this.setLayoutnew BorderLayout;JPanel jpWest=new JPanel;JPanel jpCenter=new JPanel;JPanel jpSouth=new JPanel;jpWest.setLayoutnew GridLayout4, 1;jpCenter.setLayoutnew GridLayout4, 1;jpSouth.setLayoutnew FlowLayout;jpWest.addnew JLabel"用户名:";jpWest.addnew JLabel"密 码:";jpWest.addnew JLabel"确认密码:";jpWest.addnew JLabel"邮 箱:";jpCenter.addtfUserName;jpCenter.addtfPassWord;jpCenter.addtfRePassWord;jpCenter.addtfEmail;this.addjpWest, BorderLayout.WEST;this.addjpCenter, BorderLayout.CENTER;jpSouth.addjbRegister;jpSouth.addjbCancel;jbRegister.addActionListenerthis;jbCancel.addActionListenerthis;this.addjpSouth, BorderLayout.SOUTH;this.setDefaultCloseOperationDISPOSE_ON_CLOSE;this.setLocation450, 250;this.pack;this.setVisibletrue;}}在actionPerformed方法中,如果是注册按钮的事件,则先检查用户名、密码、重复密码以及邮箱是否有空的,如果没有空的再检查两次密码输入是否一致,如果一致,则调用register方法注册,如果方法返回true,表示注册成功,如果返回false,表示注册失败。在register方法中,首先连接服务器,随后向服务器发送register命令,接着再发一个User对象。之后,再从服务器读取字符串,如果是register: true,表示注册成功,如果是register: false,表示注册失败。在登录对话框类DialogLogin中,通过单击注册按钮显示注册对话框。将原来类中注释掉的一行的注释去掉,代码如下:else if "注册".equalsstr {DialogRegister rd=new DialogRegisterthis,ip;}2. 服务器处理注册命令在服务器类的startServer方法中,与登录代码并列,加入注册的处理代码如下:ifwords\[0\].equalsCommand.REGISTER{ObjectInputStream ois=null;try {ois=new ObjectInputStreamis;User u=User ois.readObject;UserDao ud=new UserDao;ifud.addUseru{dos.writeUTFCommand.REGISTER ":true";}else{dos.writeUTFCommand.REGISTER ":false";}} catch ClassNotFoundException e {e.printStackTrace;}finally{dis.close;ois.close;dos.close;s.close;}}如果服务器收到register命令,则继续读一个User对象,然后调用UserDao类的addUser方法向数据库中添加一个记录,如果返回值为true,表明添加成功,则向客户端发送register: true,否则,向客户端发送register: false。3.4记录棋局和棋谱下棋结束后,将棋局信息保存到数据库中,将棋谱信息保存到棋谱文件中。这里我们只记录连成五子赢棋后的棋局,对于认输和超时的情况没有记录,方法都是一样的。记录棋局和棋谱的流程如图3.4所示,当客户端向服务器发送win命令后,服务器将棋局信息保存到数据库,同时也将棋谱信息保存到棋谱文件中。图3.4保存棋局和棋谱的流程图3.4.1记录棋局[45]1. 棋局管理为了方便处理棋局数据,我们首先创建棋局类Game,以及保存棋局和查找棋局的类GameDao。建立一个game包,在game包中创建Game类和GameDao类。Game类用于保存棋局数据,代码如下: public class Game implements Serializable {private static final long serialVersionUID=-1301902854300541648L;String bUser;黑方用户String wUser;白方用户Date date; 下棋日期, java.util.DateString winner; 赢棋用户String fileName; 保存棋谱的文件名public GameString bUser, String wUser, Date date,String winner {this.bUser=bUser;this.wUser=wUser;this.date=date;this.winner=winner;fileName=initFileName;
|
|