实现普通的双人五子棋,在用户界面可见棋盘状态(该谁下,模式选择),提醒用户操作,带无限悔棋功能。
Config
JFrame
中画棋盘,在鼠标监听器(MouseListener
)中添加棋子,并实现重绘chesses[][]
组保存棋盘落子情况,黑子为1,白子为-1,空为0,每次重新开始时都要对整个棋盘进行初始化。chesses
中是否有五连珠,如果有说明这个棋子胜利,弹窗提示。check
主要是对对棋子的上下左右,左上右下(斜向右),左下右上(斜向左)判断是否有5连珠,如果有返回true,下面的代码中用到static
来定义方法,方便外部调用。back[][]
中,也方便下一步的AI找坐标flag_start,flag_playr
等,若按下悔棋键,直接删除上两次的棋子存储,调用重绘。fillOval()
这个方法,所以在算出坐标的时候还要减去棋子的一半作为这个方法的参数package com.goband;
import java.awt.BasicStroke;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
public class Checkerboard extends JPanel {
private Repaint[] rep = new Repaint[1000];
private int[][] chesses = new int[Config.rows][Config.columns];
private JFrame jf = new JFrame();
private JTextArea txt = new JTextArea(35, 20);
/**
* 初始化五子棋窗体
*/
public void chshow() {
jf.setSize(1000, 750);
jf.setTitle("五子棋");
jf.setDefaultCloseOperation(3);// 设置关闭方法
jf.setLocationRelativeTo(null);// 设置居中
// jf.getContentPane().setBackground(Color.white);//设置背景色
// java设置背景色方法2,1设置getcontentPane不可见
jf.setLayout(new BorderLayout());
// JPanel center=new JPanel();
this.setBackground(Color.ORANGE);
jf.add(this, BorderLayout.CENTER);// 中间
JPanel north = new JPanel();
/*
* 东
*/
JPanel east = new JPanel();
east.setPreferredSize(new Dimension(330, 0));
jf.add(east, BorderLayout.EAST);
JLabel jl = new JLabel(" = 游戏信息提示 = ");
east.add(jl);
/**
* 添加滚动条
*/
JScrollPane js = new JScrollPane();
east.add(js);
js.setBounds(10, 10, 30, 600);
txt.setBounds(10, 10, 30, 600);
js.setViewportView(txt);// 添加到滚动窗格
// 下句会重复添加
// east.add(txt);
north.setPreferredSize(new Dimension(0, 50));
jf.add(north, BorderLayout.NORTH);//
DrawListener qizi = new DrawListener();
String[] Botton = {
"开始游戏", "悔棋", "重新开始", "人机对战", "玩家对战" };
for (int i = 0; i < Botton.length; i++) {
ImageIcon img = new ImageIcon(this.getClass().getResource(Botton[i] + ".png"));
JButton jbu = new JButton(Botton[i], img);
north.add(jbu);
jbu.addActionListener(qizi);
}
// 设置边框布局
jf.setVisible(true);
Graphics g = this.getGraphics();
qizi.setGraphics(g);
qizi.setChesses(chesses);
qizi.setrepaint(rep);
qizi.setCheckerboard(this);
this.addMouseListener(qizi);
}
public JTextArea getEast() {
return txt;
}
public void initchesses() {
for (int i = 0; i < Config.rows; i++) {
for (int j = 0; j < Config.columns; j++) {
chesses[i][j] = 0;
}
}
}
/**
* 重绘函数 绘制棋盘方法
*/
public void paint(Graphics gr) {
super.paint(gr);
Graphics2D g = (Graphics2D) gr;
g.setColor(Color.black);
g.setStroke(new BasicStroke(2.5f));
for (int i = 1; i < 1 + Config.rows; i++) {
// 行
g.drawLine(Config.start, i * Config.SIZE, Config.end, i * Config.SIZE);
}
for (int i = 1; i < 1 + Config.columns; i++) {
// 列
g.drawLine(i * Config.SIZE, Config.start, i * Config.SIZE, Config.end);
}
for (int i = 0; i < rep.length; i++) {
if (rep[i] != null) {
rep[i].display(gr);
}
}
g.fillOval(Config.start + 3 * Config.SIZE - 5, Config.start + 3 * Config.SIZE - 5, 10, 10);
g.fillOval(Config.start + 11 * Config.SIZE - 5, Config.start + 3 * Config.SIZE - 5, 10, 10);
g.fillOval(Config.start + 3 * Config.SIZE - 5, Config.start + 11 * Config.SIZE - 5, 10, 10);
g.fillOval(Config.start + 11 * Config.SIZE - 5, Config.start + 11 * Config.SIZE - 5, 10, 10);
g.fillOval(Config.start + 7 * Config.SIZE - 5, Config.start + 7 * Config.SIZE - 5, 10, 10);
}
/**
* 棋盘相关配置
*
* @author mo
*
*/
public interface Config {
public static final int start = 40;// 棋盘开始坐标(x,y)相同为start
public static final int end = 640;// 棋盘结束坐标x,y相同为end
public static final int rows = 16;// 横向条数
public static final int columns = 16;// 竖向条数
public static final int CHESS_SIZE = 35;// 棋子直径
public static final int SIZE = 40;// 单元格大小
}
/**
* 清空棋盘
*/
public void clearChesses() {
this.initchesses();
for (int i = 0; i < rep.length; i++) {
rep[i] = null;
}
this.paint(this.getGraphics());
}
}
package com.goband;
import java.awt.Color;
import java.awt.FlowLayout;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JTextArea;
import com.goband.Checkerboard.Config;
/**
* 五子棋监听器
* @author mo
*
*/
public class DrawListener implements MouseListener,ActionListener{
private int count=0,flag_start=0,flag_winner=0;
private Graphics g;
private Repaint []rep;
private int de=0;
private int [][] chesses;
private int [][] back=new int[256][2];
private Check check;
private Checkerboard board;
private String name;
private JFrame finshjf=new JFrame();
private JTextArea txt=new JTextArea();
public void setGraphics(Graphics g){
this.g=g;
}
/**
* 为了实现棋盘的重绘
*/
public void setCheckerboard(Checkerboard c){
this.board=c;
txt=board.getEast();
}
public void setChesses(int [][]c){
this.chesses=c;
check=new Check(this.chesses);
}
/**
* 重绘数组
* @param rep
*/
public void setrepaint(Repaint [] rep){
this.rep=rep;
}
public void actionPerformed(ActionEvent e){
name=e.getActionCommand();
if(name.equals("开始游戏")||name.equals("重新开始")){
board.clearChesses();
flag_start=1;
flag_winner=0;
count=0;
finshjf.setVisible(false);
txt.append("游戏开始"+"\n");
}
if(name.equals("返回棋局")){
finshjf.setVisible(false);
txt.append("返回棋局"+"\n");
}
if(name.equals("悔棋")){
if(count<2)
txt.append("不能悔棋!"+"\n");
else txt.append("悔棋成功"+"\n");
this.rep[count-1]=null;
this.rep[count-2]=null;
chesses[back[count-1][0]][back[count-1][0]]=0;
chesses[back[count-1][0]][back[count-1][1]]=0;
chesses[back[count-2][0]][back[count-2][0]]=0;
chesses[back[count-2][0]][back[count-2][1]]=0;
count-=2;
board.paint(board.getGraphics());
}
}
/**
* 鼠标点击事件
* 放下棋子
*/
public void mouseClicked(MouseEvent e){
int x0=e.getX();
int y0=e.getY();
Image img_b=new ImageIcon("D:/learning/mydemo/Javaworkspace/rect/src/com/goband/黑棋.png").getImage();
Image img_w=new ImageIcon("D:/learning/mydemo/Javaworkspace/rect/src/com/goband/白棋.png").getImage();
/**
* 判断按下是否有效
*/
if(flag_start==0) txt.append("请点击开始游戏"+"\n");
System.out.println(x0+" "+y0);
if((flag_start==1)&&((x0-Config.start)%Config.SIZE<Config.SIZE/3||
((x0-Config.start)%Config.SIZE>2*Config.SIZE/3)&&
((y0-Config.start)%Config.SIZE<Config.SIZE/3)||
(y0-Config.start)%Config.SIZE>2*Config.SIZE/3)&&
(x0>Config.SIZE*2/3)&&(y0>Config.SIZE*2/3)){
/**
* x,y保存的是画笔需要绘制的界面坐标,先用坐标减去statr取个整
*/
int x=Config.start+Config.SIZE*((x0-Config.start)/Config.SIZE);
int y=Config.start+Config.SIZE*((y0-Config.start)/Config.SIZE);
if(((x0-Config.start)%Config.SIZE>2*Config.SIZE/3)){
x=Config.start+Config.SIZE*(1+(x0-Config.start)/Config.SIZE);
}
if(((y0-Config.start)%Config.SIZE>2*Config.SIZE/3)){
y=Config.start+Config.SIZE*(1+(y0-Config.start)/Config.SIZE);
}
/*
* x,y需减去start再除棋盘大小
* 对应棋盘数组的索引
*/
int index_x=(x-Config.start)/Config.SIZE;
int index_y=(y-Config.start)/Config.SIZE;
if(chesses[index_x][index_y]==0){
System.out.println(index_x+" "+index_y);
if(count%2==0){
txt.append("当前为白棋"+"\n");
g.drawImage(img_b, x-Config.CHESS_SIZE/2, y-Config.CHESS_SIZE/2, null);
chesses[index_x][index_y]=1;
back[count][0]=index_x;
back[count][1]=index_y;
if(check.checkColumn(index_x, index_y)>=5||check.checkRow(index_x, index_y)>=5
||check.checkIncleft(index_x, index_y)>=5||check.checkIncright(index_x, index_y)>=5)
{
System.out.println("黑胜");
txt.append("游戏结束"+"\n");
txt.append("黑棋胜利"+"\n");
flag_winner=1;
}
}else{
txt.append("当前为黑棋"+"\n");
g.drawImage(img_w, x-Config.CHESS_SIZE/2, y-Config.CHESS_SIZE/2, null);
chesses[index_x][index_y]=-1;
back[count][0]=index_x;
back[count][1]=index_y;
if(check.checkColumn(index_x, index_y)>=5||check.checkRow(index_x, index_y)>=5
||check.checkIncleft(index_x, index_y)>=5||check.checkIncright(index_x, index_y)>=5)
{
System.out.println("白胜");
txt.append("游戏结束"+"\n");
txt.append("白棋胜利"+"\n");
flag_winner=-1;
}
}
Repaint r=new Repaint(x-Config.CHESS_SIZE/2, y-Config.CHESS_SIZE/2, count%2==0?img_b:img_w);
rep[de++]=r;
count++;
}
System.out.println("name:"+name);
if(flag_winner!=0||count==225) {
finshjf=this.finshShow();
finshjf.setVisible(true);
}
}
};
/**
* 一方胜利后显示
*/
public JFrame finshShow(){
flag_start=0;
board.initchesses();
JFrame jf=new JFrame("Finsh Game!");
jf.setSize(200, 120);
jf.setDefaultCloseOperation(2);
//关闭方法 :销毁不结束
jf.setLocationRelativeTo(null);
//居中显示
jf.setLayout(new FlowLayout());
//流式布局
JButton yes=new JButton("重新开始");
JButton no=new JButton("返回棋局");
jf.add(yes);
jf.add(no);
yes.addActionListener(this);
no.addActionListener(this);
JLabel jl=new JLabel();
if(flag_winner==1)
jl=new JLabel(" 黑棋胜利! ",new ImageIcon("D:/learning/mydemo/Javaworkspace/rect/src/com/goband/黑棋.png"), 0);
else if(flag_winner==-1)
jl=new JLabel(" 白棋胜利! ",new ImageIcon("D:/learning/mydemo/Javaworkspace/rect/src/com/goband/白棋.png"), 0);
else if(flag_winner==0&&count==225)
jl=new JLabel(" 平局! ");
jf.add(jl);
return jf;
}
public void mousePressed(MouseEvent e){
};
public void mouseReleased(MouseEvent e){
};
public void mouseEntered(MouseEvent e){
};
public void mouseExited(MouseEvent e){
};
}
package com.goband;
import java.awt.Graphics;
import java.awt.Image;
public class Repaint {
private int x1,y1;
private Image c;
public Repaint(int x1,int y1,Image c){
this.x1=x1;
this.y1=y1;
this.c=c;
}
public void display(Graphics g){
g.drawImage(c, x1, y1, null);
}
}
package com.goband;
import com.goband.Checkerboard.Config;
public class Check {
private int [][] chesses;
public Check(int [][]c){
this.chesses=c;
}
/**
*判断横向是否有5个相连的棋子
* @param x
* @param y
* @return
*/
public int checkRow(int x,int y){
int count =0 ;
/**
* 往右判断
*/
for(int i=x+1;i<chesses.length;i++){
if(chesses[i][y]==chesses[x][y])
count++;
else
break;
}
/*
* 往左判断
*/
for(int i=x;i>=0;i--){
if(chesses[i][y]==chesses[x][y])
count++;
else
break;
}
return count;
}
/**
* 判断纵向是否有5个相连的棋子
* @param x
* @param y
* @return
*/
public int checkColumn(int x,int y){
int count =0 ;
/**
* 往下判断
*/
for(int i=y+1;i<chesses.length;i++){
if(chesses[x][i]==chesses[x][y])
count++;
else
break;
}
/*
* 往上判断
*/
for(int i=y;i>=0;i--){
if(chesses[x][i]==chesses[x][y])
count++;
else
break;
}
return count;
}
/**
* 判断斜向左是否有5个相连的棋子
* @param x
* @param y
* @return
*/
public int checkIncleft(int x,int y){
int count =0 ;
/**
* 往左下判断
*/
for(int i=y+1,j=x-1;j>=0&&i<Config.columns;j--,i++){
if(chesses[j][i]==chesses[x][y])
count++;
else
break;
}
/**
* 往右上判断
*/
for(int i=y,j=x;j<Config.rows&&i>=0;j++,i--){
if(chesses[j][i]==chesses[x][y])
count++;
else
break;
}
return count;
}
/**
* 判断右斜线是否有5个相连棋子
* @param x
* @param y
* @return
*/
public int checkIncright(int x,int y){
int count =0 ;
/**
* 往右下判断
*/
for(int i=y+1,j=x+1;j<Config.rows&&i<Config.columns;j++,i++){
if(chesses[j][i]==chesses[x][y])
count++;
else
break;
}
/**
* 往左上判断
*/
for(int i=y,j=x;j>=0&&i>=0;j--,i--){
if(chesses[j][i]==chesses[x][y])
count++;
else
break;
}
return count;
}
}
package com.goband;
public class Main {
public static void main(String [] args){
Checkerboard c=new Checkerboard();
c.initchesses();
c.chshow();
}
}
新学了一个显示方法,解决如何在用户界面显示数据的问题!
JTextArea
这个组件,在javax.swing.JTextArea
包中append()
方法: txt.append("游戏结束"+"\n");
txt.append("白棋胜利"+"\n");
注意使用滚动条的方法:
private JTextArea txt = new JTextArea(35, 20);//后面是大小,行数列数
......
/*
* 东
*/
JPanel east = new JPanel();
east.setPreferredSize(new Dimension(330, 0));
jf.add(east, BorderLayout.EAST);
JLabel jl = new JLabel(" = 游戏信息提示 = ");
east.add(jl);
/**
* 添加滚动条
*/
JScrollPane js = new JScrollPane();
east.add(js);
js.setBounds(10, 10, 30, 600);
txt.setBounds(10, 10, 30, 600);
js.setViewportView(txt);// 添加到滚动窗格
// 下句会重复添加
// east.add(txt);
Image img_b=new ImageIcon("D:/learning/mydemo/Javaworkspace/rect/src/com/goband/黑棋.png").getImage();
Image img_w=new ImageIcon("D:/learning/mydemo/Javaworkspace/rect/src/com/goband/白棋.png").getImage();
g.drawImage(img_b, x-Config.CHESS_SIZE/2, y-Config.CHESS_SIZE/2, null);
g.drawImage(img_w, x-Config.CHESS_SIZE/2, y-Config.CHESS_SIZE/2, null);
因为绘制的是图片,所以重绘函数也要响应修改,不再是绘制圆形
package com.goband;
import java.awt.Graphics;
import java.awt.Image;
public class Repaint {
private int x1,y1;
private Image c;
public Repaint(int x1,int y1,Image c){
this.x1=x1;
this.y1=y1;
this.c=c;
}
public void display(Graphics g){
g.drawImage(c, x1, y1, null);
}
}
下一篇写人机对战,用到的是评分法