【java学习日记】初级五子棋游戏的实现(v1.0)

设计思路


  •  我们可以把五子棋分为 棋盘界面的绘制、下棋的实现与校正、为鼠标添加动作监听器、黑白棋的输赢判断这四个部分。
  • 对于棋盘界面的绘制,我们可以直接继承父类JFrame,创建一个名为GoUI的子类,在里面添加包括显示棋盘、按钮等等的方法。
  • 对于下棋的实现与校正,我们需要在指定位置绘制一个棋子,这一步需要用到Graphics并且要与动作监听器配合使用。
  • 为鼠标添加动作监听器,是为了让棋盘与鼠标产生连接,我们可以先创建一个GoListener的类,在里面写好鼠标动作的方法,然后将其传至显示界面的GoUI类里
  • 最后是黑白棋的输赢判断,我们只需要用两个数字来代表黑白子,再实时获取每个坐标上和它相邻的五个位置是否全为一样的数字,便可以判断输赢。


设计过程


棋盘界面的绘制

我们先创建一个继承了JFrame的GoUI打类,并在里面写好showUI的方法

public class GoUI extends JFrame{
	final int X = 50, Y = 75, SIZE = 50, ROWS = 15, COLS = 15;
    //使用final修饰变量,设定棋盘的初始值

	public void showUI(){
	
		setTitle ("GoBangV1.0");  //设置窗口的名称
		setSize (1000, 875);  //设置窗口的大小
		setDefaultCloseOperation (EXIT_ON_CLOSE);  //设置关闭时结束程序
		setLayout (null);  //设置流式布局为null,自定义组件位置
		JButton btn = new JButton ("开始游戏");  //创建一个按钮对象
		btn.setBounds (855, 100, 100, 35);  //设置按钮对象大小
		add (btn);  //将按钮对象添加到界面里

        setVisible (true);
		setResizable (false);// 设置窗体大小不可变



		Graphics g = getGraphics ();
		gol.g = g;

 接着我们写完程序入口,如下

public static void main(String[] args){
		GoUI goUI = new GoUI ();
		goUI.showUI ();

	}

 这一部分代码暂时完成,但还需要添加动作监听器,我们后面再做修改。


棋子的绘制

当我们设置好一个棋盘以后 ,我们就应该设置棋子了,为了方便区分,我们添加一个名为chess的类,里面完成对棋子的设定。

先创建类与对象

public class Chess{
	int r, c, chessFlag;
	int SIZE = 50;

再为之赋值

public Chess(int r, int c, int chessFlag){
		this.r = r;
		this.c = c;
		this.chessFlag = chessFlag;
	}

 接着我们创建一个名为drawChess的方法来绘制棋子

public void drawChess(Graphics g){
		int chessX = c * SIZE + 50 - 25;
		int chessY = r * SIZE + 75 - 25;
        //设置棋子的坐标

		if(chessFlag == 1){
			for(int i = 0; i < SIZE; i++){
				Color color = new Color (i * 5, i * 5, i * 5);
				g.setColor (color);
				g.fillOval (chessX + i / 2, chessY + i / 2, SIZE - i, SIZE - i);
                //通过循环,用不同颜色的圆面叠加,产生立体棋子的效果
			}
		} else{
			for(int i = 0; i < SIZE; i++){
				Color color = new Color (150 + i * 2, 150 + i * 2, 150 + i * 2);
				g.setColor (color);
				g.fillOval (chessX + i / 2, chessY + i / 2, SIZE - i, SIZE - i);
			}

		}

 这一步完成了棋子坐标、颜色和大小的设定,接下来就是将棋子绘制在棋盘上了。


为鼠标添加动作监听器

初始准备

public class GoListener implements MouseListener, ActionListener{
	final int X = 50, Y = 75, SIZE = 50, ROWS = 15, COLS = 15;
	Graphics g;

	int chessFlag = 0;  //代表棋盘的状态,是否开始游戏
	int[][] chessArr = new int[16][16];  //新建一个二维数组来存储棋子的状态

	Chess[] chessList  = new Chess[256];  //创建一个线性的数组来存储每一步的棋子
	int chessCount = 0; 

接下来我们实现点击开始游戏按钮就启动棋盘的功能。

public void actionPerformed(ActionEvent e){
		String btnText = e.getActionCommand ();  //创建btnText对象并将按钮的文字赋值

		Object source = e.getSource ();  //获取按钮的事件源
		JButton btn = (JButton) source;  //把事件源转换为对象btn
		

接下来通过比对文字是否为“开始游戏”,来判断按钮是否被点击,并且在被点击以后,改变chessFlag为1,即游戏正在进行,并且将按钮的文字设置为结束游戏。

if(btnText.equals ("开始游戏")){
			chessFlag = 1;
			btn.setText ("结束游戏");
		

接下来我们完善“结束游戏” 被点击时要做的事情。首先是清空棋子状态,即将储存棋子状态的数组全部设置为0,再完成棋盘的重绘,使得已经绘制的棋子消失。这里我们先写一个drawGoBack的方法,之后再来填充。最后还要设置按钮的文字为“开始游戏”。

if(btnText.equals ("开始游戏")){
			chessFlag = 1;
			btn.setText ("结束游戏");
		} else if(btnText.equals ("结束游戏")){
			chessFlag = 0;
		
			chessArr = new int[16][16];
		
			drawGoBack (g);

	        btn.setText ("开始游戏");

完成这些以后,我们完善当鼠标被点击后的操作(mousePressed)

 首先,如果玩家未点击开始游戏,要求先完成这步操作。接着,我们获取点击的坐标值,并且通过数学计算,算出其对应的棋盘上的行列值,并完成赋值。

	public void mousePressed(MouseEvent e){

		if(chessFlag == 0){
			JOptionPane.showMessageDialog (null, "请点击开始游戏");
			return;
		}

		int x = e.getX ();
		int y = e.getY ();

		// 计算行列值
		int r = (y - 75 + 25) / 50;
		int c = (x - 50 + 25) / 50;
		System.out.println ("r=" + r + ",c=" + c);

接着我们为了防止玩家再棋盘范围外下棋,我们添加一个提示,并为提示添加弹窗

	// 判断下棋的范围,并弹出弹窗提示
		if(r < 0 || r > 15 || c < 0 || c > 15){
			JOptionPane.showMessageDialog (null, "请在棋盘范围内下棋");
			return;
		}
		if(chessArr[r][c] != 0){
			JOptionPane.showMessageDialog (null, "此处已有棋子");
			return;
		}

我们用1和2代表黑棋白棋,并将它们储存进创建的二维数组,通过矩阵的方式,在电脑上后台模拟出当前棋盘的状态。

		chessArr[r][c] = chessFlag;

 同时,为了方便之后添加回放和悔棋功能,我们将棋子的状态(行列值、黑白棋)按下棋的顺序添加进刚开始创建的线性数组。并且用chessCount来计数。然后调用chess类中编写的绘制方法来完成棋子的绘制

		Chess chess = new Chess (r, c, chessFlag);
		chessList[chessCount] = chess;
		chessCount++;
		chess.drawChess (g);

 注意,为了实现黑白棋的交替进行,我们需要判断此时棋子为黑还是白,即是否为1,然后将下一个棋子设置为另一个数字。而在drawChess中,我们已经写好了两种情况的棋子颜色

if(chessFlag == 1){
			chessFlag = 2;
		} else if(chessFlag == 2){
			chessFlag = 1;
		}

 接着,我们先预创建一个类和对象来分别判断和记录棋子的输赢,并完成比较和结果输出。最后,在判断完输赢并输出以后,我们将棋子状态chessFlag设定为0,即游戏已结束。

boolean winFlag = GoIsWin.isWin (r, c, chessArr);
		if(winFlag){
			if(chessArr[r][c] == 1){
				JOptionPane.showMessageDialog (null, "黑棋赢了");
			} else if(chessArr[r][c] == 2){
				JOptionPane.showMessageDialog (null, "白棋赢了");
			}
			chessFlag = 0;
		}

 棋子与棋盘的绘制方法

完成以上对于动作的设置后,我们需要补全之前设置的两个方法,即绘制棋子与绘制棋盘

对于绘制棋子,我们只需遍历记录在线性数组里的数据,为每一步分别调用drawChess方法即可。

public void drawChess(Graphics g){

		for(int i = 0; i < chessCount; i++){
			Chess chess = chessList[i];
			chess.drawChess (g);
		}
	}

绘制棋盘,我们需要先绘制一个底座,再绘制一个盘面,然后为盘面画上网格线。

public void drawGoBack(Graphics g){
		//绘制底座
		Color color = new Color (166, 137, 124);
		g.setColor (color);
		g.fillRect (0, 0, 845, 870);

        //绘制盘面
		Color color1 = new Color (219, 207, 202);
		g.setColor (color1);
		g.fillRect (X - SIZE / 2, Y - SIZE / 2, COLS * SIZE + SIZE, ROWS * SIZE + SIZE);
		g.setColor (Color.BLACK);
		// 为棋盘划线,来绘制格子
		for(int i = 0; i <= 15; i++){
			g.drawLine (X, Y + i * SIZE, X + COLS * SIZE, Y + i * SIZE);
			g.drawLine (X + i * SIZE, Y, X + i * SIZE, Y + ROWS * SIZE);
		}
		g.setColor (Color.BLACK);
		g.drawRect (X - SIZE / 2, Y - SIZE / 2, COLS * SIZE + SIZE, ROWS * SIZE + SIZE);


	}

}

 这样,我们就完成了各种动作的设置与棋子棋盘的绘制。


对GoUI类添加设置好的动作监听器

当然,不要忘记将动作监听器传输到GoUI的类中,我们如下修改GoUI的代码。


public class GoUI extends JFrame{
	final int X = 50, Y = 75, SIZE = 50, ROWS = 15, COLS = 15;

	GoListener gol = new GoListener ();

	public void showUI(){
		setTitle ("GoBangV1.0");
		setSize (1000, 875);
		setDefaultCloseOperation (EXIT_ON_CLOSE);
		setLayout (null);
		JButton btn = new JButton ("开始游戏");
		btn.setBounds (855, 100, 100, 35);
		add (btn);
		btn.addActionListener (gol);


		setVisible (true);
		setResizable (false);

		// 调用 addMouseListener 添加鼠标监听器
		addMouseListener (gol);

		Graphics g = getGraphics ();
		gol.g = g;
	}

    public void paint(Graphics g){
		super.paint (g);

		gol.drawGoBack (g);
		gol.drawChess (g);


	}


	public static void main(String[] args){
		GoUI goUI = new GoUI ();
		goUI.showUI ();

	}


}


黑白棋的输赢判断

接下来,我们补全输赢判断的方法,为了方便区分,我们创建一个专门的类

我们已纵向为例,这个时候就需要用到我们创建的二维数组了。

我们创建int count来计数,然后保持列不变,遍历上下的行,如果有相等的便为count加1

private static int col (int r, int c, int[][] chessArr){
		int count = 1;
        //向下遍历
		for(int i = r + 1; i < chessArr[0].length; i++){
			if(chessArr[i][c] == chessArr[r][c]){
				count++;
			} else{
				break;
			}
		}
  
        //向上遍历
		for(int i = r - 1; i >= 0; i--){
			if(chessArr[i][c] == chessArr[r][c]){
				count++;
			} else{
				break;
			}
		}

		System.out.println ("纵向查找到:" + count);
		return count;

同理完成横向的查找

private static int row(int r, int c, int[][] chessArr){
		int count = 1;

		for(int i = c + 1; i < chessArr[0].length; i++){
			if(chessArr[r][i] == chessArr[r][c]){
				count++;
			} else{
				break;
			}
		}

		for(int i = c - 1; i >= 0; i--){
			if(chessArr[r][i] == chessArr[r][c]){
				count++;
			} else{
				break;
			}
		}

		System.out.println ("横向查找到:" + count);
		return count;
	}

但我们还需要完成斜向的判断。

我们可以使用while循环来解决,分别创建 i 和 j 、a 和 b 两组来代表行列,同时进行加减,就能达成斜向遍历的效果,代码如下。

	private static int left(int r, int c, int[][] chessArr) {
		int count = 1;
		int i = c + 1;
		int j = r + 1;
		while (i < chessArr[0].length & j < chessArr[0].length) {
			if (chessArr[j][i] == chessArr[r][c]) {
				count++;
				i++;
				j++;
			} else {
				break;
			}
		}
		int a = c - 1;
		int b = r - 1;
		while (a>= 0 & b>=0) {
			if (chessArr[b][a] == chessArr[r][c]) {
				count++;
				a--;
				b--;
			} else {
				break;
			}
		}

		System.out.println ("左斜向查找到:" + count);
		return count;
	}

	private static int right(int r, int c, int[][] chessArr){
		int count = 1;
		int i = c + 1;
		int j = r - 1;
		while (i < chessArr[0].length & j >=0) {
			if (chessArr[j][i] == chessArr[r][c]) {
				count++;
				i++;
				j--;
			} else {
				break;
			}
		}
		int a = c - 1;
		int b = r + 1;
		while (a< chessArr[0].length & b>=0) {
			if (chessArr[b][a] == chessArr[r][c]) {
				count++;
				a--;
				b++;
			} else {
				break;
			}
		}

		System.out.println ("右斜向查找到:" + count);
		return count;
	}

 这样,我们就完成各个方向的计数。

接着我们写全判断的标准,并返回布尔值。之前在动作监听器类里调用的布尔值也就成立了。

	public static boolean isWin(int r, int c, int[][] chessArr){

		if(row (r, c, chessArr) >= 5 ||
			  col (r, c, chessArr) >= 5 ||
			  left (r, c, chessArr) >= 5 ||
			  right (r, c, chessArr) >= 5){
			return true;
		}
		return false;

	}

结语


这样,一个基础的五子棋游戏也就做好了,在下一篇文章中,将会添加悔棋和回放的功能,完成进阶版的五子棋游戏。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值