开发工具与关键技术: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{}
- 在类里重写鼠标按下事件mousePressed
- e.getX()获取鼠标点击的x坐标,e.getY()获取鼠标点击的y坐标,用于判断鼠标点在那个格子内。
(3)棋子不单单只有一个,也有多个和不同的颜色,所以:
- 需要一个集合将所下的棋子装起来
ArrayList pieceslist = new ArrayList<>(); - 需要一个计步器,记录下了几步棋,用于判断下一步到哪一方下棋。
private int counts = 0; - 需要一个存储胜利后的记录颜色,胜利后的记录文字(即能表明哪一方胜利的参数)
private static String wins = "";
private static Color color = null;
(4)最后就是在鼠标按下事件里写下棋了:
- 每下一个棋子,都需要为棋子所在的格子添加一方的颜色属性,所以每下一个棋子都要遍历一次所有格子
- 在遍历里,将本次遍历到的格子提取出来,判断该格子是否与鼠标点击的地方(xy坐标)相交,需要在棋盘类里写一个方法:
public Rectangle getRect() {
return new Rectangle((int) x, (int) y, Constant.GRID_WIDTH, Constant.GRID_HEIGHT);
}
- 判断是否有一方胜利(这里:判断记录颜色和记录文字是否为空),再判断该格子是否是已经拥有一方的颜色属性,有就不能在该格子下棋。
- 若没有哪一方胜利,格子颜色为空,就下棋,步数自增一,判断步数除以2的余数,为1红色方下棋,为0黑色方下棋,假如为红,为该格子设置红色的颜色属性,说明该格子归属红色一方。
- 之后实例化棋子,将棋子添加到集合存储,最后就是胜利机制的方法(没有该方法只是不会有胜利,棋子还可以一直下)。
- 代码:在继承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();
}
}
- 最后就是把棋子集合里的棋子画在棋盘中了,在paint方法里遍历棋子集合
for (int i = 0; i < pieceslist.size(); i++) {
ChessPieces chessPieces = pieceslist.get(i);
chessPieces.draw(g);
}
六、胜利机制
1、就是判断,判断五子棋的胜利有20种,全部都要判断一次。
2、例如横着五个棋子:
- 落子是左边第五个,就要判断左边四个棋子是否是同一种颜色
- 落子是左边第一个,就要判断右边四个棋子是否是同一种颜色
- 落子是左边第二个,就要判断左边一个棋子,右边三个棋子的颜色
- 落子是左边第四个,就要判断右边一个棋子,左边三个棋子的颜色
- 落子是左边第三个,就要判断左边两个,右边两个棋子的颜色
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);
}
}
}
}