Fork me on GitHub

java控制台五子棋游戏

纪念我的第一次实践。

注意:

  • 本项目在IDEA下调试完毕,已解决目前已知所有bug,sublime上似乎跑不了,eclipse没有试过。(更新:只能在IDEA上跑,将其打包成jar后通过Powershell跑棋盘会错位)
  • 棋盘方格为搜狗输入法下的制表符,为了保证棋盘的美观,需设定IDEA控制台行间距为0.7。
  • 本项目电脑玩家落子设定为在用户最后一次落子周围八格内随机落子,若有大佬能提供合适的人工智能算法请联系QQ:549007298,感激不尽。
  • 本项目判断是否获胜设定为依次检查最后一次落子所在的每行每列及每条对角线的同色连续棋子数,若有大佬能提供更优化的算法联系方式同上。
  • 本项目前期曾参考java控制台五子棋游戏
  • 若有疑问,欢迎咨询,联系方式同上。

源码如下:

棋盘类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
package Gobang;

/*
Created by Ben Wen on 2018/8/9.
*/

import static Gobang.Gobang.computer;
import static Gobang.Gobang.man;
import static Gobang.Gobang.order;

public class Chessboard {//棋盘类
public static int BOARD_SIZE = 15;//棋盘大小
public static String BLACK = "○";
public static String WHITE = "●";
public String[][] board;//表示棋盘的数组
public int numChess = 0;//棋子总数

public void initBoard (){//初始化棋盘
board = new String[BOARD_SIZE][BOARD_SIZE];
for (int i = 0;i < BOARD_SIZE;i++) {
for (int j = 0;j < BOARD_SIZE;j++) {
board[i][j] = "╋";
}
}
}

public void printBoard (){//打印棋盘(用了些骚操作,为了保证棋盘的美观需设定IDEA控制台行间距为0.7)
System.out.println(" 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 X轴");
for (int i = 0;i < BOARD_SIZE;i++) {
if (i < 9){
System.out.print("0"+ (i+1));
} else {
System.out.print(i+1);
}
for (int j = 0;j < BOARD_SIZE;j++) {
if (j != BOARD_SIZE-1)
System.out.print(board[j][i] + "━");//注意此处将棋盘做了一次翻转处理
else System.out.println(board[j][i]);
}

if (i != BOARD_SIZE-1){
for (int j = 0;j < BOARD_SIZE-1;j++){
System.out.print(" ┃");
}
System.out.println(" ┃");
}
}
System.out.println("Y轴\n");
}

public void setBoard(int PosX,int PosY,int chessman){//落子
if (order == 1){
if (chessman == computer)
board[PosX-1][PosY-1] = WHITE;
else board[PosX-1][PosY-1] = BLACK;
} else {
if (chessman == man)
board[PosX-1][PosY-1] = WHITE;
else board[PosX-1][PosY-1] = BLACK;
}
numChess++;//总棋子数加1
}
}

游戏类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
package Gobang;

/*
Created by Ben Wen on 2018/8/9.
*/

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

import static Gobang.Chessboard.BLACK;
import static Gobang.Chessboard.BOARD_SIZE;
import static Gobang.Chessboard.WHITE;

public class Gobang {//游戏类
public static final int computer = 1;//用来表示电脑玩家
public static final int man = 2;//用来表示用户
public static final int WIN_COUNT = 5;//用来表示获胜所需连子数
public static int order;//用来表示执行顺序,1表示用户执黑先走,2表示用户执白后走
private int PosX;
private int PosY;
private int winner;//用来表示获胜方
private int[] computerPosArr;//用来获取computerDo方法的返回值
private Chessboard chessboard;
private int[] a = {0,1,2,3,4};

private Gobang (Chessboard chessboard){
this.chessboard = chessboard;
}//构造函数,便于使用Chessboard类的方法

public static void main(String[] args){
new Gobang(new Chessboard()).start();
}

private void start (){
boolean isOver = false;//游戏是否结束的标志

chessboard.initBoard();//初始化棋盘
System.out.println("请选择您是黑子先走(1)还是白子后走(2):");

while (true) {//获取order的值,即执行顺序
try {
BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));//获取用户输入
order = Integer.parseInt(reader.readLine());
if (order == 1 || order == 2) {
break;
}
System.out.println("输入错误,请输入数字1或2:");
} catch (Exception e) {
System.out.println("输入错误,请输入数字1或2:");
}
}

if (order == 1) {//用户执黑先走
chessboard.printBoard();//打印棋盘
System.out.println("请输入您下棋的坐标,应以x(空格)y的格式,其中x、y为不大于15的正整数:");
try {
BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
String inputStr = null;
while ((inputStr = reader.readLine()) != null) {
try {
isOver = false;//游戏未结束

String[] posStrArr = inputStr.split(" ");
PosX = Integer.parseInt(posStrArr[0]);//提取出用户输入中的x坐标
PosY = Integer.parseInt(posStrArr[1]);//提取出用户输入中的y坐标

if (!isValid(PosX, PosY, man)) {//判断用户输入是否合理
continue;
}
chessboard.setBoard(PosX, PosY, man);//用户落子

if (isWin(PosX, PosY, man)) {//判断用户是否获胜
isOver = true;//游戏可以结束
winner = man;//获胜者为用户
} else {//用户未获胜
computerPosArr = computerDo();//获取电脑玩家输入
chessboard.setBoard(computerPosArr[0], computerPosArr[1], computer);//电脑玩家落子
if (isWin(computerPosArr[0], computerPosArr[1], computer)) {//判断电脑玩家是否获胜
isOver = true;//游戏可以结束
winner = computer;//获胜者为电脑
}
}

if (isOver) {//游戏是否结束
if (isReplay(winner)) {//是否重新开始
chessboard.initBoard();
} else break;
}

chessboard.printBoard();
System.out.println("请输入您下棋的坐标,应以x(空格)y的格式,其中x、y为不大于15的正整数:");
} catch (NumberFormatException e) {//数字格式异常,当未按正确格式输入但PosX、PosY均有值时抛出
System.out.println("输入错误,请按 数字(空格)数字 格式输入:");
} catch (ArrayIndexOutOfBoundsException e) {//数组越界,当只输入了一个值,即PosY无值时抛出
System.out.println("输入错误,请按 数字(空格)数字 格式输入:");
}
}
} catch (IOException e) {//当输入时出现异常时抛出
e.printStackTrace();
}
} else {//用户执白后走
while (true) {
computerPosArr = computerDo();
chessboard.setBoard(computerPosArr[0], computerPosArr[1], computer);
chessboard.printBoard();//先打印电脑玩家落子后的棋盘

if (isWin(computerPosArr[0], computerPosArr[1], computer)) {
winner = computer;
isOver = true;
} else {//如果电脑玩家未获胜,则获取用户输入
System.out.println("请输入您下棋的坐标,应以x(空格)y的格式,其中x、y为不大于15的正整数:");
try {
BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
String inputStr = null;
while ((inputStr = reader.readLine()) != null){
try {
String[] posStrArr = inputStr.split(" ");
PosX = Integer.parseInt(posStrArr[0]);//提取出用户输入中的x坐标
PosY = Integer.parseInt(posStrArr[1]);//提取出用户输入中的y坐标

if (!isValid(PosX, PosY, man)) {
continue;
}
chessboard.setBoard(PosX, PosY, man);

if (isWin(PosX, PosY, man)) {
winner = man;
isOver = true;
}
} catch (NumberFormatException e) {
System.out.println("输入错误,请按 数字(空格)数字 格式输入:");
continue;
} catch (ArrayIndexOutOfBoundsException e) {
System.out.println("输入错误,请按 数字(空格)数字 格式输入:");
continue;
}
break;
}
} catch (IOException e) {
e.printStackTrace();
}
}

if (isOver) {
if (isReplay(winner)) {
chessboard.initBoard();
isOver = false;
} else break;
}
}
}
}

private int[] computerDo () {//获取电脑玩家落子(思路为在用户最近一次落子周围八个点中随机落子)
boolean isRight = false;
int randomX = 0;
int randomY = 0;

while (!isRight) {
randomX = (int)Math.round((Math.random() * 3) - 1.5);//在-1,0,1中随机获取一值(round方法表示四舍五入)
randomY = (int)Math.round((Math.random() * 3) - 1.5);

if (Math.abs(randomX) != 2 && Math.abs(randomY) != 2) {//排除当randomX和randomY等于正负2的情况
if (PosX == 0 && PosY == 0) {//若电脑玩家走第一步,则随机获取落子点
PosX = (int)(Math.random() * BOARD_SIZE);
PosY = (int)(Math.random() * BOARD_SIZE);
}
if (isValid(PosX+randomX, PosY+randomY, computer)) {//判断该获取的点是否合理
isRight = true;//合理则退出循环
}
}
}

int[] computerPosArr = {randomX+PosX, randomY+PosY};//将结果以数组形式返回
return computerPosArr;
}

private boolean isWin (int PosX, int PosY, int chessman) {//判断是否获胜
String chess;//用来表示此次调用方法需要判断的棋子的颜色
int samecount = 1;//用来统计连子数
boolean right1 = true;//表示某一个方向上同色棋子是否连续
boolean right2 = true;//表示另一个方向上同色棋子是否连续

if (order == 1)
chess = ((chessman == man) ? BLACK : WHITE);
else chess = ((chessman == computer) ? BLACK : WHITE);

if (chessboard.numChess < 9)//当总棋子数小于9时一定不会有一方获胜
return false;

for (int i = 1;i < WIN_COUNT && (right1 || right2);i++){//判断左右方向是否满足5连子
if (right1 && PosX+a[i] >= 1 && PosX+a[i] <= 15 && chessboard.board[PosX+a[i]-1][PosY-1].equals(chess)){
samecount++;
} else right1 = false;
if (right2 && PosX-a[i] >= 1 && PosX-a[i] <= 15 && chessboard.board[PosX-a[i]-1][PosY-1].equals(chess)){
samecount++;
} else right2 = false;
}
if (samecount >= 5)
return true;

samecount = 1;
right1 = true;
right2 = true;
for (int i = 1;i < WIN_COUNT && (right1 || right2);i++){//判断上下方向是否满足5连子
if (right1 && PosY+a[i] >= 1 && PosY+a[i] <= 15 && chessboard.board[PosX-1][PosY+a[i]-1].equals(chess)){
samecount++;
} else right1 = false;
if (right2 && PosY-a[i] >= 1 && PosY-a[i] <= 15 && chessboard.board[PosX-1][PosY-a[i]-1].equals(chess)){
samecount++;
} else right2 = false;
}
if (samecount >= 5)
return true;

samecount = 1;
right1 = true;
right2 = true;
for (int i = 1;i < WIN_COUNT && (right1 || right2);i++){//判断左上--右下方向是否满足5连子
if (right1 && PosX+a[i] >= 1 && PosX+a[i] <= 15 && PosY+a[i] >= 1 && PosY+a[i] <= 15 && chessboard.board[PosX+a[i]-1][PosY+a[i]-1].equals(chess)){
samecount++;
} else right1 = false;
if (right2 && PosX-a[i] >= 1 && PosX-a[i] <= 15 && PosY-a[i] >= 1 && PosY-a[i] <= 15 && chessboard.board[PosX-a[i]-1][PosY-a[i]-1].equals(chess)){
samecount++;
} else right2 = false;
}
if (samecount >= 5)
return true;

samecount = 1;
right1 = true;
right2 = true;
for (int i = 1;i < WIN_COUNT && (right1 || right2);i++){//判断左下--右上方向是否满足5连子
if (right1 && PosX-a[i] >= 1 && PosX-a[i] <= 15 && PosY+a[i] >= 1 && PosY+a[i] <= 15 && chessboard.board[PosX-a[i]-1][PosY+a[i]-1].equals(chess)){
samecount++;
} else right1 = false;
if (right2 && PosX+a[i] >= 1 && PosX+a[i] <= 15 && PosY-a[i] >= 1 && PosY-a[i] <= 15 && chessboard.board[PosX+a[i]-1][PosY-a[i]-1].equals(chess)){
samecount++;
} else right2 = false;
}
if (samecount >= 5)
return true;

return false;
}

private boolean isValid (int PosX, int PosY, int chessman){//判断输入是否合理
if (PosX < 1 || PosX > BOARD_SIZE || PosY < 1 || PosY > BOARD_SIZE){
if (chessman == man)//若判断玩家输入时的合理性时才输出这句话
System.out.println("坐标只能为小于等于" + (BOARD_SIZE) + "的正整数,请重新输入:");
return false;
}

if (!chessboard.board[PosX-1][PosY-1].equals("╋")){
if (chessman == man)
System.out.println("当前位置已有棋子,请重新输入:");
return false;
}

return true;
}

private boolean isReplay (int chessman){//判断是否开始新的一局
int x = chessboard.numChess;//表示总棋子数
int y;//表示用户落子数
if (order == 1){
if (x % 2 == 0)
y = x / 2;
else y = x / 2 + 1;
} else y = x / 2;

if (chessman == man){
chessboard.printBoard();
System.out.println("恭喜你赢了!共落子" + x + "粒。其中您落子" + y + "粒。");
} else System.out.println("很遗憾你输了!共落子" + x + "粒。其中您落子" + y + "粒。");

System.out.println("是否再来一局?(y/n)");
try {
BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
if (reader.readLine().equals("y")) {
chessboard.numChess = 0;
return true;
} else return false;
} catch (IOException e) {
e.printStackTrace();
}
return false;
}
}
-------------本文结束感谢您的阅读-------------
undefined