java实现多子棋(五子棋,三子棋等)

问题分析

我们想做一个输入一个n,我们就建立n子棋,条件是n>=3,建立的棋盘为(长宽都为为n-2)*n的棋盘。下棋时,X先下,O后下,知道一方取胜,或者为和棋。

效果

代码

package cn.ztl.eightEndOfChapter;

import java.util.Scanner;

public class newPrint {
	static boolean erro_xy = true;
	private static Scanner input;

	public static void main(String[] args) {
		int n = nPrint();
		play(n);
	}
  //输入函数
	private static int nPrint() {
		input = new Scanner(System.in);
		System.out.print("请输入想玩几子棋:");
		int n = input.nextInt();
		return n;
	}
	//游戏函数
	private static void play(int n) {
		char[][] _chessBoard = new char[(n - 2) * n][(n - 2) * n];
		CheckerBoard(n, _chessBoard);
	}

	private static void CheckerBoard(int n, char[][] qi) { // 棋盘
		// 第一次打印棋盘 ,没有棋子
		for (int i = 0; i < qi.length; i++) {
			for (int j = 0; j < qi.length; j++) {
				System.out.print("-----");
			}
			System.out.println();
			for (int j = 0; j < qi.length; j++) {
				System.out.print("|");
				System.out.print(" " + qi[i][j] + " ");
			}
			System.out.println("|");
		}
		for (int j = 0; j < qi.length; j++) {
			System.out.print("-----");
		}
		System.out.println();
		boolean times = true;//设置计数 看是白棋还是黑棋
		while (true) {//多次循环 每次为游戏者输入
			char[][] newQi;
			newQi = chessBoard(chessPlayer((n - 2) * n, times), qi, n, times);// 获得新棋谱
			if (newQi == null)//如果为null 那么结束游戏
				break;
			if (!erro_xy) {// 下棋处已经存在棋子,报错
				times = !times;
				erro_xy = true;
			}
			times = !times;//换棋子
			qi = newQi;// 转换身份
		}
	}

	private static int judgeToWin(int[] a, char[][] qi, int n, boolean times) {//判断玩家是否已经取胜或为和棋
		char temp = (times) ? 'X' : 'O';
		int DX[] = { 1, 0, 1, 1 };
		int DY[] = { 0, 1, 1, -1 };
		int c1, c2, xx, yy;
		for (int k = 0; k < 4; k++) {
			c1 = c2 = 0;
			for (xx = a[0] + DX[k], yy = a[1] + DY[k]; xx >= 0 && yy >= 0 && xx < qi.length && yy < qi.length
					&& qi[xx][yy] == temp; xx += DX[k], yy += DY[k]) {
				c1++;
			}
			for (xx = a[0] - DX[k], yy = a[1] - DY[k]; xx >= 0 && yy >= 0 && xx < qi.length && yy < qi.length
					&& qi[xx][yy] == temp; xx -= DX[k], yy -= DY[k]) {
				c2++;
			}
			if (c1 + c2 >= n - 1)
				return (times) ? 1 : 2;
		}
		return heqi(qi);
	}

	private static char[][] chessBoard(int[] a, char[][] newQi, int n, boolean times) {//将下棋人下的棋存入棋谱,并画新棋谱
		if (newQi[a[0]][a[1]] == '\u0000')
			newQi[a[0]][a[1]] = (times) ? 'X' : 'O';
		else {
			System.out.println("已经有棋子了,请重新输入");
			erro_xy = false;
		}
		for (int i = 0; i < newQi.length; i++) {
			for (int j = 0; j < newQi.length; j++) {
				System.out.print("----");
			}
			System.out.println();
			for (int j = 0; j < newQi.length; j++) {
				System.out.print("|");
				System.out.print(" " + newQi[i][j] + " ");
			}
			System.out.println("|");
		}
		for (int j = 0; j < newQi.length; j++) {
			System.out.print("----");
		}
		System.out.println();
		int key = judgeToWin(a, newQi, n, times);
		if (key == 1) {
			System.out.println("A棋手赢了");
			return null;
		} else if (key == 2) {
			System.out.println("B棋手赢了");
			return null;
		} else if (key == 3) {
			System.out.println("和棋");
			return null;
		} else {
			System.out.println();
		}
		return newQi;
	}

	private static int heqi(char[][] qi) {//和棋判断
		int sum = 0;
		for (int i = 0; i < qi.length; i++) {
			for (int j = 0; j < qi[i].length; j++) {
				if (qi[i][j] == '\u0000')
					sum++;
			}
		}
		if (sum == 0)
			return 3;
		else
			return 0;
	}

	private static int[] chessPlayer(int n, boolean times) {//下棋者 输入函数
		input = new Scanner(System.in);
		int[] a = new int[2];
		char temp = (times) ? 'A' : 'B';
		char temp2 = (times) ? 'X' : 'O';
		System.out.print("请棋手" + temp + "(" + temp2 + ")先下棋:x轴范围1-" + n + " :");
		a[0] = input.nextInt() - 1;
		System.out.print("请棋手" + temp + "(" + temp2 + ")先下棋:y轴范围1-" + n + " :");
		a[1] = input.nextInt() - 1;
		return a;
	}
}

Created with Raphaël 2.2.0主函数nPrint()输入函数play()函数,创造棋盘CheckerBoard()函数,输入棋,循环chessPlayer()函数,接收游戏者的下棋坐标chessBoard(),是否重棋,画新棋盘judgeToWin(),是否有获胜者,和棋结束yesnoyesno

分析代码

1.代码写的比较臃肿,因为还有事做,就先不简化了,有时间再做简化和图形化界面。
2.问题,很多东西可以写在方法外面的,一开始没想清楚就开写,导致最后不想改了。
3.我认为三目运算符很好用,再处理黑白棋时,如char temp2 = (times) ? ‘X’ : ‘O’;不管是打印时,还是在比较时,用它可以将黑棋白棋认为是一种棋。
4.用boolean 类型的,每次取反,可以表现两种相反的状态。
5.在计算多子同线问题时,要善用for循环(开始时的条件;循环成立的条件;每次循环的变化)

如何判断的多子共线

我们接收到下棋者输入的,xy坐标,放入坐标系中本来是要考虑8个方向,我们先考虑四个方向,当然还要考虑数组越界的情况,这四个方向都是xy坐标通过加0,加1,加-1可以到达的方向

	for (xx = a[0] + DX[k], yy = a[1] + DY[k]; xx >= 0 && yy >= 0 && xx < qi.length && yy < qi.length
					&& qi[xx][yy] == temp; xx += DX[k], yy += DY[k]) {
				c1++;
			}

而后面那个,考虑的是相反的四个方向刚好考虑完全。如果一条线上超过n-1个那就说明已经赢了。

相关推荐:

GraalVM 中 Java Map 与 Python 的双向互操作实践

本文详解如何在GraalVMPolyglot环境中安全、高效地将JavaMap传递给Python脚本,调用其方法获取值,并将处理结果(如新Map)返回Java,重点解决AttributeError:foreignobjecthasnoattribute'items'等常见互操作异常。 本文详解如何在...

PySpark Java Gateway Exited 错误的根源与解决方案

本文详解pyspark报错`[java_gateway_exited]javagatewayprocessexitedbeforesendingitsportnumber`的根本原因——虚拟环境(venv)隔离导致`java_home`和系统级java路径未被正确继承,并提供可落地的修复步骤与最佳实...

python与java用途区别有哪些

Python适合快速开发、数据科学、AI建模、轻量Web服务及自动化脚本;Java适合大型企业系统、Android开发、高并发中间件及需长期稳定维护的场景。 Python和Java虽然都能做通用开发,但实际用起来分工很明确——不是“哪个更好”,而是“谁更合适”。关键看你要解决什么问题、在什么环境里跑...

Python配置文件加载_ini与json解析【教程】

应根据实际需求选择:ini适合分节、带注释的简单配置(如数据库连接),用configparser读取;json适合嵌套复杂、跨语言共享的配置(如API参数),用json模块加载。 Python读取配置文件,ini和json是最常用的两种格式。选哪种不取决于“哪个更好”,而要看实际需求:ini更适合分...

redis怎么使用java

使用redisjava库需:1.添加依赖(jedis3.6.3);2.连接到redis服务器(指定主机和端口);3.进行基本操作(设置/获取值、检查键是否存在、删除键);4.执行复杂操作(哈希表、列表、集合、有序集合);5.发布/订阅消息(使用jedispubsub);6.关闭连接(jedis.cl...

10 对 -3 取余,结果是 1 还是 -2?Java 和 MySQL 的结果为何不同?

10对-3取余结果:1还是-2? 问题: 对-3取余时,10的余数是1还是-2?使用java和mysql计算得出的结果不同,这是否意味着这些函数存在错误? 答案: 余数正负 余数可以是正数,也可以是负数。数学上计算余数的公式为:余数=被除数-向下取整(被除数/除数)*除数根据该公式,10对-3取余的...