java實現多子棋(五子棋,三子棋等)

問題分析

咱們想作一個輸入一個n,咱們就創建n子棋,條件是n>=3,創建的棋盤爲(長寬都爲爲n-2)*n的棋盤。下棋時,X先下,O後下,知道一方取勝,或者爲和棋。java

效果

在這裏插入圖片描述

代碼

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循環(開始時的條件;循環成立的條件;每次循環的變化)web

如何判斷的多子共線

咱們接收到下棋者輸入的,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個那就說明已經贏了。svg