wjjxf 发表于 2013-1-28 18:02:09

JavaNIO开发的猜大小游戏

学习一下javaNIO用法,就开发了个简单的小游戏,猜大小,服务端用javaNIO api写的,客户端用的普通的socket,一个服务端支持多个客户端!每个客户端猜大还是小,然后由管理员控制开始猜测然后通知所有玩家。。。使用NIO传送数据,ByteBuffer需要用characterEncoding编码才行,要不然对方收不到。
这是服务端代码:
package game;import java.io.IOException;import java.net.InetSocketAddress;import java.net.ServerSocket;import java.nio.ByteBuffer;import java.nio.CharBuffer;import java.nio.channels.SelectionKey;import java.nio.channels.Selector;import java.nio.channels.ServerSocketChannel;import java.nio.channels.SocketChannel;import java.nio.charset.Charset;import java.nio.charset.CharsetDecoder;import java.nio.charset.CharsetEncoder;import java.util.ArrayList;import java.util.Date;import java.util.Iterator;import java.util.List;import java.util.Random;/** *服务端 * @version 1.0 2011-4-27*/public class BigSmallServer {protected Charset charset = Charset.forName("UTF-8");protected CharsetEncoder charsetEncoder = charset.newEncoder();protected CharsetDecoder charsetDecoder = charset.newDecoder();private Selector selector = null;List<Player> players = new ArrayList<Player>();public static void main(String[] args) throws Exception{new BigSmallServer().run();}public void print(Object o){System.out.println(new Date().toLocaleString()+":"+o);}public void run() throws Exception{selector = Selector.open();ServerSocketChannel ssc = ServerSocketChannel.open();ServerSocket serverSocket = ssc.socket();serverSocket.bind(new InetSocketAddress(8888));      ssc.configureBlocking(false);      ssc.register(selector, SelectionKey.OP_ACCEPT);                while(true){      int nKeys = selector.select();      if(nKeys > 0){         Iterator<SelectionKey> it = selector.selectedKeys().iterator();         while(it.hasNext()){         SelectionKey key = it.next();         if(key.isAcceptable()){         ServerSocketChannel server = (ServerSocketChannel) key.channel();                         SocketChannel channel = server.accept();                         if (channel == null) {                           continue;                         }                         channel.configureBlocking(false);                         channel.register(selector, SelectionKey.OP_READ);                         print("客户端:"+channel.socket().getRemoteSocketAddress()+" 建立连接...");                                 Player player = new Player();                         player.id = channel.socket().getRemoteSocketAddress().toString();                         player.sc = channel;                         players.add(player);         }         if(key.isReadable() ){         this.readDataFromSocket(key);         }          it.remove();         }//end while      }//end if      }//end while}private void readDataFromSocket(SelectionKey key) throws IOException {      ByteBuffer buf = ByteBuffer.allocate(1024);      SocketChannel sc = (SocketChannel) key.channel();      print("客户端:"+sc.socket().getRemoteSocketAddress()+" 读取数据...");            Player player = null;for(Player p: players){if(p.id.equals(sc.socket().getRemoteSocketAddress().toString())){player = p;break;}}      int readBytes = 0;      int ret;      try {             while ((ret = sc.read(buf)) > 0) {                readBytes += ret;            }            if(readBytes <= 0){            sc.close();            }      } finally {            buf.flip();      } //      String s = new String(buf.array());//      System.out.println(sb.toString());      String msg = charsetDecoder.decode(buf).toString();      String[] cmds = msg.split(":");      String cmd = cmds;      if("name".equals(cmd)){      player.name = cmds;      if(player.name.equals("admin")){      player.bAdmin = true;      }         sc.write(charsetEncoder.encode(CharBuffer.wrap( "ok:"+player.bAdmin+ "\n")));                print(player.id+" 昵称:"+player.name);      }      if("guess".equals(cmd)){      //得到猜测数据      player.guess = cmds.charAt(0);         sc.write(charsetEncoder.encode(CharBuffer.wrap( "guessok\n")));      print(player.name+" 猜测:" + player.guess);      //通知管理员有多少个人猜测了         }      if("start".equals(cmd)){      //开始,所有的guess设置为空      if(player.bAdmin){      //通知所有客户端可以开始了         for(Player p: players){         if(p.bAdmin)continue;//管理员不玩      p.guess = 0;      p.sc.write(charsetEncoder.encode(CharBuffer.wrap("start\n")));    }      }      }      if("result".equals(cmd)){      //得结果通知所有人      if(player.bAdmin){      float f = 0.5000F;//大的概率      boolean rs = this.getTrueFalse(f);         String res = "";      int cWin = 0, cLoss = 0;      for(Player p: players){      if(p.bAdmin)continue;//管理员不玩      if(rs && p.guess == 'b'){cWin++;}else if(!rs && p.guess == 's'){cWin++;}else{cLoss++;}      }                for(Player p: players){      if(p.bAdmin)continue;//管理员不玩      if(rs && p.guess == 'b'){res ="result:胜利,结果为大,积分="+(++p.score)+",本局赢/输的人数为:"+cWin+"/"+cLoss;}else if(!rs && p.guess == 's'){res ="result:胜利,结果为小,积分="+(++p.score)+",本局赢/输的人数为:"+cWin+"/"+cLoss;}else{res ="result:失败,结果为"+(rs?"大":"小")+",积分="+(--p.score)+",本局赢/输的人数为:"+cWin+"/"+cLoss;}         p.sc.write(charsetEncoder.encode(CharBuffer.wrap( res+"\n")));    }      }      }      // process buffer      // buf.clear();            }/** * 以rand的概率返回true * rand范围是0.01%-99.99%。即0.0001-0.9999 */publicboolean getTrueFalse(float r){Random rand= new Random();int v = (int) (r * 10000);if(v < 0 || v > 10000)throw new RuntimeException("out of range");rand.setSeed(System.nanoTime()+v);int r1 = rand.nextInt(10000) + v;return r1 - 10000 >=0 ?true:false; }static class Player{public String name;public String id;public int score;public boolean bAdmin;//只有管理员有权限决定开始public char guess;//猜测的大小public SocketChannel sc;//} }
这是客户端代码:
package game;import java.io.BufferedReader;import java.io.BufferedWriter;import java.io.InputStream;import java.io.InputStreamReader;import java.io.OutputStream;import java.io.OutputStreamWriter;import java.net.Socket;import java.util.Date;/** * 客户端 * @version 1.0 2011-4-27*/public class BigSmallClient {public void print(Object o){System.out.println(new Date().toLocaleString()+":"+o);}public static void main(String[] args) throws Exception{new BigSmallClient().run();}public void run()throws Exception{Socket s = new Socket("172.16.1.134", 8888);print("连接服务器成功..."+s.getRemoteSocketAddress().toString());print("请输入大名:");InputStreamins = s.getInputStream();BufferedReader sbr = new BufferedReader(new InputStreamReader(ins));BufferedReader inbr = new BufferedReader(new InputStreamReader(System.in));OutputStream os = s.getOutputStream();BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(os));String line = inbr.readLine();bw.write("name:"+line);bw.flush();line = sbr.readLine();String[] cmds = line.split(":");if(cmds.equals("ok")){if("true".equals(cmds)){while(true){print("输入命令(start,result)...");line = inbr.readLine();if("start".equals(line)){bw.write("start");bw.flush();}else if("result".equals(line)){bw.write("result");bw.flush();}else if("q".equals(line)){break;}}}else{print("设置成功,请等待开始...");line = sbr.readLine();do{cmds = line.split(":");if(cmds.equals("start")){print("可以开始了,大(b),小(s),退出(q)?");line = inbr.readLine();if(line.equals("q"))break;bw.write("guess:"+line);bw.flush();line = sbr.readLine();continue;}if(cmds.equals("guessok")){print("猜测成功,等待结果...");line = sbr.readLine();continue;}if(cmds.equals("result")){ print("结果:"+cmds);line = sbr.readLine();continue;}}while(true);}} s.close(); }}
页: [1]
查看完整版本: JavaNIO开发的猜大小游戏