使用swing实现简单的五子棋和五子棋人机对战


package wuziqi;

import java.awt.Color;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.ArrayList;
import java.util.List;

import javax.swing.ButtonGroup;
/**
 * 五子棋棋盘 
 * 20180108
 * @author howroad
 */
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JRadioButton;

public class FiveMap extends JFrame {
	/**
	 * 棋盘界面
	 * 
	 * @author howroad
	 * @version v1.4_20180110
	 *  未解决的问题: 悔棋之后小绿点不会智能的跳到该棋,悔棋有问题所以屏蔽了
	 */
	private static final long serialVersionUID = 1L;
	/**
	 * 以下两个值按照自己的需求更改
	 */
	private final static byte LENGTH = 25;// 棋盘大小(需要奇数,自适应可以直接修改)
	private final static int MYWIDTH = 800;// 棋盘高度(可以直接修改更改棋盘)

	private final static int LINEWIDTH = MYWIDTH / (LENGTH - 1);// 棋子行间距
	private final static int QIWIDTH = LINEWIDTH - 2;// (需要偶数)
	private byte[][] qi = new byte[LENGTH][LENGTH];// 棋盘大小

	private JPanel content = new JPanel(null);
	private JPanel left = new JPanel();
	private JPanel right = new JPanel();
	private JRadioButton[] rdb = new JRadioButton[4];// 单选按钮
	private ButtonGroup buttonGroup = new ButtonGroup();
	private String[] btnName = { "双人对战", "初级对战", "中级对战", "高级对战" };
	private JButton button1 = new JButton("开始");
	private JButton button2 = new JButton("悔棋");
	private byte selected = 0;// 储存单选按钮的选择状态 1代表第一个按钮被选中
	private byte color = 1;// 棋子颜色 0代表无子 1 代表黑棋 2代表白棋
	private int answerX = (LENGTH - 1) / 2;// 当前的下子
	private int answerY = (LENGTH - 1) / 2;// 当前下子
	private List<byte[][]> qis = new ArrayList<byte[][]>();// 棋子数组的集合 用于悔棋
	private boolean isStart = false;// 标志,用于判断游戏是否已经开始
	

	/**
	 * 构造函数
	 */
	public FiveMap() {
		// 添加单选按钮和按钮
		for (int i = 0; i < rdb.length; i++) {
			rdb[i] = new JRadioButton(btnName[i]);
			buttonGroup.add(rdb[i]);
			right.add(rdb[i]);
		}
		rdb[0].setSelected(true);
		right.add(button1);
		right.add(button2);
		// 设置棋盘的布局
		left.setBackground(new Color(90, 225, 90));
		left.setBounds(0, 0, MYWIDTH + 100, MYWIDTH + 100);
		right.setBounds(MYWIDTH + 100, 20, 100, MYWIDTH);
		content.add(left);
		content.add(right);
		this.add(content);
		this.setBounds(0, 0, MYWIDTH + 220, MYWIDTH + 80);
		this.setLocationRelativeTo(null);
		this.setResizable(false);
		this.setDefaultCloseOperation(EXIT_ON_CLOSE);
		this.addMouseListener(new MyMouseListener());
		// 添加开始按钮的监听器
		button1.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				selected = rdb[0].isSelected() ? 1 : selected;
				selected = rdb[1].isSelected() ? 2 : selected;
				selected = rdb[2].isSelected() ? 3 : selected;
				selected = rdb[3].isSelected() ? 4 : selected;
				isStart = true;
				init();
				if (selected == 3 || selected == 4 || selected == 2) {
					qi[answerX][answerY] = 1;
					color = 2;
				}
			}
		});
		// 添加悔棋按钮的监听器
		button2.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				if (qis.size() >= 1) {
					qis.remove(qis.size() - 1);
					if (qis.size() == 0) {
						init();
					} else {
						qi = qis.get(qis.size() - 1);
					}
					answerX = -1;
				}
				repaint();
			}

		});
		//暂时关闭悔棋
		button2.setEnabled(false);
		this.setTitle("五子棋byhowroadv1.0");
	}

	// 初始化棋子
	private void init() {
		for (int i = 0; i < LENGTH; i++) {
			for (int j = 0; j < LENGTH; j++) {
				qi[i][j] = 0;
			}
		}
		color = 1;
		qis.clear();
		answerX = (LENGTH - 1) / 2;
		answerY = (LENGTH - 1) / 2;
		repaint();
	}

	// 绘制棋盘
	public void paint(Graphics g) {
		super.paint(g);
		// 画棋盘
		for (int i = 0; i < LENGTH; i++) {
			g.drawLine(50, 50 + LINEWIDTH * i, 50 + LINEWIDTH * (LENGTH - 1), 50 + LINEWIDTH * i);
		}
		for (int i = 0; i < LENGTH; i++) {
			g.drawLine(50 + LINEWIDTH * i, 50, 50 + LINEWIDTH * i, 50 + LINEWIDTH * (LENGTH - 1));
		}
		int center = 50 + (LENGTH - 1) / 2 * LINEWIDTH - 4;
		g.fillOval(center, center, 8, 8);
		// 画棋
		for (int i = 0; i < qi.length; i++) {
			for (int j = 0; j < qi[i].length; j++) {
				if (qi[i][j] == 1) {// 画黑棋
					g.setColor(Color.BLACK);
					g.fillOval(50 + i * LINEWIDTH - QIWIDTH / 2, 50 + j * LINEWIDTH - QIWIDTH / 2, QIWIDTH, QIWIDTH);
				}
				if (qi[i][j] == 2) {// 画白棋
					g.setColor(Color.WHITE);
					g.fillOval(50 + i * LINEWIDTH - QIWIDTH / 2, 50 + j * LINEWIDTH - QIWIDTH / 2, QIWIDTH, QIWIDTH);
					g.setColor(Color.BLACK);
					g.drawOval(50 + i * LINEWIDTH - QIWIDTH / 2, 50 + j * LINEWIDTH - QIWIDTH / 2, QIWIDTH, QIWIDTH);
				}
			}
		}
		// 画小绿点
		g.setColor(Color.CYAN);
		g.fillOval(50 + answerX * LINEWIDTH - 3, 50 + answerY * LINEWIDTH - 3, 6, 6);
		g.setColor(Color.BLACK);
	}

	// 判断单选按钮选择的是哪一个并执行相应的操作
	public void choice(int choice) {
		// 双人对战
		if (choice == 1) {
			if (FiveRule3.isWin(qi, color, answerX, answerY)) {
				JOptionPane.showMessageDialog(null, color == 1 ? "黑棋获胜!" : "白棋获胜!");
				isStart = false;
				return;
			}
			color = (byte) (color == 1 ? 2 : 1);
		}
		// 初级对战
		if (choice == 2) {
			if (FiveRule3.isWin(qi, color, answerX, answerY)) {
				JOptionPane.showMessageDialog(null, color == 1 ? "黑棋获胜!" : "白棋获胜!");
				isStart = false;
				return;
			}
			color = (byte) (color == 1 ? 2 : 1);
			int[] result = FiveRule1.bestAnswer(qi, color);
			answerX = result[0];
			answerY = result[1];
			qi[answerX][answerY] = color;
			repaint();
			if (FiveRule3.isWin(qi, color, answerX, answerY)) {
				JOptionPane.showMessageDialog(null, color == 1 ? "黑棋获胜!" : "白棋获胜!");
				isStart = false;
				return;
			}
			color = (byte) (color == 1 ? 2 : 1);
		}
		// 中级对战
		if (choice == 3) {
			if (FiveRule3.isWin(qi, color, answerX, answerY)) {
				JOptionPane.showMessageDialog(null, color == 1 ? "黑棋获胜!" : "白棋获胜!");
				isStart = false;
				return;
			}
			color = (byte) (color == 1 ? 2 : 1);
			int[] result = FiveRule2.bestAnswer(qi, color);
			answerX = result[0];
			answerY = result[1];
			qi[answerX][answerY] = color;
			repaint();
			if (FiveRule3.isWin(qi, color, answerX, answerY)) {
				JOptionPane.showMessageDialog(null, color == 1 ? "黑棋获胜!" : "白棋获胜!");
				isStart = false;
				return;
			}
			color = (byte) (color == 1 ? 2 : 1);
		}

		// 高级对战
		if (choice == 4) {
			if (FiveRule3.isWin(qi, color, answerX, answerY)) {
				JOptionPane.showMessageDialog(null, color == 1 ? "黑棋获胜!" : "白棋获胜!");
				isStart = false;
				return;
			}
			color = (byte) (color == 1 ? 2 : 1);
			int[] result = FiveRule3.bestAnswer(qi, color);
			answerX = result[0];
			answerY = result[1];
			qi[answerX][answerY] = color;
			repaint();
			if (FiveRule3.isWin(qi, color, answerX, answerY)) {
				JOptionPane.showMessageDialog(null, color == 1 ? "黑棋获胜!" : "白棋获胜!");
				isStart = false;
				return;
			}
			color = (byte) (color == 1 ? 2 : 1);
		}
	}

	// 内部类,用于监听鼠标动作
	public class MyMouseListener extends MouseAdapter {
		public void mousePressed(MouseEvent e) {
			if (!isStart) {
				return;
			}
			// 将鼠标坐标转换为棋盘坐标
			answerX = Math.round((e.getX() - 50.0f) / LINEWIDTH);
			answerY = Math.round((e.getY() - 50.0f) / LINEWIDTH);
			// 判断是否再棋盘范围
			if (answerX < LENGTH && answerY < LENGTH) {
				// 判断此处是否有棋子
				if (qi[answerX][answerY] != 0) {
					return;
				}
				qi[answerX][answerY] = color;
				// 将本回合棋子放入棋子集合
				byte[][] qi2 = new byte[LENGTH][LENGTH];
				for (int i = 0; i < LENGTH; i++) {
					for (int j = 0; j < LENGTH; j++) {
						qi2[i][j] = qi[i][j];
					}
				}
				qis.add(qi2);
				repaint();
				choice(selected);
			} else {
				return;
			}
		}

	}

}


这个是静态方法

package wuziqi;

/**
 * @version 3.0
 */
import java.util.Arrays;
/**
 * 还有一种情况没有考虑到  一条横线构成44连这种情况(01_1_1_10)概率较小,暂时忽略
 * 活四和53重复时候有时候会出错,可能改好了
 * 有时候判断的分数并不是该子落下时能额外获得的分数
 */
import java.util.HashSet;
import java.util.Set;

import javax.swing.JOptionPane;

public class FiveRule3 {
	/**
	 * 用来判断求解范围,不至于全盘遍历浪费时间,判断范围为下子的矩形向外拓宽两格
	 * 
	 * @param qi 棋子的数组,下同
	 * @return XY坐标分别的最大值最小值
	 */
	private static int[] getRange(byte[][] qi) {
		int length = qi.length;
		int[] range = { -1, -1, -1, -1 };
		int minX = length;
		int minY = length;
		int maxX = -1;
		int maxY = -1;
		for (int i = 0; i < length; i++) {
			for (int j = 0; j < length; j++) {
				if (qi[i][j] == 0) {
					continue;
				}
				minX = minX < i ? minX : i;
				minY = minY < j ? minY : j;
				maxX = maxX > i ? maxX : i;
				maxY = maxY > j ? maxY : j;
			}
		}
		// 如果棋盘没有棋子
		if (maxX == -1) {
			return range;
		}
		// 判断求解范围(上下左右各向外2格)
		range[0] = minX < 2 ? 0 : minX - 2;
		range[1] = minY < 2 ? 0 : minY - 2;
		range[2] = maxX > length - 3 ? length - 1 : maxX + 2;
		range[3] = maxY > length - 3 ? length - 1 : maxY + 2;
		return range;
	}

	/**
	 * 求解最优解
	 * 
	 * @param qi 棋子的数组,下同
	 * @param color 颜色
	 * @return 棋子的坐标的数组
	 */
	public static int[] bestAnswer(byte[][] qi, int color) {
		int[] result = { -1, -1 };// 用来保存结果
		int length = qi.length;
		int[] range = getRange(qi);
		int minX = range[0];
		int minY = range[1];
		int maxX = range[2];
		int maxY = range[3];
		int[] maxScore = { -1, -1, -1 };// 用来保存分数

		for (int i = minX; i <= maxX; i++) {
			for (int j = minY; j <= maxY; j++) {
				if (qi[i][j] != 0) {
					continue;
				}
				// 获得该位置棋子的得分
				int nowScore = getScore(qi, color, i, j);
				if (maxScore[0] < nowScore) {
					maxScore[0] = nowScore;
					maxScore[1] = i;
					maxScore[2] = j;
				}
			}

		}
		if (maxScore[0] <= 2) {
			// System.out.println("随机下棋");
			if (qi[length / 2][length / 2] == 0) {
				result[0] = result[1] = length / 2;
				return result;
			}
			int loopnum = 0;
			do {
				result[0] = (int) (Math.random() * (maxX - minX) + minX);
				result[1] = (int) (Math.random() * (maxY - minY) + minY);
				if (++loopnum >= 5000) {
					JOptionPane.showMessageDialog(null, "你把电脑下崩了!");
					System.exit(0);
				}
			} while (qi[result[0]][result[1]] != 0);
			return result;
		}
		System.out.println("最高分数" + maxScore[0]);
		result[0] = maxScore[1];
		result[1] = maxScore[2];
		return result;
	}

	/**
	 * 获得该点的得分
	 * 
	 * @param qi
	 * @param color
	 * @param x
	 * @param y
	 * @return
	 */
	public static int getScore(byte[][] qi, int color, int x, int y) {
		int score = 0;
		int otherColor = color == 1 ? 2 : 1;
		// 直接胜利
		if (isWin(qi, color, x, y)) {
			return 100000;
		}
		if (isWin(qi, otherColor, x, y)) {
			return 90000;
		}

		Set<Integer> h4 = getTwoAliveFour(qi, color, x, y);// 活4
		Set<Integer> h3 = getTwoAliveThree(qi, color, x, y);// 活3
		Set<Integer> h2 = getTwoAliveTwo(qi, color, x, y);// 活二,差一步活三(包括01010不包括010010)
		Set<Integer> s4 = need1ToWin(qi, color, x, y);// 死四
		Set<Integer> s3 = need2ToWin(qi, color, x, y);// 死三,差两步5子
		boolean lh3 = lian3Alive(qi, color, x, y).size() > 0;// 连活3
		boolean ls4 = lian4Death(qi, color, x, y);// 连死4
		Set<Integer> otherh4 = getTwoAliveFour(qi, otherColor, x, y);// 活4
		Set<Integer> otherh3 = getTwoAliveThree(qi, otherColor, x, y);// 活3
		Set<Integer> otherh2 = getTwoAliveTwo(qi, otherColor, x, y);
		Set<Integer> others4 = need1ToWin(qi, otherColor, x, y);// 死四
		Set<Integer> others3 = need2ToWin(qi, otherColor, x, y);
		boolean otherlh3 = lian3Alive(qi, otherColor, x, y).size() > 0;// 连活3
		boolean otherls4 = lian4Death(qi, otherColor, x, y);// 连死4

		// 构成自己活四,双死四,死四活三(必胜),优先下活四
		if (h4.size() > 0 || s4.size() > 1
				|| s4.size() > 0 && h3.size() > 0 && (!s4.containsAll(h3) || !h3.containsAll(s4))) {
			score += 10000;
			if (h4.size() > 0) {
				score += 500;
			}
		}
		// 构成敌人活四,双死四,死四活三,如果自己有死四进攻棋就优先下,否则优先堵对方活四
		if (otherh4.size() > 0 || others4.size() > 1 || others4.size() > 0 && otherh3.size() > 0
				&& (!others4.containsAll(otherh3) || !otherh3.containsAll(others4))) {
			if (s4.size() > 0) {
				score += 500;
			}
			if (otherh4.size() > 0) {
				score += 200;
			}
			score += 9000;
		}

		// 自己双活三
		if (h3.size() > 1) {
			score += 100;
		}
		// 敌人双活三,如果自己有四个的可以试一下
		if (otherh3.size() > 1) {
			score += 90;
		}
		// 为了保证每个点的分数尽可能的不一样,多判断一些
		// 根据我的思路还应该满足h3+h2<lh3,s4+s3<ls4
		// ls4 > s4 > lh3 > h3 > otherlh3 > otherh3 > otherls4 > others4 > h2*2 >otherh2*2 > s3 > others3 > h2 > otherh2
		// 58	 50   46	40      35        30         25         20      10     8          7     6       5       4
		//这个分数的顺序可能不是很好,比如说死四和活三的分数 ,死三和活二的分数谁大谁小,见仁见智。
		// 连死四或者普通死四
		if (s4.size() > 0) {
			if (ls4) {
				score += 8;
			}
			score += 50;
			//score += 9200;//凶狠打法
		}
		// 连活三或普通活三
		if (s3.size() > 0) {
			if (lh3) {
				score += 39;
			} else if (h3.size() > 0) {
				score += 33;
			}
			score += 7 * s3.size();
		}

		// 敌人的连死四或者死四
		if (others4.size() > 0) {
			if (otherls4) {
				score += 5;
			}
			score += 20;
		}
		// 敌人的连活三或者活三
		if (others3.size() > 0) {
			if (otherlh3) {
				score += 29;
			} else if (otherh3.size() > 0) {
				score += 24;
			}
			score += 6 * others3.size();

		}
		// 剩余情况计算得分

		score += 5 * h2.size() + 4 * otherh2.size();
		return score;
	}

	/**
	 * 连死四,四子相连,且至少有一头为空
	 * 
	 * @param qi
	 * @param color
	 * @param x
	 * @param y
	 * @return 没有四子的情况返回null,有的话返回方向
	 */
	public static boolean lian4Death(byte[][] qi, int color, int x, int y) {
		int[] r1 = checkPoint1(qi, color, x, y);
		int[] r2 = checkPoint2(qi, color, x, y);
		int[] r3 = checkPoint3(qi, color, x, y);
		int[] r4 = checkPoint4(qi, color, x, y);
		// Set<Integer> result = new HashSet<Integer>();
		if (r1[0] == 4 && (r1[2] == 0 || r1[3] == 0)) {
			return true;
		}
		if (r2[0] == 4 && (r2[2] == 0 || r2[3] == 0)) {
			return true;
		}
		if (r3[0] == 4 && (r3[2] == 0 || r3[3] == 0)) {
			return true;
		}
		if (r4[0] == 4 && (r4[2] == 0 || r4[3] == 0)) {
			return true;
		}
		return false;
	}

	/**
	 * 连活三:三子相连,两头为空
	 * 
	 * @param qi
	 * @param color
	 * @param x
	 * @param y
	 * @return 没有四子的情况返回null,有的话返回方向
	 */
	public static Set<Integer> lian3Alive(byte[][] qi, int color, int x, int y) {
		int[] r1 = checkPoint1(qi, color, x, y);
		int[] r2 = checkPoint2(qi, color, x, y);
		int[] r3 = checkPoint3(qi, color, x, y);
		int[] r4 = checkPoint4(qi, color, x, y);
		Set<Integer> result = new HashSet<Integer>();
		if (r1[0] == 3 && r1[2] == 0 && r1[3] == 0) {
			result.add(1);
		}
		if (r2[0] == 3 && r2[2] == 0 && r2[3] == 0) {
			result.add(2);
		}
		if (r3[0] == 3 && r3[2] == 0 && r3[3] == 0) {
			result.add(3);
		}
		if (r4[0] == 3 && r4[2] == 0 && r4[3] == 0) {
			result.add(4);
		}
		return result;
	}

	/**
	 * 差一个子构成活三,有可能是连活二,有可能是跳活二
	 * 
	 * @param qi
	 * @param color
	 * @param x
	 * @param y
	 * @return 返回哪个方向存在活二
	 */
	public static Set<Integer> getTwoAliveTwo(byte[][] qi, int color, int x, int y) {
		// 新建一个棋子的副本
		int length = qi.length;
		byte[][] temp = new byte[length][length];
		for (int i = 0; i < qi.length; i++) {
			for (int j = 0; j < qi[i].length; j++) {
				temp[i][j] = qi[i][j];
			}
		}
		Set<Integer> result = new HashSet<Integer>();
		temp[x][y] = (byte) color;
		int[] range = getRange(temp);
		int minX = range[0];
		int minY = range[1];
		int maxX = range[2];
		int maxY = range[3];
		for (int i = minX; i <= maxX; i++) {
			for (int j = minY; j < maxY; j++) {
				if (temp[i][j] != 0) {
					continue;
				}
				result.addAll(lian3Alive(temp, color, i, j));
			}
		}
		return result;
	}

	/**
	 * 活3(包括连活三和跳活三),即差一个子构成连活四
	 * 
	 * @param qi
	 * @param color
	 * @param x
	 * @param y
	 * @return 返回哪个方向存在活三
	 */
	public static Set<Integer> getTwoAliveThree(byte[][] qi, int color, int x, int y) {
		// 新建一个棋子的副本
		int length = qi.length;
		byte[][] temp = new byte[length][length];
		for (int i = 0; i < qi.length; i++) {
			for (int j = 0; j < qi[i].length; j++) {
				temp[i][j] = qi[i][j];
			}
		}
		Set<Integer> result = new HashSet<Integer>();
		temp[x][y] = (byte) color;
		int[] range = getRange(temp);
		int minX = range[0];
		int minY = range[1];
		int maxX = range[2];
		int maxY = range[3];
		for (int i = minX; i <= maxX; i++) {
			for (int j = minY; j < maxY; j++) {
				if (temp[i][j] != 0) {
					continue;
				}
				result.addAll(getTwoAliveFour(temp, color, i, j));
			}
		}
		return result;
	}

	/**
	 * 活四:相连四个子,并且两头为空
	 * 
	 * @param qi
	 * @param color
	 * @param x
	 * @param y
	 * @return 返回哪个方向存在活四
	 */
	public static Set<Integer> getTwoAliveFour(byte[][] qi, int color, int x, int y) {
		int[] r1 = checkPoint1(qi, color, x, y);
		int[] r2 = checkPoint2(qi, color, x, y);
		int[] r3 = checkPoint3(qi, color, x, y);
		int[] r4 = checkPoint4(qi, color, x, y);
		Set<Integer> result = new HashSet<Integer>();
		if (Arrays.equals(r1, new int[] { 4, 1, 0, 0 })) {
			result.add(1);
		}
		if (Arrays.equals(r2, new int[] { 4, 2, 0, 0 })) {
			result.add(2);
		}
		if (Arrays.equals(r3, new int[] { 4, 3, 0, 0 })) {
			result.add(3);
		}
		if (Arrays.equals(r4, new int[] { 4, 4, 0, 0 })) {
			result.add(4);
		}
		return result;

	}

	/**
	 * 三子的情况(包括死三活三跳3)
	 * 
	 * @param qi
	 * @param color
	 * @param x
	 * @param y
	 * @return 没有四子的情况返回null,有的话返回方向
	 */
	public static Set<Integer> need2ToWin(byte[][] qi, int color, int x, int y) {
		// 新建一个棋子的副本
		int length = qi.length;
		byte[][] temp = new byte[length][length];
		for (int i = 0; i < qi.length; i++) {
			for (int j = 0; j < qi[i].length; j++) {
				temp[i][j] = qi[i][j];
			}
		}
		Set<Integer> result = new HashSet<Integer>();
		temp[x][y] = (byte) color;
		int[] range = getRange(temp);
		int minX = range[0];
		int minY = range[1];
		int maxX = range[2];
		int maxY = range[3];
		for (int i = minX; i <= maxX; i++) {
			for (int j = minY; j < maxY; j++) {
				if (temp[i][j] != 0) {
					continue;
				}
				result.addAll(need1ToWin(temp, color, i, j));
			}
		}
		return result;
	}

	/**
	 * 差一个子构成五子,活长连,不包括被封死的死四
	 * 
	 * @param qi
	 * @param color
	 * @param x
	 * @param y
	 * @return 没有四子的情况返回null,有的话返回方向
	 */
	public static Set<Integer> need1ToWin(byte[][] qi, int color, int x, int y) {
		// 新建一个棋子的副本
		int length = qi.length;
		byte[][] temp = new byte[length][length];
		for (int i = 0; i < qi.length; i++) {
			for (int j = 0; j < qi[i].length; j++) {
				temp[i][j] = qi[i][j];
			}
		}
		Set<Integer> result = new HashSet<Integer>();
		temp[x][y] = (byte) color;
		int[] range = getRange(temp);
		int minX = range[0];
		int minY = range[1];
		int maxX = range[2];
		int maxY = range[3];
		for (int i = minX; i <= maxX; i++) {
			for (int j = minY; j < maxY; j++) {
				if (temp[i][j] != 0) {
					continue;
				}
				if (checkPoint1(temp, color, i, j)[0] >= 5) {
					result.add(1);
				}
				if (checkPoint2(temp, color, i, j)[0] >= 5) {
					result.add(2);
				}
				if (checkPoint3(temp, color, i, j)[0] >= 5) {
					result.add(3);
				}
				if (checkPoint4(temp, color, i, j)[0] >= 5) {
					result.add(4);
				}
			}
		}
		return result;
	}

	/**
	 * 该子落下胜利
	 * 
	 * @param qi
	 * @param color
	 * @param x
	 * @param y
	 * @return
	 */
	public static boolean isWin(byte[][] qi, int color, int x, int y) {
		return checkPoint1(qi, color, x, y)[0] >= 5 || checkPoint2(qi, color, x, y)[0] >= 5
				|| checkPoint3(qi, color, x, y)[0] >= 5 || checkPoint4(qi, color, x, y)[0] >= 5;

	}

	/**
	 * 传入棋子数组/颜色/坐标,分析这个点(这是分析的第一步)(下同)
	 * 
	 * @param qi
	 *            传入的棋子数组
	 * @param color
	 *            需要分析的改点的颜色
	 * @param x
	 *            该点的横坐标
	 * @param y
	 *            该点的纵坐标
	 * @return result[1/2/3/4]分别表示该子落下后:相连的棋子个数/判断的方向/两边棋子的状态0表示无子,-1表示边界或者其他颜色的棋子
	 */
	public static int[] checkPoint1(byte[][] qi, int color, int x, int y) {
		int[] result = { -1, -1, -1, -1 };// 将结果放在这个数组里
		int length = qi.length;// 用来保存棋盘的长
		int flag = 1;// 用来计数
		int tempX = x;// 用来参与判断的坐标
		int tempY = y;
		while (true) {// 向左边依次判断
			tempX--;
			if (tempX < 0 || tempX > length - 1) {// 遇到棋盘边缘
				result[2] = -1;
				break;
			}
			if (qi[tempX][tempY] == 0) {// 遇到空位置
				result[2] = 0;
				break;
			}
			if (qi[tempX][tempY] == color) {// 遇到相同颜色
				flag++;
				continue;
			}
			result[2] = -1;// 遇到不同颜色
			break;
		}
		tempX = x;
		tempY = y;
		while (true) {// 向左边依次判断
			tempX++;
			if (tempX < 0 || tempX > length - 1) {// 遇到棋盘边缘
				result[3] = -1;
				break;
			}
			if (qi[tempX][tempY] == 0) {// 遇到空位置
				result[3] = 0;
				break;
			}
			if (qi[tempX][tempY] == color) {// 遇到相同颜色
				flag++;
				continue;
			}
			result[3] = -1;// 遇到不同颜色
			break;
		}
		result[0] = flag;
		result[1] = 1;
		// System.out.println(""+result[0]+result[1]+result[2]+result[3]);
		return result;
	}

	public static int[] checkPoint2(byte[][] qi, int color, int x, int y) {
		int[] result = { -1, -1, -1, -1 };// 将结果放在这个数组里
		int length = qi.length;// 用来保存棋盘的长
		int flag = 1;// 用来计数
		int tempX = x;// 用来参与判断的坐标
		int tempY = y;
		while (true) {// 向左边依次判断
			tempY--;
			if (tempY < 0 || tempY > length - 1) {// 遇到棋盘边缘
				result[2] = -1;
				break;
			}
			if (qi[tempX][tempY] == 0) {// 遇到空位置
				result[2] = 0;
				break;
			}
			if (qi[tempX][tempY] == color) {// 遇到相同颜色
				flag++;
				continue;
			}
			result[2] = -1;// 遇到不同颜色
			break;
		}
		tempX = x;
		tempY = y;
		while (true) {// 向左边依次判断
			tempY++;
			if (tempY < 0 || tempY > length - 1) {// 遇到棋盘边缘
				result[3] = -1;
				break;
			}
			if (qi[tempX][tempY] == 0) {// 遇到空位置
				result[3] = 0;
				break;
			}
			if (qi[tempX][tempY] == color) {// 遇到相同颜色
				flag++;
				continue;
			}
			result[3] = -1;// 遇到不同颜色
			break;
		}
		result[0] = flag;
		result[1] = 2;
		// System.out.println(""+result[0]+result[1]+result[2]+result[3]);
		return result;
	}

	public static int[] checkPoint3(byte[][] qi, int color, int x, int y) {
		int[] result = { -1, -1, -1, -1 };// 将结果放在这个数组里
		int length = qi.length;// 用来保存棋盘的长
		int flag = 1;// 用来计数
		int tempX = x;// 用来参与判断的坐标
		int tempY = y;
		while (true) {// 向左边依次判断
			tempX--;
			tempY--;
			if (tempX < 0 || tempX > length - 1 || tempY < 0 || tempY > length - 1) {// 遇到棋盘边缘
				result[2] = -1;
				break;
			}
			if (qi[tempX][tempY] == 0) {// 遇到空位置
				result[2] = 0;
				break;
			}
			if (qi[tempX][tempY] == color) {// 遇到相同颜色
				flag++;
				continue;
			}
			result[2] = -1;// 遇到不同颜色
			break;
		}
		tempX = x;
		tempY = y;
		while (true) {// 向左边依次判断
			tempX++;
			tempY++;
			if (tempX < 0 || tempX > length - 1 || tempY < 0 || tempY > length - 1) {// 遇到棋盘边缘
				result[3] = -1;
				break;
			}
			if (qi[tempX][tempY] == 0) {// 遇到空位置
				result[3] = 0;
				break;
			}
			if (qi[tempX][tempY] == color) {// 遇到相同颜色
				flag++;
				continue;
			}
			result[3] = -1;// 遇到不同颜色
			break;
		}
		result[0] = flag;
		result[1] = 3;
		// System.out.println(""+result[0]+result[1]+result[2]+result[3]);
		return result;
	}

	public static int[] checkPoint4(byte[][] qi, int color, int x, int y) {
		int[] result = { -1, -1, -1, -1 };// 将结果放在这个数组里
		int length = qi.length;// 用来保存棋盘的长
		int flag = 1;// 用来计数
		int tempX = x;// 用来参与判断的坐标
		int tempY = y;
		while (true) {// 向左边依次判断
			tempX--;
			tempY++;
			if (tempX < 0 || tempX > length - 1 || tempY < 0 || tempY > length - 1) {// 遇到棋盘边缘
				result[2] = -1;
				break;
			}
			if (qi[tempX][tempY] == 0) {// 遇到空位置
				result[2] = 0;
				break;
			}
			if (qi[tempX][tempY] == color) {// 遇到相同颜色
				flag++;
				continue;
			}
			result[2] = -1;// 遇到不同颜色
			break;
		}
		tempX = x;
		tempY = y;
		while (true) {// 向左边依次判断
			tempX++;
			tempY--;
			if (tempX < 0 || tempX > length - 1 || tempY < 0 || tempY > length - 1) {// 遇到棋盘边缘
				result[3] = -1;
				break;
			}
			if (qi[tempX][tempY] == 0) {// 遇到空位置
				result[3] = 0;
				break;
			}
			if (qi[tempX][tempY] == color) {// 遇到相同颜色
				flag++;
				continue;
			}
			result[3] = -1;// 遇到不同颜色
			break;
		}
		result[0] = flag;
		result[1] = 4;
		// System.out.println(""+result[0]+result[1]+result[2]+result[3]);
		return result;
	}

}
描述文件
/**
 * 五子棋小游戏
 * FiveRule1和FiveRule2和FiveRule3是三个版本的静态方法.
 * 第三个的思路和注释都比较清晰,前两个应该被抛弃.
 * 但是由于对活二活三的得分设置不太好,不如第二个版本激进.导致实际上,第三个版本不如第二个版本的表现.
 * 
 */
/**
 * @author howroad
 * @version v1.4
 */
package wuziqi;



  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值