准备工作
1.1材料代码
static String white = "☆"; //用来表示白棋
static String black = "★"; //用来表示黑棋
static String[][] qp = new String[15][15]; //制作棋盘的数组
static String[] num = {"⒈", "⒉", "⒊", "⒋", "⒌", "⒍", "⒎", "⒏", "⒐", "⒑", "⒒", "⒓", "⒔", "⒕", "⒖"};
static String line = "十"; //制作棋盘的材料
1.2建立主方法main
public staic void main(String[]args){
}
制作棋盘
制作如下图所示的棋盘。棋盘由数字和十字符号组成。构建两个方法paintqp(绘制棋盘)和printqp(输出棋盘)。其中绘制棋盘主要是利用for循环给二维数组qp对应的下标赋值。输出棋盘主要是用for循环遍历输出二维数组qp。
public static void paintqp() { //绘制棋盘
for (int i = 0; i < qp.length - 1; i++) { //棋盘是15×15式,但最后一列和最后一行都是num数组输出的,所以字符串Line实际是14×14
for (int j = 0; j < qp[i].length - 1; j++) { //这里循环条件写j<qp.length也可以,因为两个值是一样的。
qp[i][j] = line;
}
for (int m = 0; m < qp.length; m++) { //给最后一列赋num数组。
for (int n = 0; n < qp[m].length; n++) {
if (n == qp[m].length - 1) { //判断是否到最后一列
qp[m][n] = num[m];
}
}
}
for (int k = 0; k < qp.length; k++) { //给最后一行赋num数组。
for (int l = 0; l < qp[k].length - 1; l++) {
if (k == qp.length - 1) { //判断是否到最后一行
qp[k][l] = num[l];
}
}
}
}
}
public static void printqp() { //循环遍历输出棋盘
for (int i = 0; i < qp.length; i++) {
for (int j = 0; j < qp.length; j++) {
System.out.print(qp[i][j]);
}
System.out.println();
}
}
下棋
五子棋分为黑白两方,一般由黑方先下;因此我们可以定义一个布尔型变量flag,flag为真黑方下子,flag为假白方下子。由于在下棋时一直需要重复这段操作,所以加上一个while(true)无限循环。定义方法为start。
public static void start() { //下棋
while (true) {
if (flag) {
System.out.println("请黑棋下子");
} else {
System.out.println("请白棋下子");
}
}
}
下棋细节
下棋我们需要用到Scanner类来进行输入,我们定义一个y坐标和一个x坐标来确定棋子的位置。x方向应该向右,y方向向下,坐标原点在棋盘左上方。可以看到y是二维数组里的行数,x是二维数组里的列数。所以输出坐标时注意y和x在数组的位置。
其次要注意我们看到的位置和对应的下标,例如我们看到的是第一行第一列,实际对应的下标是0,0。当下子成功后改变二维数组对应坐标的值并重新输出棋盘。
定义方法为game。
public static void game() { //下棋的细节
int y = s.nextInt() - 1;
int x = s.nextInt() - 1; //我们看到的第1行第1个,坐标应该是第0行第0个,以此类推;所以输入后要减1
boolean con = check(x, y); //接受方法check的返回值
if (con && flag) { //若都为真,那么应该是黑棋的回合
qp[y][x] = black; //坐标相应位置变为黑棋
printqp(); //下完后更新棋盘
flag = false;//转到白棋回合
} else if (con && flag == false) { //若false为假,con为真,那么应该是白棋的回合
qp[y][x] = white; //坐标相应位置变为白棋
printqp();
flag = true;//转到黑棋回合
} else {
System.out.println("输入错误,请重新输入"); //如果con为假,那就证明输入有错误
}
}
下棋时我们需要注意以下两点,第一:棋子不能超过棋盘边界,第二:在有棋子的位置不能重复落子。 定义方法为check
public static boolean check(int x, int y) { //判断是否可以下棋
if (y < 0 || y > qp.length - 1 || x < 0 || x > qp.length - 1) { //输入的坐标是否超出边界
return false;
}
if (!qp[y][x].equals(line)) { //输入的坐标是否已经有棋子
return false;
} else {
return true;
}
}
判断输赢
当每次一方下完棋后都需要判断输赢。 五子棋胜利条件即相同颜色任意方向相连数量至少5个。
我们可以写四个方法用来判断执棋方是否已经胜利。其中水平左右方主要是x坐标的移动,垂直上下方主要是y坐标的移动。左右斜x,y坐标都要移动。再定义一个方法win将四个方法综合起来判断最终结果。
public static boolean win(int x,int y, String color) {//判断胜利
boolean one = standard(x,y,color);
boolean two = vertical(x,y,color);
boolean three = lincline(x,y,color);
boolean four = rlincline(x,y,color);
if(one||two||three||four){
return true;
}
return false;
}
public static boolean standard(int x, int y, String color) { //判断水平是否胜利
int spsum = 1;
for (int lx = x - 1; lx >= 0; lx--) { //判断左水平是否胜利
if (qp[y][lx].equals(color)) {
spsum++; //相同颜色相连则计数加1,其余类似
} else {
break; //如果没有相同颜色相连直接终止左水平,其余类似
}
if (spsum >= 5) {
return true; //左水平数量至少五个则胜利,其余类似
}
}
for (int rx = x + 1; rx < qp.length; rx++) { //判断右水平是否胜利
if (qp[y][rx].equals(color)) {
spsum++;
} else {
break;
}
if (spsum >= 5) {
return true;
}
}
return false; //没有胜利,其余类似
}
public static boolean vertical(int x, int y, String color){ //判断垂直是否胜利
int czsum=1;
for (int uy = y - 1; uy >= 0; uy--) { //判断上方是否胜利
if (qp[uy][x].equals(color)) {
czsum++;
}
else{
break;
}
if (czsum >= 5) {
return true;
}
}
for (int dy = y + 1; dy < qp.length; dy++) { //判断下方是否胜利
if (qp[dy][x].equals(color)) {
czsum++;
}
else{
break;
}
if (czsum >= 5) {
return true;
}
}
return false;
}
public static boolean lincline(int x,int y,String color){ //判断左斜是否胜利
int lqxsum=1;
for(int lxux=x-1,lxuy=y-1;lxux>=0&&lxuy>=0;lxux--,lxuy--){ //判断左斜上方是否胜利
if (qp[lxuy][lxux].equals(color)) {
lqxsum++;
}
else{
break;
}
if (lqxsum >= 5) {
return true;
}
}
for(int lxdx=x+1,lxdy=y+1;lxdx<qp.length&&lxdy<qp.length;lxdx++,lxdy++){ //判断左斜下方是否胜利
if (qp[lxdy][lxdx].equals(color)) {
lqxsum++;
}
else{
break;
}
if (lqxsum >= 5) {
return true;
}
}
return false;
}
public static boolean rlincline(int x,int y,String color){ //判断右斜是否胜利
int rqxsum=1;
for(int rxux=x+1,rxuy=y-1;rxux<qp.length&&rxuy>=0;rxux++,rxuy--){ //判断右斜上方是否胜利
if (qp[rxuy][rxux].equals(color)) {
rqxsum++;
}
else{
break;
}
if (rqxsum >= 5) {
return true;
}
}
for(int rxdx=x-1,rxdy=y+1;rxdx>=0&&rxdy<qp.length;rxdx--,rxdy++){ //判断右斜下方是否胜利
if (qp[rxdy][rxdx].equals(color)) {
rqxsum++;
}
else{
break;
}
if (rqxsum >= 5) {
return true;
}
}
return false;
}
}
问题汇总
6.1判断输赢
最开始判断输赢里没有加入return false语句,导致一直提示错误
原因在于我没有完全理解 return语句,return最主要的作用在于它在返回值时同时会停止对这段代码的执行,也就是说,当判断为胜利时判断输赢的方法会直接返回true值,根本不会再执行后面的代码。
6.2胜利后执行的操作
问题:胜利后虽然提示胜利,但是下棋仍然在继续,例如黑棋胜利后,仍会让白棋继续出子。
方案:在判断胜利后,重新开始绘制并打印棋盘即重新开始游戏。
6.3白棋胜利后的小问题
问题:黑棋胜利后会显示黑棋胜利,然后重新开始游戏,但是白棋胜利后显示完白棋胜利,因为flag值仍为false,所以重新开始时会让白子重新下棋。 但目的是不论哪方胜利重新开始后都由黑方先下棋。
方案: 在输出后加入flag=true;
完整代码和结果展示
7.1完整代码
上面只讨论了每个部分应该怎么操作,但具体在什么位置调用什么方法并没有说。这里不做过多详细说明。以下是完整代码
import java.util.Scanner;
public class wzq {
static String white = "☆";
static String black = "★";
static String[][] qp = new String[15][15];
static String[] num = {"⒈", "⒉", "⒊", "⒋", "⒌", "⒍", "⒎", "⒏", "⒐", "⒑", "⒒", "⒓", "⒔", "⒕", "⒖"};
static String line = "十";
static boolean flag = true;
static Scanner s = new Scanner(System.in);
public static void main(String[] args) {
paintqp();
printqp();
start();
}
public static void paintqp() { //绘制棋盘
for (int i = 0; i < qp.length - 1; i++) { //棋盘是15×15式,但最后一列和最后一行都是num数组输出的,所以字符串Line实际是14×14
for (int j = 0; j < qp[i].length - 1; j++) { //这里循环条件写j<qp.length也可以,因为两个值是一样的。
qp[i][j] = line;
}
for (int m = 0; m < qp.length; m++) { //给最后一列赋num数组。
for (int n = 0; n < qp[m].length; n++) {
if (n == qp[m].length - 1) { //判断是否到最后一列
qp[m][n] = num[m];
}
}
}
for (int k = 0; k < qp.length; k++) { //给最后一行赋num数组。
for (int l = 0; l < qp[k].length - 1; l++) {
if (k == qp.length - 1) { //判断是否到最后一行
qp[k][l] = num[l];
}
}
}
}
}
public static void printqp() { //循环遍历输出棋盘
for (int i = 0; i < qp.length; i++) {
for (int j = 0; j < qp.length; j++) {
System.out.print(qp[i][j]);
}
System.out.println();
}
}
public static void start() { //下棋
while (true) {
if (flag) {
System.out.println("请黑棋下子");
game();
} else {
System.out.println("请白棋下子");
game();
}
}
}
public static void game() { //下棋的细节
int y = s.nextInt() - 1;
int x = s.nextInt() - 1; //我们看到的第1行第1个,坐标应该是第0行第0个,以此类推;所以输入后要减1
boolean con = check(x, y); //接受方法check的返回值
if (con && flag) { //若都为真,那么应该是黑棋的回合
qp[y][x] = black; //坐标相应位置变为黑棋
printqp(); //下完后更新棋盘
boolean biswin=win(x,y,black);
if(biswin){
System.out.println("黑棋胜");
paintqp();
printqp();
start();
}
else {
flag = false;//没胜利转到白棋回合
}
} else if (con && flag == false) { //若false为假,con为真,那么应该是白棋的回合
qp[y][x] = white; //坐标相应位置变为白棋
printqp();
boolean wiswin=win(x,y,white);
if(wiswin){
System.out.println("白棋胜");
flag = true; //保证重新开始游戏时仍是黑方先下棋
paintqp(); //重新开始游戏
printqp();
start();
}
else {
flag = true;//没胜利转到黑棋回合
}
} else {
System.out.println("输入错误,请重新输入"); //如果con为假,那就证明输入有错误
}
}
public static boolean check(int x, int y) { //判断是否可以下棋
if (y < 0 || y > qp.length - 1 || x < 0 || x > qp.length - 1) { //输入的坐标是否超出边界
return false;
}
if (!qp[y][x].equals(line)) { //输入的坐标是否已经有棋子
return false;
} else {
return true;
}
}
public static boolean win(int x,int y, String color) {//判断胜利
boolean one = standard(x,y,color);
boolean two = vertical(x,y,color);
boolean three = lincline(x,y,color);
boolean four = rlincline(x,y,color); //分别接收四个判断方法的返回值
if(one||two||three||four){
return true;
}
return false;
}
public static boolean standard(int x, int y, String color) { //判断水平是否胜利
int spsum = 1;
for (int lx = x - 1; lx >= 0; lx--) { //判断左水平是否胜利
if (qp[y][lx].equals(color)) {
spsum++; //相同颜色相连则计数加1,其余类似
} else {
break; //如果没有相同颜色相连直接终止左水平,其余类似
}
if (spsum >= 5) {
return true; //左水平数量至少五个则胜利,其余类似
}
}
for (int rx = x + 1; rx < qp.length; rx++) { //判断右水平是否胜利
if (qp[y][rx].equals(color)) {
spsum++;
} else {
break;
}
if (spsum >= 5) {
return true;
}
}
return false; //没有胜利,其余类似
}
public static boolean vertical(int x, int y, String color){ //判断垂直是否胜利
int czsum=1;
for (int uy = y - 1; uy >= 0; uy--) { //判断上方是否胜利
if (qp[uy][x].equals(color)) {
czsum++;
}
else{
break;
}
if (czsum >= 5) {
return true;
}
}
for (int dy = y + 1; dy < qp.length; dy++) { //判断下方是否胜利
if (qp[dy][x].equals(color)) {
czsum++;
}
else{
break;
}
if (czsum >= 5) {
return true;
}
}
return false;
}
public static boolean lincline(int x,int y,String color){ //判断左斜是否胜利
int lqxsum=1;
for(int lxux=x-1,lxuy=y-1;lxux>=0&&lxuy>=0;lxux--,lxuy--){ //判断左斜上方是否胜利
if (qp[lxuy][lxux].equals(color)) {
lqxsum++;
}
else{
break;
}
if (lqxsum >= 5) {
return true;
}
}
for(int lxdx=x+1,lxdy=y+1;lxdx<qp.length&&lxdy<qp.length;lxdx++,lxdy++){ //判断左斜下方是否胜利
if (qp[lxdy][lxdx].equals(color)) {
lqxsum++;
}
else{
break;
}
if (lqxsum >= 5) {
return true;
}
}
return false;
}
public static boolean rlincline(int x,int y,String color){ //判断右斜是否胜利
int rqxsum=1;
for(int rxux=x+1,rxuy=y-1;rxux<qp.length&&rxuy>=0;rxux++,rxuy--){ //判断右斜上方是否胜利
if (qp[rxuy][rxux].equals(color)) {
rqxsum++;
}
else{
break;
}
if (rqxsum >= 5) {
return true;
}
}
for(int rxdx=x-1,rxdy=y+1;rxdx>=0&&rxdy<qp.length;rxdx--,rxdy++){ //判断右斜下方是否胜利
if (qp[rxdy][rxdx].equals(color)) {
rqxsum++;
}
else{
break;
}
if (rqxsum >= 5) {
return true;
}
}
return false;
}
}
7.2结果展示
以上为简易五子棋的制作过程。