收藏 分销(赏)

五子棋对战实验报告.docx

上传人:仙人****88 文档编号:11894836 上传时间:2025-08-19 格式:DOCX 页数:15 大小:792.52KB 下载积分:10 金币
下载 相关 举报
五子棋对战实验报告.docx_第1页
第1页 / 共15页
五子棋对战实验报告.docx_第2页
第2页 / 共15页


点击查看更多>>
资源描述
实验项目 五子棋网络对战和聊天 实验日期 20160406 实验报告要求: 一、 实验目的: 学习和使用socket编程,熟练软件开发 二、 实验原理: 使用socket进行网络通信,java作为编程语言 三、 实验要求: 编写五子棋程序可以实现联机网络对战,并且可以进行聊天 四、 实验步骤、结果(程序+注释+截图)及分析: 首先拟定编程语言与开发方案,选择java语言,考虑到java可以跨平台运行, 然后决定把这个程序拆分为客户端、服务器两个部分,每个部分再分成5个小的部分实现不同功能。 1、然后考虑使用java的swing包,创建ClientChessPanel类负责棋盘部分,包括判断输赢,使用数组chesses[i][j]记录棋盘上棋子的分布,对数组进行不同的赋值表示网格节点上无棋、黑棋、白棋;使用playChessHandler作为鼠标单击事件,单击事件调用Clientskt中的函数传送棋子坐标以及输赢信息。drawChess函数画棋子,drawGrids画网格,gameOver判断棋盘棋子分布,输赢情况。 import javax.swing.*; import java.awt.*; import java.awt.event.*; import ChatOneToOneClient.Clientskt; class ClientChessPanel extends JPanel{ private static final long serialVersionUID = 1L; private int space=20; //网格间的距离 private int grids=30; //棋盘的网格数 private int radius=space/2; //棋的半径 Clientskt skt; //当chesses[i][j]=0,表示网格节点(i,j)上无棋 //当chesses[i][j]=1,表示网格节点(i,j)上放白棋 //当chesses[i][j]=2,表示网格节点(i,j)上放黑棋 private int[][] chesses=new int[grids+1][grids+1]; private int currColor=1; //当前棋的颜色 private MouseListener playChessHandler=new MouseAdapter(){ public void mouseClicked(MouseEvent e){ if(skt.reMouseGo()){ int x=e.getX(); int y=e.getY(); //放一颗棋子 if(x<=grids*space && x>=0 && y<=grids*space && y>=0) if(chesses[round(x)][round(y)]==0){ chesses[round(x)][round(y)]=currColor; repaint(); //刷新图形 skt.dataout("x:"+String.valueOf(round(x))); skt.dataout("y:"+String.valueOf(round(y))); skt.setMouseGo(false); if(gameOver(currColor)){ skt.dataout("g:你输了"); skt.chat.clientDialog=new ClientMyDialog(skt.chat,"你赢了"); skt.chat.clientDialog.setVisible(true); } currColor=currColor==1?2:1; //切换棋子的颜色 } } } }; public int round(float a){ //获得接近a的网格节点坐标 float f=a/space; return Math.round(f); } public ClientChessPanel(int space,int grids,Clientskt skt){ this.space=space; this.grids=grids; this.radius=space/2; this.skt=skt; setBackground(Color.BLUE); setSize(space*grids,space*grids); addMouseListener(playChessHandler); startChess(); } public void startChess(){ clearGrids(); //清空棋盘 currColor=1; repaint(); //刷新图形 } private void clearGrids(){ for(int i=0;i<=grids;i++) for(int j=0;j<=grids;j++) chesses[i][j]=0; } //画一颗棋子 private void drawChess(Graphics g,int x,int y,int color){ g.setColor(color==1?Color.GREEN:Color.BLACK); g.fillOval(x*space-radius,y*space-radius,radius*2,radius*2); } //画网格  private void drawGrids(Graphics g){ g.setColor(Color.DARK_GRAY); for(int i=0;i<=grids;i++){ g.drawLine(0,i*space,grids*space,i*space); g.drawLine(i*space,0,i*space,grids*space); } } //接收对方下的棋坐标 public void paintChess(int x,int y){ if(x<=grids*space && x>=0 && y<=grids*space && y>=0){ if(chesses[x][y]==0){ chesses[x][y]=currColor; currColor=currColor==1?2:1; //切换棋子的颜色 skt.setMouseGo(false); skt.setMouseGo(true); repaint(); //刷新图形 } } } //判断游戏是否结束 public boolean gameOver(int gameOver){ int five=0;//用于判断是否有连续5个子 for(int i=0;i<grids;i++){//行 for(int j=0;j<grids;j++){//列 if(chesses[i][j]==gameOver){ five++; for(int k=1;k<5&&j<grids-4;k++){//行向比较 if(chesses[i][j+k]==gameOver){ five++; if(five==5){ return true; } } else{ five=1; k=5; } } for(int k=1;k<5&&i<grids-4;k++){//列向比较 if(chesses[i+k][j]==gameOver){ five++; if(five==5){ return true; } } else{ five=1; k=5; } } for(int k=1;k<5&&i<grids-4&&j<grids-4;k++){//右斜向比较 if(chesses[i+k][j+k]==gameOver){ five++; if(five==5){ return true; } } else{ five=1; k=5; } } for(int k=1;k<5&&i<grids-4&&j>4;k++){//左斜向比较 if(chesses[i+k][j-k]==gameOver){ five++; if(five==5){ return true; } } else{ five=1; k=5; } } } } five=0; } return false; } public void paintComponent(Graphics g){ //覆盖paintComponent()方法 super.paintComponent(g); //必须先调用父类的方法 drawGrids(g); //画网格 for(int i=0;i<=grids;i++) for(int j=0;j<=grids;j++) if(chesses[i][j]!=0) drawChess(g,i,j,chesses[i][j]); //画棋子 } } 2、 ClientComponentPopupMenu类主要负责聊天的部分,使用JTextField并且对其添加单击事件以及鼠标事件,可以实现文本的剪贴、复制粘贴等功能。 import java.awt.*; import java.awt.event.*; import java.awt.print.*; import javax.swing.*; import javax.swing.text.*; public class ClientComponentPopupMenu extends JPopupMenu implements MouseListener,ActionListener{ private static final long serialVersionUID = 1L; public static ClientComponentPopupMenu sharedInstance = null; public static void installToComponent(JTextComponent c){ if(c instanceof JTextArea && !(c instanceof JPasswordField)){ c.addMouseListener(ClientComponentPopupMenu.getSharedInstance()); } else if(c instanceof JTextField && !(c instanceof JPasswordField)){ c.addMouseListener(ClientComponentPopupMenu.getSharedInstance()); } } public static void uninstallFromComponent(JTextComponent c){ if(c instanceof JTextArea && !(c instanceof JPasswordField)){ c.removeMouseListener(getSharedInstance()); } else if(c instanceof JTextField && !(c instanceof JPasswordField)){ c.removeMouseListener(getSharedInstance()); } } JMenuItem cutItem,copyItem,pasteItem,deleteItem,selectAllItem,printItem; //构造器 public ClientComponentPopupMenu(){ add(cutItem = new JMenuItem("剪切 (T)")); add(copyItem = new JMenuItem("复制 (C)")); add(pasteItem = new JMenuItem("粘贴 (P)")); add(deleteItem = new JMenuItem("删除 (D)")); addSeparator(); add(selectAllItem = new JMenuItem("全选 (A)")); addSeparator(); add(printItem = new JMenuItem("打印 (R)")); //设置快捷键 cutItem.setMnemonic('T'); copyItem.setMnemonic('C'); pasteItem.setMnemonic('P'); deleteItem.setMnemonic('D'); selectAllItem.setMnemonic('A'); printItem.setMnemonic('R'); //增加监听 cutItem.addActionListener(this); copyItem.addActionListener(this); pasteItem.addActionListener(this); deleteItem.addActionListener(this); selectAllItem.addActionListener(this); printItem.addActionListener(this); } //如果对象不存在,创建一个对象 public static ClientComponentPopupMenu getSharedInstance(){ //单例模式 if (sharedInstance == null){ sharedInstance = new ClientComponentPopupMenu(); } return sharedInstance; } public void mouseReleased(MouseEvent e){ if(e.isPopupTrigger()&&e.getSource() instanceof JTextArea){ //e.isPopupTrigger()鼠标右键 JTextArea textfield = (JTextArea) e.getSource(); if(Boolean.TRUE.equals(textfield.getClientProperty("DisablePopupMenu"))){ return; } textfield.requestFocusInWindow(); this.show(textfield,e.getX(),e.getY()); //获得组件及位置 } else if(e.isPopupTrigger()&&e.getSource() instanceof JTextField){ JTextField textfield = (JTextField) e.getSource(); if(Boolean.TRUE.equals(textfield.getClientProperty("DisablePopupMenu"))){ return; } textfield.requestFocusInWindow(); this.show(textfield,e.getX(),e.getY()); //获得组件及位置 } } public void mouseClicked(MouseEvent e){ } public void mousePressed(MouseEvent e){ } public void mouseEntered(MouseEvent e){ } public void mouseExited(MouseEvent e){ } public void show(Component invoker,int x,int y){ JTextComponent tc = (JTextComponent) invoker; String sel = tc.getSelectedText(); boolean selected = sel != null&& !sel.equals(""); boolean enableAndEditable = tc.isEnabled()&&tc.isEditable(); //禁用与启用 cutItem.setEnabled(selected && enableAndEditable); copyItem.setEnabled(selected && tc.isEnabled()); deleteItem.setEnabled(selected && enableAndEditable); pasteItem.setEnabled(enableAndEditable); selectAllItem.setEnabled(tc.isEnabled()); super.show(invoker,x,y); } public void actionPerformed(ActionEvent e){ JTextComponent tc =(JTextComponent) getInvoker(); if(e.getSource() == cutItem){ tc.cut(); } else if(e.getSource() == copyItem){ tc.copy(); } else if (e.getSource() == pasteItem){ tc.paste(); } else if (e.getSource() == selectAllItem){ tc.selectAll(); } else if (e.getSource() == deleteItem){ Document doc = tc.getDocument(); int start = tc.getSelectionStart(); int end = tc.getSelectionEnd(); try{ Position p0 = doc.createPosition(start); Position p1 = doc.createPosition(end); if((p0 != null) && (p1 !=null)&&(p0.getOffset()!=p1.getOffset())){ doc.remove(p0.getOffset(),p1.getOffset() - p0.getOffset()); } } catch(BadLocationException be){ } } if(e.getSource() == printItem ){ try { tc.print(); } catch (PrinterException e1) { // TODO Auto-generated catch block e1.printStackTrace(); } } } } 3、 ClientMyDialog类是游戏结束时的提示对话框。 public class ClientMyDialog extends JDialog{ private static final long serialVersionUID = 1L; private JLabel label1 ; private JButton jbtn=new JButton("确定"); public ClientMyDialog(JFrame parent,String info) { super(parent, "客户端提示信息", true); label1=new JLabel(info); Container contentPane = getContentPane(); contentPane.setLayout(new BorderLayout()); contentPane.add(label1,BorderLayout.NORTH); contentPane.add(jbtn,BorderLayout.SOUTH); jbtn.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent arg0) { // TODO Auto-generated method stub dispose(); // 关闭对话框 } }); setLocation(300, 300); pack(); } } 4、 Clientskt是网络通信部分,首先客户端要输入ip地址、端口号,theInputStream和theOutputStream传输流信息。 public class Clientskt extends Thread{ Socket skt; InetAddress host; int port; BufferedReader theInputStream; PrintStream theOutputStream; String readin; ChatOneToOneClient chat; int x=-1,y=-1;//用于接收坐标 private boolean mouseGo=false;//使棋盘能放棋子 public Clientskt(String ip,int p,ChatOneToOneClient chat){ try { host=InetAddress.getByName(ip); port=p; this.chat=chat; } catch (Exception e) { // TODO: handle exception chat.ta.append(e.toString()); } } public void run(){ try { chat.ta.append("尝试联机\n"); skt=new Socket(host,port); chat.ta.append("联机成功\n"); theInputStream=new BufferedReader(new InputStreamReader(skt.getInputStream())); theOutputStream=new PrintStream(skt.getOutputStream()); chat.tftype.setEditable(true); mouseGo=true; while(true){ readin=theInputStream.readLine(); if(readin.startsWith("chat:")){ readin=readin.substring(5, readin.length()); chat.ta.append(readin+"\n"); chat.ta.setCaretPosition(chat.ta.getText().length()); } else if(readin.startsWith("g:")){ readin=readin.substring(2, readin.length()); mouseGo=false; chat.clientDialog=new ClientMyDialog(chat,readin); chat.clientDialog.setVisible(true); } else{ if(readin.startsWith("x:")){ readin=readin.substring(2, readin.length()); x=Integer.parseInt(readin); } else{ readin=readin.substring(2, readin.length()); y=Integer.parseInt(readin); } if(x!=-1&&y!=-1){ chat.chessPanel.paintChess(x, y); x=-1; y=-1; } } } } catch (SocketException e) { // TODO: handle exception chat.ta.append("联机中断"); chat.clientBtn.setEnabled(true); chat.tfaddress.setEditable(true); try { skt.close(); } catch (IOException err) { // TODO: handle exception chat.ta.append(err.toString()); } }catch(IOException e){ chat.ta.append(e.toString()); } } public void dataout(String data){ theOutputStream.println(data); } public boolean reMouseGo(){ return mouseGo; } public void setMouseGo(boolean MouseGO){ this.mouseGo=MouseGO; } } 5、 ChatOneToOneClient类布局整体程序,采用BorderLayout进行布局,其中tftype作为聊天输入框,对其添加键盘事件。 服务器端程序类似于客户端。 public class ChatOneToOneClient extends JFrame{ private static final long serialVersionUID = 1L; ClientMyDialog clientDialog; Container contentPane; JButton clientBtn; JTextArea ta; JLabel inputIP,myName; JTextField tfaddress,tfport,tftype; int port; Clientskt client; static ChatOneToOneClient frm; JScrollPane pane ; JPanel north,south,center,east,west; ClientChessPanel chessPanel; public ChatOneToOneClient(){ contentPane=getContentPane(); north=new JPanel(); south=new JPanel(); center=new JPanel(); east=new JPanel(); west=new JPanel(); inputIP=new JLabel("请输入IP:"); myName=new JLabel("某某,25565"); clientBtn=new JButton("连接"); ta=new JTextArea(20,15); tfaddress=new JTextField(9); tfport=new JTextField("8888"); tfport.setEditable(false); tftype=new JTextField(50); pane=new JScrollPane(ta); ta.setEditable(false); tftype.addKeyListener(new KeyListener() { @Override public void keyTyped(KeyEvent e) { // TODO Auto-generated method stub } @Override public void keyReleased(KeyEvent e) { // TODO Auto-generated method stub } @Override public void keyPressed(KeyEvent e) { // TODO Auto-genera
展开阅读全文

开通  VIP会员、SVIP会员  优惠大
下载10份以上建议开通VIP会员
下载20份以上建议开通SVIP会员


开通VIP      成为共赢上传

当前位置:首页 > 包罗万象 > 大杂烩

移动网页_全站_页脚广告1

关于我们      便捷服务       自信AI       AI导航        抽奖活动

©2010-2026 宁波自信网络信息技术有限公司  版权所有

客服电话:0574-28810668  投诉电话:18658249818

gongan.png浙公网安备33021202000488号   

icp.png浙ICP备2021020529号-1  |  浙B2-20240490  

关注我们 :微信公众号    抖音    微博    LOFTER 

客服