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]