用Java写一个五子棋小游戏

2023-11-17

棋盘是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;
	}

}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

用Java写一个五子棋小游戏 的相关文章

  • 在java中轮询Http服务器(重复发送http get请求)

    当对其进行 REST 调用时 我的 Web 服务器会发送一些信息 我想不断轮询该服务器 间隔5秒后重复发送HTTP GET请求 以检查返回的信息是否有任何变化 做到这一点最有效的方法是什么 您能提供一些代码示例吗 请注意 我只想开发客户端代
  • 使用 Java 的 Apache Http 摘要身份验证

    我目前正在开发一个 Java 项目 但无法使 http 摘要身份验证正常工作 我尝试使用 Apache 网站 但没有帮助 我有一个需要 HTTP 摘要身份验证的网站 DefaultHttpClient httpclient new Defa
  • Netbeans 8.1 Gnome 3 GTK+ UI 字体和选项卡高度

    我刚刚在运行 GNOME 3 桌面的 Ubuntu 16 04 上安装了 NetBeans 8 1 如果可能的话 我想继续使用 IDE 的 GTK 外观和感觉 但 UI 上的字体 尤其是选项卡中的字体 太小且重叠 我尝试添加 fontsiz
  • 带路径压缩算法的加权 Quick-Union

    有一种 带路径压缩的加权快速联合 算法 代码 public class WeightedQU private int id private int iz public WeightedQU int N id new int N iz new
  • java中监视目录变化

    我正在使用 WatchService 来监视目录中的更改 特别是目录中新文件的创建 下面是我的代码 package watcher import java nio file import static java nio file Stand
  • 使用 Tabula 通过 Python 读取 pdf 时出现 Java 错误

    我已经安装了 tabula 库 用于使用 python 将 pdf 读取到 pandas 数据框中 但是当我运行代码时 import tabula df tabula read pdf sample1 pdf pages 1 我得到了例外
  • 与 Eclipse 中的 Java Content Assist 交互

    作为我的插件项目的一部分 我正在考虑与 Eclipse 在 Java 文件上显示的内容辅助列表进行交互 我正在尝试根据一些外部数据对列表进行重新排序 我看过一些有关创建新内容辅助的教程 但没有看到有关更改现有内容辅助的教程 这可能吗 如果是
  • 为什么即使我的哈希码值相同,“==”也会返回 false

    我写了一个像这样的课程 public class HashCodeImpl public int hashCode return 1 public static void main String args TODO Auto generat
  • 什么是抽象类? [复制]

    这个问题在这里已经有答案了 当我了解抽象类时 我说 WT H 问题 创建一个无法实例化的类有什么意义呢 为什么有人想要这样的课程 什么情况下需要抽象类 如果你明白我的意思 最常见的是用作基类或接口 某些语言有单独的interface构建 有
  • 如何在 JPQL 或 HQL 中进行限制查询?

    在 Hibernate 3 中 有没有办法在 HQL 中执行相当于以下 MySQL 限制的操作 select from a table order by a table column desc limit 0 20 如果可能的话 我不想使用
  • 从 MATLAB 调用 Java?

    我想要Matlab程序调用java文件 最好有一个例子 需要考虑三种情况 Java 内置库 也就是说 任何描述的here http docs oracle com javase 6 docs api 这些项目可以直接调用 例如 map ja
  • 将巨大的模式编译成Java

    有两个主要工具提供了将 XSD 模式编译为 Java 的方法 xmlbeans 和 JAXB 问题是 XSD 模式确实很大 30MB 的 XML 文件 大部分模式在我的项目中没有使用 所以我可以注释掉大部分代码 但这不是一个好的解决方案 目
  • java inputstream 打印控制台内容

    sock new Socket www google com 80 out new BufferedOutputStream sock getOutputStream in new BufferedInputStream sock getI
  • Android 无法解析日期异常

    当尝试解析发送到我的 Android 客户端的日期字符串时 我得到一个无法解析的日期 这是例外 java text ParseException 无法解析的日期 2018 09 18T00 00 00Z 位于 偏移量 19 在 java t
  • 提高 PostgreSQL 1 亿数据左连接查询性能

    我在用Postgresql 9 2 version Windows 7 64 bit RAM 6GB 这是一个Java企业项目 我必须在我的页面中显示订单相关信息 有三个表通过左连接连接在一起 Tables TV HD 389772 行 T
  • 如何将 HTML 链接放入电子邮件正文中?

    我有一个可以发送邮件的应用程序 用 Java 实现 我想在邮件中放置一个 HTML 链接 但该链接显示为普通字母 而不是 HTML 链接 我怎样才能将 HTML 链接放入字符串中 我需要特殊字符吗 太感谢了 Update 大家好你们好 感谢
  • Java Swing - 如何禁用 JPanel?

    我有一些JComponents on a JPanel我想在按下 开始 按钮时禁用所有这些组件 目前 我通过以下方式显式禁用所有组件 component1 setEnabled false 但是有什么办法可以一次性禁用所有组件吗 我尝试禁用
  • 将 JScrollPane 添加到 JFrame

    我有一个关于向 Java 框架添加组件的问题 我有一个带有两个按钮的 JPanel 和一个添加了 JTable 的 JScrollPane 我想将这两个添加到 JFrame 中 我可以将 JPanel 添加到 JFrame 或将 JScro
  • 子类构造函数(JAVA)中的重写函数[重复]

    这个问题在这里已经有答案了 为什么在派生类构造函数中调用超类构造函数时 id 0 当创建子对象时 什么时候在堆中为该对象分配内存 在基类构造函数运行之后还是之前 class Parent int id 10 Parent meth void
  • Java 11 - 将 Spring @PostConstruct 替换为 afterPropertiesSet 或使用 initMethod

    我正在使用 spring 应用程序 有时会使用 PostConstruct用于代码和测试中的设置 看来注释将被排除在外Java 11 https www baeldung com spring postconstruct predestro

随机推荐

  • 泛型,序列化

    何为泛型 1 JDK1 5以后推出的一种新的参数化的类型 2 通常可以理解为一种一种编译类型 在运行时无效 3 类型生活中的标签 为什么使用泛型 1 约束类中属性类型 方法参数类型 方法返回值类型 2 提高运行时性能 List s new
  • 西门子PLC的TCP通讯(不同项目下)②--TRCV_C指令

    西门子PLC的TCP通讯 不同项目下 TRCV C指令 上期主要了解了TSEND C指令的各项参数的意义 隐藏参数LEN等可以默认 本期将了解另一个配套组合指令块TRCV C 这是个接收指令块 大概呢跟发送指令TSEND C差不多 1 0
  • pinia的基本使用

    npm install pinia 安装pinia import createPinia from pinia app use createPinia main js中使用pinia 新建一个store文件夹 类似于vuex src sto
  • 前端技术搭建扫雷小游戏(内含源码)

    The sand accumulates to form a pagoda 写在前面 功能介绍 页面搭建 样式设置 逻辑部分 写在前面 上周我们实通过前端基础实现了贪吃蛇游戏 今天还是继续按照我们原定的节奏来带领大家完成一个游戏 功能也比较
  • Python机器学习笔记:深入理解Keras中序贯模型和函数模型

    先从sklearn说起吧 如果学习了sklearn的话 那么学习Keras相对来说比较容易 为什么这样说呢 我们首先比较一下sklearn的机器学习大致使用流程和Keras的大致使用流程 sklearn的机器学习使用流程 from skle
  • Linux下minicom的配置和使用方法

    安装配置minicom lsmod grep usbserial 如果直接使用串口线 而没有用到USB转串口设备 此步可以跳过 如果有usbserial 说明系统支持USB转串口 安装minicom Fedora自带有minicom 此步可
  • shell 守护进程之 mongodb

    场景 因为某些原因 mongodb 挂掉了 需要重启 思路 写个守护进程脚本 每分钟查看mongodb状态 这里查看mongodb进程是否存在 如果挂掉就重启 执行 1 创建sh文件 mkdir p data wwww guard mong
  • it技术交流社区与学习资料的网站大全

    点击上方蓝字 优派编程 选择 加为星标 第一时间关注原创干货 对国内技术社区 博客园 https www cnblogs com 掘金 https juejin cn 思否 https segmentfault com 开源中国 https
  • Ubuntu18.04升级到20.04

    升级方式 命令行升级 正常情况下使用如下命令即可 sudo do release upgrade 当提示如下错误信息时 得先升级本地软件包 Please install all available updates for your rele
  • 区块链的简单实现

    区块链的简单实现 什么是区块链 块结构 创世区块 hash 验证块的有效性 记录数据 从其他节点接收一个块 编写测试代码 测试结果 完整代码 什么是区块链 一个维护着一个持续增长的有序数据记录列表的这么一个分布式数据库 下面我将简单用nod
  • 玩转X-CTR100 l STM32F4 l U-Blox NEO-6M GPS卫星定位-nmealib解码库移植解码

    我造轮子 你造车 创客一起造起来 塔克创新资讯 塔克社区 www xtark cn 塔克博客 www cnblogs com xtark 本文介绍X CTR100控制器 扩展GPS卫星定位模块 型号为GY GPS6MV2 使用U BLOX
  • 数据库连接自动断开:CJCommunicationsException

    报错信息 com mysql cj exceptions CJCommunicationsException The last packet successfully received from the server was 99 117
  • JavaSE基础知识(个人总结)

    声明 1 本文为我的个人复习总结 并非那种从零基础开始普及知识 内容详细全面 言辞官方的文章 2 由于是个人总结 所以用最精简的话语来写文章 3 若有错误不当之处 请指出 基础 杂记 JRE JVM 常用类库 JDK JRE 诸多工具 如j
  • vue 循环遍历 搜寻资料

    写vue 循环遍历的 大全例子解释 转载连接 https www cnblogs com xulei1992 p 6015416 html https www jqhtml com 49765 html https blog csdn ne
  • mysql truncate语句_MySQL DELETE语句和TRUNCATE TABLE语句的区别

    在MySQL数据库中 DELETE语句和TRUNCATE TABLE语句都可以用来删除数据 但是这两种语句还是有着其区别的 下文就为您介绍这二者的差别所在 MySQL DELETE语句和TRUNCATE TABLE语句功能相似 但是二者究竟
  • Unity 游戏入门 九、 精灵动画 Sprite Animation

    1 Animator 为了在游戏对象上有动画 需要添加一个组件Animator 在工程窗口中 双击Robot 预制体 如图所示 添加Animator组件 2 Creating a New Controller 在工程窗口Animator文件
  • 分组排序取前几条之子查询和用户变量的使用

    关于一次面试的sql题 题目 在一张订单表中有三个字段 order id sale num type 类型有 衣服 鞋子 皮包 现在希望取出每种类型销量前三的记录 我在面试时候还想 啥 啥玩意 要我写单表的查询 看不起我 这不就是group
  • [QT编程系列-31]:多线程机制 - Qthread工作原理

    目录 一 Qthread工作原理 二 QThread的start 方法 三 QT 线程的生命周期 四 事件循环机制 五 QThread自带信号 六 如何在run函数中多次执行 七 QThread什么时候发送finished信号 八 为什么不
  • VS2019运行报错:引发了未经处理的异常:读取访问权限冲突。_Pnext 是 0xE。

    我们在运行VS2019代码时 报错如下信息 反复检查了代码 发现代码是没有问题的 我的代码如下 include
  • 用Java写一个五子棋小游戏

    棋盘是15 15 可以自己规定 游戏规则 1 对局双方各执一色棋子 2 空棋盘开局 3 黑先 白后 交替下子 每次只能下一子 4 棋子下在棋盘的空白点上 棋子下定后 不得向其它点移动 不得从棋盘上拿掉或拿起另落别处 5 黑方的第一枚棋子可下