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



Java的五子棋实现的更多相关文章

  1. [Java]局域网五子棋

    提示: 下面给的代码有问题哦,可以自己去调试 可用版下载 请点击这里 密码:x6ve(退出程序,端口并没有被关闭,可自行修改代码实现) img

  2. Java控制台五子棋(纯算法)

    Java五子棋小游戏 本方案是基于控制台写的一个代码 没有花里胡哨的界面,只为研究算法 仅仅用了200行代码 下面是的是运行结果 游戏运行结果 这里我就很简单的复制了一个结果 第9回合,下子方:玩家2 ...

  3. Java 判断五子棋五子相连

    #开始 最近在忙着做一个基于酷Q的QQ机器人,想到了做游戏,第一个想到的霸气点的游戏就是五子棋啊  ` _>` 因为没有图形界面的原因 所有核心就是判断是否在棋盘上出现了五个棋子连在一起的情况 ...

  4. Java实现五子棋

    代码: package com.hotusm.datastructure.list; import com.hotusm.datastructure.Log; /** * @author luqiba ...

  5. JAVA上百实例源码以及开源项目

    简介 笔者当初为了学习JAVA,收集了很多经典源码,源码难易程度分为初级.中级.高级等,详情看源码列表,需要的可以直接下载! 这些源码反映了那时那景笔者对未来的盲目,对代码的热情.执着,对IT的憧憬. ...

  6. 158个JAVA免豆精品资料汇总

    附件完整版下载地址: http://down.51cto.com/data/431561 附件部分预览~ java中国移动收费系统[源代码] http://down.51cto.com/data/70 ...

  7. 【转】【JAVA资料免费下载】158个JAVA免豆精品资料汇总——下载目录

    附件完整版下载地址: http://down.51cto.com/data/431561 附件部分预览~ java中国移动收费系统[源代码] http://down.51cto.com/data/70 ...

  8. JAVA上百实例源码网站

    JAVA源码包1JAVA源码包2JAVA源码包3JAVA源码包4 JAVA开源包1 JAVA开源包2 JAVA开源包3 JAVA开源包4 JAVA开源包5 JAVA开源包6 JAVA开源包7 JAVA ...

  9. Spark案例分析

    一.需求:计算网页访问量前三名 import org.apache.spark.rdd.RDD import org.apache.spark.{SparkConf, SparkContext} /* ...

随机推荐

  1. Python内置函数(65)——staticmethod

    英文文档: staticmethod(function) Return a static method for function. A static method does not receive a ...

  2. emqtt 试用(三)mqtt 知识

    一.概念 MQTT 协议客户端库: https://github.com/mqtt/mqtt.github.io/wiki/libraries 例如,mosquitto_sub/pub 命令行发布订阅 ...

  3. 新概念英语(1-105)Full Of Mistakes

    Lesson 105 Full of mistakes 错误百出 Listen to the tape then answer this question. What was Sandra's pre ...

  4. RTSP连接中断重连的问题

    最近在调查的一个问题. 起因是我司的一款数据链产品,15km数字图传,测试时发现视频画面经常会出现马赛克或卡顿. 图传设置了10Mbps速率,而视频码流是4Mbps,按道理不应该出现这种问题. 经过几 ...

  5. [LuoguP1113] 杂物 - 拓扑排序

    其实只是纪念下第一篇洛谷题解? Description John的农场在给奶牛挤奶前有很多杂务要完成,每一项杂务都需要一定的时间来完成它.比如:他们要将奶牛集合起来,将他们赶进牛棚,为奶牛清洗乳房以及 ...

  6. Spark:性能调优

    来自:http://blog.csdn.net/u012102306/article/details/51637366 资源参数调优 了解完了Spark作业运行的基本原理之后,对资源相关的参数就容易理 ...

  7. Java-NIO(七):阻塞IO与非阻塞IO

    阻塞IO 传统的 IO 流都是阻塞式的. 也就是说,当一个线程调用 read() 或 write()时,该线程被阻塞,直到有一些数据被读取或写入,该线程在此期间不能执行其他任务. 因此,在完成网络通信 ...

  8. 线程的同步控制(Synchronization)

    临界区(Critical Sections) 摘要 临界区(Critical Section) 用来实现"排他性占有".适合范围时单一进程的各线程之间. 特点 一个局部对象,不是一 ...

  9. X5 Blink下文字自动变大

    在X5 Blink中,页面排版时会主动对字体进行放大,会检测页面中的主字体,当某一块的字体在我们的判定规则中,认为字体的字号较小,并且是页面中的主要字体,就会采用主动放大的操作.这显然不是我们想要的. ...

  10. [LeetCode] Open the Lock 开锁

    You have a lock in front of you with 4 circular wheels. Each wheel has 10 slots: '0', '1', '2', '3', ...