结对编程3——黄金点小游戏实现局域网联机
一、项目成员
| 2018141461085 | 龚泽楠 |
| 2018141461012 | 蔡铧荣 |
二、项目名称
黄金点小游戏
三、项目简介
游戏规则: N个同学( N通常大于 10 ),每人写一个 0~100 之间的有理数 (不包括 0或100) ,交给裁判算出所有数字的平均值然后乘以 0.618 (所谓黄金分割常数),得到 G值。提交的数字最靠近 G(取绝对值)的同 学得到 N分,离 G最远的同学得到- 2分,其他同学得 0分。
黄金点游戏其实是一个博弈论G值(博弈值,在黄金点游戏中为黄金点;在市场竞标中为标线;在拍卖中为成交额)的数据收集实验,因此该项目为社会公益项目,普遍情况黄金点游戏项目都会将最后数据或实时数据上传至网络公开使用。
这个游戏规定第一名得到全部的分数, 第二名(不管多接近)到倒数第二名都是 0 分,最后一名还要倒扣分。
四、UI设计
为了实现局域网联机功能,项目重新设计了新的UI界面,设计如下:


五、概要设计(局域网通讯部分)
目前设计思路为分为服务器和客户端两个程序,服务器主要负责接收以及整合所有客户端发来的数据,并将这些数据传回客户端。
黄金点的计算以及得分排名的计算等都在客户端本地完成。
服务器只起到分发数据,判断玩家状态的作用。

六、实现代码
目前只实现了部分项目功能。数据传输使用Socket。数据传送形式使用Json传输。
客户端登录连接服务器:
package gp.Client; import java.awt.FlowLayout; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.io.IOException; import java.net.InetAddress; import java.net.UnknownHostException; import javax.swing.Box; import javax.swing.JButton; import javax.swing.JDialog; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JTextField; public class Main { public static void main(String[] args) throws UnknownHostException { //登录界面设计 Box baseBox, box1 = null, box2 = null; JFrame LoginUI = new JFrame(); LoginUI.setLayout(new FlowLayout()); LoginUI.setBounds(0, 0, 300, 110); LoginUI.setLocationRelativeTo(LoginUI.getOwner()); LoginUI.setTitle("黄金点小游戏登录"); LoginUI.setResizable(false); box1 = Box.createVerticalBox(); box1.add(new JLabel("服务器地址")); box1.add(Box.createVerticalStrut(10)); box1.add(new JLabel("用户姓名")); box1.add(Box.createVerticalStrut(10)); box2 = Box.createVerticalBox(); final JTextField textField1 = new JTextField(10); box2.add(textField1); box2.add(Box.createVerticalStrut(10)); final JTextField textField2 = new JTextField(10); box2.add(textField2); box2.add(Box.createVerticalStrut(10)); baseBox = Box.createHorizontalBox(); baseBox.add(box1); baseBox.add(Box.createHorizontalStrut(10)); baseBox.add(box2); LoginUI.add(baseBox); JButton button = new JButton("登陆"); button.setLocation(50, 50); LoginUI.add(button); LoginUI.setLocationRelativeTo(LoginUI.getOwner()); LoginUI.setVisible(true); LoginUI.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); //获取本地IP InetAddress ip = InetAddress.getLocalHost(); String IPs = ip.toString(); String []IP = IPs.split("\\/"); //登录按钮点击事件 button.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { if (isIP(IP[1].trim())) { try { GoldenPointUI ui = new GoldenPointUI(textField1.getText(), textField2.getText()); new Thread(ui).start(); LoginUI.setVisible(false); } catch (IOException e1) { e1.printStackTrace(); } } else { Error.show("IP格式不正确"); } } }); } //判断函数,检测IP地址是否出错 public static boolean isIP(String str) { String[] ss = str.split("\\."); for (String string : ss) { try { int a = Integer.parseInt(string); if (a <= 0 || a > 255) return false; } catch (Exception e) { return false; } } return true; } } class Error { public static void show(String text) { JDialog dialog = new JDialog(); JLabel label = new JLabel(text); dialog.add(label); dialog.setSize(100, 100); dialog.setLocationRelativeTo(null); dialog.setModal(true); dialog.setVisible(true); dialog.setResizable(true); } }
客户机接受服务器信息代码:
@Override public void run() { try { DataInputStream dis = new DataInputStream(socket.getInputStream()); DataOutputStream dos = new DataOutputStream(socket.getOutputStream()); dos.write(player_name.getBytes()); while (true) { //repaint(); byte[] b = new byte[3000]; dis.read(b); String msg = new String(b).trim(); System.out.println("服务端发来:" + msg); JSONObject json = new JSONObject(msg); int commandType = json.getInt("type"); switch (commandType){ case 1: //收到确认玩家提交数据 (提示玩家等待其他人提交) break; case 2: //收到确认所有玩家已经提交数据 (返回黄金点,游戏结果等数据) break; case 3: //收到玩家姓名,等信息 (设置相关文本) break; case 4: //收到提交玩家数字的命令 (设置轮数文本,显示提交按钮,提示玩家输入数据) break; default: System.out.println("json数据不合法"); break; } } } catch (IOException e) { e.printStackTrace(); } catch (JSONException e) { e.printStackTrace(); } } boolean isString(String string) { try{ int num = Integer.valueOf(string); return true; }catch(Exception e){ return false; } }
客户端发送数据代码:
package gp.Client; import java.io.DataOutputStream; import java.io.IOException; public class ToServer { // 给服务器端发送消息 public static void sendMsg(String str, DataOutputStream dos) throws IOException { System.out.println("发送给服务器:" + str); dos.write(str.getBytes()); } }
服务器接受程序代码:
package gp.Server; import javax.swing.*; import java.io.DataInputStream; import java.io.DataOutputStream; import java.net.ServerSocket; import java.net.Socket; public class Main { public static Player[] players = new Player[4]; public static void main(String[] args) { try { Socket[] socket = new Socket[5]; DataOutputStream[] dos = new DataOutputStream[5]; DataInputStream[] dis = new DataInputStream[5]; Thread[] thread = new Thread[5]; int x = 1; // 等待连接 ServerSocket ss = new ServerSocket(8888); String[] playernames = new String[5]; //接收所有玩家登录信息 while (true) { socket[x] = ss.accept(); dos[x] = new DataOutputStream(socket[x].getOutputStream()); dis[x] = new DataInputStream(socket[x].getInputStream()); System.out.println(socket[x].getInetAddress().getHostAddress() + "连接"); byte[] b = new byte[1024]; dis[x].read(b); playernames[x] = new String(b).trim(); /*players[x].setName(playernames[x]); players[x].setPlayNumber(x); System.out.println(playernames[x]);*/ x += 1; if (x == 5) { System.out.println(x + "wwww"); break; } } ServerCtrl sc = new ServerCtrl(socket, dos, dis); for (int i = 1; i <= 4; i++) { thread[i] = new Thread(new SocketThread(sc, dis[i])); } // 玩家姓名列表,并发送到各个 String playername = playernames[1] + " " + playernames[2] + " " + playernames[3] + " " + playernames[4]; sc.setPlayer(playername); // 发送完毕后开启四个线程接收各个客户端的消息 thread[1].start(); thread[2].start(); thread[3].start(); thread[4].start(); } catch (Exception e) { // TODO: handle exception } } }
服务器接收线程:
package gp.Server; import java.io.DataInputStream; import java.io.IOException; import org.json.JSONException; import org.json.JSONObject; public class SocketThread implements Runnable{ private DataInputStream dis; private ServerCtrl sc; private int bossflag ; public SocketThread(ServerCtrl sc, DataInputStream dis) { super(); this.sc = sc; this.dis = dis; this.bossflag=0; } @Override public void run() { try { while (true) { byte [] b = new byte[10240]; this.dis.read(b); String clientMsg = new String(b).trim();// 来自客户端的命令 JSONObject json = new JSONObject(clientMsg);// 转化为json数据格式 System.out.println("服务器收到:"+clientMsg); switch (json.getInt("type")) { case 1://接收提交黄金点信息 receivePoint(json); break; case 2://接收下一局请求信息 break; case 3: break; default: System.out.println("json数据不合法"); break; } } } catch (Exception e) { // TODO: handle exception } } //接收提交黄金点信息处理程序 private void receivePoint(JSONObject json) throws JSONException, IOException { int num = json.getInt("mark"); String point = json.getString("point"); Main.players[num].setPoint(point); for(int i = 1; i < Main.players.length; i++){ if(Main.players[i].isSubmitted() && i < 4){ continue; }else if(Main.players[i].isSubmitted() && i == 4){ String result = Main.players[1].getPoint() + " " + Main.players[2].getPoint() + " " + Main.players[3].getPoint() + " " + Main.players[4].getPoint(); sc.sendResult(result); }else { break; } } } }
服务器发送程序代码:
package gp.Server; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.IOException; import java.net.Socket; import java.util.ArrayList; import java.util.Collections; import java.util.List; import org.json.JSONException; import org.json.JSONObject; public class ServerCtrl { Socket[] socket = new Socket[5]; DataOutputStream[] dos = new DataOutputStream[5]; DataInputStream[] dis = new DataInputStream[5]; public ServerCtrl(Socket[] socket, DataOutputStream[] dos, DataInputStream[] dis) { super(); this.socket = socket; this.dos = dos; this.dis = dis; } public void setPlayer(String playername) throws JSONException, IOException { JSONObject json = new JSONObject(); json.put("type", 3); json.put("msg", playername); System.out.println(json.toString()); sendMsg(json); } public void sendResult(String result) throws JSONException, IOException { JSONObject json = new JSONObject(); json.put("type", 2); json.put("msg", result); System.out.println(json.toString()); sendMsg(json); } private void sendMsg(JSONObject json) throws IOException { for (int i = 1; i <= 4; i++) { dos[i].write(json.toString().getBytes()); } System.out.println("服务器发送"+json.toString()); } }
七、运行结果截图




八、 后期计划
1、继续实现局域网相关功能。
2、将产品进行优化,将主要计算移植到服务器程序中,实现客户端轻量化。
3、增加其他功能
浙公网安备 33010602011771号