这样的问题,你们不会认为是作业吧?
百度了一番,没百到。或者说,如何在调用repaint方法时,保持指定的graphics对象显示在前面?
还是那个棋盘棋子的问题,下棋的效果是终于做出来了。但是,现在的问题是:每次重绘后,棋盘的网格显示在棋子的上面,这不符合人的习惯。所以请教一下。代码如下:package gobang;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import java.awt.Graphics;public class TestChess extends JPanel{
private static final long serialVersionUID = 4785452373598819718L;
private int x, y; //位置
final int ChessSize = 28;//棋子大小
private int width=600, height=600;//
private int d = width / 20;
public int boardOps[][] = new int[20][20];//0表示无子,1表示白子,2表示黑子
ImageIcon whiteIcon = new ImageIcon("image/white.png");
Image white = whiteIcon.getImage();
public TestChess() {
this.addMouseListener(new MouseAdapter() {
int i=0, j=0;
public void mouseClicked(MouseEvent e) {
x = e.getX();
y = e.getY();
if(x>d-1 && x<width-d+1 && y>d-1 && y<height-d+1){
boolean flag = true;
if(x%30<12) x = x - x%30;
else if(x%30>18) x = x - x%30 + 30;
else flag = false;
if(y%30<12) y = y - y%30;
else if(y%30>18) y = y - y%30 + 30;
else flag = false;
i = x/30;
j = y/30;
if(flag){
boardOps[i][j] = 1;
repaint();
//其他操作
}
}
}
});
}
public void paint(Graphics g) {//画棋盘
for(int i = 0; i<=width; i+= d){//画网格
if(i==0 || i==width){
g.drawLine(i, 0, i, height);
g.drawLine(0, i, width, i);
}else{
g.drawLine(i, d, i, height-d);
g.drawLine(d, i, width-d, i);
}
}
int k=1;
char c='A';
for(int i = d; i<=width-d; i+=d){//位置标签
String str0 = String.format("%02d", k);
g.drawString(str0,10, i+10);
String str1 = String.valueOf(c);
g.drawString(str1,i,20);
c++;
k++;
}
g.drawImage(white, x-ChessSize/2, y-ChessSize/2, ChessSize, ChessSize, this);
} public static void main(String[] args) {
JFrame frame = new JFrame();
frame.add(new TestChess());
frame.setTitle("TestChess");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(800, 800);
frame.setVisible(true); }}
百度了一番,没百到。或者说,如何在调用repaint方法时,保持指定的graphics对象显示在前面?
还是那个棋盘棋子的问题,下棋的效果是终于做出来了。但是,现在的问题是:每次重绘后,棋盘的网格显示在棋子的上面,这不符合人的习惯。所以请教一下。代码如下:package gobang;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import java.awt.Graphics;public class TestChess extends JPanel{
private static final long serialVersionUID = 4785452373598819718L;
private int x, y; //位置
final int ChessSize = 28;//棋子大小
private int width=600, height=600;//
private int d = width / 20;
public int boardOps[][] = new int[20][20];//0表示无子,1表示白子,2表示黑子
ImageIcon whiteIcon = new ImageIcon("image/white.png");
Image white = whiteIcon.getImage();
public TestChess() {
this.addMouseListener(new MouseAdapter() {
int i=0, j=0;
public void mouseClicked(MouseEvent e) {
x = e.getX();
y = e.getY();
if(x>d-1 && x<width-d+1 && y>d-1 && y<height-d+1){
boolean flag = true;
if(x%30<12) x = x - x%30;
else if(x%30>18) x = x - x%30 + 30;
else flag = false;
if(y%30<12) y = y - y%30;
else if(y%30>18) y = y - y%30 + 30;
else flag = false;
i = x/30;
j = y/30;
if(flag){
boardOps[i][j] = 1;
repaint();
//其他操作
}
}
}
});
}
public void paint(Graphics g) {//画棋盘
for(int i = 0; i<=width; i+= d){//画网格
if(i==0 || i==width){
g.drawLine(i, 0, i, height);
g.drawLine(0, i, width, i);
}else{
g.drawLine(i, d, i, height-d);
g.drawLine(d, i, width-d, i);
}
}
int k=1;
char c='A';
for(int i = d; i<=width-d; i+=d){//位置标签
String str0 = String.format("%02d", k);
g.drawString(str0,10, i+10);
String str1 = String.valueOf(c);
g.drawString(str1,i,20);
c++;
k++;
}
g.drawImage(white, x-ChessSize/2, y-ChessSize/2, ChessSize, ChessSize, this);
} public static void main(String[] args) {
JFrame frame = new JFrame();
frame.add(new TestChess());
frame.setTitle("TestChess");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(800, 800);
frame.setVisible(true); }}
package finalFiveChess;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?"黑":"白")+"方请下子...");
}
});
}
/**
* 判断当前落子方是否获胜的方法
* @return
*/
public boolean wasWin(){
return wasWinAtV()||wasWinAtH()||wasWinAtLD()||wasWinAtRD();
}
/**
* 判断水平方向上是否获胜
* @return
*/
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;
}
/**
* 判断垂直方向上是否获胜
* @return
*/
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;
}
/**
* 判断左斜方向上时候获胜
* @return
*/
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;
}
/**
* 判断右斜方向上是否获胜
* @return
*/
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);
}
}
}
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;/**
* 棋盘类,用来绘制棋盘
* @author Administrator
*
*/
public class ChessBoard extends JFrame implements ActionListener{
private GraphicPanel panel;
private JMenuBar bar;//菜单条
private JMenu game;//游戏菜单
public static JLabel label;//状态栏
public static final int DEFAULT_WIDTH=650;//棋盘宽度
public static final int DEFAULT_HEIGHT=700;//棋盘高度
public ChessBoard(){
super("五子棋 v1.1");
label=new JLabel(" ",JLabel.CENTER);
panel=new GraphicPanel();
this.add(panel,BorderLayout.CENTER);
this.add(label,BorderLayout.SOUTH);
bar=new JMenuBar();
game=new JMenu("游戏");
JMenuItem item=null;
game.add(item=new JMenuItem("重新开始")); item.addActionListener(this);
game.add(item=new JMenuItem("保存游戏...")); item.addActionListener(this);
game.add(item=new JMenuItem("装载游戏...")); item.addActionListener(this);
game.addSeparator();
game.add(item=new JMenuItem("退出")); item.addActionListener(this);
bar.add(game);
this.setJMenuBar(bar);
}
public void showMe(){
this.setSize(DEFAULT_WIDTH,DEFAULT_HEIGHT);
this.setVisible(true);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
public void actionPerformed(ActionEvent e) {
if(e.getActionCommand().equals("保存游戏...")){
//1,弹出保存文件对话框
JFileChooser jfc=new JFileChooser();
jfc.showSaveDialog(this);
// 2,获得用户选择的文件
File f=jfc.getSelectedFile();
// 3,调用
if(f!=null){
if(panel.saveToFile(f)){
JOptionPane.showMessageDialog(this,"保存成功!");
}else{
JOptionPane.showMessageDialog(this,"保存文件失败!");
}
}
return;
}
if(e.getActionCommand().equals("装载游戏...")){
//1,弹出打开文件对话框
JFileChooser jfc=new JFileChooser();
jfc.showOpenDialog(this);
//2,获得用户选择的文件
File f=jfc.getSelectedFile();
// 3,调用
if(f!=null){
if(!panel.loadFromFile(f)){
JOptionPane.showMessageDialog(this,"文件格式不正确或已损坏!");
}
}
return;
}
if(e.getActionCommand().equals("重新开始")){
panel.clear();
}
if(e.getActionCommand().equals("退出")){
System.exit(0);
}
} public static void main(String[] args){
new ChessBoard().showMe();
}}
repaint重载!
repaint重载!
repaint重载!
repaint重载!
repaint重载!