编写一个简易的五子棋
- 要求
- 绘制棋盘 3
- 提示黑方(用 1 表示)和白方(用 2 表示)分别下棋(X,Y 轴位置) 并重新绘制棋盘。
- 每当一方下棋后判断是否获胜 。
由于代码多了看起来比较麻烦,这里选择写在多个方法里。
主体部分
思路是使用空的二维数组作为棋盘,然后给棋盘赋值网格线作为基础,打印棋盘让用户进行选择。之后接收用户的输入,并且每次落子都顺带判断胜负。
import java.util.Scanner;
public class WuZiQi {
//空棋盘
private static int[][] board = new int[16][16];
public static void main(String[] args) {
//设定棋盘 初始化 边界序号 打印棋盘
markBoard();
initBoard();
printBoard();
//接受用户输入
startGame();
}
方法startGame()
先获取落子信息,如果输入值为null说明落子位置有误,重新等待输入。
之后调用setChess()方法,来转换棋权,同时打印新落子后的棋盘。
每次落子都需要调用win()方法来判断是否胜利。
//开始游戏
private static void startGame(){
//创建循环来处理用户落子
while(true) {
Chessman chessman = getUserInput();
if(chessman == null) {
continue;
}
//落子之后重新打印棋盘
setChess(chessman);
printBoard();
if(win(chessman)) {
System.out.println("胜利");
return;
}
}
}
方法markBoard()
这个方法用于给空的二维数组赋值,来创建边界序号。
//边界序号
private static void markBoard() {
int m = 0;
for(int i = 0; i < board.length; i++) {
m = i;
for(int j = 0; j < board[i].length; j++) {
board[i][j] = m;
m++;
}
}
}
方法printBoard()
//打印棋盘
private static void printBoard() {
for (int i = 0; i < board.length; i++) {
for (int j = 0; j < board[i].length; j++) {
System.out.print(board[i][j]+"\t");
}
System.out.println();
}
}
方法initBoard()
初始化棋盘,将除了边界序号的部分都赋值为0.
//初始化棋盘
private static void initBoard() {
for (int i = 1; i < board.length; i++) {
for (int j = 1; j < board[i].length; j++) {
board[i][j] = 0;
}
}
}
方法setChess()
声明一个布尔类型的变量,通过true/false来判断是该谁下棋。每落子一次true/false值互换。
//落子 判断该谁落子
private static boolean firstMan = true;
private static void setChess( Chessman chessman) {
if(firstMan) {
board[chessman.x][chessman.y] = 1;
}else {
board[chessman.x][chessman.y] = 2;
}
firstMan = !firstMan;
}
方法getUserInput()
起初思考让用户单独输入横纵坐标,但是操作起来用户非常麻烦。所以想着使用一个string类型的数组来储存输入,长度为2,让用户输入x,y,再由split删除“,”即可,分出的两个字符串刚好放入数组中。
之后还需要对落子位置进行判断,如果在不为0的地方落子则会提示已经有棋子了。
//获取落子的位置
private static Chessman getUserInput() {
int setMan;
if(firstMan) {
setMan = 1;
}else {
setMan = 2;
}
Scanner scanner = new Scanner(System.in);
System.out.println("请" + setMan + "玩家落子");
String text = scanner.next();
String[] texts = text.split(",");
int a = -1;
int b = -1;
a = Integer.valueOf(texts[0]);
b = Integer.valueOf(texts[1]);
//如果用户输入的数值超出棋盘范围,则返回值为null
if(a < 0 || a > board.length) {
System.out.println("输入错误 请重新输入");
return null;
}
if(b < 0 || b > board.length) {
System.out.println("输入错误 请重新输入");
return null;
}
if(0 != board[a][b]) {
System.out.println("此处已经有棋子了");
return null;
}
return new Chessman(a,b);
}
方法win()
每次落子都需要进行是否胜利的判断。可以用遍历棋子所在的横 纵 斜 反斜 四个方向上的值来判断是否有连续的五子。横纵方向的判断非常好理解,只需要控制X或Y不变进行遍历即可,斜向卡壳了很久,因为在xy都有变化时总是会出现超出边界的问题。后来通过增加了if_continue语句来忽略超出边界的部分从而解决了问题。另外在思考斜线时使用的是斜率的思考方法,但是总感觉有所欠缺,需多多练习。
//获胜判断
private static boolean win( Chessman chessman) {
int count = 0;
//横向
for(int c = 1; c < board.length; c++) {
//如果横坐标和k值相等 则连子数加一
if(board[chessman.x][c] == board[chessman.x][chessman.y]) {
count++;
}else {
count = 0;
}
if(count == 5) {
return true;
}
}
//纵向
for(int c =1; c < board.length; c++) {
if(board[c][chessman.y] == board[chessman.x][chessman.y]) {
count++;
}else {
count = 0;
}
if(count == 5) {
return true;
}
}
//斜向下
int z1 =chessman.x - chessman.y;
//System.out.println("零点是" + z1);
for (int k = 0; k < board.length; z1++, k++) {
if (z1 >= board.length || z1 < 0) {
continue;
}
if (board[z1][k] ==(board[chessman.x][chessman.y])) {
count++;
} else {
count = 0;
}
if (count == 5) {
return true;
}
}
//斜向上
int z2 = chessman.y+chessman.x;
for(int k = 1; k < board.length; k++) {
if(z2 >= board.length || z2 < k) {
continue;
}
if(board[z2-k][k] == board[chessman.x][chessman.y]) {
count++;
} else {
count = 0;
}
if (count == 5) {
return true;
}
}
return false;
}
}
声明一个Chessman类。
public class Chessman{
public int x;
public int y;
Chessman(int x ,int y){
this.x = x;
this.y = y;
}
}
其中一个次的输出结果