package day19.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 java.io.OutputStream;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
/**
* 棋盘中间的网格图形,覆盖了该类的paintComponent()方法,重新绘制图形。
* @author Administrator
*
*/
public class GraphicPanel extends JPanel{
private ChessBoard cb;
private OutputStream out;
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;//棋子半径
private boolean click;
private boolean win;
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;//则不做任何处理
}
//如果没轮到我下旗
if(cb.getIsMe()!=null&&isBlack!=cb.getIsMe()){
ChessBoard.label.setText("现在不是你下");
return;
}
//将棋盘上该位置设置为指定棋子
allChess[boardY][boardX]=isBlack?'@':'O';
GraphicPanel.this.boardX=boardX;//保存最后一次有效落子的坐标
GraphicPanel.this.boardY=boardY;
// click=true;
//重画棋盘
repaint();
if(wasWin()){
win=true;
try {
out.write(-1);
out.write(-1);
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
String mesg=(isBlack?"黑":"白")+"方获胜!";
ChessBoard.label.setText(mesg);
JOptionPane.showMessageDialog(GraphicPanel.this,mesg);
clear();
return;
}
try {
out.write(boardX);
out.write(boardY);
} catch (IOException e2) {
e2.printStackTrace();
}
//改变下棋方
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);