GIỚI THIỆU Lý chọn đề tài Cờ caro trị chơi nhỏ hấp dẫn khơng thiếu phần sáng tạo, hẳn trải nghiệm qua trò chơi nhỏ lúc xả stress bạn bè Nhưng sống đại ngày trực tiếp ngồi chơi cờ Vì thế, chơi cờ caro online qua mạng đời phục vụ nhu cầu Yêu cầu 2.1 Server: • Lắng nghe • Phục vụ yêu cầu Client • Xử lý nước Client để gửi kết thắng thua bàn cờ cho Client bàn cờ 2.2 Client: • Kết nối Server • Gửi yêu cầu cho Server phục vụ: mời chơi, chấp nhận lời mời, nước đi, chơi lại Một số kỹ thuật liên quan • Sử dụng mơ hình mạng Client/Server, giao thức TCP/IP • Cổng kết nối 9000 • Sử dụng Socket kỹ thuật multithread Java, số tính khác • Lựa chọn ngôn ngữ: Java (Java xem ngôn ngữ lập trình ứng dụng cho mạng đặc tính riêng biệt chúng đa hệ nền, đa luồng, bảo mật, hướng đối tượng, phân tán, ứng dụng web…) Nội dung 4.1 Server 4.1.1 Giao diện Server có chức sau: Start Server LUAN VAN CHAT LUONG download : add luanvanchat@agmail.com Listbox danh sách người online Listbox cập nhật player chơi Text Area lưu thông tin kết nối đến Server player 4.1.2 Các giao thức liên lạc Server Client Connect: liên lạc connect client server Khi client đăng nhập gửi chuỗi: “Connect:username” Cổng mặc định nhận giao thức Server Client cổng 9000 Disconnect : client gửi tín hiệu ngắt kết nối, Server gửi tính hiệu có client ngắt kết nối cho tồn thể client: “Disconnect:username” CallPlay: client gửi tính hiệu mời client khác chơi cờ: “CallPlay:username_của_người_mời:username_của_đối_thủ” Yes: client( đối thủ) đồng ý chơi, client gửi lên: “Yes:username_người_yes:username_người mời mình” KieuConDi: nhận tín hiệu đồng ý chời, server gửi kiểu quy định cho trước “KieuConDi:username1:X:username2:O” (X (username1 or O) X, username2 O) LUAN VAN CHAT LUONG download : add luanvanchat@agmail.com Play: client gửi nước “Play:username_của_mình:: username_của_đối_thủ” Played: server nhận tín hiệu client gửi nước đi, server gửi client trở lại: “Played:username1::username2” RePlay: client gửi tín hiệu chơi lại lên server cho đối thủ biết muốn chơi lại: “RePlay:username_của_mình:username_đối_thủ” WIN: server gửi tín hiệu người thắng “WIN:username_thăng::username_thua” Lose: xử thua cho client đó: “Lose:username” ReConnect: client gửi tín hiệu connect lại để chơi với người khác, không muốn chơi với người A nữa: “ReConnect:username_của_mình” 4.1.3 Class chương trình phía Server: Server.java a RefreshListUserPlaying Cập nhật danh sách người chơi game while(userPlaying != null){ String display = ""; for(String s:userPlaying){ if(display.equals("")){ display = s; } else{ display = display + ":" + s; } } String []sql = display.split(":"); jListPlaying.setListData(sql); } b refreshListUser Cập nhật danh sách người online while(userOnline != null){ String display = ""; for(String s:userOnline){ if(display.equals("")){ display = s; } LUAN VAN CHAT LUONG download : add luanvanchat@agmail.com else{ display = display + ":" + s; } } String []sql = display.split(":"); jListConnected.setListData(sql); } c processRequest Tạo kết nối Client với Server thông qua lớp Connection.java try{ communitySocket = serverSocket.accept(); handleConnection(communitySocket); System.out.println("So luong ket noi: listCon.size() + "\n" + "so user online: " + userOnline.size()); }catch(Exception e){ e.printStackTrace(); } " + luong d.Các Function addUser(String UserID, Connection con): thêm user vào list user online tương ứng với connection addUserFree(String uid): thêm user chưa chọn bạn chơi game addUserPlay(String userid) : thêm user vào danh sách người có bạn chơi (đang chơi) closeConnection(Connection con, String uid): đóng kết nối tương ứng với user đăng ký (khi nhận tín hiệu disconnect từ client gửi về) listCon.remove(con); userOnline.remove(uid); userIDToConnect.remove(uid); if(userPlaying != null && userPlaying.size() > && userPlaying.contains(uid)) userPlaying.remove(uid); if(userFree != null && userFree.size() > && userFree.contains(uid)) userFree.remove(uid); removeUserPlay(String user): xóa user chọn bạn chơi danh sách người chời chưa chọn bạn chơi runServer() : chạy luồng server (lắng nghe-chờ tín hiệu kết nối từ client) LUAN VAN CHAT LUONG download : add luanvanchat@agmail.com userOnline = new ArrayList(); userPlaying = new ArrayList(); userFree = new ArrayList(); listCon = new ArrayList(); userIDToConnect = new HashMap(); Thread serverThread = new Thread(new processRequest()); serverThread.start(); Thread refresh = new Thread(new refreshListUser()); refresh.start(); Thread playing = new Thread(new RefreshListUserPlaying()); playing.start(); sendToAllClient(string): gửi tín hiệu phản hồi từ server đến tất client setDetailConnect(string): server lưu vết client connect & disconnect handleConnect(Socket clientSocket): tạo Connection cho socket client Connection conn = new Connection(this, clientSocket); Thread t = new Thread(conn); t.start(); listCon.add(conn); Các class lại dùng để mở rộng ứng dụng sau 4.1.4 Class hổ trợ: Connection.java a CreateBanco: Tạo bàn cờ, set kiểu cho player, phân tích nước để đưa định thắng thua b Player: Tạo người chơi protected String player = null; protected String kieudi = null; protected String status = "NONE"; public Player(String p, String k){ player = p; kieudi = k; status = "NONE"; } public void setstatus(String t){ status = t; } LUAN VAN CHAT LUONG download : add luanvanchat@agmail.com public String getPlayer(){ return player; } public String getKieuDi(){ return kieudi; } c Các Function: Connection(Server ser, Socket s): Định nghĩa biến public Connection(Server ser, Socket s){ server = ser; communitySocket = s; } closeConnectionSocket(): Đóng kết nối Client closeconnection try{ if(in != null) in.close(); if(out != null) out.close(); communitySocket.close(); player1 = null; player2 = null; userID1 = null; userID2 = null; }catch(Exception ex){ } run(): Lắng nghe kết nối, yêu cầu từ phía Client, thực thi, kiểm tra yêu cầu trả kết phù hợp với yêu cầu Client OutputStream socketOut = null; InputStream socketIn = null; while(true){ try{ if(communitySocket.isClosed()) break; socketOut = communitySocket.getOutputStream(); out = new OutputStreamWriter(socketOut); socketIn = communitySocket.getInputStream(); if(socketIn == null) return; in = new BufferedReader(new InputStreamReader(socketIn)); String input = in.readLine(); System.out.println(input); System.out.println( "Nhan cho 2."); if(input.equals("") || input.isEmpty() || input.toString() == null){ System.out.println("Null rui?"); return; } header:userID1:port:hostAddress:userID2:port:hostAddress neu la callPlay LUAN VAN CHAT LUONG download : add luanvanchat@agmail.com if(input.startsWith("Connect:")){ String detail[] = input.substring(8).split(":"); if(detail.length > 0){ userID = detail[0]; System.out.println(userID); listenPortofClient = communitySocket.getPort(); hostAdress = communitySocket.getInetAddress().toString(); this.server.addUser(userID, this); this.server.setDetailConnection(userID + " connect from " + communitySocket.getInetAddress() + " from port: " + communitySocket.getPort()); } } else if(input.startsWith("ReConnect:")){ String detail[] = input.substring(10).split(":"); if(detail.length > 0){ this.server.addUserFree(detail[0]) ; this.server.removeUserPlay(detail[ 0]); bc = null; } } else if(input.startsWith("Disconnect:")){ String detail[] = input.substring(11).split(":"); this.server.closeConnection(this, detail[0]); this.server.setDetailConnection(userID + " disconnected"); this.server.sendToAllClient("Disconnec t:" + userID); closeConnectionSocket(); } else if(input.startsWith("CallPlay:")){ String detail[] = input.substring(9).split(":"); if(detail.length > 0){ this.server.sendToAllClient("CallPlay:" + detail[1] + ":" + detail[0]); } } else if(input.startsWith("NoRePlay:")){ String detail[] = input.substring(9).split(":"); if(detail.length > 0){ this.server.removeUserPlay(detail[0]); LUAN VAN CHAT LUONG download : add luanvanchat@agmail.com this.server.addUserFree(detail[0]) ; this.server.sendToAllClient("NoRePlay:" + detail[0]); } } … } 4.2 Client 4.2.1 Giao diện Client Địa IP Server Tên bạn Danh sách người online: danh sách người chưa chơi Button “Mời chơi”: chọn người muốn chơi xong click vào nút mời chơi, người mời chơi xuất hộp thông báo: Nếu đồng ý chơi click vào “yes” Giao diện bàn cờ xuất sau: LUAN VAN CHAT LUONG download : add luanvanchat@agmail.com LUAN VAN CHAT LUONG download : add luanvanchat@agmail.com 4.2.2 Class chương trình Client BanCoJFrame.java a Vịng lập “for” tạo bàn cờ jPanelBanCo.setLayout(new GridLayout(10, 10)); for(int i = 0; i < 10; ++i) for(int j = 0; j < 10; ++j){ btn[i][j] = new Button(""); btn[i][j].setSize(35, 35); btn[i][j].setActionCommand("bt" + i + "_" + j); btn[i][j].setCursor(new java.awt.Cursor(java.awt.Cursor.CROSSHAIR_CURSOR)); btn[i][j].setFont(new Font("Times New Roman", 1, 16)); btn[i][j].addActionListener(new ActionListener(){ public void actionPerformed(ActionEvent e) { choice = e.getActionCommand(); send(); disable(); } }); jPanelBanCo.add(btn[i][j]); } b class ClassReceive Nhận giao thức từ Server để xử lý public void run(){ try{ while(true){ in = new BufferedReader(new InpuStreamReader(socket.getInputStream())); out = new PrintWriter(socket.getOutputStream()); String input = in.readLine(); if(input == null){ System.out.println("du lieu bi null"); return; } System.out.println(input); String []detail = input.split(":"); int n = detail.length; System.out.println(n); if(n > 0){ if(detail[0].equals("Update")){ String []spl = new String[n-1]; int j = 0; for(int i = 1; i < n; ++i){ System.out.println(detail[i]); if(!detail[i].equals("") && ! detail[i].equals(jTextFieldDangNhap.getText())) spl[j++] = detail[i]; LUAN VAN CHAT LUONG download : add luanvanchat@agmail.com } jListDanhSach.setListData(spl); } else if(detail[0].equals("Disconnect")){ if(detail[1].equals(usernameCalled)){ String message = "Đối phương nghỉ chơi!\nBạn có muốn chơi khơng?\nClick Yes để tìm người chơi khác.\nClick No để khỏi trị chơi."; int answer = JOptionPane.showConfirmDialog(frame, message, "Thông báo", JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE); if(answer == JOptionPane.YES_OPTION){ jButtonMoiChoi.setEnabled(true); out.println("ReConnect:" + username); out.flush(); clearBanCo(); jPanelBanCo.setVisible(false); } else if(answer == JOptionPane.NO_OPTION) { out.println("Disconnect:" + username); out.flush(); setVisible(false); dispose(); } } } else if(detail[0].equals("CallPlay")){ if(detail[1].equals(username)){ int resulf = JOptionPane.showConfirmDialog(frame, "Bạn nhận lời mời từ " + username, "Mời chơi", JOptionPane.YES_NO_OPTION); if(resulf == JOptionPane.YES_OPTION){ out.println("Yes:" + username + ":" + detail[2]); jPanelBanCo.setVisible(true); jButtonMoiChoi.setEnabled(false); if(detail[2] != null && ! detail[2].equals(username)) usernameCalled = detail[2]; LabelPlayer2.setText(usernameCalled); } else{ out.println("No:" + username + ":" + detail[2]); jPanelBanCo.setVisible(false); jButtonMoiChoi.setEnabled(true); usernameCalled = null; } out.flush(); } LUAN VAN CHAT LUONG download : add luanvanchat@agmail.com } else if(detail[0].equals("Yes")){ if(detail[2].equals(username)){ jPanelBanCo.setVisible(true); jButtonMoiChoi.setEnabled(false); usernameCalled = detail[1]; jLabelPlayer1.setText(username); jLabelPlayer2.setText(usernameCalled); jLabelKq.setText("Ai thắng ta ???"); jLabelDiTruoc.setText(goFirst); } else if(detail[1].equals(username)){ jPanelBanCo.setVisible(true); jButtonMoiChoi.setEnabled(false); usernameCalled = detail[2]; jLabelPlayer1.setText(username); jLabelPlayer2.setText(usernameCalled); jLabelKq.setText("Ai thắng ta ???"); jLabelDiTruoc.setText(goFirst); } } else if(detail[0].equals("No")){ if(detail[1].equals(username) && detail[2].equals(usernameCalled)){ jPanelBanCo.setVisible(false); jButtonMoiChoi.setEnabled(true); } jLabelDiTruoc.setText(" "); } else if(detail[0].equals("KieuConDi")){ if(detail[1].equals(username)){ if(detail[4] != null) kieucondi = detail[2]; if(detail[4] != null) kieuConDiDoiThu = detail[4]; } else if(detail[3].equals(username)){ if(detail[4] != null) kieucondi = detail[4]; if(detail[2] != null) kieuConDiDoiThu = detail[2]; } } else if(detail[0].equals("Played")){ if(detail[1].equals(usernameCalled)){ if(detail[3] != null){ String nuocdi[] = detail[2].split(","); if(nuocdi.length > 1){ setNuocDi(Integer.parseInt(nuocdi[0]), Integer.parseInt(nuocdi[1]), kieuConDiDoiThu); ToDo(10); } } LUAN VAN CHAT LUONG download : add luanvanchat@agmail.com } else if(detail[1].equals(username)){ } } else if(detail[0].equals("WIN")){ if(detail[2] != null){ String nuocdi[] = detail[2].split(","); if(nuocdi.length > 1) setNuocDi(Integer.parseInt(nuocdi[0]), Integer.parseInt(nuocdi[1]), kieuConDiDoiThu); } if(detail[1].equals(username)){ jLabelKq.setText("Bạn thắng!"); clearBanCo(); jPanelBanCo.setVisible(false); } else if(detail[3] != null && detail[3].equals(username)){ System.out.println(detail[3] + "=" + usernameCalled); jLabelKq.setText("Bạn thua rồi!"); waiting(5); String message = "Bạn thua rồi! Bạn có muốn chơi khơng?\n Click Yes để chơi lại.\n Click No để tìm người chơi khác."; int answer = JOptionPane.showConfirmDialog(frame, message, "Thông báo", JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE); if(answer == JOptionPane.YES_OPTION){ jButtonMoiChoi.setEnabled(true); out.println("CallPlay:" + usernameCalled + ":" + username); out.flush(); clearBanCo(); timeWaiting.cancel(); } else if(answer == JOptionPane.NO_OPTION){ out.println("ReConnect:" + username); out.flush(); clearBanCo(); jPanelBanCo.setVisible(false); out.println("NoRePlay:" + usernameCalled); out.flush(); jButtonMoiChoi.setEnabled(true); timeWaiting.cancel(); } } } else if(detail[0].equals("NoRePlay")){ if(detail[1] != null && detail[1].equals(usernameCalled)){ jButtonMoiChoi.setEnabled(true); LUAN VAN CHAT LUONG download : add luanvanchat@agmail.com } } } } }catch(Exception ex){ System.out.println("Khong the nhan du lieu."); ex.printStackTrace(); } } c Các function Function doConnected(): quản lí việc đăng nhập user public boolean doConnected(){ try{ if(jTextFieldDangNhap.getText().length() 0){ int i = Integer.parseInt(n1[0]); int j = Integer.parseInt(n1[1]); System.out.println(i); System.out.println(j); if(kieucondi == null && kieuConDiDoiThu != null){ if(kieuConDiDoiThu.equals("X")) kieucondi = "O"; else if(kieuConDiDoiThu.equals("O")) kieucondi = "X"; } if(kieuConDiDoiThu == null && kieucondi != null){ if(kieucondi.equals("X")) kieuConDiDoiThu = "O"; else if(kieucondi.equals("O)")) kieucondi = "X"; } if(kieucondi == null && kieuConDiDoiThu == null){ kieucondi = "X"; kieuConDiDoiThu = "O"; } btn[i][j].setLabel(kieucondi); System.out.println(username + " di kieu: " + kieucondi); btn[i][j].setEnabled(false); if(time != null){ time.cancel(); time = null; } if(timeWaiting != null){ timeWaiting.cancel(); timeWaiting = null; } try{ out.println("Play:" + username + ":" + n1[0] + "," + n1[1] + ":" + usernameCalled); out.flush(); }catch(Exception e){ System.err.println(e); } } }catch (IOException ex) { Logger.getLogger(BanCoJFrame.class.getName()) log(Level.SEVERE, null, ex); } } Function doReceive(Socket s): danh sách user online public void doReceive(Socket s){ Socket soc = s; try{ LUAN VAN CHAT LUONG download : add luanvanchat@agmail.com in = new BufferedReader(new InputStreamReader(soc.getInputStream())); String input = in.readLine(); if(input == null){ System.out.println("du lieu bi null"); return; } String []detail = input.split(":"); int n = detail.length; if(n > 0){ if(detail[0].equals("Update")){ String []spl = new String[n-1]; for(int i = 1; i< n; ++i) spl[i] = detail[i]; jListDanhSach.setListData(spl); } } }catch(Exception ex){…} Function callPlay(String userID): mời bạn chơi cờ public void callPlay(String userID){ try { out = new PrintWriter(socket.getOutputStream()); out.println("CallPlay:" + username + ":" + userID); out.flush(); jButtonMoiChoi.setEnabled(false); usernameCalled = userID; } catch (IOException ex) { … } } Function setNuocDi(int row, int col, String kieu) Function clearBanCo() Kết đạt mặt hạn chế LUAN VAN CHAT LUONG download : add luanvanchat@agmail.com ... LUAN VAN CHAT LUONG download : add luanvanchat@agmail.com 4.2.2 Class chương trình Client BanCoJFrame .java a Vòng lập “for” tạo bàn cờ jPanelBanCo.setLayout(new GridLayout(10, 10)); for(int i... class lại dùng để mở rộng ứng dụng sau 4.1.4 Class hổ trợ: Connection .java a CreateBanco: Tạo bàn cờ, set kiểu cho player, phân tích nước để đưa định thắng thua b Player: Tạo người chơi protected... không muốn chơi với người A nữa: “ReConnect:username_của_mình” 4.1.3 Class chương trình phía Server: Server .java a RefreshListUserPlaying Cập nhật danh sách người chơi game while(userPlaying