本次制作五子棋这个小程序,是对java一些基础知识的运用以及巩固。在编写代码之前,我们必须要将五子棋的一些功能梳理清楚,这样才方便实现。
五子棋的游戏规则:①一黑一白,轮流下棋;②五子连棋为胜;③可以进行悔棋;④可以进行人机对战。
注意事项:①下过棋的地方不能再下,意味着必须要加判断条件;②拖动界面的时候窗体上的棋盘和棋子不能消失,意味着必须进行paint方法重写;③下棋的时候棋子是下在横竖线的交点处,而实际下棋的时候不会刚好点到这个位置,意味着必须进行位置矫正;
以上便是我暂时的思路,下面开始书写代码。
首先可以将棋盘的一些固定数据放在接口中,因为这样方便日后的数据修改,也方便阅读理解,代码如下:
public interface GoBaangConfig {
int SIZE=50;//棋盘间距和棋子直径
int X=100;//棋盘左上角x坐标
int Y=100;//棋盘左上角y坐标
int ROW=15;
int CLOUN=15;//棋盘的行列值
}
然后是窗体的各项代码,因为要进行paint方法重写,所以要继承JFrame类,代码如下:
import java.awt.Graphics;
import java.awt.Image;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
public class StartGame {
public static void main(String[]args){
GoBangUI gobangUI=new GoBangUI();
gobangUI.initGoBangMainUI();
}
}
public class GoBangUI extends JFrame implements GoBaangConfig{
public static final Image img=new ImageIcon("E:\\23.jpg").getImage();
public GoBangListener gl = new GoBangListener();//鼠标监听器
public void initGoBangMainUI(){
GoBangUI jf=new GoBangUI();///注意是重写的子类对象GoBangUI
jf.setSize(1000,1000);//窗体大小
jf.setTitle("五子棋");//窗体的标题
jf.setLocationRelativeTo(null);//让窗体位于正中
jf.setDefaultCloseOperation(3);//退出进程
jf.setVisible(true);//窗体可见
//3.获取画笔
Graphics g=jf.getGraphics();//必须在窗体可见之后
//2.监听器
GoBangListener gl=new GoBangListener();
jf.addMouseListener(gl);//在窗体上添加鼠标监听器
gl.g=g;//将监听器的画笔与窗体绑定
}
public void paint(Graphics g){
super.paint(g);//继承父类paint方法的重绘组件
System.out.println("绘制组件!");
//绘制背景图
g.drawImage(img,X,Y,ROW*SIZE,CLOUN*SIZE,null);
//绘制棋盘
for(int i=0;i<=15;i++){
g.drawLine(X, Y+i*SIZE, X+ROW*SIZE, Y+i*SIZE);
g.drawLine(X+i*SIZE, Y, X+i*SIZE, Y+CLOUN*SIZE);
}
}
然后是鼠标监听器的代码编写,这里一定要注意记得要将各种接口的抽象方法写出来加方法体(即使没有任何实际代码),否则就会报错,因为是要点击下棋,所以重点是要重写鼠标点击这个方法,我认为mousePressed和mouseClicked都可,代码如下:
import java.awt.Color;
import java.awt.Graphics;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
public class GoBangListener implements GoBaangConfig, MouseListener, MouseMotionListener{
int chessX,chessY;
Graphics g;
int flag=0;//flag用于实现黑白棋轮换
public void setGraphics(Graphics g){this.g=g;}
@Override
public void mousePressed(MouseEvent e) {
int x = e.getX();
int y = e.getY();
//棋子位置矫正,运用了整数计算时不保留小数的特点
int chessX = (x+SIZE/2-X)/SIZE;
int chessY = (y+SIZE/2-Y)/SIZE;
System.out.println("chessX:"+chessX);
System.out.println("chessY:"+chessY);
if(flag==0){
//下黑棋
flag++;
g.setColor(Color.BLACK); g.fillOval(chessX*SIZE+X-SIZE/2,chessY*SIZE-SIZE/2+Y,SIZE,SIZE); //这样可以下到交点处
}else{
g.setColor(Color.WHITE);
g.fillOval(chessX*SIZE+X-SIZE/2,chessY*SIZE-SIZE/2+Y,SIZE,SIZE);// 下白棋
flag=0;
//下完白棋之后 赋值为下黑棋可以通过的条件
}
}
@Override
public void mouseDragged(MouseEvent e) {
}
@Override
public void mouseMoved(MouseEvent e) {
}
@Override
public void mouseClicked(MouseEvent e) {
}
@Override
public void mouseReleased(MouseEvent e) {
}
@Override
public void mouseEntered(MouseEvent e) {
}
@Override
public void mouseExited(MouseEvent e) {
}
}
然后是一些可以改进的地方:①可以记录黑白棋各自下的的步数;②可以设置一个开始游戏的画面;③判断输赢的方法;④下棋的范围限制。
记录黑白棋棋的步数代码改进,加在监听器中:
int count1=0;int count2=0;
if(flag==0){
//下黑棋
g.setColor(Color.BLACK);
chessNum=1;
chessNumArr[chessX][chessY]=chessNum; System.out.println("weishenm:"+chessNumArr[chessX][chessY]);
flag++;
count1++; g.fillOval(chessX*SIZE+X-SIZE/2,chessY*SIZE-SIZE/2+Y,SIZE,SIZE); if(whetherwin.iswin1(chessNumArr,chessX,chessY)){
JOptionPane.showMessageDialog(null, "黑棋win!!");
}
}else{
g.setColor(Color.white);
// 下白棋
chessNum=2;
chessNumArr[chessX][chessY]=chessNum;
System.out.println("weishenm:"+chessNumArr[chessX][chessY]);
flag=0;
count2++;
g.fillOval(chessX*SIZE+X-SIZE/2,chessY*SIZE-SIZE/2+Y,SIZE,SIZE);
if(whetherwin.iswin2(chessNumArr,chessX,chessY)){
JOptionPane.showMessageDialog(null, "白棋win!!");
}
//下完白棋之后 赋值为下黑棋可以通过的条件
}
write();//记录步数
public void write(){
g.setColor(new Color(238,238,238));
g.fillRect(850,800,300,400);
g.setColor(Color.BLACK);
Font font=new Font("楷体",1,26);
g.setFont(font);
g.drawString("黑棋走了"+count1+"步", 850, 800);
g.drawString("白棋走了"+count2+"步", 850, 850);
System.out.println("按下鼠标按键");
}
设置开始游戏的新界面代码加在界面类中:
public void startUI(){
JFrame jjf=new JFrame();
jjf.setSize(1000,1000);
jjf.setLocationRelativeTo(null);
jjf.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
JButton btn=new JButton("开始游戏");
btn.addActionListener(gl);
ImageIcon icon=new ImageIcon("60.png");
JLabel label=new JLabel(icon);
jjf.add(label,BorderLayout.CENTER);
jjf.add(btn,BorderLayout.SOUTH);
jjf.setVisible(true);
gl.setGobangUI(this);
gl.setStartjf(jjf);
}
在鼠标监听器中也要相应进行调整:
int[][] chessNumArr=new int[ROW+1][CLOUN+1];
int chessNum=0;//chessNum:0代表空棋,1代表黑,2代表白
public void setGraphics(Graphics g){this.g=g;}
public void setStartjf(JFrame jjf){this.jjf=jjf;}
public void setGobangUI(GoBangUI gobangUI){this.gobangUI=gobangUI;}
public void actionPerformed(ActionEvent e){
//识别按钮内容
String st=e.getActionCommand();
if(st.equals("开始游戏")){
jjf.setVisible(false);
gobangUI.initGoBangMainUI();
}
}
//在调试界面下显示数字棋盘
for (int i = 0; i < chessNumArr.length; i++) {
for (int j = 0; j < chessNumArr[i].length; j++) {
System.out.print(chessNumArr[j][i]+" ");
}
System.out.println();
}
}
总结:本次五子棋的制作暂时就到这里,仍然存在的问题是没有实现悔棋、清屏以及个性化的弹窗功能和登录账号功能,甚至还有录制棋局等功能,都需要我在后续的学习过程中慢慢完善。