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(),是否有获胜者,和棋 结束 yes no yes no
分析代码

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个那就说明已经赢了。

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
乘三对弈时,可由对弈双方中任意一方持任黑色子先下,另一方持另白色子后下,并交替进行;对弈过程中,分为放和走两个阶段,下面分别介绍: 第一阶段:放   开局时,先下一方在盘中任一下棋点上放一子,后下一方再在先下一方放点以外的其他下棋点上放一子,依次循环,轮流放子,在放子过程中,如果有一方的三个子成一线(即为成三)时,成三的一方可以吃掉另一方的一枚非成三的子(如果对方的子全部都是成三状态,那就可以吃掉对方任意一颗子)。然后由被吃方继续下子。直到双方手中无子(先下一方必先于后下一方无子)。   成三:当一方的三枚子成一线(即纵线或横线的三个下棋点上为同一色子)时,该方成三;得到成三的一方可吃掉对方的一枚子;然后由对方继续下棋。   需注意的是:一方成三吃掉对方的子后,在放阶段接下来的一段时间内,任何一方均不得再将子放在被吃掉子的那个下棋点上,直到走阶段开始。   第二阶段:走   走阶段开始于放阶段结束,双方手中均已无子时。由先放完一方先走子每次只能向周边空的位移动一步;对弈双方轮流。成三时与放阶段成三一样。   开三:当一方的子再走一步就能成三时,称为开三。   输赢判断:   1、当盘上一方的子数少于3个时,即没有成三的可能时,局终,盘上多一方为胜方,少一方为负方。   2、当盘上一方的子都无法移动时,局终,子无法移动的一方为负方。另外一方为胜方。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值