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

for(int k=0;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)

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

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

}

}else if(orientation == ORIENTATION_UD){

int bottomBound = (y+4)

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上运行的结果:

java实现五子棋_Java的五子棋实现相关推荐

  1. java绘制棋盘_java绘制五子棋棋盘

    本文实例为大家分享了java绘制五子棋棋盘的具体代码,供大家参考,具体内容如下 源码: import javax.imageio.ImageIO; import javax.swing.*; impo ...

  2. java五子棋_java实现五子棋

    一.需求分析 1.画一个15x15的棋盘版面 2.功能按钮:开始游戏,悔棋,认输 3.单选按钮:人人对战.人机对战 4.要求:在棋盘上下棋子,棋子必须要在交叉点上:同一个位置上不能有再下棋子:棋子不能 ...

  3. java绘制五子棋_java绘制五子棋棋盘

    免费资源网,https://freexyz.cn/ 本文实例为大家分享了java绘制五子棋棋盘的具体代码,供大家参考,具体内容如下 源码: import javax.imageio.ImageIO; ...

  4. java 网络五子棋_Java实现五子棋网络版

    本文实例为大家分享了Java实现五子棋网络版的具体代码,供大家参考,具体内容如下 需求分析: 对于网络五子棋而言,在普通五子棋的基础上需要添加以下功能: 1.拥有服务器端和客户端,用户通过客户端登录服 ...

  5. java实现五子棋_java实现五子棋

    [java]代码库import java.awt.Color; import java.awt.Font; import java.awt.Graphics; import java.awt.Tool ...

  6. java中五子棋_Java简单五子棋的实现

    在经过了几天的学习后,已经可以实现一个简单的五子棋游戏了,下面我就写一下编写程序 的过程和自己在这个过程中的心得体会. 第一步:绘制棋盘和实现落子 具体的过程就不写了,我是绘制了一个15*15的棋盘, ...

  7. java 控制台五子棋_java控制台五子棋

    package frank; import java.io.*; public class App { //棋盘 private String[][] board; //棋盘大小 private st ...

  8. 五子棋java百度文库_JAVA课程设计 五子棋(内附完整代码).doc

    JAVA课程设计 五子棋(内附完整代码) JAVA课程设计 设计题目:五子棋游戏 简要的介绍五子棋 五子棋的起源 五子棋,又被称为"连五子.五子连.串珠.五目.五目碰.五格.五石.五法.五联 ...

  9. java实训五子棋_Java棋类游戏实践之单机版五子棋

    本文实例讲述了java实现的五子棋游戏代码,分享给大家供大家参考,具体代码如下 一.实践目标 1.掌握JavaGUI界面设计 2.掌握鼠标事件的监听(MouseListener,MouseMotion ...

  10. java实现五子棋窗口_Java swing五子棋的实现方法

    今天给大家介绍一下如何用Java swing实现五子棋的开发即用Java开发图形界面程序五子棋,代码由于太多,只贴部分,最下面会附上下载地址,废话不多说,下面我们先看一下运行结果: 接下来我们看代码: ...

最新文章

  1. 加速100倍,性能媲美SOTA!浙大提出无数据知识蒸馏新方法FastDFKD
  2. 总结vue中父向子,子向父以及兄弟之间通信的几种方式
  3. Linux中防火墙(一)
  4. 不符合条件重新输入 c语言,2016年计算机考试上机应试技巧
  5. 链接h5代码_H5域名被微信拦截的原因及解决方案?
  6. 【编译原理】文法分类
  7. java中的hashset_Java中的HashSet
  8. 重写(覆盖)重载与多态
  9. Android四大组件---Activity
  10. C语言排序方法-----选择排序法
  11. Intellij Idea下tomcat设置自动编译
  12. vim 寄存器 操作_说实话,Intellij IDEA 自带的 Vim 插件真心不错。。。
  13. JMP 16 全新发布,让分析更高效、更自动化
  14. 删除mac开机启动项
  15. 解决MacOs10.15+ shimo 无法正常使用 PPTP协议问题
  16. 【转载】Aquanaut:水下变形金刚
  17. 孙鑫老师VC笔记(转)
  18. 配置 SNAT 和NAT
  19. 将 ICDAR 2015 的 Ground Truth 标注在图像数据上
  20. [1168]OSS ossutil64安装及使用

热门文章

  1. FFmpeg 的AVCodecContext结构体详解
  2. PDF转ONENOTE的方法
  3. AI绘画升温、AI写作降温,AIGC玩“变脸”
  4. 笔记本电脑开不了机怎么重装系统?小熊U盘重装win7系统教程
  5. 【精品字体】我有故事你有酒么字体
  6. java linux 时间戳转时间_java算法unix时间戳转换(java算法)
  7. js实现地图四级联动
  8. Maxon电机使用记录
  9. EAS 后台事务定时执行设置
  10. windows下如何安装ipython_Windows下IPython安装