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[0];
        if("name".equals(cmd)){
        	player.name = cmds[1];
        	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[1].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
	 */
	public  boolean 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("请输入大名:");
		InputStream  ins = 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[0].equals("ok")){
			if("true".equals(cmds[1])){
				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[0].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[0].equals("guessok")){
						print("猜测成功,等待结果...");
						line = sbr.readLine();
						continue;
					}
					if(cmds[0].equals("result")){ 
						print("结果:"+cmds[1]);
						line = sbr.readLine();
						continue;
					}
				}while(true);
			}
		}
		 
		s.close(); 
	}

}


你可能感兴趣的:(java,游戏,.net,socket,OS)