使用游戏的方式学习编程效率更高
学习编程刚开始都是比较枯燥的阶段,但是如果带着需求和兴趣去体验一门编程语言,学习的效果将事半功倍,而且编程语言的语法和特性带着兴趣去解决一个一个问题,记忆也更加深刻。将学习转为游戏方式的方法就是实际尝试编写一些游戏,下面几个编程游戏是比较流行的:
- 猜数字
- 石头剪刀布
- 太空侵略者
- 跳棋或者国际象棋
这篇我们就尝试使用Java编写一个井字游戏。
井字游戏
井字游戏的规则:两个玩家,一个打圈(◯),一个打叉(),轮流在3乘3的格上打自己的符号,最先以横、直、斜连成一线则为胜。
井字游戏难度处于中等水平,你能够编写猜数字游戏或石头剪刀布,那么就能编写Java井字游戏,遇到困难再解决,自然就掌握了,比苦读硬记效果好。Java 井字游戏的编程实现不像跳棋或国际象棋那么困难,但是当你尝试实现更复杂的棋盘游戏时,关于多维数组、异常处理和流控制的许多经验将会有所帮助。
如何编写一个Java的井字游戏
为了实现Java版本的井字游戏,我们先对游戏规则进行梳理,然后抽象流程,并使用合适的数据结构和流程去模拟游戏。下面我整理了八个步骤,逐步实现开发完这个游戏的目标。
- 创建一个Java类,命名TicTacToe
- 声明所有需要的变量
- 打印一个基本的井字游戏棋盘
- 接受用户的输入
- 检查一方是否获胜
- 如果没有获胜,另外一方继续输入
- 如果棋盘方格都已被占据,则游戏结束
- 运行游戏
Step1:创建Java类
首先,创建一个名为 TicTacToe 的类,该类具有可运行的 main 方法,如下所示。
本例中的所有代码都位于 TicTacToe 类的 main 方法中,或者位于声明为此类一部分的方法中。
/* A Tic Tac Toe Game coded in Java */
public class TicTacToe {
public static void main(String[] args)
{
}
}
Step2: 声明变量
井字棋盘有 9 个方格。在我们的游戏中,我们会显示每个未选中方格的编号,并询问玩家要标记哪个方格。
char[] board = { '1','2','3',
'4','5','6',
'7','8','9' };
```
我们还需要记录轮到谁了,以及已经玩了多少个方格。如果九个方格都玩完了,没有获胜者,游戏就会以平局结束。
```java
var numberOfSquaresPlayed = 0;
var whoseTurnItIs = 'x';
```
我们使用一个字符数组来存储数字1-9,9个数字就是棋盘每个方格的位置,用户交互时就是根据数字表名,棋子将落在何处。
### Step3:打印出井字棋盘
每次选中一个方块,我们都会重新绘制棋盘。 由于这是一款简单的主机游戏,因此棋盘的显示并不复杂。它看起来就像下面的图片一样:
![在这里插入图片描述](https://i-blog.csdnimg.cn/direct/087f4a89f4db4f3184874112e0f6bc61.png)
我们在名为 printTheBoard() 的方法中输入生成并打印出 Java 井字游戏板的逻辑:
```java
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]);
}
```
当第一次输出时:
```java
1 | 2 | 3
- + - + -
4 | 5 | 6
- + - + -
7 | 8 | 9
```
随着游戏的进行,棋盘会用 x 和 o 进行更新。完整的井字游戏 Java 战斗如下所示:
```java
X | O | X
- + - + -
X | 5 | O
- + - + -
X | O | 9
```
### Step4: 接受用户输入
只要 numberOfSquaresPlayed 小于 9,我们就会向玩家显示棋盘的当前状态并提示他们选择一个方块,利用 Java 的 Scanner 类进行用户输入:
```java
while (numberOfSquaresPlayed < 9) {
printTheBoard(board);
getTheUserToSelectTheirSquare(board, whoseTurnItIs);
if (theyWonTheGame(board, whoseTurnItIs)) {
gameEndingMessage = "恭喜,你是大赢家!";
break;
} else if (numberOfSquaresPlayed == 9) {
gameEndingMessage = "一场恶战,双方平局!";
} else {
numberOfSquaresPlayed++;
whoseTurnItIs = (whoseTurnItIs == 'x') ? 'o' : 'x';
continue;
}
}
```
注意,字符数组如何根据轮到谁来更新,是使用 X 还是 O。
```java
board[input-1] = whoseTurnItIs;
```
由于数组是从零开始的,因此我们从用户提供的数字中减一。如果用户选择数字 5 的平方,则它对应于数组中的索引 4。
### Step5: 检查是否获胜
每次用户选择一个方格时,我们都会检查他们是否完成了一条线并赢得了游戏。
井字棋有八种获胜方式:
- 三条水平线。
- 三条垂直线。
- 两条穿过方格的对角线。
在这种情况下,条件逻辑可能会变得很复杂,因为必须根据当前玩家的字母检查潜在获胜行中的每个方格。
对第一条水平线的检查可能如下所示:
```java
if ((board[0] == whoseTurnItIs) &&
(board[1] == whoseTurnItIs) &&
(board[2] == whoseTurnItIs))
{
System.out.println("You won!!! Congratulations!");
break;
}
```
需要进行八次这样的检查才能确定游戏是否已经获胜,这可能会变得很麻烦。
另一种选择稍微简洁一些,它利用了 char 类型的一个鲜为人知的特性。
char 是一种整数类型
很少有人知道,Java 中的 char 实际上是一种整数类型。你可以像对 int、double 或 float 一样对其执行数学运算。
这意味着你可以将给定行中的三个字符相加,然后查看结果是否等于 'x' 字符自身相乘三次的结果。如果是,你就知道一行中有三个 'x' 字符。如果是第二个玩家的回合,对 'o' 字符执行相同的操作。
以下逻辑利用了 char 的基于整数的性质来查看给定的行、列或对角线是否已完成:
```java
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("恭喜,你是大赢家!");
break;
} else {
numberOfSquaresPlayed++;
whoseTurnItIs = (whoseTurnItIs == 'x') ? 'o' : 'x';
}
```
编程的过程要灵活使用数据结构的特性,要会变通,虽然char这种使用场景以后都可能不是再遇到了。
### Step6: 回合切换
果我们的条件检查显示一行已经完成,我们会祝贺玩家并跳出循环,正如我们从上面的代码中看到的那样:
```java
printTheBoard(board);
System.out.println("恭喜,你是大赢家!");
break;
```
如果一行未完成,我们会增加所玩方块的数量并改变回合。我们使用三元运算符来实现这一点。
```java
numberOfSquaresPlayed++;
whoseTurnItIs = (whoseTurnItIs == 'x') ? 'o' : 'x';
```
作为一名新开发人员,我一直不喜欢三元运算符的神秘语法。作为一名经验丰富的 Java 开发人员,我仍然不喜欢它,但他用起来确实方便。
### Step7: 处理平局
如果游戏进行了九次并且没有获胜者,则循环退出。 此时,我们宣布比赛平局并向双方表示祝贺:
```java
if (numberOfSquaresPlayed == 9)
{
printTheBoard(board);
System.out.println("一场恶战,双方平局!");
}
```
### Step8: 运行游戏
将所有代码整合在一起,保存更改,然后运行 Java 井字棋游戏。
只要你提供有效的输入并遵循正常流程,游戏就会完美执行。
以下是到目前为止编写的完整、可运行的 TicTacToe Java 类:
## 游戏源码
```java
package com.example.demo;
import java.util.Scanner;
/**
* @author: xiaohei
* @date: 2024/10/14 14:13
*/
public class TictakToe {
public static void main(String[] args) {
char[] board = { '1', '2', '3',
'4', '5', '6',
'7', '8', '9' };
int numberOfSquaresPlayed = 0;
char whoseTurnItIs = 'x';
String gameEndingMessage = "";
while (numberOfSquaresPlayed < 9) {
printTheBoard(board);
getTheUserToSelectTheirSquare(board, whoseTurnItIs);
if (theyWonTheGame(board, whoseTurnItIs)) {
gameEndingMessage = "恭喜,你是大赢家!";
break;
} else if (numberOfSquaresPlayed == 9) {
gameEndingMessage = "一场恶战,双方平局!";
} 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("轮到玩家 %s 选择未被占据的方格:", whoseTurnItIs);
Scanner scanner = new java.util.Scanner(System.in);
int input = scanner.nextInt();
if (Character.isDigit(board[input - 1])) {
board[input - 1] = whoseTurnItIs;
break;
} else {
System.out.println("这个地方已经被占用了");
}
} catch (Exception e) {
System.out.println("程序异常,重试");
}
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
}
}
```
本站资源均来自互联网,仅供研究学习,禁止违法使用和商用,产生法律纠纷本站概不负责!如果侵犯了您的权益请与我们联系!
转载请注明出处: 免费源码网-免费的源码资源网站 » 【Java教程】使用Java编写井字游戏
发表评论 取消回复