用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)){
					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;
	}

}

猜你喜欢

转载自blog.csdn.net/ck784101777/article/details/80948367