Java的五子棋实现,java开发面试笔试题


我总结出了很多互联网公司的面试题及答案,并整理成了文档,以及各种学习的进阶学习资料,免费分享给大家。
扫描二维码或搜索下图红色VX号,加VX好友,拉你进【程序员面试学习交流群】免费领取。也欢迎各位一起在群里探讨技术。
推荐文章:Java 面试知识点解析Mysql优化技巧(数据库设计、命名规范、索引优化

 

 

 

Java 五子棋

注:除机器人算法外其余借鉴于MLDN。

package MyFiveChess;

import robot.*;

import java.awt.*;

import javax.swing.*;

public class Gobang {

    public static void main(String[] args) {

        EventQueue.invokeLater(() -> {

            JFrame frame = new MyFiveChessFrame(new StupidRobot());

            frame.setTitle("五子棋");

            frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);

            frame.setVisible(true);

        });

    }

}

创建一个名为MyFiveChess的包,类名为Gobang,主方法中调用机器人类(StudipRobot)创建一个JFrame的框架,名为五子棋。

package MyFiveChess;

import robot.*;

import java.awt.Color;

import java.awt.Dimension;

import java.awt.Font;

import java.awt.Graphics;

import java.awt.Image;

import java.awt.event.MouseEvent;

import java.awt.event.MouseListener;

import javax.swing.ImageIcon;

import javax.swing.JComponent;

import javax.swing.JFrame;

import javax.swing.JOptionPane;

class MyFiveChessFrame extends JFrame

{

   public MyFiveChessFrame(IRobot robot)

   {

      add(new ImageComponent(robot));

      pack();

   }

}

/**

 * A component that displays a tiled image

 */

class ImageComponent extends JComponent implements MouseListener

{

   private static final int DEFAULT_WIDTH = 500;//因为图片的大小为500*500,

   private static final int DEFAULT_HEIGHT = 500;//所以这里设置组件大小也为500*500

   int x;                                 //原图是没有棋盘的,这里我们要自己画

   int y;                                 //棋盘,故需要全局变量来获取棋盘坐标

   int allchess[][] = new int[16][16];    //构造一个数组来存取当前局势情况

   boolean isBlack = true;                //0代表没有棋,1代表黑子,2代表白子

   boolean canPlay = true;//isBlack是用来说明当前应该是黑子或者白子落棋                

   private Image image;   //canPlay是用来设置当游戏结束后不能够再落子

   private IRobot iRobot; //用来存储传入构造器的iRobot

   private String string = "It's Black";  //图片上当前会显示该黑子落棋

   

   public ImageComponent(IRobot iRobot)

   {

       this.iRobot = iRobot;    

       addMouseListener(this); //要实现当点击鼠标就发生响应就必须实现MouseListener接口

       image = new ImageIcon("background.jpg").getImage();

   }                           //背景图在最下面会贴出来的

   public void paint(Graphics g) //构造paint方法

   {

      if (image == null) return;

     

      g.drawImage(image, 0, 0, null);

      

      g.setFont(new Font("宋体", 0, 16));

      g.setFont(new Font("Times New Roman", 0, 27));

      g.drawString(string, 135, 34);

      

      for (int i = 0; i < 16; i++) {//这里是在画棋盘(国际棋盘大小15*15)

        g.drawLine(10, 50 + i*24, 369, 50 + i*24);

        g.drawLine(10 + i*24, 50, 10 + i*24, 410);

    } 

      

      

      for (int i = 0; i < 16; i++) {

        for(int j = 0; j < 16; j++)

        {

            if(allchess[i][j] == 1) {//为1时是黑子,这里需要调用fillOval方法画圆

            int tempx = i * 24 + 10; 

            int tempy = j * 24 + 50;

            g.fillOval(tempx-7, tempy-7, 14, 14);

            }

            if (allchess[i][j] == 2) {//当白子的时候需要画一个白色的圆再添加一个黑色的框

                int tempx = i * 24 + 10;

                int tempy = j * 24 + 50;

                g.setColor(Color.WHITE);

                g.fillOval(tempx-7, tempy-7, 14, 14);

                g.setColor(Color.BLACK);

                g.drawOval(tempx-7, tempy-7, 14, 14);

            }

        }

        

    }

   }

   

   public Dimension getPreferredSize() { return new Dimension(DEFAULT_WIDTH, DEFAULT_HEIGHT); }

SuppressWarnings("deprecation")

@Override

public void mouseClicked(MouseEvent e) {//下面就是实现游戏界面右边的几个功能

    // TODO Auto-generated method stub

    if (x>400 && x<470 && y>50 && y<80) {

        int restart = JOptionPane.showConfirmDialog(this, "是否确认重新开始游戏");

        if (restart == 0) {

            allchess = new int[16][16];

            string = "It's Black";

            isBlack = true;     

            this.repaint();

        }

    }

    if (x>400 && x<470 && y>100 && y<130) {

        String input = JOptionPane.showInputDialog("请输入最大下棋时间(单位分),0代表无限制:");//这部分功能没有实现,本来是想用线程来实现一个游戏倒计时功能的,但是因为某些原因就放弃了

    }

    if (x>400 && x<470 && y>150 && y<180) {

        JOptionPane.showMessageDialog(this, "五子棋你都不会下么,如果不会,请参见百度,谢谢!");

    }

    if (x>400 && x<470 && y>250 && y<280) {

        int abandoning = JOptionPane.showConfirmDialog(this, "已经决定了么");

        if (abandoning == 0) {

            if(isBlack) JOptionPane.showMessageDialog(this, "黑方认输");

            canPlay = false;

            System.exit(0);

        }

    

    }

    if (x>400 && x<470 && y>300 && y<330) {

        JOptionPane.showMessageDialog(this, "本软件由杨易大佬与曾鑫开发,若有问题,请自行解决.");

    }

    if (x>400 && x<470 && y>350 && y<380) {

        int Continue = JOptionPane.showConfirmDialog(this, "不再玩一会么");

        if(Continue == 0) {

            JOptionPane.showMessageDialog(this, "大爷再见,欢迎下次再来。");

            System.exit(0);

        }

    }

}

@Override

public void mousePressed(MouseEvent e) {

    // TODO Auto-generated method stub

    //System.out.println("X" + e.getX());//在划线之前要确认坐标,需要输出坐标

    //System.out.println("Y" + e.getY());

        

    if (canPlay == true) { 

        x = e.getX();

        y = e.getY();

        if (x>10 && x<369 && y>49 && y<408) {

            float xxx = (float) 24.0;

            x = Math.round((x - 10)/xxx);//实现坐标的4舍5入

            y = Math.round((y - 49)/xxx);

            if(allchess[x][y] == 0)

            {

                if (isBlack == true) {

                    allchess[x][y] = 1;

                    iRobot.retrieveGameBoard(allchess);//该机器人下棋时,需要将现在棋盘的局势传递过去

                    isBlack = false;

                    string = "It's White";

                    boolean winFlag = this.checkWin();//每下一次棋时都需要检查是否胜出

                    if (winFlag == true) {

                        JOptionPane.showMessageDialog(this, "Game over"+(allchess[x][y]==1 ? "Black" : "White") + "winned");

                        canPlay = false;

                    }

                    RobotAction();//机器人下棋

                    this.repaint();

                }

            }

            else {

                JOptionPane.showMessageDialog(this, "Please play chess in the chessboard");

            }

        }

        

    }

}

void RobotAction(){

    

    Pair pair = iRobot.getDeterminedPos();//机器人类将返回一个pair类回来

    x = pair.x;

    y= pair.y;

    allchess[x][y] = 2;

    isBlack = true;

    string = "It's Black";

    

    boolean winFlag = this.checkWin();

    if (winFlag == true) {

        JOptionPane.showMessageDialog(this, "Game over"+(allchess[x][y]==1 ? "Black" : "White") + " winned");

        canPlay = false;

    }

}

@Override

public void mouseReleased(MouseEvent e) {

    // TODO Auto-generated method stub

    

}

@Override

public void mouseEntered(MouseEvent e) {

    // TODO Auto-generated method stub

    

}

@Override

public void mouseExited(MouseEvent e) {

    // TODO Auto-generated method stub

    

}

private boolean checkWin() {//检测当前是否由五子连线的方法,简述一下,这个方法其实很简单,只要我们在每一次落子的时候检查是否由五子连线就可以确保一旦有人胜出,我们就可以马上发现。先检查横线和竖线,再检查左右斜线。

        

    boolean flag = false; //设置的标志,当由五子连线时就返回flag=false

    int count = 1;        //计数当前由几颗棋子相连

    int color = allchess[x][y];

    int i = 1;

    

    while(((x+i)<16)&&color == allchess[x+i][y]) {

        count++;

        i++;

        }

    i = 1;

    while(((x-i)>=1)&&color == allchess[x-i][y]) {

        count++;

        i++;

        }

    if(count>=5)

        {flag = true;}

    //?????ж?

    int count2 = 1;

    int i2 = 1;

    while(((y+i2)<16)&&color == allchess[x][y+i2]) {

        count2++;

        i2++;

        }

    i = 1;

    while(((y-i2)>=1)&&color == allchess[x][y-i2]) {

        count2++;

        i2++;

        }

    if(count2>=5)

        {flag = true;}

    

    int count3 = 1;

    int i3 = 1;

    while(((y-i3)>=1)&&((x+i3)<16)&&color == allchess[x+i3][y-i3]) {

        count3++;

        i3++;

        }

    i = 1;

    while(((x-i3)>=1)&&((y+i3)<16)&&color == allchess[x-i3][y+i3]) {

        count3++;

        i3++;

        }

    if(count3>=5)

        {flag = true;}

    int count4 = 1;

    int i4 = 1;

    while(((y-i4)>=1)&&((x-i4)>=1)&&color == allchess[x-i4][y-i4]) {

        count4++;

        i4++;

        }

    i = 1;

    while(((x+i4)<16)&&((y+i4)<16)&&color == allchess[x+i4][y+i4]) {

        count4++;

        i4++;

        }

    if(count4>=5)

        {flag = true;}

    

    return flag;

    

   }

}

这段代码有点长,但是并不难,大家仔细看下就会明白的。

下面贴出机器人的代码:

package robot;

import java.util.Random;

public interface IRobot {

    static final Random rand = new Random();

    /**

     * There we provide a default implementation to simulate robot's behavior

     *

     * @return a {@code robot.Pair} which contains a valid (x,y) position

     */

    default Pair getDeterminedPos() {

        return new Pair(rand.nextInt(15) + 1, rand.nextInt(15) + 1);

    }

    /**

     * This method is used to retrieve game board such that robot can determine its (x,y) position

     * @param gameBoard the 2-dimension array to represent the game board

     */

    void retrieveGameBoard(int[][] gameBoard);

}
package robot;

public class Pair {

    public int x;

    public int y;

    public Pair(){}

    public Pair(int x, int y) {

        this.x = x;

        this.y = y;

    }

}
package robot;

public class StupidRobot implements IRobot {

    private static final int BOARD_SIZE = 15;

    private static final int ROLE_OPPONENT = 1;

    private static final int ROLE_ROBOT = 2;

    private static final int ROLE_NON = 0;

    private static final int ORIENTATION_LR = 0;

    private static final int ORIENTATION_UD = 1;

    private static final int ORIENTATION_LT_RD = 2;

    private static final int ORIENTATION_RT_LD = 3;

    private int[][] boardRef = null;

    /**

     * There we provide a default implementation to simulate robot's behavior

     *

     * @return a {@code robot.Pair} which contains a valid (x,y) position

     */

    @Override

    public Pair getDeterminedPos() {

        int[][] situationRobot  = new int[boardRef.length][boardRef[0].length];

        int[][] situationOpponent  = new int[boardRef.length][boardRef[0].length];

        int maxRobotScore = 0;

        Pair maxRobotPoint = new Pair();

        int maxOpponentScore = 0;

        Pair maxOpponentPoint = new Pair();

        for(int i=0;i<BOARD_SIZE;i++){

            for(int k=0;k<BOARD_SIZE;k++){

                if(boardRef[i][k]!=ROLE_NON){

                    situationOpponent[i][k]=situationRobot[i][k]=0;

                }else{

                    boardRef[i][k] = ROLE_OPPONENT;

                    situationOpponent[i][k] = evaluateScore(ROLE_OPPONENT,i,k);

                    boardRef[i][k]=ROLE_NON;

                    if(situationOpponent[i][k]>maxOpponentScore){

                        maxOpponentScore = situationOpponent[i][k];

                        maxOpponentPoint.x = i;

                        maxOpponentPoint.y = k;

                    }

                    boardRef[i][k]=ROLE_ROBOT;

                    situationRobot[i][k]=evaluateScore(ROLE_ROBOT,i,k);

                    boardRef[i][k]=ROLE_NON;

                    if(situationRobot[i][k]>maxRobotScore){

                        maxRobotScore = situationRobot[i][k];

                        maxRobotPoint.x = i;

                        maxRobotPoint.y = k;

                    }

                }

            }

        }

        if(maxRobotScore > maxOpponentScore || maxRobotScore==Integer.MAX_VALUE){

            return maxRobotPoint;

        }else{

            return maxOpponentPoint;

        }

    }

    /**

     * This method is used to retrieve game board such that robot can determine its (x,y) position

     *

     * @param gameBoard the 2-dimension array to represent the game board

     */

    @Override

    public void retrieveGameBoard(int[][] gameBoard) {

        boardRef = gameBoard;

    }

    /**

     * The policy of evaluating was referred to https://www.cnblogs.com/maxuewei2/p/4825520.html

     * @param role the role of current player

     * @param x position x

     * @param y position y

     * @param orientation orientation of determining line

     * @return

     */

    private int patternRecognition(int role, int x,int y,int orientation){

        StringBuilder sb = new StringBuilder();

        if(orientation==ORIENTATION_LR){

            int leftBound = (x - 4)>=0?x-4:0;

            int rightBound = (x +4)<BOARD_SIZE?x+4:BOARD_SIZE-1;

            for(int i=leftBound;i<=rightBound;i++){

                sb.append(boardRef[i][y]);

            }

        }else if(orientation == ORIENTATION_UD){

            int bottomBound = (y+4)<BOARD_SIZE?y+4:BOARD_SIZE-1;

            int topBound = (y-4)>=0?y-4:0;

            for(int i=topBound;i<=bottomBound;i++){

                sb.append(boardRef[x][i]);

            }

        }else if(orientation== ORIENTATION_LT_RD){

            int leftBound = 0,rightBound = 0,bottomBound = 0,topBound = 0;

            

           for(int i=1;i<=4;i++){

               leftBound = x-i;

               topBound = y-i;

               if(leftBound<0||topBound<0){

                   leftBound++;

                   topBound++;

                   break;

               }

           }

           for(int k=1;k<=4;k++){

               rightBound = x+k;

               bottomBound = y+k;

               if(rightBound>BOARD_SIZE||bottomBound>BOARD_SIZE){

                   rightBound--;

                   bottomBound--;

                   break;

               }

           }

            for(int i=topBound,k=leftBound;i<=bottomBound && k<=rightBound;i++,k++){

                sb.append(boardRef[k][i]);

            }

        }else if(orientation== ORIENTATION_RT_LD){

            int leftBound = 0,rightBound = 0,bottomBound = 0,topBound = 0;

            for(int i=1;i<=4;i++){

                rightBound = x+i;

                topBound = y-i;

                if(rightBound>BOARD_SIZE||topBound<0){

                    rightBound--;

                    topBound++;

                    break;

                }

            }

            for(int k=1;k<=4;k++){

                leftBound = x-k;

                bottomBound = y+k;

                if(leftBound<0||bottomBound>BOARD_SIZE){

                    leftBound++;

                    bottomBound--;

                    break;

                }

            }

            for(int i=topBound,k=rightBound;i<=bottomBound && k>=leftBound;i++,k--){

                sb.append(boardRef[k][i]);

            }

        }

        String str = sb.toString();

        if(str.contains(role == ROLE_ROBOT ? "22222" : "11111")){

            return Integer.MAX_VALUE;

        }

        if(str.contains(role == ROLE_ROBOT ? "022220" : "011110")){

            return 300000;

        }

        if(str.contains(role == ROLE_ROBOT ? "22202" : "11101") ||

                str.contains(role == ROLE_ROBOT ? "20222" : "10111")){

            return 3000;

        }

        if(str.contains(role == ROLE_ROBOT ? "0022200" : "0011100")){

            return 3000;

        }

        if(str.contains(role == ROLE_ROBOT ? "22022" : "11011")){

            return 2600;

        }

        if(str.contains(role == ROLE_ROBOT ? "22220" : "11110")||

            str.contains(role == ROLE_ROBOT ? "02222" : "01111")){

            return 2500;

        }

        if(str.contains(role == ROLE_ROBOT ? "020220" : "010110")||

                str.contains(role == ROLE_ROBOT ? "022020" : "011010")){

            return 800;

        }

        if(str.contains(role == ROLE_ROBOT ? "00022000" : "00011000")){

            return 650;

        }

        if(str.contains(role == ROLE_ROBOT ? "20022" : "10011")||

                str.contains(role == ROLE_ROBOT ? "22002" : "11001")){

            return 600;

        }

        if(str.contains(role == ROLE_ROBOT ? "20202" : "10101")){

            return 550;

        }

        if(str.contains(role == ROLE_ROBOT ? "22200" : "11100")||

                str.contains(role == ROLE_ROBOT ? "00222" : "00111")){

            return 500;

        }

        if(str.contains(role == ROLE_ROBOT ? "0020200" : "0010100")){

            return 250;

        }

        if(str.contains(role == ROLE_ROBOT ? "020020" : "010010")){

            return 200;

        }

        if(str.contains(role == ROLE_ROBOT ? "22000" : "11000")||

                str.contains(role == ROLE_ROBOT ? "00022" : "00011")){

            return 150;

        }

        return 0;

    }

    private int evaluateScore(int role,int x, int y){

        int a = patternRecognition(role,x,y,ORIENTATION_RT_LD);

        int b = patternRecognition(role,x,y,ORIENTATION_LT_RD);

        int c = patternRecognition(role,x,y,ORIENTATION_UD);

        int d = patternRecognition(role,x,y,ORIENTATION_LR);

        return Math.max(Math.max(Math.max(a,b),c),d);

    }

}

好吧,机器人类的代码不是我写的,所以我没有发言权,如果大家想实现的是人机对棋就研究一下这段代码,如果不是那就可以跳过了,只要修改下我最开始贴出的代码就好了。╮(╯-╰)╭


以下是再Eclipse和打包成exe上运行的结果:





 


转载:https://www.cnblogs.com/DevLegal/p/8831894.html

推荐内容:
JAVA多线程和并发基础面试问答
JAVA多线程和并发基础面试题
java执行Shell命令
40个Java多线程面试问题
java面试题整理
Java在常见的spring面试问题TOP50
最新Java校招面试题及答案
Java面试题——中级(下)
JAVA工程师面试题库
JAVA面试相关

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值