首页>代码>java swing开发的五子棋小游戏>/五子棋/src/chess/view/GraphicPanel.java
package chess.view;

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.FileOutputStream;
import java.io.IOException;

import javax.swing.JOptionPane;
import javax.swing.JPanel;


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坐标。(x-20)/40
				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;
	}
	

	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);
		}
		
	}
}
最近下载更多
ewan007  LV29 3月3日
huangzy  LV12 2023年4月6日
总有人间一两风  LV8 2022年12月12日
2483935277  LV3 2022年9月3日
Qzi qzi  LV1 2022年6月24日
yebaobo  LV4 2022年2月13日
zzy1170707748  LV1 2021年12月20日
models10086  LV1 2021年12月16日
chen_jw  LV10 2021年12月14日
myh7719  LV2 2021年12月3日
最近浏览更多
860421  LV3 4月18日
ewan007  LV29 3月3日
luyouqi  LV1 2月29日
kuknkk  LV1 2023年12月27日
周俊杰  LV1 2023年12月25日
张晨荣  LV1 2023年12月19日
2386136609  LV1 2023年12月17日
暂无贡献等级
violetluo 2023年12月1日
暂无贡献等级
微信网友_6672184532766720  LV3 2023年10月6日
顶部 客服 微信二维码 底部
>扫描二维码关注最代码为好友扫描二维码关注最代码为好友