五子棋(重绘棋盘)

package fivechess; import java.awt.BasicStroke; import java.awt.Color; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.Shape; import java.awt.Stroke; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import java.awt.geom.Ellipse2D; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import javax.swing.JOptionPane; import javax.swing.JPanel; /** * 棋盘中间的网格图形,覆盖了该类的paintComponent()方法,重新绘制图形。 * @author Administrator * */ public class GraphicPanel extends JPanel{ private boolean isBlack=true;//当前下子是否是黑方 private char[][] allChess;//保存所有棋子的数组 private int boardX=-1;//最后一次有效落子在棋盘的x,y坐标 private int boardY=-1; public static final int ROW_NUM=16;//行数 public static final int COL_NUM=16;//列数 public static final int LEFT_BORDER=20;//左边界 public static final int RIGTH_BORDER=20;//右边界 public static final int UP_BORDER=20;//上边界 public static final int DOWN_BORDER=20;//下边界 public static final int ROW_GAP=40;//行间隙 public static final int COL_GAP=40;//列间隙 public static final int ChessRadio=15;//棋子半径 public GraphicPanel(){ allChess=new char[ROW_NUM][COL_NUM]; for(int i=0;i<allChess.length;i++){//给旗子数组实例化 for(int j=0;j<allChess[i].length;j++){ allChess[i][j]='*';//初始时都赋为‘*’ } } ChessBoard.label.setText((isBlack?"黑":"白")+"方请下子..."); addMouseListener(new MouseAdapter(){//给该面板添加鼠标事件监听 public void mouseClicked(MouseEvent e) { int button=e.getButton(); if(button!=MouseEvent.BUTTON1){//如果不是鼠标左键点击 return;//则不做任何处理 } int x=e.getX();//获得鼠标点击位置的x,y坐标 int y=e.getY(); //如果鼠标点击点没有发生在棋盘的有效位置 if(x<LEFT_BORDER/2 || x> LEFT_BORDER+(COL_NUM-1)*COL_GAP+RIGTH_BORDER/2 || y<UP_BORDER/2 || y>UP_BORDER+(ROW_NUM-1)*ROW_GAP+DOWN_BORDER/2){ ChessBoard.label.setText("无效位置!"); return;//则不做任何处理 } //将鼠标点击点的x,y坐标换算成棋盘上的x,y坐标。 int boardX=Math.round((float)(x-LEFT_BORDER)/ROW_GAP); int boardY=Math.round((float)(y-UP_BORDER)/COL_GAP); //如果该位置上有棋子 if(allChess[boardY][boardX]!='*'){ ChessBoard.label.setText("该位置有棋子"); return;//则不做任何处理 } //将棋盘上该位置设置为指定棋子 allChess[boardY][boardX]=isBlack?'@':'O'; GraphicPanel.this.boardX=boardX;//保存最后一次有效落子的坐标 GraphicPanel.this.boardY=boardY; //重画棋盘 repaint(); if(wasWin()){ String mesg=(isBlack?"黑":"白")+"方获胜!"; ChessBoard.label.setText(mesg); JOptionPane.showMessageDialog(GraphicPanel.this,mesg); clear(); return; } //改变下棋方 isBlack=!isBlack; ChessBoard.label.setText((isBlack?"黑":"白")+"方请下子..."); } }); } public boolean wasWin(){ return wasWinAtV()||wasWinAtH()||wasWinAtLD()||wasWinAtRD(); } private boolean wasWinAtV(){ char ch=isBlack?'@':'O'; int i=boardX; while(i>=0 && allChess[boardY][i]==ch){//向左找到第一个不是ch的字符 i--; } int num=0; i++; while(i<allChess.length && allChess[boardY][i]==ch){ num++; i++; } return num>=5; } private boolean wasWinAtH(){ char ch=isBlack?'@':'O'; int i=boardY; while(i>=0 && allChess[i][boardX]==ch){//向左找到第一个不是ch的字符 i--; } int num=0; i++; while(i<allChess.length && allChess[i][boardX]==ch){ num++; i++; } return num>=5; } private boolean wasWinAtLD(){ char ch=isBlack?'@':'O'; int i=boardY; int j=boardX; while(i>=0 && j<allChess.length && allChess[i][j]==ch){//向左找到第一个不是ch的字符 i--; j++; } int num=0; i++; j--; while(i<allChess.length && j>=0 && allChess[i][j]==ch){ num++; i++; j--; } return num>=5; } private boolean wasWinAtRD(){ char ch=isBlack?'@':'O'; int i=boardY; int j=boardX; while(i>=0 && j>=0 && allChess[i][j]==ch){//向左找到第一个不是ch的字符 i--; j--; } int num=0; i++; j++; while(i<allChess.length && j<allChess.length && allChess[i][j]==ch){ num++; i++; j++; } return num>=5; } /** * 该方法在获胜后重新绘制棋盘,并初始化参数。 * */ public void clear(){ boardX=-1; boardY=-1; for(int i=0;i<allChess.length;i++){ for(int j=0;j<allChess[i].length;j++){ allChess[i][j]='*';//初始时都赋为‘*’ } } isBlack=true; // 重画棋盘 repaint(); ChessBoard.label.setText((isBlack?"黑":"白")+"方请下子..."); } /** * 把当前棋盘状态保存到指定的文件中! * @param f */ public boolean saveToFile(File f){ //1,建立一个FileOutputStream FileOutputStream fos=null; try { fos=new FileOutputStream(f); for(int i=0;i<allChess.length;i++){ for(int j=0;j<allChess[i].length;j++){ if(i==boardY && j==boardX){ fos.write(isBlack?'W':'B'); }else{ fos.write(allChess[i][j]); } } } } catch (IOException e) { e.printStackTrace(); return false; }finally{ if(fos!=null)try{fos.close();}catch(IOException e){} } return true; } /** * 从指定的文件中装载棋盘信息 * @param f */ public boolean loadFromFile(File f){ FileInputStream fis=null; try { fis=new FileInputStream(f); for(int i=0;i<allChess.length;i++){ for(int j=0;j<allChess[i].length;j++){ char c=(char)fis.read(); if(c!='*' && c!='O' && c!='@' && c!='W' && c!='B'){ return false; } if(c=='B'){ allChess[i][j]='@'; boardX=j; boardY=i; isBlack=false; }else if(c=='W'){ allChess[i][j]='O'; boardX=j; boardY=i; isBlack=true; }else{ allChess[i][j]=c; } } } } catch (IOException e) { e.printStackTrace(); return false; }finally{ if(fis!=null)try{fis.close();}catch(IOException e){} } this.repaint(); return true; } @Override /** * 该方法为覆盖父类的方法,每次重画棋盘时系统会自动调用该方法。 */ public void paintComponent(Graphics g){ super.paintComponent(g); //定义画笔类型 Stroke stroke=new BasicStroke(2.0f); Graphics2D g2=(Graphics2D)g; g2.setStroke(stroke); //循环画出若干水平平行直线 for(int i=0;i<ROW_NUM;i++){ g2.drawLine(LEFT_BORDER,UP_BORDER+ROW_GAP*i, (COL_NUM-1)*COL_GAP+LEFT_BORDER,UP_BORDER+ROW_GAP*i); } //循环画出若干垂直平行直线 for(int i=0;i<COL_NUM;i++){ g2.drawLine(LEFT_BORDER+COL_GAP*i,UP_BORDER, LEFT_BORDER+COL_GAP*i,(ROW_NUM-1)*ROW_GAP+UP_BORDER); } //循环读取allChess数组,根据数组的内容画出每一个棋子。 for(int i=0;i<allChess.length;i++){ for(int j=0;j<allChess[i].length;j++){ if(allChess[i][j]=='*'){ continue; } Shape s=new Ellipse2D.Double(j*COL_GAP+LEFT_BORDER-ChessRadio, i*ROW_GAP+UP_BORDER-ChessRadio,ChessRadio*2,ChessRadio*2); g2.setColor(Color.BLACK); g2.draw(s); if(allChess[i][j]=='@'){ g2.setColor(Color.BLACK); }else{ g2.setColor(Color.WHITE); } g2.fill(s); } } if(boardX!=-1){//在最后一次有效落点位置画一个红‘X’,用以标识。 g2.setColor(Color.RED); g2.drawLine(boardX*ROW_GAP+LEFT_BORDER-5,boardY*COL_GAP+UP_BORDER-5,boardX*ROW_GAP+LEFT_BORDER+5,boardY*COL_GAP+UP_BORDER+5); g2.drawLine(boardX*ROW_GAP+LEFT_BORDER+5,boardY*COL_GAP+UP_BORDER-5,boardX*ROW_GAP+LEFT_BORDER-5,boardY*COL_GAP+UP_BORDER+5); } } }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值