使用 Java 编写井字游戏

学习如何编码可能会令人沮丧,但是如果您将体验游戏化,那么沮丧就会变得更容易忍受。

将学习游戏化的方法之一是实际编写一些游戏。学习时最流行的一些编程游戏包括:

  • 一名猜数字的人。
  • 剪刀石头布。
  • 蛇或者蜈蚣。
  • 太空侵略者。
  • 跳棋或者国际象棋。

难度处于中等水平的是井字游戏。如果你能编写一个猜数字游戏或石头剪刀布游戏,那么你应该能够编写一个 Java 井字游戏,尽管它的挑战性要大得多。

Java 井字游戏的编码并不像跳棋或国际象棋那么困难,但是当您尝试实现更复杂的棋盘游戏时,关于多维数组、异常处理和流控制的许多经验教训将对您有所帮助。

如何编写 Java 井字游戏

要编写 Java 井字游戏程序,我们将遵循以下八个步骤,使我们能够逐步实现完成游戏的目标:

  1. 创建一个名为的可运行 Java 类TicTacToe
  2. 声明所有必需的变量。
  3. 打印一个基本的井字游戏棋盘。
  4. 从两个玩家处获取用户输入。
  5. 检查是否有获胜的玩法。
  6. 如果比赛没有获胜,则更换球员。
  7. 如果所有方格都被占据,则游戏结束。
  8. 运行 Java 井字游戏应用程序。

步骤 1:创建TicTacToe Java 类

首先,创建一个名为的类TicTacToe,该类具有可运行的 main 方法,如下所示。

本例中的所有代码都位于TicTacToe类的 main 方法中,或者位于声明为此类一部分的方法中。您也可以选择在 JShell 中运行此示例,我始终推荐使用 JShell 来学习 Java 和快速制作原型。

 

/* 用 Ja​​va 编写的井字游戏 */ 
public class TicTacToe {

  public static void main(String[] args) 
  {

  }

}

第 2 步:声明所需变量

井字棋盘有 9 个方格。在我们的游戏中,我们会显示每个未选中方格的编号,并询问玩家要标记哪个方格。

java井字游戏多维数组

board[] 数组的每个元素代表游戏板上的一个位置。

char [] board = { '1','2','3',
                  '4','5','6', 
                 '7','8','9'   };

我们还需要记录轮到谁了,以及已经玩了多少个方格。如果九个方格都玩完了,没有获胜者,游戏就会以平局结束。

var numberOfSquaresPlayed = 0; 
var whoseTurnItIs = 'x' ;

为此,我们从一个包含数字 1-9 的字符数组开始,如下所示:

步骤 3:打印井字棋棋盘

每当选择一个方格,我们就会重新绘制棋盘。

由于这是一款简单的主机游戏,因此棋盘的显示并不复杂。它看起来就像下面的图片一样:

Java 井字游戏应用板

在游戏过程中,玩家选择一个空位的数字。

我们在名为的方法中输入生成和打印出 Java 井字游戏板的逻辑printTheBoard()

private static void printTheBoard(char[] board) 
{
  System.out.println( board[0] + " | " +  board[1] + " | " + board[2]);
  System.out.println( " - + - + - " );
  System.out.println( board[3] + " | " +  board[4] + " | " + board[5]);
  System.out.println( " - + - + - " );
  System.out.println( board[6] + " | " +  board[7] + " | " + board[8]);
}

首次绘制棋盘时,它仅显示数字:

1 | 2 | 3 
-+-+- 
4| 5 | 6 
- + - + - 
7 | 8 | 9

随着游戏的进行,棋盘会用 x 和 o 进行更新。完整的井字游戏 Java 战斗如下所示:

X | 氧 | X 
- + - + - 
X | 5 | 氧
- + - + - 
X | 氧 | 9

步骤 4:获取用户输入

只要小于numberOfSquaresPlayed9,我们就会向玩家显示棋盘的当前状态并提示他们选择一个方格,利用 Java 的Scanner类进行用户输入:

while ( numberOfSquaresPlayed < 9) 
{ 
  printTheBoard ( board ); 
  System. out .printf("选择玩家 %s 的方格: ", whoseTurnItIs );
 
  var scanner = new java.util.Scanner(System. in ); 
  var input = scanner.nextInt();
 
  board[input-1] = whoseTurnItIs; 
}

请注意,char根据轮到谁,数组会用 X 或 O 进行更新。

棋盘[输入-1] = whoseTurnItIs;

由于数组是从零开始的,因此我们从用户提供的数字中减一。如果用户选择数字 5 的平方,则它对应于数组中的索引 4。

第 5 步:查看获胜者

每次用户选择一个方块时,我们都会检查他们是否完成一行并赢得了游戏。

赢得井字游戏有八种方法:

  • 三条水平线。
  • 三条垂直线。
  • 两条穿过广场的线。

在这种情况下,条件逻辑会变得很难看,因为必须根据当前玩家的字母检查可能获胜的行中的每个方格。

第一条水平线的检查可能看起来像这样:

if ((board[0] == whoseTurnItIs) &&
    (board[1] == whoseTurnItIs) &&
    (board[2] == whoseTurnItIs)) 
{ 
   System.out.println ("你了!!!恭喜! "); 
   break ; 
}  

需要进行八次这样的检查来判断比赛是否获胜,这可能会变得很难看。

另一个选项稍微不那么冗长,涉及使用这种类型的鲜为人知的功能char

char 是整数类型

很少有人知道,Java 中的实际上是整数类型。你可以像对intdouble 或 floatchar进行数学运算一样对其进行数学运算。

这意味着您可以将给定行中的三个数字相加chars,看看结果是否等于“x”字符乘以自身三次。如果相等,则说明一行中有三个“x” 。如果轮到第二个玩家,则chars对“o”执行相同操作。char

以下逻辑使用字符的基于整数的性质来查看给定的行、列或交叉是否已完成:

if ( (board[0] + board[1] + board[2] == (whoseTurnItIs * 3)) // 第一行 
   || (board[3] + board[4] + board[5] == (whoseTurnItIs * 3)) // 第二行
   || (board[6] + board[7] + board[8] == (whoseTurnItIs * 3)) // 第三行
   || (board[0] + board[3] + board[6] == (whoseTurnItIs * 3)) // 第一列
   || (board[1] + board[4] + board[7] == (whoseTurnItIs * 3)) // 第二列
   || (board[2] + board[5] + board[8] == (whoseTurnItIs * 3)) // 第三列
   || (board[0] + board[4] + board[8] == (whoseTurnItIs * 3)) // 第一 对角线
   || (board[2] + board[4] + board[6] == (whoseTurnItIs * 3)) // 第二条对角线
)
{ 
  printTheBoard (board); 
  System. out .println("你赢了!!!恭喜! "); 
  break ; 
} else { 
  numberOfSquaresPlayed++; 
  whoseTurnItIs = (whoseTurnItIs == 'x') ? 'o' : 'x'; 
}

享受成功执行数学运算的喜悦char。你可能在整个职业生涯中都不会再看到char像这样使用 Java。

第 6 步:轮流

如果我们的条件检查显示一行已经完成,我们会祝贺玩家并跳出循环,正如我们从上面的代码中看到的那样:

printTheBoard (board); 
System. out .println("你赢了!!!恭喜! "); 
break ;

如果一行未完成,我们会增加所玩方块的数量并改变回合。我们使用三元运算符来实现这一点。

numberOfSquaresPlayed++; 
whoseTurnItIs = (whoseTurnItIs == 'x') ? 'o' : 'x';

Java 的条件运算符

三元运算符是一种快捷方式,它简化了基于条件语句结果的分配。

我们可以简单地说:

if (whoseTurnItIs == 'x')
{ 
  whoseTurnItIs = 'o'; 
} else { 
  whoseTurnItIs = 'x'; 
}

但是,我们使用三元运算符来使语法更精确。

whoseTurnItIs = (whoseTurnItIs == 'x') ? 'o' : 'x';

作为一名新开发人员,我一直不喜欢三元运算符的神秘语法。作为一名经验丰富的 Java 开发人员,我仍然不喜欢它,但我更欣赏它。

第七步:处理领带

如果游戏进行九次仍没有获胜者,则退出循环。

此时,我们宣布比赛打平,并向双方表示祝贺:

if (numberOfSquaresPlayed == 9)
{ 
  printTheBoard (board); 
  System.out.println ("一场恶战,打成平局!" ); 
}

步骤 8:运行井字游戏 Java 游戏

将所有这些代码放在一起并保存更改,然后运行 ​​Java 井字游戏。

只要您提供有效的输入并遵循快乐的路径,游戏就会完美执行。

TicTacToe以下是到目前为止编写的完整、可运行的Java 类代码:

package com.mcnz.vector;

public class TicTacTest {

  public static void main(String[] args) 
  {
    char[] board = { '1', '2', '3', 
                     '4', '5', '6', 
                     '7', '8', '9' };

    var numberOfSquaresPlayed = 0;
    var whoseTurnItIs = 'x';

    while (numberOfSquaresPlayed < 9) 
    {
      printTheBoard(board);
      System.out.printf("Choose a square player %s:", whoseTurnItIs);
      var scanner = new java.util.Scanner(System.in);
      var input = scanner.nextInt();
      board[input - 1] = whoseTurnItIs;

      if (  (board[0] + board[1] + board[2] == (whoseTurnItIs * 3)) // first row 
         || (board[3] + board[4] + board[5] == (whoseTurnItIs * 3)) // second row
         || (board[6] + board[7] + board[8] == (whoseTurnItIs * 3)) // third row
         || (board[0] + board[3] + board[6] == (whoseTurnItIs * 3)) // first column
         || (board[1] + board[4] + board[7] == (whoseTurnItIs * 3)) // second column
         || (board[2] + board[5] + board[8] == (whoseTurnItIs * 3)) // third column
         || (board[0] + board[4] + board[8] == (whoseTurnItIs * 3)) // first diagonal
         || (board[2] + board[4] + board[6] == (whoseTurnItIs * 3)) // second diagonal
      ) 
      {
         printTheBoard(board);
         System.out.println("You won!!! Congratulations!");
         break;
      } else {
         numberOfSquaresPlayed++;
         whoseTurnItIs = (whoseTurnItIs == 'x') ? 'o' : 'x';
      }
    }
  }

  private static void printTheBoard(char[] board) 
  {
    System.out.printf("%n %s | %s | %s %n", board[0], board[1], board[2]);
    System.out.println(" - + - + - ");
    System.out.printf(" %s | %s | %s %n", board[3], board[4], board[5]);
    System.out.println(" - + - + - "); 
    System.out.printf(" %s | %s | %s %n%n", board[6], board[7], board[8]);
  }
} /* Java井字游戏结束*/

 

增强 Java Tic-Tac-Toe 应用程序

通过实现核心逻辑,您可以通过增强 Java 井字游戏来推动您的编程知识的发展。

可能的增强包括以下内容:

Java 井字游戏源代码

稍微增强的 Java 井字游戏的完整代码如下。添加您自己的增强功能,进一步加深您对 Java 的理解。

/* Java tic-tac-toe Game source code */
package com.mcnz.tictactoe;

public class TicTacToe {

  public static void main(String[] args) {

    char[] board = { '1', '2', '3',
                     '4', '5', '6',
                     '7', '8', '9' };

    var numberOfSquaresPlayed = 0;
    var whoseTurnItIs = 'x';
    var gameEndingMessage = "";

    while (numberOfSquaresPlayed < 9) {
      printTheBoard(board);
      getTheUserToSelectTheirSquare(board, whoseTurnItIs);
  
      if (theyWonTheGame(board, whoseTurnItIs)) {
        gameEndingMessage = "You won!!! Congratulations!";
        break;
      } else if (numberOfSquaresPlayed == 9) {
        gameEndingMessage = "A tough battle fought to a draw!";
      } else {
        numberOfSquaresPlayed++;
        whoseTurnItIs = (whoseTurnItIs == 'x') ? 'o' : 'x';
        continue;
      }
    }
    printTheBoard(board);
    System.out.println(gameEndingMessage);
  }

  private static void printTheBoard(char[] board) {
    System.out.printf("%n %s | %s | %s %n", board[0], board[1], board[2]);
    System.out.println(" - + - + - ");
    System.out.printf(" %s | %s | %s %n",   board[3], board[4], board[5]);
    System.out.println(" - + - + - ");
    System.out.printf(" %s | %s | %s %n%n", board[6], board[7], board[8]);
  }

  private static void getTheUserToSelectTheirSquare(char[] board, char whoseTurnItIs) {

    do {
      try {
        System.out.printf("Would player %s please choose an unchosen square:", whoseTurnItIs);
        var scanner = new java.util.Scanner(System.in);
        var input = scanner.nextInt();

        if (Character.isDigit(board[input - 1])) {
          board[input - 1] = whoseTurnItIs;
          break;
        } else {
          System.out.println("Sorry, that's taken.");
        }
      } catch (Exception e) {
        System.out.println("Something went wrong. Let's try that again.");
      }
      printTheBoard(board);
    } while (true);
  }

  private static boolean theyWonTheGame(char[] board, char whoseTurnItIs) {
    return (board[0] + board[1] + board[2] == (whoseTurnItIs * 3)) // first row  
    || (board[3] + board[4] + board[5] == (whoseTurnItIs * 3))     // second row
    || (board[6] + board[7] + board[8] == (whoseTurnItIs * 3))     // third row
    || (board[0] + board[3] + board[6] == (whoseTurnItIs * 3))     // first column
    || (board[1] + board[4] + board[7] == (whoseTurnItIs * 3))     // second column
    || (board[2] + board[5] + board[8] == (whoseTurnItIs * 3))     // third column
    || (board[0] + board[4] + board[8] == (whoseTurnItIs * 3))     // first cross
    || (board[2] + board[4] + board[6] == (whoseTurnItIs * 3));    // second cross
  }
} 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值