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. angluarjs2入门学习资源

    http://www.runoob.com/angularjs2/angularjs2-tutorial.htmlhttps://segmentfault.com/a/1190000008423981 ...

  2. python入门(13)获取函数帮助和调用函数

    Python内置了很多有用的函数,我们可以直接调用. 要调用一个函数,需要知道函数的名称和参数,比如求绝对值的函数abs,只有一个参数.可以直接从Python的官方网站查看文档: http://doc ...

  3. 十个你需要在 PHP 7 中避免的坑

    1. 不要使用 mysql_ 类函数 终于,你不用再看到建议不要使用 mysql_ 函数的提示了.因为 PHP 7 从核心上完全移除了它们,这意味着请你移步至更好的 mysqli_ 类函数,或者更灵活 ...

  4. H5 仿ios select滚动选择器。框架。

    官网上描述的很详细,并且开源,轻量. 有兴趣的可以去尝试官网上的demo写的也很好,并且每个参数也解释的很详细. http://zhoushengfe.com/iosselect/website/in ...

  5. POJ-1328 Radar Installation--区间选点问题(贪心)

    题目链接: https://vjudge.net/problem/POJ-1328 题目大意: 假设陆地的海岸线是一条无限延长的直线,海岛是一个个的点,现需要在海岸线上安装雷达,使整个雷达系统能够覆盖 ...

  6. [转]最常用的15大Eclipse开发快捷键技巧

    作者:Java我人生(陈磊兴)   原文出处http://blog.csdn.net/chenleixing/article/details/44600587 做Java开发的,经常会用Eclipse ...

  7. Menu-菜单组件

    #menu菜单组件 from tkinter import * master=Tk() def callback(): print('你好咯!!') m = Menu(master) m.add_co ...

  8. vue.js初识(一)

    一 什么是vue? Vue (读音 /vjuː/,类似于 view) 是一套用于构建用户界面的渐进式框架.与其它大型框架不同的是,Vue 被设计为可以自底向上逐层应用.Vue 的核心库只关注视图层,不 ...

  9. 两个activity的3D翻转动画.md

    一.业务需求 这里在公司项目设计时,用到了一个小的需求,就是点击一个按钮然后整个activity的页面进行3d翻转; 二.设计思路 由于是2个activity的之间的翻转动画,就意味着前90度是A页面 ...

  10. 在一个没有设置宽高的容器中,为什么设置position:absolute后就可以全屏显示了?

    此场景适用于移动端百分比布局,背景全屏显示. 在一个没有设置宽高的容器中设置背景,想要背景全屏显示,设置bcakground-size:100%;后还需设置position:absolut; 原因: ...