Java五子棋

开发工具与关键技术:MyEclipse 10、JAVA
作者:曾浩源
撰写时间:2019年04月27日

在做一个应用或者程序的时候,首先想到的是,我们需要哪些部分来组成我们的程序,例如这个简单五子棋,它需要:

1.常量 (有些数据经常用,而不需要改变)
2.游戏主窗口 (创建窗口都需要的,常用,把它封装到一个【窗口模板】类里)
3.棋盘 (即:二维网格,创建棋盘类)
4.棋子 (可为图片,也可以绘制)
5.下棋 (即为鼠标事件)
6.判断胜利规则
一、常量

常量有什么,如:窗口的大小,窗口的xy坐标,棋盘每个格子的宽高,棋子的大小,棋子的颜色,棋盘有多少个格子。
棋盘应该有几个格子?它格子的数量就是:

 //(窗口的宽度-10) 乘以 (窗口的高度-40)   减的数量根据电脑而异(自己调试完美) (得出的面积)除以(格子的面积)  最后就是格子的数量啦
public static final int BORAD_COUNTS = ((MAIN_WIDTH - 10) * (MAIN_HEIGHT - 40)) / (GRID_WIDTH * GRID_HEIGHT);  			

要减的数量最好设置成一个固定的常量,因为到后面也会经常使用。

二、游戏主窗口

在每个窗体应用都是有主窗口的,因此封装好一个(窗口模板)可万用,需要临时添加内容,在主窗口继承窗口模板后,自行重写super调用一次,下面继续添加内容即可。

三、棋盘
1、棋盘是由二维网格绘制出来,就需要:

x坐标,y坐标,因为二维网格又是由多个格子组合成的,所以需要用集合将他们放在一起,放在一起后就是基本步骤:创建有参构造器,创建getters和setters方法。

2、有了xy坐标,存储格子的集合,就可用for循环将棋盘绘制出来了

循环一个格子,先判断它的x坐标是否超出窗口宽度,若没有,添加进集合,然后在该格子的基础下的x坐标加一个格子的宽度,若超过了,重置x坐标为初始值(10),y坐标加一个格子的高度,然后添加进集合,之后为该格子的x坐标添加一个格子的宽度。

	public void draw(Graphics g) {
		for (int i = 0; i < chessBorads.size(); i++) {
			ChessBorad borad = chessBorads.get(i);
			g.drawRect((int) borad.getX(), (int) borad.getY(),Constant.GRID_WIDTH, Constant.GRID_HEIGHT);
		}
	}
	public void creatboradlist() {
		for (int i = 0; i < Constant.BORAD_COUNTS; i++) {
			// 判断 x小于窗口长度-10 若超出宽度则else
			if (x < Constant.MAIN_WIDTH - 10) {
				chessBorads.add(new ChessBorad(x, y));
				x += Constant.GRID_WIDTH;
			} else if (y < Constant.MAIN_HEIGHT - 40) {// 超出宽度后
				x = 10;// x重新赋值为10
				y += Constant.GRID_HEIGHT; // y轴纵向加一个格子的高度
				chessBorads.add(new ChessBorad(x, y));
				x += Constant.GRID_WIDTH;
			}
		}
	}
创建棋盘集合creatboradlist的方法在无参构造器调用就好,这样可以实例化棋盘。
四、棋子
1、棋子拥有哪些属性?

如:xy轴、棋子的颜色、棋子占的格子,之后又是基本步骤:创建有参构造器,创建getters和setters方法。

2、这实现的是绘制棋子:

保存原有颜色,改变画笔颜色,画棋子,恢复画笔颜色。

	public void draw(Graphics g){
		Color c=g.getColor();
		g.setColor(color);
		g.fillOval((int)x+2, (int)y+2, Constant.CHESS_WIDHT, 							Constant.CHESS_HEIGHT);
		g.setColor(c);
	}
3、注意事项:

Constant是常量的意思,用它把常量给装起来;CHESS_WIDHT棋子的宽度;
x+2是为了让棋子在格子内居中;
在构造器里给x,y赋值是需要:
this.x = borad.getX();
this.y = borad.getY();
borad:棋子占的格子。

五、下棋
1、封装好了棋盘、棋子,但还没有将它们显示到窗口里面,所以:

(1)实例化棋盘

ChessBorad borad = new ChessBorad();

(2)Paint方法里画棋盘

public void paint(Graphics g) {
	borad.draw(g);
}
2、棋子需要下才有,所以要先下棋(鼠标事件):

(1)重写frame方法,添加鼠标监听事件;

	public void frame() {
		super.frame();
		//重新创建MouseMonitor类继承鼠标MouseAdapter
		addMouseListener(new MouseMonitor());
	}

(2)重新写一个类继承鼠标事件

class MouseMonitor extends MouseAdapter{}
  1. 在类里重写鼠标按下事件mousePressed
  2. e.getX()获取鼠标点击的x坐标,e.getY()获取鼠标点击的y坐标,用于判断鼠标点在那个格子内。

(3)棋子不单单只有一个,也有多个和不同的颜色,所以:

  1. 需要一个集合将所下的棋子装起来
    ArrayList pieceslist = new ArrayList<>();
  2. 需要一个计步器,记录下了几步棋,用于判断下一步到哪一方下棋。
    private int counts = 0;
  3. 需要一个存储胜利后的记录颜色,胜利后的记录文字(即能表明哪一方胜利的参数)
private static String wins = "";   
private static Color color = null;

(4)最后就是在鼠标按下事件里写下棋了:

  1. 每下一个棋子,都需要为棋子所在的格子添加一方的颜色属性,所以每下一个棋子都要遍历一次所有格子
  2. 在遍历里,将本次遍历到的格子提取出来,判断该格子是否与鼠标点击的地方(xy坐标)相交,需要在棋盘类里写一个方法:
public Rectangle getRect() {
	return new Rectangle((int) x, (int) y,  Constant.GRID_WIDTH, Constant.GRID_HEIGHT);
}
  1. 判断是否有一方胜利(这里:判断记录颜色和记录文字是否为空),再判断该格子是否是已经拥有一方的颜色属性,有就不能在该格子下棋。
  2. 若没有哪一方胜利,格子颜色为空,就下棋,步数自增一,判断步数除以2的余数,为1红色方下棋,为0黑色方下棋,假如为红,为该格子设置红色的颜色属性,说明该格子归属红色一方。
  3. 之后实例化棋子,将棋子添加到集合存储,最后就是胜利机制的方法(没有该方法只是不会有胜利,棋子还可以一直下)。
  4. 代码:在继承MouseAdapter内重写鼠标按下事件
public void mousePressed(MouseEvent e) {
	//因为每个格子都要判断,所以每下一个棋子都需要循环所有格子
	for (int j = 0; j < borad.chessBorads.size(); j++) {
		//将循环到的格子取出来
		ChessBorad boradone = borad.chessBorads.get(j);
		//判断格子的矩形是否与鼠标点击的xy坐标相交
		boolean ingrid = boradone.getRect().contains(e.getX(), e.getY());
		//若color,wins不为空,则是游戏结束,有一方获得胜利
		if (null == color && wins == "") {
			//相交返回true
			if (ingrid) {
				//判断格子是否有一方的颜色
				if (null == boradone.getChesscolor()) {
					//没有counts++ 判断是哪个颜色下棋
					counts++;
					if (counts % 2 == 1) {		//余数为1 下红色棋子
						//设置格子(已经下了红色棋子)
						boradone.setChesscolor(Color.RED);
						//将棋子添加到棋子集合 (实例化棋子)
						pieceslist.add(new ChessPieces(Color.RED,boradone));
						//判断胜利机制(五颗棋子一条线为胜利)
						JudgmentMechanism.win(e, borad, j, wins, color);
					} else {
						//设置格子(已经下了黑色棋子)
						boradone.setChesscolor(Color.BLACK);
						//将棋子添加到棋子集合 (实例化棋子)
						pieceslist.add(new ChessPieces(Color.BLACK, boradone));
						//判断胜利机制(五颗棋子一条线为胜利)
						JudgmentMechanism.win(e, borad, j, wins, color);
					}
				}
			}
		}
		//获取胜利的颜色
		color = JudgmentMechanism.getColor();
		//获取胜利的文字
		wins = JudgmentMechanism.getWins();
	}
}
  1. 最后就是把棋子集合里的棋子画在棋盘中了,在paint方法里遍历棋子集合
for (int i = 0; i < pieceslist.size(); i++) {
	ChessPieces chessPieces = pieceslist.get(i);
	chessPieces.draw(g);
}
六、胜利机制
1、就是判断,判断五子棋的胜利有20种,全部都要判断一次。
2、例如横着五个棋子:
  1. 落子是左边第五个,就要判断左边四个棋子是否是同一种颜色
  2. 落子是左边第一个,就要判断右边四个棋子是否是同一种颜色
  3. 落子是左边第二个,就要判断左边一个棋子,右边三个棋子的颜色
  4. 落子是左边第四个,就要判断右边一个棋子,左边三个棋子的颜色
  5. 落子是左边第三个,就要判断左边两个,右边两个棋子的颜色
3、有四个方向,所以就20种,其中一个的代码:
// 直左走赢
public static Color GoLeftWin(double x1, double y1, ChessBorad borad) {
	double x2 = x1 + Constant.GRID_WIDTH;//原x坐标加上一个格子的宽度
	double x3 = x2 + Constant.GRID_WIDTH;
	double x4 = x3 + Constant.GRID_WIDTH;
	double x5 = x4 + Constant.GRID_WIDTH;
	return judge(x1, y1, x2, y1, x3, y1, x4, y1, x5, y1, borad);//判断
}
// 判断机制
public static Color judge(double x1, double y1, double x2, double y2, double x3,
	 double y3, double x4, double y4, double x5, double y5, ChessBorad borad) {
	//要在棋盘类内添加一个可以根据xy,获取该格子颜色的方法
	Color color1 = borad.boradcolor(x1, y1);		
	Color color2 = borad.boradcolor(x2, y2);
	Color color3 = borad.boradcolor(x3, y3);
	Color color4 = borad.boradcolor(x4, y4);
	Color color5 = borad.boradcolor(x5, y5);
	if (color1 != null && color2 != null && color3 != null
			&& color4 != null && color5 != null) {
		if (color1.equals(color2) && color1.equals(color3)
				&& color1.equals(color4) && color1.equals(color5)) {
			return color1;
		}
	}
	return null;
}
public static void win(MouseEvent e, ChessBorad borad, int j, String wins,
	Color color) {
	double x1 = borad.chessBorads.get(j).getX();
	double y1 = borad.chessBorads.get(j).getY();
	//用三目运算,判断其中一个不为null就为颜色c赋值
	Color c = UpperLeftWin(x1, y1, borad) != null ? UpperLeftWin(x1, y1, borad)
		: UpperRightWin(x1, y1, borad) != null ? UpperRightWin(x1, y1, borad)
		: LowerLeftWin(x1, y1, borad) != null ? LowerLeftWin(x1, y1, borad)
		: LowerRightWin(x1, y1, borad) != null ? LowerRightWin(x1, y1, borad)
		: GoUpperWin(x1, y1, borad) != null ? GoUpperWin(x1, y1, borad) 
		: GoLowerWin(x1, y1, borad) != null ? GoLowerWin(x1, y1, borad) 
		: GoLeftWin(x1, y1, borad) != null ? GoLeftWin(x1, y1, borad) 
		: GoRightWin(x1, y1, borad) != null ? GoRightWin(x1, y1, borad)
		: HengZKongWin(x1, y1, borad) != null ? HengZKongWin(x1, y1, borad)
		: ShuZKongWin(x1, y1, borad) != null ? ShuZKongWin(x1, y1, borad)
		: YouXKongWin(x1, y1, borad) != null ? YouXKongWin(x1, y1, borad)
		: ZuoXKongWin(x1, y1, borad) != null ? ZuoXKongWin(x1, y1, borad)
		: HengYkongYiWin(x1, y1, borad) != null ? HengYkongYiWin(x1, y1, borad)
		: HengZkongYiWin(x1, y1, borad) != null ? HengZkongYiWin(x1, y1, borad)
		: ShuSKongYiWin(x1, y1, borad) != null ? ShuSKongYiWin(x1, y1, borad)
		: ShuXKongYiWin(x1, y1, borad) != null ? ShuXKongYiWin(x1, y1, borad)
		: XieZShangKongWin(x1, y1, borad) != null ? XieZShangKongWin(x1, y1, borad)
		: XieZXiaKongWin(x1, y1, borad) != null ? XieZXiaKongWin(x1, y1, borad)
		: XieYShangKongWin(x1, y1, borad) != null ? XieYShangKongWin(x1, y1, borad)
		: XieYXiaKongWin(x1, y1, borad);
	if (null != c){ 
	//有值后添加文字
	String string = "";	
		if (c != null && c.equals(Constant.RED_CHESS)) {
			string = "红色方";
		} else if (c != null && c.equals(Constant.BLACK_CHESS)) {
			string = "黑色方";
		}
		JudgmentMechanism.wins = "恭喜" + string + "获胜";
		JudgmentMechanism.color = c;
	}
}
最后就是在paint方法里判断color和wins是否有值,有值即为一方胜利,则显示出文字,显示出文字后,就要关闭窗口才可以重新开始,那如何不关闭窗口按回车键就可重新开始呢?
if (wins != "" && null != color) {
	Font font = g.getFont();
	Color c = g.getColor();
	g.setFont(new Font("宋体", Font.BOLD, 90));
	g.setColor(color);
	g.drawString(wins, Constant.MAIN_WIDTH / 2 / 2 / 2,
			Constant.MAIN_HEIGHT / 3);
	g.setFont(new Font("宋体", Font.BOLD, 50));
	g.setColor(Color.BLUE);
	g.drawString("请按回车键重新开始", Constant.MAIN_WIDTH / 2 / 2,
			Constant.MAIN_HEIGHT / 2);
	g.setFont(font);
	g.setColor(c);
}
添加键盘监听事件,按回车键后进行判断,是否有一方胜利,否则不会重新开始,有一方胜利后,清空已下的棋子,即清空棋子集合,循环所有格子,将格子的颜色归属全部设置为null,就胜利颜色设置为null,将胜利文字设置为“”空,下棋步数设置为0,同时将规则类里的胜利颜色,胜利文字都设置为空。
public void frame() {
	super.frame();
	addMouseListener(new MouseMonitor());
	addKeyListener(new KeyMonitor());
}

class KeyMonitor extends KeyAdapter {
	@Override
	public void keyPressed(KeyEvent e) {
		if (e.getKeyCode() == KeyEvent.VK_ENTER) {
			if (color != null && wins != "") {
				pieceslist.clear();
				for (int j = 0; j < borad.chessBorads.size(); j++) {
					borad.chessBorads.get(j).setChesscolor(null);
				}
				color = null;
				wins = "";
				counts = 0;
				JudgmentMechanism.setColor(color);
				JudgmentMechanism.setWins(wins);
			}
		}
	}
}
  • 3
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值