用Java写一个五子棋小游戏

xiaoxiao2021-02-28  21

棋盘是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)){ 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; } }
转载请注明原文地址: https://www.6miu.com/read-2602898.html

最新回复(0)