Java基本功練習九(多維數組強化一[五子棋、九個正面和背面、矩陣相乘])

       多維數組可以解決很多複雜的問題,比如本例的五子棋就是其中一種,雖然九個正面和背面遊戲有些簡單,但還是自己動手設計,熟悉下多維數組的用法。另外,矩陣相乘作爲這篇博文的開篇,一是爲了複習多維數組,二是爲了給五子棋練習基本功,本博文重點在五子棋

       示例一:矩陣相乘。(複習數組的使用)顯示相乘的a和b矩陣,運算後顯示c矩陣的結果。

運行效果如圖:

如下是實現源代碼:

package Blog;

import java.util.Scanner;

public class blogTryProject{
	public static void main(String[]args){
		double[][] a = new double[3][3];
		double[][] b = new double[3][3];
		double[][] c = new double[3][3];
		a = create(a);
		b = create(b);
		System.out.println("a矩陣爲:");
		print(a);
		System.out.println("b矩陣爲:");
		print(b);
		c = multiplyMatrix(a,b);
		System.out.println("a * b 的結果爲:");
		print(c);
	}
	public static void print(double[][] c){
		for(int i = 0;i < c.length;i++){
			for(int j = 0;j < c[0].length;j++)
				System.out.printf("%4.1f  ",c[i][j]);
			System.out.println();
		}
	}
	public static double[][] create(double[][] num){
		for(int i = 0;i < num.length;i++)
			for(int j = 0;j < num[0].length;j++)
				num[i][j] = (Math.random()*10);
		return num;
	}
	public static double[][] multiplyMatrix(double[][] a,double[][] b){
		double[][] c = new double[a.length][a[0].length];
		for(int i = 0;i < c.length;i++)
			for(int j = 0;j < c[0].length;j++)
				for(int k = 0;k < c.length;k++)
					c[i][j] += a[i][k] * b[k][j];
		return c;
	}
}
       示例二:九個正面和背面遊戲。一個3X3的矩陣中放了9個硬幣,這些硬幣有些面向上,有些面向下。可以使用3X3矩陣中的0(正面)或1(反面)便是硬幣的狀態。下面是一些列子:

每個狀態都可以使用一個二進制數表示。例如前面的矩陣對應到數字爲:

總共有512中可能。可以使用十進制數0,1,2,...,511來表示這個矩陣的所有狀態。編寫程序,提示用戶輸入一個在0到511之間的數字,然後顯示用字符H和T表示對應的矩陣。運行效果如下圖所示:

        這個示例沒什麼技術難點,無非就是幾次數據的轉換,寫對對應關係的語句就可以了,只是作爲數組的練習。示例三才是本文重點。
實現源代碼如下:

package Blog;

import java.util.Scanner;

import java.util.Arrays;

public class blogTryProject {
	//九個正面和背面的遊戲
	public static void main(String[]args){
		Scanner input = new Scanner(System.in);
		System.out.print("Enter the number of 0 ~ 511 : ");
		int number = input.nextInt();
		int n = 0;
		int[] num = new int[9];
		while(number != 0){
			num[n++] = number % 2;
			number /= 2;
		}
		int nn = 8;
		char[][] state = new char[3][3];
		for(int i = 0;i < 3;i++){
			for(int j = 0;j < 3;j++){
				if(num[nn--] == 1)
					state[i][j] = 'T';
				else
					state[i][j] = 'H';
				System.out.print(state[i][j]+"  ");
			}
			System.out.println();
		}
	}
}
        示例三:五子棋遊戲(控制檯形式)。以控制檯的形式顯示棋盤,每下一顆子,刷新一次棋盤。要求只能用基本數據類型數組和循環實現!編寫程序,每次提示玩家輸入所下棋子的座標,如“12”表示第一行第二列下子,直到一方勝出,遊戲結束。如果棋盤下滿了棋子而沒有分出勝負,則顯示平局!(本例是8路棋盤的五子棋)


運行效果如下圖所示:


實現的源代碼如下所示:
package wuziqi;

import java.util.Scanner;

//五子棋遊戲
public class wuziqi {
	public static void main(String[]args){
		Scanner input = new Scanner(System.in);
		final int ROW = 8;//棋盤大小
		final int COLUMN = 8;
		final int NUMBER_OF_WIN = 5;//相連的棋子數
		int count = 0;//該誰下棋子判斷標誌
		String x = "| X ";//玩家X標誌
		String o = "| O ";//玩家O標誌
		String yuanShiYuSu = "|   ";//數組初始值
		String[][] qi = new String[ROW][COLUMN];//創建數組
		
		for(int i = 0;i < qi.length;i++)//數組初始化
			for(int j = 0;j < qi[0].length;j++)
				qi[i][j] = yuanShiYuSu;
		int row = 0,column = 0;//下棋時輸入的行列初始值
		
		
		//畫出棋盤
		for(int i = 0;i < ROW;i++)
			System.out.print(" *"+(i+1)+" ");
		System.out.println();
		for(int i = 0;i < ROW;i++){
			System.out.println(" ---------------------------------");
			System.out.print((i+1));
			for(int j = 0;j < COLUMN;j++){
				System.out.print(qi[i][j]);
			}
			System.out.println("|");
		}
		System.out.println(" ---------------------------------");
		
		//下棋循環開始
		while(true){
			if(count % 2 == 0){//判斷該誰下子
				boolean flag = true;//X的輸入控制
				while(flag){
					System.out.print("Enter row(1~8) and "
							+ "column(1~8) for player X:");
					int number = input.nextInt();
					row = number / 10;
					column = number % 10;
					//輸入合法性判斷
					if(row >=1 && row <=ROW && column >=1 && column <=COLUMN){
						if(qi[row-1][column-1] == yuanShiYuSu)
						{qi[row-1][column-1] = x;flag = false;}
						else
							System.out.println("You enter the row position! reEnter.");
					}
					else
						System.out.println("You enter the row position! reEnter.");
				}
			}//if結束
			else{
				boolean flag = true;//O的輸入控制
				while(flag){
					System.out.print("Enter row(1~8) and "
							+ "column(1~8) for player O:");
					int number = input.nextInt();
					row = number / 10;
					column = number % 10;
					//輸入合法性判斷
					if(row >=1 && row <=ROW && column >=1 && column <=COLUMN){
						if(qi[row-1][column-1] == yuanShiYuSu)
						{qi[row-1][column-1] = o;flag = false;}
						else
							System.out.println("You enter the row position! reEnter.");
					}
					else
						System.out.println("You enter the row position! reEnter.");
				}
			}//else結束
			
			count++;//棋子計數增加,用以判斷誰輸入棋子
			
			//畫出棋盤
			for(int i = 0;i < ROW;i++)
				System.out.print(" *"+(i+1)+" ");
			System.out.println();
			for(int i = 0;i < ROW;i++){
				System.out.println(" ---------------------------------");
				System.out.print((i+1));
				for(int j = 0;j < COLUMN;j++){
					System.out.print(qi[i][j]);
				}
				System.out.println("|");
			}
			System.out.println(" ---------------------------------");
			
			
			//是否贏了誰贏了
			boolean flagForXWin = false;
			boolean flagForOWin = false;
			
			//正對角檢測
			for (int i = 0; i < ROW - (NUMBER_OF_WIN -1); i++) {
				for (int j = 0; j < COLUMN - (NUMBER_OF_WIN - 1); j++) {
					if (qi[i][j] == x && qi[i + 1][j + 1] == x
							&& qi[i + 2][j + 2] == x
							&& qi[i + 3][j + 3] == x
							&& qi[i + 4][j + 4] == x)
						flagForXWin = true;
					else if (qi[i][j] == o && qi[i + 1][j + 1] == o
							&& qi[i + 2][j + 2] == o
							&& qi[i + 3][j + 3] == o
							&& qi[i + 4][j + 4] == o)
						flagForOWin = true;
					if(flagForXWin || flagForOWin)
						break;
				}
			}
			if(flagForXWin || flagForOWin){
				if(flagForXWin)
				   System.out.println("X player Win!");
				else
				   System.out.println("O player Win!");
				break;
			}
			//正對角檢測結束
			
			//反對角檢測
			for (int i = 0; i < ROW - (NUMBER_OF_WIN -1); i++) {
				for (int j = COLUMN - 1; j >= COLUMN - (NUMBER_OF_WIN - 1); j--) {
					if (qi[i][j] == x && qi[i + 1][j - 1] == x
							&& qi[i + 2][j - 2] == x
							&& qi[i + 3][j - 3] == x
							&& qi[i + 4][j - 4] == x)
						flagForXWin = true;
					else if (qi[i][j] == o && qi[i + 1][j - 1] == o
							&& qi[i + 2][j - 2] == o
							&& qi[i + 3][j - 3] == o
							&& qi[i + 4][j - 4] == o)
						flagForOWin = true;
					if(flagForXWin || flagForOWin)
						break;
				}
			}
			if(flagForXWin || flagForOWin){
				if(flagForXWin)
				   System.out.println("X player Win!");
				else
				   System.out.println("O player Win!");
				break;
			}
			//反對角檢測結束
			
			
			//行檢測開始
			flagForXWin = false;
			flagForOWin = false;
			for(int i = 0;i < qi.length;i++){
				for(int j = 0;j < qi[0].length - (NUMBER_OF_WIN - 1);j++){
					if(qi[i][j] == x && qi[i][j + 1] == x
							&& qi[i][j + 2] == x
							&& qi[i][j + 3] == x
							&& qi[i][j + 4] == x)
							flagForXWin = true;
					else if(qi[i][j] == o && qi[i][j + 1] == o
							&& qi[i][j + 2] == o
							&& qi[i][j + 3] == o
							&& qi[i][j + 4] == o)
							flagForOWin = true;
					if(flagForXWin || flagForOWin)
						break;
				}
			}
			if(flagForXWin || flagForOWin){
				if(flagForXWin)
				   System.out.println("X player Win!");
				else
				   System.out.println("O player Win!");
				break;
			}
			//行檢測結束
			
			//列檢測開始
			flagForXWin = false;
			flagForOWin = false;
			for(int j = 0;j < qi.length;j++){
				for(int i = 0;i < qi[0].length- (NUMBER_OF_WIN - 1);i++){
					if(qi[i][j] == x && qi[i+1][j] == x
							&& qi[i+2][j] == x
							&& qi[i+3][j] == x
							&& qi[i+4][j] == x)
							flagForXWin = true;
					else if(qi[i][j] == o && qi[i+1][j] == o
							&& qi[i+2][j] == o
							&& qi[i+3][j] == o
							&& qi[i+4][j] == o)
							flagForOWin = true;
					if(flagForXWin || flagForOWin)
						break;
				}
			}
			if(flagForXWin || flagForOWin){
				if(flagForXWin)
				   System.out.println("X player Win!");
				else
				   System.out.println("O player Win!");
				break;
			}
			//列檢測結束
			
			//是否是平局的判斷
			if(count == ROW * COLUMN){
				if(!flagForXWin && !flagForOWin)
				{System.out.println("Nobody win!");break;}
			}
			//平局判斷結束
		}//下棋循環結束	
	}//方法塊結束	
}//類塊結束
        筆者也是初學者,所以寫的代碼方法比較直接,沒有考慮升級,並且編寫和調試了大半個下午,雖然有點曲折,但是收穫也是不小的。代碼中的註釋足夠詳細,所以請童鞋們學習完之後以完善以下功能多加練習!

        作爲練習,請改進上述五子棋的功能:1)提示輸入棋盤大小;2)提示1個玩家還是2個玩家,1個玩家則需要和電腦下棋(一種簡單的方法是產生隨機數模擬人的輸入);3)實時顯示玩家下了多少步棋;4)將五子棋改爲六子棋。

        如果學習完之後能將上述功能一一改進並實現沒有Bug,那就基本掌握了數組的用法。

        如果上述幾點都實現了,那麼請升級爲改進五子棋輸贏判斷方法:本篇博文五子棋的輸贏檢測方法是遍歷棋盤,每次輸入一顆新棋子都要遍歷棋盤,效率比較低。請改進爲只需判斷當前所下棋子周圍的情況來評定輸贏情況!

       如果還有餘力,可以考慮增加悔棋的功能!!!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章