Java能开发的东西还是很多的,我们生活中有很多都是利用java开发的,比如小程序,网页等,当然java也可以开发一些小型游戏,那Java如何设计五子棋游戏?下面来我们就来给大家讲解一下。
棋盘是15*15(可以自己规定)
游戏规则:
(1)对局双方各执一色棋子。
(2)空棋盘开局。
(3)黑先、白后,交替下子,每次只能下一子。
(4)棋子下在棋盘的空白点上,棋子下定后,不得向其它点移动,不得从棋盘上拿掉或拿起另落别处。
(5)黑方的第一枚棋子可下在棋盘任意交叉点上。
(6)任意一方达成五连子即可获胜
Java开发用到了Swing轻量级组件用来处理游戏界面,判断胜利的逻辑代码是核心。
1.整体的设计
public class MyJpanel extends JFrame { PicJpanel pj; public MyJpanel() { init(); } private void init() { // 逻辑代码处理部分 } public static void main(String[] args) { new MyJpanel(); } } class PicJpanel extends JPanel { MyJpanel mj; public PicJpanel(MyJpanel mj) { // 设定面板在窗体中的位置以及高度和宽度 this.setBounds(0, 0, mj.getWidth(), mj.getHeight()); this.mj = mj; } /** * 画组件 */ @Override protected void paintComponent(Graphics g) { // 设置一个背景 try { BufferedImage bi = ImageIO.read(new File("img/bj.jpg")); g.drawImage(bi, 0, 0, this); } catch (IOException e) { e.printStackTrace(); } } class MyMouse extends MouseAdapter { MyJpanel mj; public MyMouse(MyJpanel mj) { super(); this.mj = mj; } @Override public void mousePressed(MouseEvent e) { //点击事件的处理 } }
MyJpanel 继承Jfram作为整体的一个框架,PicJpanel继承JPanel描绘图画,两者是通过双向关联来互相取值的.MyMouse用来处理点击时间(也是双向关联Jfram)。
2.整体设计模式确定后,就是画图了
在MyJpanel的Init()方法里设置大小,布局方式等,在PicJanel里的paintComponent(Graphics g)方法里通过画图工具画出棋盘。
画图的思路是通过循环画一个15*15的格子。
init()和paintComponent(Graphics g)里的代码:
private void init() { // 窗体的常用设置 this.setSize(750, 780); // 设置窗体的大小,宽度和高度,单位是像素 this.setDefaultCloseOperation(this.EXIT_ON_CLOSE); // 设置窗体关闭时主线程自动关闭 this.setLocationRelativeTo(null); // 设置窗体出现的位置在显示器正中间 this.setResizable(false); // 设置窗体固定大小 this.setLayout(null); // 不启用布局管理器,改为手动布局 this.setTitle("画图"); // 添加面板到窗体 pj = new PicJpanel(this); this.add(pj); this.setVisible(true); }
protected void paintComponent(Graphics g) { // 设置一个背景 try { BufferedImage bi = ImageIO.read(new File("img/bj.jpg")); g.drawImage(bi, 0, 0, this); } catch (IOException e) { e.printStackTrace(); } g.setColor(Color.BLACK); //通过循环画格子 for (int i = 0; i < 15; i++) { for (int j = 0; j < 15; j++) { g.drawRect(50 * i, 50 * j, 50, 50); } } }
画好之后就是这样
3.接着添加点击事件
要求
1.精确点击
2.首先落子的是黑棋
2.每次一方下完棋子颜色改变
说一下思路,我这里是750*750的,行和列都是15,这样就很容易获取x和y的值(通过鼠标点击事件getX和getY再除以50则可得到x,y),说到x,y大家肯定想到要使用二维数组,每错,我们在前台看到的是棋盘,但是实际存储值的地方在二维数组,所以要定义一个二维数组map[15][15]。每次获取到x和y则将map[x][y]=1或2(黑子或白子),每次点击之后都要调用repaint()方法重新绘制图画。看看MyMouse里的mousePressed()方法。
在这之前先在MyJpanel里设置2个全局变量
int map[][] = new int[15][15]; // 棋盘
int flag = 2; // 1为白 2为黑 黑白交替默认为黑
由于MyMouse 关联了MyJpanel 所以可以获取到MyJpanel 的值
public void mousePressed(MouseEvent e) { Point p = e.getPoint(); // 获取鼠标点下的位置的坐标 // 点击之后map值发生改变 int x = (int) p.getX() / (750 / 15); int y = (int) p.getY() / (750 / 15); System.out.println("x=" + p.getX() + " y=" + p.getY()); System.out.println("x=" + x + " y=" + y); // 改变棋子的颜色 if (map[y][x] == 0) { map[y][x] = mj.flag; } // 改变顺序 if (mj.flag == 1) { mj.flag = 2; } else if (mj.flag == 2) { mj.flag = 1; } //重置绘图 mj.pj.repaint(); }
做完点击事件处理后,要回到图像处理部分PicJpanel在循环里添加一行代码如下:
for (int i = 0; i < 15; i++) { for (int j = 0; j < 15; j++) { g.drawRect(50 * i, 50 * j, 50, 50); // 1为白 if (map[i][j] == 1) { g.setColor(Color.WHITE); g.fillOval(50 * j, 50 * i, 50, 50); } g.setColor(Color.black); // 2为黑 if (map[i][j] == 2) { g.setColor(Color.black); g.fillOval(50 * j, 50 * i, 50, 50); } }
看看效果
点击第一行一列后台处理之后输出结果。嗯差不多做了一大半了。剩下来的就是核心部分了
4.胜负判断
每次调用鼠标点击时间都要判断一次输赢。
讲一下思路。要判断输赢。要判断每次落子的地方该子的四个大方向是否有五颗连续的子,4个大方向为上下,左右,左斜,右斜,想一下米子的写法就可以了。同方向上是否有五颗颜色一样的棋子,实际上就是连续问题,这里有很多处理方法。博主给出的不是最佳方案。
4步完成后稍微修改处理一下代码就可以了。
代码如下,这个小游戏主要是画图和数组两个部分的内容,基础稍好的同学可以试着自己实现一下,可以参照设计思路,细节上可以自己处理。
import java.awt.Color; import java.awt.Graphics; import java.awt.Point; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import java.awt.event.MouseListener; import java.awt.image.BufferedImage; import java.io.File; import java.io.IOException; import javax.imageio.ImageIO; import javax.swing.JFrame; import javax.swing.JOptionPane; import javax.swing.JPanel; public class MyJpanel extends JFrame { PicJpanel pj; int map[][] = new int[16][16]; // 棋盘 int flag = 2; // 1为白 2为黑 黑白交替默认为黑 int winer = 0; //规定赢者 public int[][] getMap() { return map; } public void setMap(int[][] map) { this.map = map; } public MyJpanel() { init(); } private void init() { // 窗体的常用设置 this.setSize(750, 780); // 设置窗体的大小,宽度和高度,单位是像素 this.setDefaultCloseOperation(this.EXIT_ON_CLOSE); // 设置窗体关闭时主线程自动关闭 this.setLocationRelativeTo(null); // 设置窗体出现的位置在显示器正中间 this.setResizable(false); // 设置窗体固定大小 this.setLayout(null); // 不启用布局管理器,改为手动布局 this.setTitle("画图"); // 添加面板到窗体 pj = new PicJpanel(this); pj.addMouseListener(new MyMouse(this)); // 给面板添加一个鼠标监听事件 this.add(pj); this.setVisible(true); } public static void main(String[] args) { new MyJpanel(); } } class PicJpanel extends JPanel { MyJpanel mj; public PicJpanel(MyJpanel mj) { // 设定面板在窗体中的位置以及高度和宽度 this.setBounds(0, 0, mj.getWidth(), mj.getHeight()); this.mj = mj; } /** * 画组件 */ @Override protected void paintComponent(Graphics g) { try { BufferedImage bi = ImageIO.read(new File("img/bj.jpg")); g.drawImage(bi, 0, 0, this); } catch (IOException e) { e.printStackTrace(); } int map[][] = mj.map; g.setColor(Color.BLACK); for (int i = 0; i < 15; i++) { for (int j = 0; j < 15; j++) { g.drawRect(50 * i, 50 * j, 50, 50); // 1为白 if (map[i][j] == 1) { g.setColor(Color.WHITE); g.fillOval(50 * j, 50 * i, 50, 50); } g.setColor(Color.black); // 2为黑 if (map[i][j] == 2) { g.setColor(Color.black); g.fillOval(50 * j, 50 * i, 50, 50); } } } // g.setColor(Color.RED);//设置画笔为红色 // g.drawRect(50, 50, 100, 100);//画一个矩形.前面两个参数决定位置,后两个参数决定大小 // g.setColor(Color.BLUE); // g.fillRect(200,50, 100, 100);//画一个实心的矩形 // g.drawOval(50, 200, 100, 100); // g.fillOval(200, 200, 100, 100); } } class MyMouse extends MouseAdapter { MyJpanel mj; public MyMouse(MyJpanel mj) { super(); this.mj = mj; } @Override public void mousePressed(MouseEvent e) { //重置1 if (mj.winer != 0) { mj.setMap(new int[16][16]); mj.winer = 0; mj.pj.repaint(); return; } int map[][] = mj.map; Point p = e.getPoint(); // 获取鼠标点下的位置的坐标 // 点击之后map值发生改变 int x = (int) p.getX() / (750 / 15); int y = (int) p.getY() / (750 / 15); System.out.println("x=" + p.getX() + " y=" + p.getY()); System.out.println("x=" + x + " y=" + y); // 改变棋子的颜色 if (map[y][x] == 0) { map[y][x] = mj.flag; } // 改变顺序 if (mj.flag == 1) { mj.flag = 2; } else if (mj.flag == 2) { mj.flag = 1; } //判断输赢 MyMouse mouse = new MyMouse(mj); if (mouse.isWin(y, x, map)) { if (map[y][x] == 1) { mj.winer = 1; mj.pj.repaint(); //弹出获胜信息 JOptionPane.showMessageDialog(mj, "白子胜"); //重置棋子颜色为黑棋 mj.flag = 2; } if (map[y][x] == 2) { mj.winer = 2; mj.pj.repaint(); JOptionPane.showMessageDialog(mj, "黑子胜"); //重置棋子颜色为黑棋 mj.flag = 2; } } //先调整数组 在绘图 mj.setMap(map); mj.pj.repaint(); } public boolean isWin(int x, int y, int map[][]) { // 对胜负判断 // 4个方向 左右 上下 左斜 右斜 // 对一个棋子的一个方向的10颗棋子进行判断 是否满足5子连续 // 左右 int num = 1; for (int i = 0; i < 14; i++) { if (map[x][i] != 0) { if (map[x][i] == map[x][i + 1]) { num++; if (num >= 5) { System.out.println("win"); return true; } } else { num = 1; } } } // 上下 num = 1; for (int i = 0; i < 14; i++) { if (map[i][y] != 0) { if (map[i][y] == map[i + 1][y]) { num++; if (num >= 5) { System.out.println("win"); return true; } } else { num = 1; } } } num = 1; // 右斜 x-1 j+1 for (int i = 0; i < map.length * 2 - 1; i++) { for (int j = 1; j < map.length; j++) { if (((i - j) >= 0) && ((i - j) < map.length)) { if (map[j][i - j] != 0) { if (map[j][i - j] == map[j - 1][i - j + 1]) { num++; if (num >= 5) { System.out.println("win"); return true; } } else { num = 1; } } } } } num = 1; //左斜 x+1 y+1 for (int i = -map.length; i < map.length; i++) { for (int j = 1; j < map.length; j++) { if (((i + j) >= 0) && ((i + j) < map.length)) { < p = "" > if (map[j][j + i] != 0) { if (map[j][i + j] == map[j + 1][i + j + 1]) { num++; if (num >= 5) { System.out.println("win"); return true; } } else { num = 1; } } } } } return false; } }
我们再使用java开发游戏的时候,一定要明确项目开发思路,这样才会开发好项目,减少出错的机会!最后大家如果想要了解更多java实战知识,敬请关注奇Q工具网。
推荐阅读: