前言
利用权值法实现简单的人机五子棋,没有利用博弈树等高深的方法。而且里面的权值判断法都是本人自己设定的,只是基本实现了自动下棋功能,而且时不时会有几步臭棋。
效果图
图片有点大 基本上要实现的功能就是如图所示
实现步骤
UI过程:
1.首先是要将棋盘画出来 再添加按钮,再加监听
所要用到的API类:JFrame BorderLayout JPanel MouseListener MouseEvent
Graphics Color 数组
代码示例:
import javax.swing.*;
import java.awt.*;
import java.awt.event.MouseAdapter;
public class GobangMain extends JPanel implements GobangConfig{ //界面的实现
public static void main(String[] args) {
GobangMain pa=new GobangMain(); //实例化界面对象
pa.showUI();
}
public void setarray(int [][]array) { //预先对数组初始化(数组用于记录棋子 0 空 1黑子 2白子
for(int i=0;i
可以看到这里我们继承了GobangConfig接口 先来看看这个接口
public interface GobangConfig {
public static final int X=20,Y=20,SIZE=50, ROW = 15, COLUMN = 15,QSIZE=40;
public static final int [][]chessArray=new int [ROW][COLUMN];
public static final int [][]weightArray=new int [ROW][COLUMN]; //权值数组,每个点的权值分数存储
}
这里我们利用此接口设置了棋盘行列 ROW COLUMN,棋子大小QSIZE 画出来之后每个格子的大小SIZE ,X Y 为开始画棋盘时离界面边缘的距离
到这里,界面就可以出现了,现在窗体上面已经出现了棋盘,按钮等组件
接下来 自然就是要在棋盘上面画出棋子,这里我们就用到了监听
废话少说,直接上代码:
package 五子棋1;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.image.BufferedImage;
import java.io.File;
import java.util.HashMap;
import javax.imageio.ImageIO;
import javax.swing.JLabel;
public class GobangListener extends MouseAdapter implements GobangConfig,ActionListener{
static HashMap map = new HashMap(); //定义了两个HashMap 键值对,分别用于对电脑和玩家的棋进行对应的评分
static {
map.put("012",10); //眠1
map.put("210",10); //眠1
map.put("010",40); //活1
map.put("0110",100); //活2
map.put("0112",50); //眠2
map.put("2110",50); //眠2
map.put("01110",4500); //活3
map.put("01112",500); //眠3
map.put("21110",500); //眠3
map.put("011112",3500); //眠四
map.put("211110",3500); //眠四
map.put("011110",5500); //活四
map.put("21112",80); //死三
map.put("211112",100); //死四
map.put("2112",60);
map.put("0111110",20000); //活五
map.put("2111110",20000); //眠五
map.put("0111112",20000);
}
static HashMap map2 = new HashMap();
static {
map2.put("012",15); //眠1
map2.put("210",15); //眠1
map2.put("010",55); //活1
map2.put("0110",150); //活2
map2.put("0112",70); //眠2
map2.put("2110",70); //眠2
map2.put("01110",6000); //活3
map2.put("01112",800); //眠3
map2.put("21110",800); //眠3
map2.put("011112",9000); //眠四
map2.put("211110",9000); //眠四
map2.put("011110",20000); //活四
map2.put("21112",200); //
map2.put("211112",500); //
map2.put("2112",30); //
}
public GameOver1 robotwin=new GameOver1(); //实例化窗口对象,用于游戏结束后弹出此提示窗口
public GameOver2 peoplewin=new GameOver2();
public GobangMain pa; //将GobangMain 传到监听,用于调用重绘
public Graphics2D g;
private int flag; //用于记录当前棋子 黑棋1 白棋2
public GobangListener(GobangMain pa) { //传入GobangMain 重写构造函数
this.pa=pa;
}
private int [] hr=new int [150]; //用于记录每次下棋的行位置(用于多次悔棋时使用)
private int [] hc=new int [150]; //用于记录每次下棋的列位置(用于多次悔棋时使用)
private int hui=0; //记录下棋步数(悔棋时利用)
private String name="wu"; //用于记录点击"开始新游戏"之前的状态
private String name2;
public void actionPerformed(ActionEvent e) {
name2=name; //用name2记录点击按钮之前的状态
name=e.getActionCommand();
if(name.equals("悔棋")&&(name2.equals("玩家对战"))) {
int m=hr[hui-1];
int n=hc[hui-1];
flag=chessArray[m][n];
chessArray[m][n]=0;
pa.paint(g);
hui--;
name=name2;
}
if(name.equals("悔棋")&&(name2.equals("人机对战"))) {
int m1=hr[hui-1];
int n1=hc[hui-1];
int m2=hr[hui-2];
int n2=hc[hui-2];
chessArray[m1][n1]=0;
chessArray[m2][n2]=0;
pa.paint(g);
hui=hui-2;
name=name2;
}
if(name.equals("开始新游戏")) {
for(int i=0;imax) {
max=weightArray[i][j];
mi=i;
mj=j;
}
}
g.setColor(Color.BLACK); //电脑在权值最大点处下棋
g.fillOval(mi*SIZE+X-QSIZE/2, mj*SIZE+Y-QSIZE/2, QSIZE, QSIZE);
hr[hui]=mi;
hc[hui]=mj;
hui++;
chessArray[mi][mj]=1;
Check(chessArray[mi][mj],mi,mj);
}
public int getvalue(int flag1,int flag2) { //getvalue(1,2)为计算电脑权值 getvalue(2,1) 为计算玩家权值
int zvalue=0;
String code;
Integer value;
Integer value1;
int []flags=new int[8];
for(int j=0;j0) {
if(chessArray[i-1][j]==0&&chessArray[i-2][j]==flag1&&chessArray[i-3][j]==flag1&&chessArray[i-4][j]==flag1) {
if(flag1==1) zvalue=zvalue+3499;
else zvalue=zvalue+10000;
flags[2]=1;
}
else if(chessArray[i-1][j]==flag1&&chessArray[i-2][j]==0&&chessArray[i-3][j]==flag1&&chessArray[i-4][j]==flag1) {
if(flag1==1) zvalue=zvalue+3499;
else zvalue=zvalue+10000;
}
}
if(j-4>0) {
if(chessArray[i][j-1]==0&&chessArray[i][j-2]==flag1&&chessArray[i][j-3]==flag1&&chessArray[i][j-4]==flag1) {
if(flag1==1) zvalue=zvalue+3499;
else zvalue=zvalue+10000;
flags[3]=1;
}
else if(chessArray[i][j-1]==flag1&&chessArray[i][j-2]==0&&chessArray[i][j-3]==flag1&&chessArray[i][j-4]==flag1) {
if(flag1==1) zvalue=zvalue+3499;
else zvalue=zvalue+10000;
}
}
if((i+40)&&(j-4>0)) {
if(chessArray[i-1][j-1]==0&&chessArray[i-2][j-2]==flag1&&chessArray[i-3][j-3]==flag1&&chessArray[i-4][j-4]==flag1) {
if(flag1==1) zvalue=zvalue+3499;
else zvalue=zvalue+10000;
flags[5]=1;
}
else if(chessArray[i-1][j-1]==flag1&&chessArray[i-2][j-2]==0&&chessArray[i-3][j-3]==flag1&&chessArray[i-4][j-4]==flag1) {
if(flag1==1) zvalue=zvalue+3499;
else zvalue=zvalue+10000;
}
}
if((i+40)) {
if(chessArray[i+1][j-1]==0&&chessArray[i+2][j-2]==flag1&&chessArray[i+3][j-3]==flag1&&chessArray[i+4][j-4]==flag1) {
if(flag1==1) zvalue=zvalue+3499;
else zvalue=zvalue+10000;
flags[6]=1;
}
else if(chessArray[i+1][j-1]==flag1&&chessArray[i+2][j-2]==0&&chessArray[i+3][j-3]==flag1&&chessArray[i+4][j-4]==flag1) {
if(flag1==1) zvalue=zvalue+3499;
else zvalue=zvalue+10000;
}
}
if((j+40)) {
if(chessArray[i-1][j+1]==0&&chessArray[i-2][j+2]==flag1&&chessArray[i-3][j+3]==flag1&&chessArray[i-4][j+4]==flag1) {
if(flag1==1) zvalue=zvalue+3499;
else zvalue=zvalue+10000;
flags[7]=1;
}
else if(chessArray[i-1][j+1]==flag1&&chessArray[i-2][j+2]==0&&chessArray[i-3][j+3]==flag1&&chessArray[i-4][j+4]==flag1) {
if(flag1==1) zvalue=zvalue+3499;
else zvalue=zvalue+10000;
}
}
if(i+30) {
if(chessArray[i-1][j]==0&&chessArray[i-2][j]==flag1&&chessArray[i-3][j]==flag1&&flags[2]!=1) {
if(flag1==1) zvalue=zvalue+3300;
else zvalue=zvalue+5500;
flags[2]=1;
}
}
if(j-3>0) {
if(chessArray[i][j-1]==0&&chessArray[i][j-2]==flag1&&chessArray[i][j-3]==flag1&&flags[3]!=1) {
if(flag1==1) zvalue=zvalue+3300;
else zvalue=zvalue+5500;
flags[3]=1;
}
}
if((i+30)&&(j-3>0)) {
if(chessArray[i-1][j-1]==0&&chessArray[i-2][j-2]==flag1&&chessArray[i-3][j-3]==flag1&&flags[5]!=1) {
if(flag1==1) zvalue=zvalue+3300;
else zvalue=zvalue+5500;
flags[5]=1;
}
}
if((i+30)) {
if(chessArray[i+1][j-1]==0&&chessArray[i+2][j-2]==flag1&&chessArray[i+3][j-3]==flag1&&flags[6]!=1) {
if(flag1==1) zvalue=zvalue+3300;
else zvalue=zvalue+5500;
flags[6]=1;
}
}
if((j+30)) {
if(chessArray[i-1][j+1]==0&&chessArray[i-2][j+2]==flag1&&chessArray[i-3][j+3]==flag1&&flags[7]!=1) {
if(flag1==1) zvalue=zvalue+3300;
else zvalue=zvalue+5500;
flags[7]=1;
}
}
if(i>0) { //水平方向判断————————————
if(chessArray[i-1][j]==flag1) code="3"; //避免重复判断
if(chessArray[i-1][j]==0) code="0";
else code="2";
}
else { //处于边界位置时
code="2";
}
for(int ti=i;ti0) { //竖直方向判断
if(chessArray[i][j-1]==flag1) code="3";
if(chessArray[i][j-1]==0) code="0";
else code="2";
}
else code="2";
for(int tj=j;tj0&&j>0) { //斜向右下判断
if(chessArray[i-1][j-1]==flag1) code="3";
else if(chessArray[i-1][j-1]==flag2) code="2";
else code="0";
}
else code="2";
int ti=i,tj=j;
int min=(chessArray.length-ti)<(chessArray[0].length-tj)? (chessArray.length-ti):(chessArray[0].length-tj);
for(int m=0;m0&&j>0) { //斜向左下判断
if(chessArray[i+1][j-1]==flag1) code="3";
else if(chessArray[i+1][j-1]==flag2) code="2";
else code="0";
}
else code="2";
ti=i;
tj=j;
min=ti<(chessArray[0].length-tj)? ti:(chessArray[0].length-tj);
for(int m=0;m=0;i--){ //纵向
if(chessArray[x][i]==f) count++;
else break;
}
for(int i=y+1;i=0;i--){ //横向
if(chessArray[i][y]==f) count++;
else break;
}
for(int i=x+1;i
几点说明,除了里面的权值函数,其他的悔棋,玩家自己对战,等等都已经实现了基本的使用, 其中最多的就是对棋局打分的函数,个人认为这个函数依每个人想法不同而不同,读者尽量还是自己想想 完全可以按照自己的思路来写 更有大牛可以用博弈树等高端手法 本人写的权值判断函数个人认为一般,还算基础 大家对此还是看看就行,因为本人实在写得杂乱无章()
忘了把窗体代码加上 补一个:
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Font;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
public class GameOver1 extends JFrame{
public static void main(String[] args) {
// TODO Auto-generated method stub
GameOver1 frame=new GameOver1();
frame.setUI();
}
public void setUI() {
this.setTitle("结束窗口");
this.setDefaultCloseOperation(3);
this.setLocationRelativeTo(null);
this.setSize(300, 300);
JLabel l=new JLabel(" 电脑胜利!");
JLabel l2=new JLabel();
l2.setLayout(new FlowLayout());
Font F=new Font("楷体",Font.BOLD+ Font.ITALIC,20);
l.setFont(F);
JButton b=new JButton("确定");
l2.add(b);
b.setPreferredSize(new Dimension(80,40));
this.setLayout(new BorderLayout());
this.add(l,BorderLayout.NORTH);
this.add(l2,BorderLayout.CENTER);
this.setVisible(true);
}
}
还有一个:
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Font;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
public class GameOver2 extends JFrame{
public static void main(String[] args) {
// TODO Auto-generated method stub
GameOver2 frame=new GameOver2();
frame.setUI();
}
public void setUI() {
this.setTitle("结束窗口");
this.setDefaultCloseOperation(3);
this.setLocationRelativeTo(null);
this.setSize(300, 300);
JLabel l=new JLabel(" 玩家胜利!");
JLabel l2=new JLabel();
l2.setLayout(new FlowLayout());
Font F=new Font("楷体",Font.BOLD+ Font.ITALIC,20);
l.setFont(F);
JButton b=new JButton("确定");
l2.add(b);
b.setPreferredSize(new Dimension(80,40));
this.setLayout(new BorderLayout());
this.add(l,BorderLayout.NORTH);
this.add(l2,BorderLayout.CENTER);
this.setVisible(true);
}
}
end