java--五子棋初级版(自定义规则,模拟人机对战)

用java打个五子棋,主要理清思路就很简单了,还有就是规则的制定。

完成一个人机对战的五子棋项目,基本效果如下:

在这里插入图片描述

第一部分 Java绘图原理
1.基本概念
像素,坐标

2.组件自定义绘图原理
参见:https://www.cnblogs.com/leier/archive/2012/03/31/2426520.html
3.Graphics对象的常用方法
setFont(), setColor(), drawLine(), drawString(), drawOval(), drawRect(), fillOval(), fillRect(), drawImage()

第二部分 绘制棋盘
1.基本思路
在一个JPanel上绘制一个背景,然后绘制水平和垂直的若干条线,使其构成等距离的格子,通常是15*15(条线)。
2.代码实现
(1)主类代码:
在这里插入图片描述
(2) ChessPanel代码:
在这里插入图片描述

第三部分 绘制棋子
1.基本思路
使用drawOval()可以绘制空心的圆,使用fillOval()可以填充实心的圆。

2.坐标计算
由于格子是水平和垂直的有下标的,而绘制时需要使用实际的像素坐标,所以,需要进行行列下标到像素坐标的转换:
int x = col * GRID_WIDTH;
int y = row * GRID_WIDTH;

3.代码实现
(1)ChessPanel代码:
在这里插入图片描述

第四部分 鼠标下棋
1.基本思路
需要处理鼠标单点事件,获取鼠标所在的位置,然后计算出应该绘制棋子的行列下标,并使用一个二维数组来全局存储棋子的位置。

2.鼠标位置与行列下标计算
int x = e.getX();
int y = e.getY();
int row = y / GRID_WIDTH;
int col = x / GRID_WIDTH;
3.代码实现
(1) ChessPanel属性和构造方法代码:
在这里插入图片描述

(2)监听器类(内部类)代码:
在这里插入图片描述

(3)绘图代码:

在这里插入图片描述

第五部分 判断胜负
1.基本思路
判断胜负是因为在当前位置(row, col)落子导致了胜负,所以,判断胜负其实是在当前落子位置为中心,横向搜索左边第4个位置开始到右边第4个位置(其余位置不需要考虑),或者从上到下,或者正向45度,或者反向45度位置。

2.处理方法
处理方法有很多,可以采用计数的方式,也可以采用字符串连接的方式,此处采用了将从左边第4颗开始,到右边第4颗结束,将每颗的颜色表示成字符1(黑色)或者2(白色),只需要判断其中是否有连续的5个1或5个2,即“11111”或“22222”即可知道胜负。

3.代码实现
(1)监听器类(内部类)代码:
在这里插入图片描述

(2)checkWin判断胜负的代码:

/** 判断胜负
* @param row 落子的行下标
* @param col 落子的列下标
* @return 是否获胜,true-是,false-否
*/
public boolean checkWin(int row, int col) {}

在这里插入图片描述

在这里插入图片描述

(3)重置游戏状态

在这里插入图片描述

第六部分 人机对战
1.基本思路
当人点了鼠标落子以后,轮到电脑下棋,电脑的基本思想就是,在棋盘的空白处的每个位置,进行判断,当前位置的进攻指数和防守指数分别为多少,在进攻指数和防守指数中取一个较大值作为当前位置的评估值,在整个棋盘的所有空白处找到一个最大值,最大值的那个位置即为应该落子的位置。

2.某个位置的进攻指数和防守指数的评估方法
可以参见:https://www.cnblogs.com/songdechiu/p/5768999.html
本例中简化此问题,依据第五部分中胜负判断的方式,对连续9个位置形成的字符串进行搜索、评分,得出一个评估方案。如“11111”代表连续5个黑色,评分100,“011110”代表连续4个黑色,两端为空位置,评分90……。

3.代码实现
(1)监听器类(内部类)代码:

在这里插入图片描述

(2)电脑下棋的代码:

在这里插入图片描述

(3)评估关键参数代码:
在这里插入图片描述

(4) 评估方法代码:

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

下面见完整代码:

代码一:(使用直接在面板上绘色代表棋子,我分成两个java文件写的)

import java.awt.Color;
import java.awt.Container;

import javax.swing.JFrame;
import javax.swing.JPanel;

import org.omg.CORBA.PUBLIC_MEMBER;



//界面
public class MyFrame extends JFrame {
   
	public MyFrame(){
   
		this.setTitle("五子棋");
		this.setSize(630,650);
		Container cp = getContentPane();
		JPanel jPanel = new ChessBang();
		jPanel.setBackground(Color.orange);
		cp.add(jPanel);
		
		this.setDefaultCloseOperation(EXIT_ON_CLOSE);
		//)设置窗口相对于指定组件的位置。 如果组件当前未显示,或者 c 为 null,则此窗口将置于屏幕的中央
		this.setLocationRelativeTo(null);
		this.setDefaultCloseOperation(DISPOSE_ON_CLOSE);
		//设置窗口不可改变
		setResizable(false);
		
	}
	public static void main(String[] args) {
   
		JFrame frame = new MyFrame();
		frame.setVisible(true);
	}

}

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 javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JPanel;

//实现
public class ChessBang extends JPanel {
   
	public static final int GRID_WIDTH = 40;
	// 下棋的长度
	public static final int LINE_COUNT = 15;
	//光圈的点所在位置
	Point lastchessPoint = new Point(-1,-1);
	private String[] blackKey = {
    "11111", "011110", "11110", "01111", "11011",
			"10111", "11101", "01110", "11100", "00111",
			"0111", "1110","1011", "1101", "111",
			"01100", "00110", "011", "110", "11" };
	private String[] whiteKey = {
    "22222", "022220", "22220", "02222", "22022",
			"20222", "22202", "02220", "22200", "00222", "0222", "2220",
			"2022", "2202", "222", "02200", "00220", "022", "220", "22" };
	private int[] keyValues = {
    100, 90, 80, 80, 80, 80, 80, 70, 60, 60, 50,
			50, 50, 50, 40, 30, 30, 20, 20, 10 };
	private MouseListener listener = null;

	int[][] chessItems = new int[LINE_COUNT][LINE_COUNT];
	public boolean isBlack = true;// 记录成黑色的

	// 构造方法
	public ChessBang() {
   
		listener = new ChessListener();
		// 监听器
		this.addMouseListener(listener);
	}

	// 求点
	public class ChessListener extends MouseAdapter {
   
		public void mouseClicked(MouseEvent e) {
   
			int x = e.getX();
			int y = e.getY();
			int row = y / 40; // 不是x除
			int col = x / 40;
			// 在空处填棋子
			if (chessItems[row][col] == 0) {
   
				if (isBlack == true)
					chessItems[row][col] = 1;
				else
					chessItems[row][col] = 2;

				ChessBang.this.repaint();
				// 判输赢
				if (IsWin(row, col) == true) {
   
					JOptionPane.showMessageDialog(null, "你赢了!");
					reset();
					return;
				}
				// 这个放在后面的效率会更高
				isBlack = !isBlack;
				computer();
			}
		}
	}

	//
	public void computer() {
   
		// 落子的颜色
		int chesscomputer = isBlack ? 1 : 2;
		int t = 0;
		int rowcomputer = -1;
		int colcomputer = -1;
		for (int i = 0; i < LINE_COUNT; i++) {
   
			for (int j = 0; j < LINE_COUNT; j++) {
   
				if (chessItems[i][j] != 0)
					continue;
				int atack = checkMax(i, j, chesscomputer);
				int defend = checkMax(i, j, 3 - chesscomputer) - 1;
				int max = Math.max(atack, defend);
				if (max > t) {
   
					rowcomputer = i;
					colcomputer = j;
					t = max;
				}
			}
		}
		//记录位置
		lastchessdraw(rowcomputer, colcomputer);
		// 下棋
		chessItems[rowcomputer][colcomputer] = chesscomputer;
		
		isBlack = !isBlack;
		repaint();
		// 判输赢
		if (IsWin(rowcomputer, colcomputer) == true) {
   
			JOptionPane
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值