井字游戏
文章目录
前言
(全部代码在文章末尾)
在学习完Java的方法后,老师一般会布置一些作业,例如我们下面要写的井字游戏。
下面我们利用java来写一个井字游戏(注,本文没有运用到java后面学习的类和对象思想,只是一个简单作业),点击进入大佬写的带有图形化界面的博客
一、井字棋是什么?
井字棋,英文名叫Tic-Tac-Toe,是一种在3*3格子上进行的连珠游戏,和五子棋类似,由于棋盘一般不画边框,格线排成井字故得名。游戏需要的工具仅为纸和笔,然后由分别代表O和X的两个游戏者轮流在格子里留下标记(一般来说先手者为X),任意三个标记形成一条直线,则为获胜。(来源于百度百科)
二、设计界面
首先我们要设计界面,当然,不是Java的知识点里的GUI界面,只是简单的在输出终端设计一个图形,这里我直接套用老师给的图形界面。
2.1 代码
这里我们传入一个字符串二维数组,对其中的值(空格)进行输出,我们可以运行测试一下。
代码如下:
public static void square(String[][] array) {//输出图形
for (String[] strings : array) {
System.out.println("-------------");
for (String string : strings) {
System.out.print("|" + " " + string + " ");
}
System.out.print("|\n");
}
System.out.println("-------------");
}
2.2 运行测试
2 2.1 代码
我们对主函数进行修改,并测试
public static void main(String[] args) {
String[][] array = new String[][]{{" ", " ", " "}, {" ", " ", " "}, {" ", " ", " "}}; //方法所需的数组
square(array);
}
2 2.2 运行结果
三、输入
这里我们定义了两个方法,方法input的作用是输入,方法TraversalArray的作用是判断玩家输入的位置是否存在值,在方法input中,我们利用while嵌套if语句实现输入,if语句的作用是判断玩家输入的位置是否存在·,以及玩家输入的位置是否存在值。
3.1 代码
代码如下:
public static void input(String[][] array, String str) {
Scanner sc = new Scanner(System.in);
int num1;//行
int num2;//列
while (true) {
System.out.print(str + "玩家请选择行(1,2,3):");
num1 = sc.nextInt() - 1; //数组下标是从零开始计算,这里我们需要减一
System.out.print(str + "玩家请选择列(1,2,3):");
num2 = sc.nextInt() - 1; //数组下标是从零开始计算,这里我们需要减一
if (num1 > 3 || num1 < 0 || num2 > 3 || num2 < 0) {
System.out.println("输入的位置不存在,请重新输入");
} else {//输入正确的情况下
if (TraversalArray(num1,num2,array)) {//对数组进行赋值
array[num1][num2] = str;
System.out.println(" ");
break;
}
}
}
}
public static boolean TraversalArray(int num1,int num2,String[][] array){ //遍历数组判断位置是否被占用
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
if (num1 == i && num2 == j) {
if (array[num1][num2].equals("X") || array[num1][num2].equals("O")) {
System.out.println("这个位置已被占用,请选择另一个位置");
return false;//位置已被占用,无法赋值
}
}
}
}
return true;
}
3.2 运行测试
这里我们修改主函数,进行测试
3. 2.1 代码
public static void main(String[] args) {
String[][] array = new String[][]{{" ", " ", " "}, {" ", " ", " "}, {" ", " ", " "}};
String str;//用于对数组array进行赋值
for (int i = 1; i<3; i++) {
if (i % 2 == 0) {
str = "O";
} else {
str = "X";
}
square(array);
input(array, str);
}
}
运行测试
3.2.2 运行结果
从结果上看,这两个方法没有问题
四、判断胜利
这里我们定义了两个方法,方法input的作用是输入,方法TraversalArray的作用是判断玩家输入的位置是否存在值,在方法input中,我们利用while嵌套if语句实现输入,if语句的作用是判断玩家输入的位置是否存在·,以及玩家输入的位置是否存在值。
4.1.代码
这里使用IsVictory1方法和IsVictory2方法进行判断胜利。
4.1.1代码一
对IsVictory2方法中的统计数组进行判断,如果在水平、竖直、两条对角线的位置满足条件则判断胜利
public static boolean IsVictory1(String[][] array) {//判断哪个玩家胜利或者是平局
int[] count = new int[]{0, 0, 0, 0, 0, 0, 0, 0, 8};//存储从水平、竖直、对角线扫描的X、O的个数
boolean suspend1 = true;//在判断胜利或者平局的情况下,对程序进行中止运行
IsVictory2(array, count);//调用函数统计X和O,及空格的个数
for (int i = 0; i < count.length; i++) {//判断哪个玩家胜利,或者是平局
if (i <= 3 && count[i] == 3) {
square(array);
System.out.print("O玩家赢了");
suspend1 = false;
break;
} else if (i > 3 && count[i] == 3) {
square(array);
System.out.print("X玩家赢了");
suspend1 = false;
break;
} else if (i == count.length - 1 && count[8] == 8) {
square(array);
System.out.print("平局");
suspend1 = false;
break;
}
}
return suspend1;
}
4.1.2代码二
这里遍历数组对每个位置的元素进行统计,并放在一个新的数组中。
public static void IsVictory2(String[][] array, int[] count) {//判断是否胜利
boolean suspend = false;//跳出外层循环,中止扫描
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) { //统计水平、竖直、对角线扫描到的X、O的个数
if (array[i][j].equals("O")) {
count[0] += 1;
}
if (array[j][i].equals("O")) {
count[1] += 1;
}
if (i == j && array[i][j].equals("O")) {
count[2] += 1;
}
if (i + j == 2 && array[i][j].equals("O")) {
count[3] += 1;
}
if (array[i][j].equals("X")) {
count[4] += 1;
}
if (array[j][i].equals("X")) {
count[5] += 1;
}
if (i == j && array[i][j].equals("X")) {
count[6] += 1;
}
if (i + j == 2 && array[i][j].equals("X")) {
count[7] += 1;
}
if (array[i][j].equals(" ")) {
count[8] = 0;
}
}
for (int k = 0; k < count.length; k++) {//对统计的X、O进行判断,如果四个方向上的任意一个方向的X或O的个数为3,则跳出扫描
if (count[k] == 3) {
suspend = true;
break;
} else if (k == count.length - 1) { //仅对行和列进行重置,对角线不重置。
count[0] = 0;
count[1] = 0;
count[4] = 0;
count[5] = 0;
}
}
if (suspend) {//配合上一个for循环,跳出外层循环
break;
}
}
}
4.2 运行测试
4.2.2 代码
在主函数中,我们对数组进行了修改,方便测试。
public static void main(String[] args) {
String[][] array = new String[][]{{"O", "X", " "}, {"O", " ", "X"}, {"O", "X", " "}};
IsVictory1(array);
}
4.2.3 运行结果
从以上结果看出我们的方法目前没有问题,为什么是暂时呢,因为我没有把全部胜利的方法试过一遍。
五、全部代码及运行结果
5.1 代码
import java.util.Scanner;
public class TicTacToe1 {
public static void main(String[] args) {
String[][] array = new String[][]{{" ", " ", " "}, {" ", " ", " "}, {" ", " ", " "}};
String str;//用于对数组array进行赋值
boolean suspend1 = true;//如果IsVictory返回false,则中止运行
for (int i = 1; suspend1; i++) {
if (i % 2 == 0) {
str = "O";
} else {
str = "X";
}
square(array);
input(array, str);
suspend1 = IsVictory1(array);
}
}
public static void square(String[][] array) {//输出图形
for (String[] strings : array) {
System.out.println("-------------");
for (String string : strings) {
System.out.print("|" + " " + string + " ");
}
System.out.print("|\n");
}
System.out.println("-------------");
}
public static void input(String[][] array, String str) {
Scanner sc = new Scanner(System.in);
int num1;//行
int num2;//列
while (true) {
System.out.print(str + "玩家请选择行(1,2,3):");
num1 = sc.nextInt() - 1;
System.out.print(str + "玩家请选择列(1,2,3):");
num2 = sc.nextInt() - 1;
if (num1 > 3 || num1 < 0 || num2 > 3 || num2 < 0) {
System.out.println("输入的位置不存在,请重新输入");
} else {//输入正确的情况下
if (TraversalArray(num1, num2, array)) {//对数组进行赋值
array[num1][num2] = str;
System.out.println(" ");
break;
}
}
}
}
public static boolean TraversalArray(int num1, int num2, String[][] array) { //遍历数组判断位置是否被占用
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
if (num1 == i && num2 == j) {
if (array[num1][num2].equals("X") || array[num1][num2].equals("O")) {
System.out.println("这个位置已被占用,请选择另一个位置");
return false;//位置已被占用,无法赋值
}
}
}
}
return true;
}
public static boolean IsVictory1(String[][] array) {//判断哪个玩家胜利或者是平局
int[] count = new int[]{0, 0, 0, 0, 0, 0, 0, 0, 8};//存储从水平、竖直、对角线扫描的X、O的个数
boolean suspend1 = true;//在判断胜利或者平局的情况下,对程序进行中止运行
IsVictory2(array, count);//调用函数进行判断胜利
for (int i = 0; i < count.length; i++) {//判断哪个玩家胜利,或者是平局
if (i <= 3 && count[i] == 3) {
square(array);
System.out.print("O玩家赢了");
suspend1 = false;
break;
} else if (i > 3 && count[i] == 3) {
square(array);
System.out.print("X玩家赢了");
suspend1 = false;
break;
} else if (i == count.length - 1 && count[8] == 8) {
square(array);
System.out.print("平局");
suspend1 = false;
break;
}
}
return suspend1;
}
public static void IsVictory2(String[][] array, int[] count) {//判断是否胜利
boolean suspend = false;//跳出外层循环,中止扫描
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) { //统计水平、竖直、对角线扫描到的X、O的个数
if (array[i][j].equals("O")) {
count[0] += 1;
}
if (array[j][i].equals("O")) {
count[1] += 1;
}
if (i == j && array[i][j].equals("O")) {
count[2] += 1;
}
if (i + j == 2 && array[i][j].equals("O")) {
count[3] += 1;
}
if (array[i][j].equals("X")) {
count[4] += 1;
}
if (array[j][i].equals("X")) {
count[5] += 1;
}
if (i == j && array[i][j].equals("X")) {
count[6] += 1;
}
if (i + j == 2 && array[i][j].equals("X")) {
count[7] += 1;
}
if (array[i][j].equals(" ")) {
count[8] = 0;
}
}
for (int k = 0; k < count.length; k++) {//对统计的X、O进行判断,如果四个方向上的任意一个方向的X或O的个数为3,则跳出扫描
if (count[k] == 3) {
suspend = true;
break;
} else if (k == count.length - 1) { //仅对行列进行重置,对角线不重置。
count[0] = 0;
count[1] = 0;
count[4] = 0;
count[5] = 0;
}
}
if (suspend) {//配合上一个for循环,跳出外层循环
break;
}
}
}
}
5.2 结果
这里就简单的测试一下。
六 总结
以上就是今天要讲的内容,本文介绍了如何使用Java程序进行井字游戏简单制作。
在本次Java项目中,我们成功地实现了一个井字游戏的简单版本。以下是我们在项目中的一些主要发现和经验:
理解游戏规则:首先,我们需要深入理解井字游戏的规则。这包括如何判断胜利条件,以及如何处理平局的情况。我们发现,理解这些规则是实现井字游戏的关键。
设计数据结构:我们选择使用二维数组来表示棋盘。每个元素可以存储一个玩家的棋子,或者表示空格。这种数据结构使得我们能够方便地处理棋子的放置和胜利条件的判断。
实现游戏逻辑:在理解了游戏规则和数据结构之后,我们开始实现游戏的逻辑。这包括轮流让玩家放置棋子,判断胜利条件,以及处理平局的情况。在这个过程中,我们发现我们需要对Java的基础知识有深入的理解,例如循环、条件判断等。
测试和调试:在实现完游戏逻辑之后,我们进行了大量的测试和调试。我们发现,测试是找出代码中错误的重要手段。通过测试,我们能够确保我们的代码能够正确地运行,并且能够处理各种可能的情况。
优化和改进:在项目完成后,我们进行了一些优化和改进。例如,我们添加了一个用户界面,使得玩家能够更方便地与游戏交互。此外,我们还添加了一些额外的功能,例如悔棋和重新开始游戏。
总的来说,通过这个Java项目,我们深入理解了井字游戏的规则和实现方法。同时,我们也学习了许多Java编程的技巧和方法。我们相信,这些经验和知识将对我们未来的学习和工作产生积极的影响。