fbpx

[email protected]

购物车

 查看订单

  • 我的帐户
东东购 | EasternEast
  • 中文书店
    • 畅销排行榜
      • 小说 畅销榜
      • 童书 畅销榜
      • 外语畅销榜
      • 管理畅销榜
      • 法律畅销榜
      • 青春文学畅销榜
    • 热门分类
      • 社会小说
      • 成功/励志 畅销榜
      • 人物传记
      • 大陆原创
      • 绘本童书
      • 影视小说
    • 文学推荐
      • 文集
      • 戏剧
      • 纪实文学
      • 名家作品
      • 民间文学
      • 中国现当代随笔
    • 新书热卖榜
      • 小说 新书热卖榜
      • 青春文学 新书热卖榜
      • 童书 新书热卖榜
      • 管理 新书热卖榜
      • 成功/励志 新书热卖榜
      • 艺术 新书热卖榜
  • 精选分类
    • 小说
    • 保健养生
    • 烹饪/美食
    • 风水/占卜
    • 青春文学
    • 童书
    • 管理
    • 成功/励志
    • 文学
    • 哲学/宗教
    • 传记
    • 投资理财
    • 亲子家教
    • 动漫/幽默
    • 法律 Legal
    • 经济 Economics
    • 所有分类
  • 关于东东
  • 帮我找书
搜索
首页计算机/网络程序设计Java五子棋游戏制作

Java五子棋游戏制作

五子棋游戏制作,深入学习Java

作者:宁淑荣 杨国兴 出版社:清华大学出版社 出版时间:2017年05月 

ISBN: 9787302465638
年中特卖用“SALE15”折扣卷全场书籍85折!可与三本88折,六本78折的优惠叠加计算!全球包邮!
trust badge

EUR €23.99

类别: 研究生/本科/专科教材, 程序设计 SKU:5d875d125f98494bcc151647 库存: 缺货
  • 描述
  • 评论( 0 )

描述

开 本: 16开纸 张: 胶版纸包 装: 平装-胶订是否套装: 否国际标准书号ISBN: 9787302465638丛书名: 计算机系列教材

编辑推荐
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创建估值类Evaluate/100

4.2.4实现计算机智能下棋/111

4.3极小极大搜索法提高下棋水平/112

4.3.1极小极大算法与棋局的评价/113

4.3.2极小极大算法的实现/115

4.4AlphaBeta搜索方法/124

4.4.1AlphaBeta搜索方法简介/124

4.4.2AlphaBeta搜索方法实现/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网站上下载mysqlconnectorjava压缩文件,然后解压缩。在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 main(String[] 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);}}createDatabase(stmt, “fiveChess”);try {stmt.close();conn.close();} catch (SQLException e) {e.printStackTrace();}}public static void createDatabase(Statement stmt, String dbName){try {stmt.executeUpdate(“create database ” dbName);stmt.executeUpdate(“use ” dbName);String sql;sql=”create table user(id int auto_increment not null primary key,” “name VARCHAR(10) not null, ” “password VARCHAR(10) not null,” “email VARCHAR(30) not null,” “level int not null,” “regDate date not null)”;stmt.executeUpdate(sql);sql=”insert into user(name,password,email,level,regDate) ” “values(‘test1’, ‘test1′,’[email protected]’,1,’2016-01-22′)”;stmt.executeUpdate(sql);sql=”insert into user(name,password,email,level,regDate) ” “values(‘test2’, ‘test2′,’[email protected]’,1,’2016-01-22′)”;stmt.executeUpdate(sql);sql=”create table game(id int auto_increment not null primary key,” “gameDate date not null, ” “playerBlack VARCHAR(10) not null, ” “playerWhite VARCHAR(10) not null, ” “winner VARCHAR(10) not null, ” “manualFileName VARCHAR(100) not null)”;stmt.executeUpdate(sql);sql=”insert into game(gameDate, playerBlack, playerwhite, winner,manualFileName)” ” values(‘2016-01-22′,’test1′,’test2′,’test2′,’game1201601221205.fiv’)”; stmt.executeUpdate(sql);sql=”insert into game(gameDate, playerBlack, playerwhite, winner,manualFileName)” ” values(‘2016-01-22′,’test1′,’test2′,’test1′,’game1201601221848.fiv’)”;stmt.executeUpdate(sql);} catch(SQLException 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:3306/fiveChess”,”root”,”1234″);} catch(ClassNotFoundException e) {e.printStackTrace();System.exit(-1);}catch(SQLException e) {e.printStackTrace();if(conn!=null){try {conn.close();} catch (SQLException e1) {e1.printStackTrace();System.exit(-1);}}}}public Connection getConn() {return conn;}}DBConnection类的代码也比较简单,在构造方法中创建Connection对象。其他类可以调用DBConnection类的getConn()方法获得这个数据库连接对象。3.2.2用户管理[4/5]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 User(String 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 setEmail(String email) {this.email=email;}public String getPassWord() {return passWord;}public void setPassWord(String passWord) {this.passWord=passWord;}public String getUserName() {return userName;}public void setUserName(String userName) {this.userName=userName;}public int getLevel() {return level;}public void setLevel(int level) {this.level=level;}public Date getRegDate() {return regDate;}public void setRegDate(Date 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 addUser(User 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 “‘”);if(rs.next()){return false;}else{String sql=”insert into user(userName,passWord,email,level,regDate)” “values(?,?,?,?,?)”;pstmt=conn.prepareStatement(sql);pstmt.setString(1,userName);pstmt.setString(2, passWord);pstmt.setString(3, email);pstmt.setInt(4, level);pstmt.setDate(5, new java.sql.Date(regDate.getTime()));pstmt.executeUpdate();return true;}} catch (SQLException e) {e.printStackTrace();return false;}finally{if(rs!=null){try {rs.close();} catch (SQLException e) {e.printStackTrace();}}if(st!=null){try {st.close();} catch (SQLException e) {e.printStackTrace();}}}}public User getUser(String userName, String passWord) {try {st=conn.createStatement();String sql=”select  from user where name='” userName “‘ and passWord='” passWord “‘”;rs=st.executeQuery(sql);if(rs.next()){String email=rs.getString(“email”);int level=rs.getInt(“level”);Date regDate=rs.getDate(“regDate”);return new User(userName,passWord,email,level,regDate);}else{return null;}} catch (SQLException e) {e.printStackTrace();return null;}finally{if(rs!=null){try {rs.close();} catch (SQLException e) {e.printStackTrace();}}if(st!=null){try {st.close();} catch (SQLException e) {e.printStackTrace();}}}}}addUser(User user)方法向用户表添加一个用户。因为表中不允许有同名的用户,因此首先在用户表中查找和user同名的记录,如果找到,则不能添加,返回false。如果找不到,则将user对象代表的用户数据添加到用户表中,返回true。getUser(String userName, String passWord)方法在用户表中查找参数指定的用户名和密码对应的记录,如果找到,则由这条记录的数据创建User对象,并返回,如果找不到,则返回null。3. 测试用户类和用户管理类完成了User类和UserDao类之后,可以添加一个临时的测试类,测试UserDao类添加用户和查找用户的功能,例如下面的程序。public class Test {public static void main(String[] args) {UserDao dao=new UserDao();User user=new User(“test3″,”aaa”,”tetsts”,1,new Date());if(dao.addUser(user))System.out.println(“添加成功!”);elseSystem.out.println(“添加失败!”);User user2=dao.getUser(“test3”, “aaa”);if(user2!=null){System.out.println(“找到该用户!”);System.out.println(user2);}else{System.out.println(“未找到该用户!”);}
User user3=dao.getUser(“test3”, “dddd”);if(user3!=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准备工作[4/5]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用户登录[4/5]1. Communication类的登录方法由于“连接服务器”已经被“登录”代替了,因此可以删除FiveClient类中的connect()方法。将Communication类中的connect()方法改为login()方法,代码如下: public boolean login(String ip, String userName, String passWord) {try {s=new Socket(ip,FiveServer.TCP_PORT);dis=new DataInputStream(s.getInputStream());dos=new DataOutputStream(s.getOutputStream());dos.writeUTF(Command.LOGIN “:” userName “:” passWord);String msg=dis.readUTF();String[] words=msg.split(“:”);if(words[0].equals(Command.LOGIN) && words[1].equals(“true”)){fc.isConnected=true;new ReceaveThread(s).start();fc.control.exitGameButton.setEnabled(true);fc.control.loginButton.setEnabled(false);fc.control.joinGameButton.setEnabled(true);fc.control.cancelGameButton.setEnabled(false);return true;}else{s.close();return false;}} catch (UnknownHostException e) {e.printStackTrace();} catch (IOException e) {if(s!=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 JTextField(14);JTextField tfPassword=new JTextField(14);JButton jbLogin=new JButton(“登录”);JButton jbRegister=new JButton(“注册”);JButton jbCancel=new JButton(“取消”);String ip;FiveClient fc;public DialogLogin(Window parent, String ip) {super(parent, “用户登录”,Dialog.ModalityType.APPLICATION_MODAL);fc=(FiveClient) parent;this.ip=ip;createGUI();}public void actionPerformed(ActionEvent e) {String str=e.getActionCommand();if (“登录”.equals(str)) {String userName=tfUserName.getText();String passWord=tfPassword.getText();if((userName==null)||(userName.isEmpty()) || (passWord==null)||(passWord.isEmpty())){JOptionPane.showMessageDialog(this, “各项数据不能为空!”);return;}else {if(fc.getC().login(ip, userName, passWord)){JOptionPane.showMessageDialog(this, “登录成功!”);this.dispose();}else{JOptionPane.showMessageDialog(this, “用户名或密码不符!”);}}}else if (“注册”.equals(str)) {//DialogRegister rd=new DialogRegister(this,ip);}else if(“取消”.equals(str)){this.dispose();}} public void createGUI() {this.setLayout(new BorderLayout());JPanel jpWest=new JPanel();JPanel jpCenter=new JPanel();JPanel jpSouth=new JPanel();jpWest.setLayout(new GridLayout(3, 1));jpCenter.setLayout(new GridLayout(3, 1));jpSouth.setLayout(new FlowLayout());jpWest.add(new JLabel(“用户名:”));jpWest.add(new JLabel(“密 码:”));jpCenter.add(tfUserName);jpCenter.add(tfPassWord);this.add(new JPanel(),BorderLayout.NORTH);this.add(jpWest,BorderLayout.WEST);this.add(jpCenter,BorderLayout.CENTER);jpSouth.add(jbLogin);jpSouth.add(jbRegister);jpSouth.add(jbCancel);jbLogin.addActionListener(this);jbRegister.addActionListener(this);jbCancel.addActionListener(this);this.add(jpSouth,BorderLayout.SOUTH);this.setDefaultCloseOperation(DISPOSE_ON_CLOSE);this.setLocation(450,250);this.pack();this.setVisible(true);}}由于对话框本身负责事件监听,因此DialogLogin类实现了ActionListener接口。为了便于看清程序的逻辑结构,我们将创建界面的代码放在了一个单独方法createGUI()中。在构造方法中设置对话框的父窗口(由参数指定)、标题以及显示模式,然后调用createGUI()方法创建对话框界面并显示。在actionPerformed()方法中,处理3个按钮的单击事件。如果是“登录”按钮,则首先获取编辑框中的用户名和密码,如果用户名和密码都不为空,则调用Communication类中的login()方法登录,如返回true,则登录成功,返回false,则登录失败。如果是“注册”按钮,则显示注册对话框,完成注册功能(注册功能的实现稍后给出)。如果是“取消”按钮,则使对话框消失。3. 显示登录对话框在fiveClient中修改登录按钮的监听程序段,显示登录对话框,代码如下: else if(e.getSource()==control.loginButton){c=new Communication(FiveClient.this);DialogLogin dr=new DialogLogin(FiveClient.this, FiveClient.this.control.inputIP.getText());}在创建DialogLogin对象时,要通过构造方法的参数指定对话框的父窗口和服务器的ip地址。4. 服务器处理login命令 由于现在已经不需要服务器为用户起名了,因此可以删除服务器类的静态成员clientNameNum,然后修改startServer()方法。修改后的代码如下: public void startServer(){try {ss=new ServerSocket(TCP_PORT);while(true){Socket s=ss.accept();InputStream is=s.getInputStream();OutputStream os=s.getOutputStream();DataInputStream dis=new DataInputStream(is);DataOutputStream dos=new DataOutputStream(os);String msg=dis.readUTF();String[] words=msg.split(“:”);if(words[0].equals(Command.LOGIN)){String userName=words[1];String passWord=words[2];UserDao ud=new UserDao();if(ud.getUser(userName, passWord)!=null){dos.writeUTF(Command.LOGIN “:true”);clientNum ;Client c=new Client(userName, s); clients.add(c);lStatus.setText(“连接数” clientNum);taMessage.append(s.getInetAddress().getHostAddress() ” ” userName “\n”);tellName(c);addAllUserToMe(c);addMeToAllUser(c);new ClientThread(c).start();}else{dos.writeUTF(Command.LOGIN “:false”);s.close();}}}} catch(IOException 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 JTextField(20);JTextField tfPassword=new JTextField(20);JTextField tfRePassword=new JTextField(20);JTextField tfEmail=new JTextField(20);JButton jbRegister=new JButton(“注册”);JButton jbCancel=new JButton(“取消”);String ip;public DialogRegister(Window parent, String ip) {super(parent, “用户注册”, Dialog.ModalityType.APPLICATION_MODAL);this.ip=ip;createGUI();}public void actionPerformed(ActionEvent e) {String str=e.getActionCommand();if (“注册”.equals(str)) {String userName=tfUserName.getText();String passWord=tfPassWord.getText();String rePassWord=tfRePassWord.getText();String email=tfEmail.getText();if((userName==null)||(userName.isEmpty()) || (passWord==null)||(passWord.isEmpty()) || (rePassWord==null)||(rePassWord.isEmpty()) || (email==null)||(email.isEmpty())){JOptionPane.showMessageDialog(this, “各项数据不能为空!”);return;}if (!(passWord.equals(rePassWord))) {JOptionPane.showMessageDialog(this, “两次密码不一致!”);return;} else {if(register(new User(userName,passWord,email,1,new Date()))){JOptionPane.showMessageDialog(this, “注册成功!”);}else{JOptionPane.showMessageDialog(this, “注册失败!可能重名。”);}}}else if(“取消”.equals(str)){this.dispose();}} public boolean register(User u){Socket s=null;InputStream is=null;OutputStream os=null;DataInputStream dis=null;DataOutputStream dos=null;ObjectOutputStream oos=null;try {s=new Socket(ip, FiveServer.TCP_PORT);is=s.getInputStream();os=s.getOutputStream();dis=new DataInputStream(is);dos=new DataOutputStream(os);dos.writeUTF(Command.REGISTER);oos=new ObjectOutputStream(os);oos.writeObject(u);String msg=dis.readUTF();if(msg.equals(Command.REGISTER “:true”)){return true;}else{return false;}} catch(UnknownHostException e) {e.printStackTrace();return false;} catch(IOException e) {e.printStackTrace();return false;}finally{try {oos.close();dos.close();dis.close();s.close();} catch(IOException e) {e.printStackTrace();}}}public void createGUI() {this.setLayout(new BorderLayout());JPanel jpWest=new JPanel();JPanel jpCenter=new JPanel();JPanel jpSouth=new JPanel();jpWest.setLayout(new GridLayout(4, 1));jpCenter.setLayout(new GridLayout(4, 1));jpSouth.setLayout(new FlowLayout());jpWest.add(new JLabel(“用户名:”));jpWest.add(new JLabel(“密 码:”));jpWest.add(new JLabel(“确认密码:”));jpWest.add(new JLabel(“邮 箱:”));jpCenter.add(tfUserName);jpCenter.add(tfPassWord);jpCenter.add(tfRePassWord);jpCenter.add(tfEmail);this.add(jpWest, BorderLayout.WEST);this.add(jpCenter, BorderLayout.CENTER);jpSouth.add(jbRegister);jpSouth.add(jbCancel);jbRegister.addActionListener(this);jbCancel.addActionListener(this);this.add(jpSouth, BorderLayout.SOUTH);this.setDefaultCloseOperation(DISPOSE_ON_CLOSE);this.setLocation(450, 250);this.pack();this.setVisible(true);}}在actionPerformed()方法中,如果是“注册”按钮的事件,则先检查用户名、密码、重复密码以及邮箱是否有空的,如果没有空的再检查两次密码输入是否一致,如果一致,则调用register()方法注册,如果方法返回true,表示注册成功,如果返回false,表示注册失败。在register()方法中,首先连接服务器,随后向服务器发送register命令,接着再发一个User对象。之后,再从服务器读取字符串,如果是“register: true”,表示注册成功,如果是“register: false”,表示注册失败。在登录对话框类DialogLogin中,通过单击“注册”按钮显示注册对话框。将原来类中注释掉的一行的注释去掉,代码如下:else if (“注册”.equals(str)) {DialogRegister rd=new DialogRegister(this,ip);}2. 服务器处理注册命令在服务器类的startServer()方法中,与登录代码并列,加入注册的处理代码如下:if(words[0].equals(Command.REGISTER)){ObjectInputStream ois=null;try {ois=new ObjectInputStream(is);User u=(User) ois.readObject();UserDao ud=new UserDao();if(ud.addUser(u)){dos.writeUTF(Command.REGISTER “:true”);}else{dos.writeUTF(Command.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记录棋局[4/5]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 Game(String bUser, String wUser, Date date,String winner) {this.bUser=bUser;this.wUser=wUser;this.date=date;this.winner=winner;fileName=initFileName();
书摘插画
插图

插图

插图

插图

插图

插图

抢先评论了 “Java五子棋游戏制作” 取消回复

评论

还没有评论。

相关产品

加入购物车

Python基础教程(第3版)

EUR €58.99
阅读更多
缺货

数据结构——C++版(第四版)(英文影印版)

EUR €63.99
加入购物车

笨办法学Python 3

EUR €38.99
加入购物车

数据结构和编程设计——应用C语言(第二版)(影印版)

EUR €56.99

东东购的宗旨是服务喜爱阅读中文书籍的海外人民,提供一个完善的购书平台,让国人不论何时何地都能沉浸在书香之中,读着熟悉的中文字,回忆着家乡的味道。


安全加密结账 安心网络购物 支持Paypal付款

常见问题

  • 货物配送
  • 退换货政策
  • 隐私政策
  • 联盟营销

客户服务

  • 联系东东
  • 关于东东
  • 帮我找书
  • 货物追踪
  • 会员登入

订阅最新的优惠讯息和书籍资讯

选择币别

EUR
USD
CAD
AUD
NZD
NOK
GBP
CHF
SEK
CNY
UAH
ILS
SAR
MXN
KRW
MYR
SGD
HUF
TRY
JPY
HKD
TWD
facebookinstagram
©2020 东东购 EasternEast.com

限时特卖:用“SALE15”优惠券全场书籍85折!可与三本88折,六本78折的优惠叠加计算。 忽略