Java基本功练习九(多维数组强化一[五子棋、九个正面和背面、矩阵相乘])

时间:2021-03-24 14:09:35

       多维数组可以解决很多复杂的问题,比如本例的五子棋就是其中一种,虽然九个正面和背面游戏有些简单,但还是自己动手设计,熟悉下多维数组的用法。另外,矩阵相乘作为这篇博文的开篇,一是为了复习多维数组,二是为了给五子棋练习基本功,本博文重点在五子棋

       示例一:矩阵相乘。(复习数组的使用)显示相乘的a和b矩阵,运算后显示c矩阵的结果。

运行效果如图:Java基本功练习九(多维数组强化一[五子棋、九个正面和背面、矩阵相乘])Java基本功练习九(多维数组强化一[五子棋、九个正面和背面、矩阵相乘])

如下是实现源代码:

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(反面)便是硬币的状态。下面是一些列子:

Java基本功练习九(多维数组强化一[五子棋、九个正面和背面、矩阵相乘]) 每个状态都可以使用一个二进制数表示。例如前面的矩阵对应到数字为: Java基本功练习九(多维数组强化一[五子棋、九个正面和背面、矩阵相乘])
总共有512中可能。可以使用十进制数0,1,2,...,511来表示这个矩阵的所有状态。编写程序,提示用户输入一个在0到511之间的数字,然后显示用字符H和T表示对应的矩阵。运行效果如下图所示: Java基本功练习九(多维数组强化一[五子棋、九个正面和背面、矩阵相乘])Java基本功练习九(多维数组强化一[五子棋、九个正面和背面、矩阵相乘])
        这个示例没什么技术难点,无非就是几次数据的转换,写对对应关系的语句就可以了,只是作为数组的练习。示例三才是本文重点。 实现源代码如下:

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路棋盘的五子棋)


运行效果如下图所示: Java基本功练习九(多维数组强化一[五子棋、九个正面和背面、矩阵相乘])Java基本功练习九(多维数组强化一[五子棋、九个正面和背面、矩阵相乘])Java基本功练习九(多维数组强化一[五子棋、九个正面和背面、矩阵相乘])Java基本功练习九(多维数组强化一[五子棋、九个正面和背面、矩阵相乘])

实现的源代码如下所示:
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,那就基本掌握了数组的用法。

        如果上述几点都实现了,那么请升级为改进五子棋输赢判断方法:本篇博文五子棋的输赢检测方法是遍历棋盘,每次输入一颗新棋子都要遍历棋盘,效率比较低。请改进为只需判断当前所下棋子周围的情况来评定输赢情况!

       如果还有余力,可以考虑增加悔棋的功能!!!