五子棋是一种双人对战棋类游戏,规则简单,这篇文章就介绍如何用Java实现一个简单的五子棋。
主要思路:在窗体上画出棋盘,利用事件监听机制,当鼠标点击时在特定位置画出棋子,交替设置颜色达到黑白交替下子的效果。
此处需要用到图形界面中的API
import java.awt.*
import javax.swing.*
窗体弹出的同时绘制棋盘,就需要重写paint方法。新建ChessFrame类继承JFrame后重写paint方法,点击棋盘时获取鼠标点击的坐标在合适的落子点画棋子。因为棋盘的棋子半径、行数和列数、行与行以及列与列的间距之后要多次用到,将其在新建接口Config中设为静态常量
public interface Config{
public static final int X=100 //第一列在屏幕上的坐标
public static final int Y=100//第一行在屏幕上的坐标
public static final int SIZE=30//列与列、行与行间距
public static final int CHESS_SIZE=25//棋子半径
public static final int ROW=15//行数
public static final int COLUMN=15//列数
public static final int [][]chessArray=new int[ROW][COLUMN];//存储棋盘上的棋子
考虑到重绘问题,我们重写paint方法。除了棋盘之外,当窗体大小改变时还要根据记录下的状态在改变后的窗体上重新绘制棋子,那用什么记录是否有棋子呢?用一个15*15的二维数组chessArray[][],chessArray[i][j]的值表示i行j列上的状态,我们规定0代表无棋子,1代表黑棋,2代表白棋,这样重绘时遍历数组,根据数组保存的数字判断是否有棋子,是什么颜色的棋子。
public class ChessFrame extends JFrame implements Config{
//继承JFrame类和Config接口
public static void main (String [] args){
ChessFrame chessFrame=new ChessFrame();
chessFrame.initUI();//初始化棋盘方法
}
public void initUI(){
//定义初始化方法设置棋盘窗体
this.setTitle("五子棋");
this.setSize(700,700);
this.setLocationRelativeTo(null);
this.setDefaultCloseOperation(3);
this.setVisible(true);
//继承JFrame后chessFrame对象具有JFrame对象的所有特性
}
public void paint(Graphics g){
super.paint(g);//调用父类的paint方法绘制窗体
for(int i=0;i|
鼠标点击时画笔在棋盘上画出棋子,此处需要用到鼠标事件监听
需要用到的API
import java.awt.*
import javax.swing.*
新建FrameListener类继承MouseAdapter,接口Config,并重写mouseClicked方法
public class FrameListener extends MouseAdapter implements Config{
private Graphics g;//画笔对象
private chessFrame frame;//窗体棋盘对象
private boolean flag=true;//黑白棋标识位
public FrameListener(ChessFrame frame){
this.frame=frame
}//获取棋盘窗体
public void mouseClicked(MouseEvent e){
if(g==null)
g=frame.getGraphics();//获取棋盘窗体上的画笔对象
int x1=e.getX();
int y1=e.getY();
//获取点击处的坐标
int r=(x1-X+SIZE/2)/SIZE;//计算最近的棋盘落子点的行数
int c=(y1-Y+SIZE/2)/SIZE;//计算最近的棋盘落子点的列数
if (x >= X - SIZE / 2 && x <= X + SIZE * (COLUMN - 1)
&& y >= Y - SIZE / 2 && y <= Y + SIZE * (ROW - 1)) {
x 1= r * SIZE - CHESS_SIZE / 2 + X;
y 1= c * SIZE - CHESS_SIZE / 2 + Y;
}
//如果在棋盘内或边缘外不超过棋子半径的范围内
if(chessArray[r][c]==0){//空位才能下子
if(flag){
g.setColor(Color.BLACK);
chessArray[r][c]=1;//标志这里下的是黑棋
}
else{
g.setColor(Color.WHITE);
chessArray[r][c]=2;//标志这里下的是白棋
}
g.fillOval(x1,y1,CHESS_SIZE,CHESS_SIZE);
flag=!flag;//转换标志位
}
}
然后在ChessFrame中添加监听
public void initUI(){
...//同上
FrameListener fl=new FrameListener(this);//实例化监听器,将棋盘窗体传递过去
this.addMouseListener(fl);
现在可以下棋了,但是还缺少输赢判定,五子棋的输赢判断规则是无论横竖斜同一色的棋连成五子则获胜。 新建Win类用于判断,传入下棋的行列数,从这个位置向各个方向寻找是否连成五子,若是返回true,否则返回false
package zsw.FiveChess;
public class Win implements Config{
public static boolean judge(int r,int c)
{
if(judgeH(r,c)||judgeR(r,c)||judgeL(r,c)||judgeN(r,c))//水平、竖直、左倾斜、右倾斜四个方向任一满足条件
return true;
return false;
}
public static boolean judgeH(int r,int c)//水平方向
{
int countL=1;//水平计数变量
for(int r1=r-1;r1>=0;r1--)//左
{
if(chessArray[r1][c]!=0&&chessArray[r1][c]==chessArray[r][c])
countL++;
else
break;
}
for(int r2=r+1;r2=5)
return true;
return false;
}
public static boolean judgeR(int r,int c)//竖直方向
{
int countH=1;//竖直计数变量
for(int c1=c-1;c1>=0;c1--)
{
if(chessArray[r][c]!=0&&chessArray[r][c]==chessArray[r][c1])
countH++;
else
break;
}
for(int c2=c+1;c2=5)
return true;
return false;
}
public static boolean judgeL(int r,int c)//左斜方向
{
int countQ=1;//左斜计数变量
for(int c1=c-1,r1=r-1;c1>=0&&r1>=0;c1--,r1--)
{
if(chessArray[r][c]!=0&&chessArray[r][c]==chessArray[r1][c1])
countQ++;
else
break;
}
for(int r2=r+1,c2=c+1;c2=5)
return true;
return false;
}
public static boolean judgeN(int r,int c)//右斜方向
{
int countV=1;//右斜计数变量
for(int r1=r-1,c1=c+1;r1>=0&&c1=0;r2++,c2--)
{
if(chessArray[r][c]!=0&&chessArray[r][c]==chessArray[r2][c2])
countV++;
else
break;
}
if(countV>=5)
return true;
return false;
}
}
然后在FrameListener类中添加输赢判断,每下一步判断一次,若符合条件就提示胜利
public void mouseClicked(MouseEvent e){
...//同上
if(Win.judge(r,c)){
String msg = (flag % 2 == 0) ? "白棋胜利!" : "黑棋胜利!";
JOptionPane.showMessageDialog(frame, msg);
if (flag)
System.out.println("白旗胜利");
else
System.out.println("黑棋胜利");
}
}
简易五子棋就完成了。