思路:
游戏主界面: 1.一个15*15的五子棋界面; 2.能够在界面上下黑白棋子; 3.需要把棋子下在交叉点上; 4.实现棋子重绘;——作用:当界面大小被改变时能够保持棋盘和棋盘上面的棋子不会消失; 5.相同位置不能下多个棋子; 6.只有当“开始新游戏”的按钮被点击时,才能开始下棋; 1.一个15*15的五子棋界面; 需要重写GoBangframe的重绘方法,使其在界面刚生成时就产生一个15*15的棋盘。(重绘方法会在每次页面大小被改变时执行,因此当你改变大小时,棋盘不会消失)。这里我们可以通过两个for循环画出15条行线和15条列线。 2.能够在界面上下黑白棋子; 实现这个功能需要定义一个变量turn表名当前轮到哪方下棋。如果turn=1表明轮到黑方,turn=2表明轮到白方。每次黑方下完棋之后turn+1,白方下完棋之后turn-1。 3.需要把棋子下在交叉点上; 如果鼠标点击在交叉点处的某个范围内,我们都把棋子下在这个交叉点上。在这个由于格子大小是40,我们定义的范围时以交叉点为中心的上下20的正方形。这样我们就能确保每一次点击都会落到某一个交叉点处,不会覆盖也不会出现没有落子的情况。 4.实现棋子重绘;——作用:当界面大小被改变时能够保持棋盘上面的棋子不消失; 前面的棋盘重绘,虽然15*15的棋盘不会消失,但是棋子会消失。因此我们在重绘出棋盘以后还要把棋子也重新画上去。这里用了一个二维数组isAvail[15][15]来保存棋子信息,如果isArray[i][j]=0,表明这个位置没有棋子,等于1表明是一个黑棋子,等于2表明是一个白棋子。我们根据这些信息,遍历isArray数组,把棋子重新绘制上去。 5.相同位置不能下多个棋子; 判断isArray[i][j]是不是等于0,如果是0就可以下,如果不是则提示玩家下在其它地方。 6.只有当“开始新游戏”的按钮被点击时,才能开始下棋; 下棋是通过监听棋盘界面来实现的,因此我们只需要监听“开始新游戏”这个按钮,如果这个按钮被点击了,我们在给棋盘界面添加监听方法,否则不添加。 实现五子棋界面需要的API类: JFrame 顶级容器类 BorderLayout 框架布局类——把容器分为上北下南左西右东中间五个部分,每个部分只能添加一个组件。 需要把整个界面分为左右两部分。选择在框架布局的中间和右边两个部分。 这里我们还需要另一个容器类——JPanel 面板容器类。主要用来实现右边的部分,因为原本框架布局的右边部分只能添加 一个组件,但是我们需要添加的组件不只一个,因此就先这个部分加上一个JPanel,然后再在JPanel上加我们需要的组件, 包括按钮等等。 JFrame和JPanel的区别:JFrame是最底层的容器,JPanel放在它上面,同一个界面只有一个JFrame,但是一个JFrame 上面可以有多个JPanel。相当于JFrame是一个大餐桌,JPanel是盘子,如果我们要对餐桌JFrame上的东西进行管理分类等, 我们就需要使用这些JPanel盘子。 FlowLayout 流式布局类。因为我们右边的JPanel部分需要将按钮等组件由上到下进行排列。 JButton 按钮组件类 JComboBox 下拉列表框类——实现那个人人对战和人机对战的选择 Dimension 封装组件宽度和高度的类——组件类不能直接用setSize方法来设置 事件监听机制的类: ActionListener 状态监听处理类 ActionEvent 状态监听事件,监听某个组件的状态是否有改变 MouseListener 鼠标监听处理类 MouseEvent 鼠标监听事件,里面包含鼠标被点击等事件的处理方法。当界面被点击时就放下一个棋子。 绘画所需要的类: Graphics|Graphics2D 画笔类 Color 颜色类,需要设置画笔的颜色,实现黑白棋子 1.判断输赢——出现了五颗连在一起的同颜色的棋子 A.判断的时间:刚落完棋子的时候 B.判断的范围: 一开始我想要遍历整个棋盘,但仔细想想这个想法是不切实际的。整个棋盘太大了,而且相连的棋子情况不好细分。 于是我就换了一种思路:既然我们是在落子的时候开始判断,那么显然我们是要围绕我们刚落的这个棋子来进行判断。 每一个点一共有四个方向可能出现五个相连的棋子。与这个棋子是否能决定输赢相关联的棋子每一个方向上有八个, 往前四个往后四个。也就是每一个方向我们都要遍历九个棋子的颜色,判断是否有五个相同颜色的棋子, 有就说明输赢已经出现。假设我们落下的棋子对应的数组位置为isAvail[i][j]。 同一行上:遍历isAvail[i-4][j]...isAvail[i+4][j]; 同一列上:遍历isAvail[i][j-4]...isAvail[i][j+4]; 同一斜线上(左上到右下):遍历isAvail[i-4][j-4]...isAvail[i+4][j+4] 同一斜线上(左下到右上):令sum=i+j;遍历isAvail[i-4][sum-(i-4)]...isAvail[i+4][sum-(i+4)]; C.注意事项: 要注意防止数组越界,iaAvail[i][j]中的i,j均不能小于0,大于14; 要注意五个棋子必须是相连的,在我们一次遍历的时候一旦出现了没有棋子或者是其他棋子,必须把前面的计数值清空,重新开始计数; 2.实现悔棋操作 设置一个ChessPosition对象,该对象包含listi,listj两个数据,分别表示我们与棋子对应的数组位置中的i和j。 定义一个动态的ChessPosition对象数组ChessPositonList,每当我们落下一颗棋子时, 就把这个棋子的数组位置信息添加到对象数组中。每当我们点击悔棋时,我们就把turn相应的数值转换到另一方, 并且用remove方法,取出对象数组中最后一步所对应的棋子信息,并且删除这个信息。 然后根据这个信息把isAvail数组中对应的位置重新置为0,并且调用GoBangframe对象的重绘方法。 3.实现认输操作 一旦“认输”按钮被点击,先通过turn的数值判断当前是轮到哪一方。如果是白方,就输出“黑方赢”的信息;如果是黑方,就输出“白方赢”的信息。
具体代码:
public class Main { public static void main(String[] args) { new Welcome(); } }
//设置按钮监听方法ButttonLitener类 import javax.swing.*; import java.awt.event.ActionListener; import java.awt.event.ActionEvent; import java.awt.*; import static com.sun.deploy.uitoolkit.ToolkitStore.dispose; import static java.lang.System.*; //实现对JPanel的监听接口处理 public class ButtonListener extends JFrame implements ActionListener{ public WuZiQi wu; Date date=new Date(); public ButtonListener(WuZiQi wu) { this.wu=wu;//获取左半部分的画板 } //当界面发生操作时进行处理 public void actionPerformed(ActionEvent e) { //获取当前被点击按钮的内容,判断是不是"开始新游戏"这个按钮 if(e.getActionCommand().equals("开始")) { //如果是开始新游戏的按钮,再为左半部分设置监听方法 MouserListe fl=new MouserListe(); fl.setGraphics(wu);//获取画笔对象 wu.addMouseListener(fl);//监听 }//判断当前点击的按钮是不是悔棋 else if(e.getActionCommand().equals("悔棋")) { if(wu.ChessPositonList.size()>1) { //把棋子数组相应的位置置为0; ChessPosition l=new ChessPosition(); ChessPosition l1=new ChessPosition(); //获取最后一个棋子的对象信息(移除) l=wu.ChessPositonList.remove(wu.ChessPositonList.size()-1); l1=wu.ChessPositonList.remove(wu.ChessPositonList.size()-1); //把相应的数组位置置为0 wu.isAvail[l.Listi][l.Listj]=0; wu.isAvail[l1.Listi][l1.Listj]=0; //把玩家还原为上一步的玩家 /* 悔棋应该是己方落子且敌方也落子之后己方悔棋,需要撤销敌方和己方的两手棋子,悔棋后 依旧是己方落子 */ if(wu.turn==1) { wu.turn--; } else { wu.turn++; } //直接调用wu的重绘方法,重绘方法的画笔应该是在棋盘页面还没生成的时候就要获取 //调用repaint会自动调用paint方法,而且不用给参数 wu.repaint(); } else { System.out.println("不能悔棋!"); } }else if(e.getActionCommand().equals("认输")) { if(wu.turn==2){ JOptionPane.showMessageDialog(null, "白方赢"); this.dispose(); new WuZiQi().initUI(); }else if(wu.turn==1) { JOptionPane.showMessageDialog(null, "黑方赢"); this.dispose(); new WuZiQi().initUI(); /* for(int ii=0;ii<date.row;ii++) { for(int jj=0;jj<date.column;jj++) { wu.isAvail[ii][jj]=0; } } wu.repaint();*/ } }else if(e.getActionCommand().equals("退出")){ JOptionPane.showMessageDialog(null, "谢谢使用,再见!"); System.exit(0); } } }
//新建一个棋子类ChessPosition保存每一步棋子所在的位置 public class ChessPosition { public int Listi, Listj; public ChessPosition() { } public ChessPosition(int Listi, int Listj) { this.Listi = Listi; this.Listj = Listj; } }
/* 定义与棋盘数据相关的接口,保存棋盘的起点,格子大小,行数列数等信息 */ public class Date { public int x=20,y=20,size=40,row=15,column=15; //x=20,y=20 棋盘的起点 //size=40 格子大小 //row,column=15 行列数皆为15 }
import javax.swing.*; import java.awt.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; /* 游戏使用帮助 */ public class Help extends JFrame implements ActionListener { JPanel jPanel; JButton b1,b2; TextArea text; public Help(){ this.setTitle("游戏帮助"); b1=new JButton("确定"); b2=new JButton("退出"); this.setBounds(100,100,300,300); text=new TextArea("双方分别使用黑白两色的棋子,空棋盘开局。黑色棋子先下,白色棋子后下," + "每次只能下一子。轮流下子是双方的权利,但允许任何一方放弃下子权," + "先形成5子连线者获胜。",8,15); jPanel=new JPanel(); jPanel.add(text); jPanel.add(b1); jPanel.add(b2); this.add(jPanel); this.setBackground(Color.blue); this.setVisible(true); this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); b1.addActionListener(this); b2.addActionListener(this); } @Override public void actionPerformed(ActionEvent e) { if(e.getSource()==b1){ this.dispose(); new Welcome(); }else{ JOptionPane.showMessageDialog(this,"谢谢使用,再见!"); System.exit(0); } } }
//import java.awt.*; //import java.awt.event.MouseEvent; //import java.awt.event.MouseListener; // ///* // // */ //public class MouserListe implements MouseListener { // WuZiQi wuziqi;//定义WuZiQi对象 // Date date; // int turn=1;//判断当前轮到谁了,1表示黑方,2表示白方 // // public void setGraphics(WuZiQi wuziqi) { // this.wuziqi=wuziqi; // } // // @Override // public void mouseClicked(MouseEvent e) { // int x=e.getX(); // int y=e.getY();//得到鼠标的(像素)位置 // // // //计算棋子要落在棋盘的哪个交叉点上 // int countx=(x/40)*40+20; // int county=(y/40)*40+20; // Graphics g=wuziqi.getGraphics();// // // // // if(wuziqi.isAvail[(countx-20)/40][(county-20)/40]!=0) { // System.out.println("此处已经有棋子了,请下在其它地方"); // } // else { // //当前位置可以落子,先计算棋盘上棋子在数组中相应的位置 // int colu=(countx-20)/40; // int ro=(county-20)/40; // // if(turn==1) { // //先设置颜色 // g.setColor(Color.black); // //落子 // g.fillOval(countx-date.size/2, county-date.size/2, date.size, date.size); // //设置当前位置已经有棋子了,棋子为黑子 // wuziqi.isAvail[colu][ro]=1; // turn++; // } // else { // g.setColor(Color.white); // g.fillOval(countx-date.size/2, county-date.size/2, date.size, date.size); // //设置当前位置已经有棋子了,棋子为白子 // // wuziqi.isAvail[colu][ro]=2; // turn--; // } // } // // // // } // // @Override // public void mousePressed(MouseEvent e) { // // } // // @Override // public void mouseReleased(MouseEvent e) { // // } // // @Override // public void mouseEntered(MouseEvent e) { // // } // // @Override // public void mouseExited(MouseEvent e) { // // } // // public void setGraphics() { // // } //} import javax.swing.*; import java.awt.event.ActionListener; import java.awt.event.MouseListener; import java.awt.event.ActionEvent; import java.awt.Graphics; import java.awt.Color; //实现对WuZiQi界面的监听接口处理 public class MouserListe implements MouseListener { Date date = new Date(); public WuZiQi gf; public int turn = 1;//判断当前轮到谁了,1表示黑方,2表示白方 public void setGraphics(WuZiQi gf) { this.gf = gf; } public void mouseClicked(java.awt.event.MouseEvent e) { //获取鼠标位置(像素) int x = e.getX(); int y = e.getY(); //计算棋子要落在棋盘的哪个交叉点上 int countx = (x / 40) * 40 + 20; int county = (y / 40) * 40 + 20; Graphics g = gf.getGraphics();//获取画笔 //相同位置不能下多个棋子 //判断isArray[i][j]是不是等于0,如果是0就可以下 if (gf.isAvail[(countx - 20) / 40][(county - 20) / 40] != 0) { JOptionPane.showMessageDialog(null, "此处已经有棋子了,请下在其它地方"); } else { //当前位置可以落子,先计算棋盘上棋子在数组中相应的位置 int colu = (countx - 20) / 40; int ro = (county - 20) / 40; if (turn == 1) { //先设置颜色 g.setColor(Color.black); //落子 g.fillOval(countx - date.size / 2, county - date.size / 2, date.size, date.size); //设置当前位置已经有棋子了,棋子为黑子 gf.isAvail[colu][ro] = 1; //把当前所下的棋子位置保存在动态数组中 gf.ChessPositonList.add(new ChessPosition(colu, ro)); turn++; //判断是否已经出现五颗棋子了 //列判断 //首先界定数组范围,防止越界 int imin = colu - 4, imax = colu + 4; if (imin < 0) imin = 0; if (imax > 14) imax = 14; int count1 = 0;//判断相连的棋子数 for (int i = imin; i <= imax; i++) { if (gf.isAvail[i][ro] == 1) count1++; //如果出现了其他棋子,或者是没有棋子时,就重新开始计数 else count1 = 0; if (count1 == 5) { JOptionPane.showMessageDialog(null, "黑方赢"); new WuZiQi().initUI(); return; /*for (int ii = 0; ii < date.row; ii++) { for (int jj = 0; jj < date.column; jj++) { gf.isAvail[ii][jj] = 0; } } gf.repaint();*/ } } //行判断 //首先界定数组范围,防止越界 int jmin = ro - 4, jmax = ro + 4; if (jmin < 0) jmin = 0; if (jmax > 14) jmax = 14; int count2 = 0;//判断相连的棋子数 for (int j = jmin; j <= jmax; j++) { if (gf.isAvail[colu][j] == 1) count2++; else count2 = 0; if (count2 == 5) { JOptionPane.showMessageDialog(null, "黑方赢"); new WuZiQi().initUI(); return; /*for (int ii = 0; ii < date.row; ii++) { for (int jj = 0; jj < date.column; jj++) { gf.isAvail[ii][jj] = 0; } } gf.repaint();*/ } //如果出现了其他棋子,或者是没有棋子时,就重新开始计数 } //135度判断左下到右上 //首先界定数组范围,防止越界 int count3 = 0;//判断相连的棋子数 for (int i = -4; i <= 4; i++) { if ((colu + i >= 0) && (ro + i >= 0) && (colu + i <= 14) && (ro + i <= 14)) { if (gf.isAvail[colu + i][ro + i] == 1) count3++; //如果出现了其他棋子,或者是没有棋子时,就重新开始计数 else count3 = 0; if (count3 == 5) { JOptionPane.showMessageDialog(null, "黑方赢"); new WuZiQi().initUI(); return; /*for (int ii = 0; ii < date.row; ii++) { for (int jj = 0; jj < date.column; jj++) { gf.isAvail[ii][jj] = 0; } } gf.repaint();*/ } } } //左上到右下 int count4 = 0;//判断相连的棋子数 for (int i = -4; i <= 4; i++) { if ((colu + i >= 0) && (ro - i >= 0) && (colu + i <= 14) && (ro - i <= 14)) { //System.out.print("count4:"+count4); if (gf.isAvail[colu + i][ro - i] == 1) count4++; //如果出现了其他棋子,或者是没有棋子时,就重新开始计数 else count4 = 0; if (count4 == 5) { JOptionPane.showMessageDialog(null, "黑方赢"); new WuZiQi().initUI(); return; /*for (int ii = 0; ii < date.row; ii++) { for (int jj = 0; jj < date.column; jj++) { gf.isAvail[ii][jj] = 0; } } gf.repaint();*/ } } } } else { g.setColor(Color.white); g.fillOval(countx - date.size / 2, county - date.size / 2, date.size, date.size); //设置当前位置已经有棋子了,棋子为白子 //把当前所下的棋子位置保存在动态数组中 gf.ChessPositonList.add(new ChessPosition(colu, ro)); gf.isAvail[colu][ro] = 2; turn--; //列判断 //首先界定数组范围,防止越界 int imin = colu - 4, imax = colu + 4; if (imin < 0) imin = 0; if (imax > 14) imax = 14; int count1 = 0;//判断相连的棋子数 for (int i = imin; i <= imax; i++) { if (gf.isAvail[i][ro] == 2) count1++; //如果出现了其他棋子,或者是没有棋子时,就重新开始计数 else count1 = 0; if (count1 == 5) { JOptionPane.showMessageDialog(null, "白方赢"); new WuZiQi().initUI(); return; /*for (int ii = 0; ii < date.row; ii++) { for (int jj = 0; jj < date.column; jj++) { gf.isAvail[ii][jj] = 0; } } gf.repaint();*/ } } //行判断 //首先界定数组范围,防止越界 int jmin = ro - 4, jmax = ro + 4; if (jmin < 0) jmin = 0; if (jmax > 14) jmax = 14; int count2 = 0;//判断相连的棋子数 for (int j = jmin; j <= jmax; j++) { if (gf.isAvail[colu][j] == 2) count2++; //如果出现了其他棋子,或者是没有棋子时,就重新开始计数 else count2 = 0; if (count2 == 5) { JOptionPane.showMessageDialog(null, "白方赢"); new WuZiQi().initUI(); return; /*for (int ii = 0; ii < date.row; ii++) { for (int jj = 0; jj < date.column; jj++) { gf.isAvail[ii][jj] = 0; } } gf.repaint();*/ } } //135度判断 //首先界定数组范围,防止越界 int count3 = 0;//判断相连的棋子数 for (int i = -4; i <= 4; i++) { if ((colu + i >= 0) && (ro + i >= 0) && (colu + i <= 14) && (ro + i <= 14)) { if (gf.isAvail[colu + i][ro + i] == 2) count3++; //如果出现了其他棋子,或者是没有棋子时,就重新开始计数 else count3 = 0; if (count3 == 5) { JOptionPane.showMessageDialog(null, "白方赢"); new WuZiQi().initUI(); return; /*for (int ii = 0; ii < date.row; ii++) { for (int jj = 0; jj < date.column; jj++) { gf.isAvail[ii][jj] = 0; } } gf.repaint();*/ } } } int count4 = 0;//判断相连的棋子数 for (int i = -4; i <= 4; i++) { if ((colu + i >= 0) && (ro - i >= 0) && (colu + i <= 14) && (ro - i <= 14)) { if (gf.isAvail[colu + i][ro - i] == 2) count4++; //如果出现了其他棋子,或者是没有棋子时,就重新开始计数 else count4 = 0; if (count4 == 5) { JOptionPane.showMessageDialog(null, "白方赢"); new WuZiQi().initUI(); return; /*for (int ii = 0; ii < date.row; ii++) { for (int jj = 0; jj < date.column; jj++) { gf.isAvail[ii][jj] = 0; } } gf.repaint();*/ } } } /* 判断是否和局 */ int k=0; for (int i = 0; i < date.row; i++) {//循环所有的交叉点 for (int j = 0; j < date.column; j++) { if (gf.isAvail[i][j]!=0) { k++; } } if(k==30){ JOptionPane.showMessageDialog(null, "和局"); new WuZiQi().initUI(); return; } } } } } // Method descriptor #8 (Ljava/awt/event/MouseEvent;)V public void mousePressed(java.awt.event.MouseEvent e) { } // Method descriptor #8 (Ljava/awt/event/MouseEvent;)V public void mouseReleased(java.awt.event.MouseEvent e) { } // Method descriptor #8 (Ljava/awt/event/MouseEvent;)V public void mouseEntered(java.awt.event.MouseEvent e) { } // Method descriptor #8 (Ljava/awt/event/MouseEvent;)V public void mouseExited(java.awt.event.MouseEvent e) { } }
import javax.swing.*; import java.awt.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; /* 游戏主界面: 1. 15*15格子 2, */ public class Welcome extends JFrame implements ActionListener { JLayeredPane layeredPane; JPanel jpanel; JLabel jlable; JButton b1,b2,b3;//开始游戏 帮助 结束游戏 //创建一个容器 Container ct; //创建背景面板。 BackgroundPanel bgp; public Welcome (){ this.setTitle("五子棋"); /*this.setBounds(50,50,580,550); jlable=new JLabel(); ImageIcon img=new ImageIcon("D:\\wuziqi.jpg"); jlable=new JLabel(img); jpanel=new JPanel(); b1=new JButton("开始"); b2=new JButton("帮助"); b3=new JButton("退出"); jpanel.add(b1); jpanel.add(b2); jpanel.add(b3); jpanel.add(jlable); this.add(jpanel);*/ //不采用任何布局方式。 ct=this.getContentPane(); this.setLayout(null); //在这里随便找一张400*300的照片既可以看到测试结果。 bgp=new BackgroundPanel((new ImageIcon("D://wuziqi.jpg")).getImage()); bgp.setBounds(0,0,600,550); ct.add(bgp); //创建按钮 b1=new JButton("开始"); b2=new JButton("帮助"); b3=new JButton("退出"); b1.setBounds(130,30,80,30); b2.setBounds(230,30,80,30); b3.setBounds(330,30,80,30); ct.add(b1); ct.add(b2); ct.add(b3); this.setSize(600,550); this.setLocation(200,100); this.setBackground(Color.blue); this.setVisible(true); this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); b1.addActionListener(this); b2.addActionListener(this); b3.addActionListener(this); } @Override public void actionPerformed(ActionEvent e) { if(e.getSource()==b1){ this.dispose(); new WuZiQi().initUI(); }else if(e.getSource()==b2){ this.dispose(); new Help(); }else{ JOptionPane.showMessageDialog(this,"谢谢使用,再见!"); System.exit(0); } } } class BackgroundPanel extends JPanel { Image im; public BackgroundPanel(Image im) { this.im = im; this.setOpaque(true); } //Draw the back ground. public void paintComponent(Graphics g) { super.paintComponents(g); g.drawImage(im, 0, 0, this.getWidth(), this.getHeight(), this); } }
import javax.swing.*; import java.awt.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; /* 游戏主界面: 1. 15*15格子 2, */ public class Welcome extends JFrame implements ActionListener { JLayeredPane layeredPane; JPanel jpanel; JLabel jlable; JButton b1,b2,b3;//开始游戏 帮助 结束游戏 //创建一个容器 Container ct; //创建背景面板。 BackgroundPanel bgp; public Welcome (){ this.setTitle("五子棋"); /*this.setBounds(50,50,580,550); jlable=new JLabel(); ImageIcon img=new ImageIcon("D:\\wuziqi.jpg"); jlable=new JLabel(img); jpanel=new JPanel(); b1=new JButton("开始"); b2=new JButton("帮助"); b3=new JButton("退出"); jpanel.add(b1); jpanel.add(b2); jpanel.add(b3); jpanel.add(jlable); this.add(jpanel);*/ //不采用任何布局方式。 ct=this.getContentPane(); this.setLayout(null); //在这里随便找一张400*300的照片既可以看到测试结果。 bgp=new BackgroundPanel((new ImageIcon("D://wuziqi.jpg")).getImage()); bgp.setBounds(0,0,600,550); ct.add(bgp); //创建按钮 b1=new JButton("开始"); b2=new JButton("帮助"); b3=new JButton("退出"); b1.setBounds(130,30,80,30); b2.setBounds(230,30,80,30); b3.setBounds(330,30,80,30); ct.add(b1); ct.add(b2); ct.add(b3); this.setSize(600,550); this.setLocation(200,100); this.setBackground(Color.blue); this.setVisible(true); this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); b1.addActionListener(this); b2.addActionListener(this); b3.addActionListener(this); } @Override public void actionPerformed(ActionEvent e) { if(e.getSource()==b1){ this.dispose(); new WuZiQi().initUI(); }else if(e.getSource()==b2){ this.dispose(); new Help(); }else{ JOptionPane.showMessageDialog(this,"谢谢使用,再见!"); System.exit(0); } } } class BackgroundPanel extends JPanel { Image im; public BackgroundPanel(Image im) { this.im = im; this.setOpaque(true); } //Draw the back ground. public void paintComponent(Graphics g) { super.paintComponents(g); g.drawImage(im, 0, 0, this.getWidth(), this.getHeight(), this); } }
import javax.swing.*; import java.awt.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.util.ArrayList; //游戏主界面 public class WuZiQi extends JPanel { public int turn=1; int[][] isAvail=new int [15][15];//定义一个二维数组来储存棋盘的落子情况 public ArrayList<ChessPosition> ChessPositonList=new ArrayList<ChessPosition>();//保存每一步的落子情况 Date date=new Date(); JButton b1,b2,b3,b4; //创建一个容器 Container ct; public void initUI() { //初始化一个界面,并设置标题大小等属性 JFrame jf=new JFrame(); jf.setTitle("五子棋");//界面名字 jf.setSize(800,650);//界面大小 jf.setLocationRelativeTo(null);//界面置于屏幕中间 jf.setLayout(new BorderLayout());//设置顶级容器JFrame为框架布局 Dimension dim1=new Dimension(150,0);//设置右半部分的大小 Dimension dim3=new Dimension(550,0);//设置左半部分的大小 Dimension dim2=new Dimension(140,40);//设置右边按钮组件的大小 //实现左边的界面,把WuZiQi对象添加到框架布局的中间部分 this.setPreferredSize(dim3);//设置下棋界面的大小(界面左半部分) this.setBackground(Color.LIGHT_GRAY);//设置下棋界面的颜色 //这里的话直接把左边的画板添加上去,指明是在框架布局的中间版块 jf.add(this,BorderLayout.CENTER);//添加到框架布局的中间部分 //实现右边的JPanel容器界面 JPanel jp=new JPanel(); jp.setPreferredSize(dim1);//设置JPanel的大小 jp.setBackground(Color.white);//设置右边的界面颜色为白色 jf.add(jp,BorderLayout.EAST);//添加到框架布局的东边部分 jp.setLayout(new FlowLayout());//设置JPanel为流式布局 //把按钮等组件依次加到JPanel上面 //设置按钮及大小 b1=new JButton("开始"); b1.setPreferredSize(dim2); b2=new JButton("悔棋"); b2.setPreferredSize(dim2); b3=new JButton("认输"); b3.setPreferredSize(dim2); b4=new JButton("退出"); b4.setPreferredSize(dim2); //依次把三个按钮组件加上去 jp.add(b1); jp.add(b2); jp.add(b3); jp.add(b4); //按键注册 ButtonListener butListen=new ButtonListener(this); b1.addActionListener(butListen);//添加发生操作的监听方法 b2.addActionListener(butListen); b3.addActionListener(butListen); b4.addActionListener(butListen); //设置选项按钮 /*String[] boxname= {"人人对战","人机对战"}; JComboBox box=new JComboBox(boxname); jp.add(box); */ jf.setVisible(true);//界面可见 } //重绘界面(重写第一个大的JPanel方法)及棋子 /*棋盘重绘,虽然15*15的棋盘不会消失,但是棋子会消失。在重绘出棋盘后还要把棋子也重新画上去。 用一个二维数组isAvail[15][15]来保存棋子信息, isArray[i][j]=0,表明这个位置没有棋子,等于1表明是一个黑棋子,等于2表明是一个白棋子。 根据这些信息,遍历isArray数组,把棋子重新绘制上去。 */ public void paint(Graphics g){ super.paint(g);//画出白框 //重绘出棋盘 g.setColor(Color.black); for(int i=0;i<date.row;i++) {//drawLine(x1,y1,x2,y2)方法是画一条线,x1,y1 是起点的坐标, x2,y2 是终点的坐标 g.drawLine(date.x, date.y+date.size*i, date.x+date.size*(date.column-1), date.y+date.size*i); } for(int j=0;j<date.column;j++) { g.drawLine(date.x+date.size*j, date.y, date.x+date.size*j, date.y+date.size*(date.row-1)); } //重绘出棋子 for(int i=0;i<date.row;i++) {//循环所有的交叉点 for(int j=0;j<date.column;j++) { if(isAvail[i][j]==1) { int countx=date.size*i+20; int county=date.size*j+20; g.setColor(Color.black); g.fillOval(countx-date.size/2, county-date.size/2, date.size, date.size); } else if(isAvail[i][j]==2) { int countx=date.size*i+20; int county=date.size*j+20; g.setColor(Color.white); g.fillOval(countx-date.size/2, county-date.size/2, date.size, date.size); } } } } }