Java——五子棋
Posted 真真最可爱
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java——五子棋相关的知识,希望对你有一定的参考价值。
Java——五子棋(3)
这里我新加一个指示器的功能,比如说这个样子:
就是会提示你到底下在哪个位置的指示器。
代码如下:具体的我注释好了,仔细认真看,一定会成功的,不懂得小伙伴随时私信我,或者评论都可,秒回。
package xq0817;
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
public class Pointer {
private int i=0; //二维数组下标
private int j=0;
private int x=0;//二维数组的坐标
private int y=0;
int h=40;//指示器的高
private boolean isShow=false; //是否展示指示器
public Pointer(int i,int j,int x,int y) {
this.i=i;
this.j=j;
this.x=x;
this.y=y;
}
//绘制指示器的方法
public void draw(Graphics g) {
// System.out.print(isShow);
if(isShow) {
g.setColor(Color.red);
// g.drawRect(x-h/2, y-h/2, h, h);
drawPointer(g);
}
}
public void drawPointer(Graphics g) {
//设置2d画笔
Graphics2D g2D =(Graphics2D)g;
//设置画笔粗细
g2D.setStroke(new BasicStroke(2.0f));
int x1,x2,y1,y2;
//左上角的绘制
x1=this.x-h/2;
y1=this.y-h/2;
x2=x1+h/4;
y2=y1;
g2D.drawLine(x1, y1, x2, y2);
x2=x1;
y2=y1+h/4;
g2D.drawLine(x1, y1, x2, y2);
//右上角的绘制
x1=this.x+h/2;
y1=this.y-h/2;
x2=x1-h/4;
y2=y1;
g2D.drawLine(x1, y1, x2, y2);
x2=x1;
y2=y1+h/4;
g2D.drawLine(x1, y1, x2, y2);
//左下角的绘制
x1=this.x-h/2;
y1=this.y+h/2;
x2=x1+h/4;
y2=y1;
g2D.drawLine(x1, y1, x2, y2);
x2=x1;
y2=y1-h/4;
g2D.drawLine(x1, y1, x2, y2);
//右下角的绘制
x1=this.x+h/2;
y1=this.y+h/2;
x2=x1-h/4;
y2=y1;
g2D.drawLine(x1, y1, x2, y2);
x2=x1;
y2=y1-h/4;
g2D.drawLine(x1, y1, x2, y2);
}
//判断是否在指示器的范围
public boolean isPoint(int x,int y) {
int x1=this.x-h/2;
int y1=this.y-h/2;
int x2=this.x+h/2;
int y2=this.y+h/2;
return x>x1&&y>y1&&x<x2&&y<y2;
}
public boolean isShow(){
return isShow;
}
public void setShow(boolean isShow) {
this.isShow =isShow;
}
}
在窗体中
package xq0817;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
public class GameUI extends JFrame implements Runnable {
int[][]piece=new int [16][16];
//创建指示器数组
Pointer pointers[][]=new Pointer [15][15];
String[] btnstrs = {"开始游戏","认输","悔棋","复盘","退出","时间设置","人机对战"};
String message="黑方先行";
//保存最多拥有多少时间(秒)
int maxTime=0;
//做一个倒计时的线程类
Thread t = new Thread(this);
//借口的线程方法
public void run() {
}
public void initUI() {
GameUI jf =new GameUI();
jf.setTitle( "五子棋");
jf.setSize(900,800);
jf.setLocationRelativeTo(null);
jf.setDefaultCloseOperation(3);
//添加流式布局管理器
FlowLayout fl = new FlowLayout();
jf.setLayout(fl);
//添加按钮
jf.setVisible(true);
//画笔:从窗体上获取画笔对象,一定要在窗体可见之后
Graphics g=jf.getGraphics();
GameMouse mouse = new GameMouse(g,jf);
jf.addMouseListener( mouse);
jf.addMouseMotionListener(mouse);
jf.piece =mouse.piece ;
jf.pointers =mouse.pointers ;
Dimension dim = new Dimension(100,40); //按钮的尺寸
for (int i = 0; i < btnstrs.length; i++) { // 在循环中调用下面封装的方法
addButton(btnstrs[i],dim,Color.white,mouse,jf);
}
jf.setVisible(true);
}
public void addButton(String btnstr,Dimension dim, Color color, ActionListener mouse,JFrame jf){
JButton btn = new JButton(btnstr);
btn.setBackground(color);
btn.setPreferredSize(dim);
jf.add(btn);
btn.addActionListener(mouse);
}
public void setMessage( String message){
this.message =message;
}
public void paint(Graphics g) {
super.paint(g);
//画出指示器
drawPointer(g);
g.setColor(Color.black );
g.setFont( new Font("黑体",Font.BOLD ,20));
g.drawString("游戏信息:"+message,360 , 110);
g.setFont( new Font("黑体",Font.BOLD ,20));
g.drawString("黑方时间:无限制",200 , 740);
g.setFont( new Font("黑体",Font.BOLD ,20));
g.drawString("白方时间:无限制",520 , 740);
for (int i = 0; i < 15; i++) {
g.setColor(Color.orange );
g.drawLine(160, 120+i*40, 720, 120+i*40); //画棋盘横线
g.drawLine(160+i*40, 120, 160+i*40,680); //画棋盘竖线
}
g.setColor(Color.black );
g.fillOval(440-3,400-3,6,6);
g.fillOval(280-3,240-3,6,6);
g.fillOval(600-3,240-3,6,6);
g.fillOval(280-3,560-3,6,6);
g.fillOval(600-3,560-3,6,6);
for(int i=0; i<15; i++) { //重绘棋子
for(int j=0; j<15; j++) {
if(piece[i][j]==1) {
int tempX=i*40+160;
int tempY=j*40+120;
g.setColor(Color.black );
g.fillOval(tempX-20, tempY-20, 40, 40);
}else if (piece[i][j]==2) {
int tempX=i*40+160;
int tempY=j*40+120;
g.setColor(Color.white );
g.fillOval(tempX-20, tempY-20, 40, 40);
}
}
}
}
public void drawPointer(Graphics g) {
Pointer pointer;
for(int i=0;i<15;i++) {
for(int j=0;j<15;j++) {
pointer=pointers[i][j];
if(pointer!=null) {
pointer.draw(g);
}
}
}
}
public static void main (String[] args) {
GameUI ui = new GameUI();
ui.initUI();
}
}
package xq0817;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.util.ArrayList;
import java.util.HashMap;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
public class GameMouse implements MouseListener, ActionListener,MouseMotionListener {
int[][] piece = new int[15][15];
int[][] piece1=new int [15][15]; //记录棋子颜色
int[][] piece2=new int [15][15]; // 记录棋子编号
public ArrayList<Position>PositonList=new ArrayList<Position>();//保存每一步的落子情况
public int turn = 1; // 判断下黑棋还是白棋
boolean canplay = true; // 游戏结束后不能在下棋了
String message="黑方先行";
//保存最多拥有多少时间(秒)
int maxTime=0;
int sum;
GameUI jf;
//定义指示器数组
Pointer pointers[][]=new Pointer [15][15];
public Graphics g;
int x = 0;
int y = 0;
int i = 0;
int j = 0;
//创建指示器数组内容
public void creatPointer() {
for(int i=0;i<15;i++) {
for(int j=0;j<15;j++) {
Pointer pointer=new Pointer(i,j,i*40+160,j*40+120);
pointers[i][j]=pointer;
}
}
}
public GameMouse(Graphics g, GameUI jf) {
this.g = g;
this.jf = jf;
this.creatPointer();
}
//棋子相连情况的划分
public static HashMap<String,Integer> map = new HashMap<String,Integer>();//设置不同落子情况和相应权值的数组
static {
//被堵住
map.put("01", 17);//眠1连
map.put("02", 12);//眠1连
map.put("001", 17);//眠1连
map.put("002", 12);//眠1连
map.put("0001", 17);//眠1连
map.put("0002", 12);//眠1连
map.put("0102",17);//眠1连,15
map.put("0201",12);//眠1连,10
map.put("0012",15);//眠1连,15
map.put("0021",10);//眠1连,10
map.put("01002",19);//眠1连,15
map.put("02001",14);//眠1连,10
map.put("00102",17);//眠1连,15
map.put("00201",12);//眠1连,10
map.put("00012",15);//眠1连,15
map.put("00021",10);//眠1连,10
map.put("01000",21);//活1连,15
map.put("02000",16);//活1连,10
map.put("00100",19);//活1连,15
map.put("00200",14);//活1连,10
map.put("00010",17);//活1连,15
map.put("00020",12);//活1连,10
map.put("00001",15);//活1连,15
map.put("00002",10);//活1连,10
//被堵住
map.put("0101",65);//眠2连,40
map.put("0202",60);//眠2连,30
map.put("0110",65);//眠2连,40
map.put("0220",60);//眠2连,30
map.put("011",65);//眠2连,40
map.put("022",60);//眠2连,30
map.put("0011",65);//眠2连,40
map.put("0022",60);//眠2连,30
map.put("01012",65);//眠2连,40
map.put("02021",60);//眠2连,30
map.put("01102",65);//眠2连,40
map.put("02201",60);//眠2连,30
map.put("00112",65);//眠2连,40
map.put("00221",60);//眠2连,30
map.put("01010",75);//活2连,40
map.put("02020",70);//活2连,30
map.put("01100",75);//活2连,40
map.put("02200",70);//活2连,30
map.put("00110",75);//活2连,40
map.put("00220",70);//活2连,30
map.put("00011",75);//活2连,40
map.put("00022",70);//活2连,30
//被堵住
map.put("0111",150);//眠3连,100
map.put("0222",140);//眠3连,80
map.put("01112",150);//眠3连,100
map.put("02221",140);//眠3连,80
map.put("01101",1000);//活3连,130
map.put("02202",800);//活3连,110
map.put("01011",1000);//活3连,130
map.put("02022",800);//活3连,110
map.put("01110", 1000);//活3连
map.put("02220", 800);//活3连
map.put("01111",3000);//4连,300
map.put("02222",3500);//4连,280
}
public void mouseClicked(MouseEvent e) {
x = e.getX();
y = e.getY();
if (canplay == true) { // 如果游戏没结束 可以下棋
if (x >= 160 && x <= 720 + 10 && y >= 120 - 10 && y <= 680 + 10) { // 使棋子下在棋盘中
// 二维数组的下标
if ((x - 160) % 40 < 20) {
i = (x - 160) / 40;
} else if (((x - 160) % 40 >= 20)) {
i = (x - 160) / 40 + 1;
}
if ((y - 120) % 40 < 20) {
j = (y - 120) / 40;
} else if (((y - 120) % 40 >= 20)) {
j = (y - 120) / 40 + 1;
}
if (piece[i][j] == 0) { // 如果数组为0,则可以下棋,(保证棋子不能下在有棋子的地方)
int tempx = i * 40 + 160;
int tempy = j * 40 + 120;
if (turn == 1) { // 下黑棋
g.setColor(Color.black);
g.fillOval(tempx - 20, tempy - 20, 40, 40);
piece[i][j] = 1;
turn++;
jf.setMessage("轮到白方");
jf.repaint();
//把当前所下的棋子位置保存在动态数组中
PositonList.add(new Position(i,j));
piece2[i][j]=sum;
sum++;
} else if (turn == 2) { // 下白棋
g.setColor(Color.white);
g.fillOval(tempx - 20, tempy - 20, 40, 40);
piece[i][j] = 2;
turn--;
jf.setMessage("轮到黑方");
jf.repaint();
PositonList.add(new Position(i,j));
piece2[i][j]=sum;
sum++;
}
boolean winflag = this.checkWin(); // 传递判断输赢方法的布尔数据
if (winflag ) {
JOptionPane.showMessageDialog(null, "游戏结束" + (piece[i][j] == 1 ? "黑方胜利!" : "白方胜利!"));
canplay = false; // 游戏结束则不能在下棋
}
} else {
JOptionPane.showMessageDialog(null, "当前位置已经有子");
}
} else {
JOptionPane.showMessageDialog(null, "请在棋盘上落子");
}
}
}
public void actionPerformed(ActionEvent e) {
String btnstr = e.getActionCommand();// 字符串
System.out.println("点击了" + btnstr);
if (btnstr.equals("开始游戏")) {
int result = JOptionPane.showConfirmDialog(null, "是否重新开始游戏?");
if (result == 0) {
for (int i = 0; i < 15; i++) {
for (int j = 0; j < 15; j++) {
piece[i][j] = 0;
}
}
canplay = true; //可以现在下棋了
turn=1; //黑子先下
jf.repaint();
}
} else if (btnstr.equals("认输")) {
if(canplay==true) {
int result = JOptionPane.showConfirmDialog(null, "是否认输?");
if (result == 0) {
if (turn == 1) {
JOptionPane.showMessageDialog(null, "游戏结束,黑方认输,白方获胜!");
} else if (turn == 2) {
JOptionPane.showMessageDialog(null, "游戏结束,白方认输,黑方获胜!");
}
}canplay = false;
if(result !=0) {
canplay=true;
}
}else {
JOptionPane.showMessageDialog(null, "游戏已经结束,无法认输!");
}
} else if (btnstr.equals("退出")) {
int result = JOptionPane.showConfirmDialog(null, "是否退出游戏?");
if (result == 0) {
System.exit(0);
}
}else if (btnstr.equals("时间设置")) {
String input = JOptionPane.showInputDialog("请输入游戏的最大时间(分钟):") ;
maxTime= Integer.parseInt( input)*60;
}else if (btnstr.equals("悔棋")) {
if(canplay==true) {
if(PositonList.size()>1) {
Position l1= new Position(i,j);
//获取最后一个棋子的对象信息
l1=PositonList.remove(PositonList.size()-1);
//把相应的数组位置置为0
piece[l1.i][l1.j]=0;
//把玩家还原为上一步的玩家
if(turn==1) turn++;
else turn--;
jf.repaint();
}
else {
JOptionPane.showMessageDialog(null, "不能在悔棋啦!");
}
}else {
JOptionPane.showMessageDialog(null, "游戏已经结束啦,不能悔棋!");
}
}else if (btnstr.equals("复盘")) {
if(canplay==false) { //游戏结束后刷新棋盘
for (int m = 0; m < 15; m++) {
for (int n = 0; n < 15; n++) {
piece1[m][n]=piece[m][n];
piece[m][n] = 0;
}
}
jf.repaint();
int k=0;
if(k <= sum) {
for(int m=0; m<15; m++){
for (int n=0; n<15; n++) {
if(piece2[m][n]==k) {
if (turn == 1) { // 下黑棋
g.setColor(Color.black);
g.fillOval((i * 40 + 160) - 20, (j * 40 + 120) - 20, 40, 40);
k++;
break;
} else if (turn== 2) { // 下白棋
g.setColor(Color.white);
g.fillOval((i * 40 + 160) - 20, (j * 40 + 120) - 20, 40, 40);
k++;
break;
}
}
}
}
}
}else if(canplay==true) {
JOptionPane.showMessageDialog(null, "游戏没有结束,无法复盘");
}
}
/*else if(btnstr.equals("人机对战")) {
Integer[][] weightArray;
if(canplay) {
g.setColor(Color.black);
g.fillOval((i * 40 + 160) - 20, (j * 40 + 120) - 20, 40, 40);
piece[i][j]=1;
PositonList.add(new Position(i,j));
turn++;
//判断黑方是否赢
boolean winflag = this.checkWin(); // 传递判断输赢方法的布尔数据
if (winflag ) {
JOptionPane.showMessageDialog(null, "游戏结束" + (piece[i][j] == 1 ? "黑方胜利!" : "白方胜利!"));
canplay = false; // 游戏结束则不能在下棋
}
//机器落子
//先计算出各个位置的权值
for(int i=0;i<piece.length;i++) {
for(int j=0;j<piece[i].length;j++) {
//首先判断当前位置是否为空
if(piece[i][j]==0) {
//往左延伸
String ConnectType="0";
int jmin=Math.max(0, j-4);
for(int positionj=j-1;positionj>=jmin;positionj--) {
//依次加上前面的棋子
ConnectType=ConnectType+piece[i][positionj];
}
//从数组中取出相应的权值,加到权值数组的当前位置中
Integer valueleft=map.get(ConnectType);
if(valueleft!=null) weightArray[i][j]+=valueleft;
//往右延伸
ConnectType="0";
int jmax=Math.min(14, j+4);
for(int positionj=j+1;positionj<=jmax;positionj++) {
//依次加上前面的棋子
ConnectType=ConnectType+piece[i][positionj];
}
//从数组中取出相应的权值,加到权值数组的当前位置中
Integer valueright=map.get(ConnectType);
if(valueright!=null) weightArray[i][j]+=valueright;
//联合判断,判断行
weightArray[i][j]+=unionWeight(valueleft,valueright);
//往上延伸
ConnectType="0";
int imin=Math.max(0, i-4);
for(int positioni=i-1;positioni>=imin;positioni--) {
//依次加上前面的棋子
ConnectType=ConnectType+piece[positioni][j];
}
//从数组中取出相应的权值,加到权值数组的当前位置中
Integer valueup=map.get(ConnectType);
if(valueup!=null) weightArray[i][j]+=valueup;
//往下延伸
ConnectType="0";
int imax=Math.min(14, i+4);
for(int positioni=i+1;positioni<=imax;positioni++) {
//依次加上前面的棋子
ConnectType=ConnectType+piece[positioni][j];
}
//从数组中取出相应的权值,加到权值数组的当前位置中
Integer valuedown=map.get(ConnectType);
if(valuedown!=null) weightArray[i][j]+=valuedown;
//联合判断,判断列
weightArray[i][j]+=unionWeight(valueup,valuedown);
//往左上方延伸,i,j,都减去相同的数
ConnectType="0";
for(int position=-1;position>=-4;position--) {
if((i+position>=0)&&(i+position<=14)&&(j+position>=0)&&(j+position<=14))
ConnectType=ConnectType+piece[i+position][j+position];
}
//从数组中取出相应的权值,加到权值数组的当前位置
Integer valueLeftUp=map.get(ConnectType);
if(valueLeftUp!=null) weightArray[i][j]+=valueLeftUp;
//往右下方延伸,i,j,都加上相同的数
ConnectType="0";
for(int position=1;position<=4;position++) {
if((i+position>=0)&&(i+position<=14)&&(j+position>=0)&&(j+position<=14))
ConnectType=ConnectType+piece[i+position][j+position];
}
//从数组中取出相应的权值,加到权值数组的当前位置
Integer valueRightDown=map.get(ConnectType);
if(valueRightDown!=null) weightArray[i][j]+=valueRightDown;
//联合判断,判断行
weightArray[i][j]+=unionWeight(valueLeftUp,valueRightDown);
//往左下方延伸,i加,j减
ConnectType="0";
for(int position=1;position<=4;position++) {
if((i+position>=0)&&(i+position<=14)&&(j-position>=0)&&(j-position<=14))
ConnectType=ConnectType+piece[i+position][j-position];
}
//从数组中取出相应的权值,加到权值数组的当前位置
Integer valueLeftDown=map.get(ConnectType);
if(valueLeftDown!=null) weightArray[i][j]+=valueLeftDown;
//往右上方延伸,i减,j加
ConnectType="0";
for(int position=1;position<=4;position++) {
if((i-position>=0)&&(i-position<=14)&&(j+position>=0)&&(j+position<=14))
ConnectType=ConnectType+piece[i-position][j+position];
}
//从数组中取出相应的权值,加到权值数组的当前位置
Integer valueRightUp=map.get(ConnectType);
if(valueRightUp!=null) weightArray[i][j]+=valueRightUp;
//联合判断,判断行
weightArray[i][j]+=unionWeight(valueLeftDown,valueRightUp);
}
}
}
//打印出权值
for(int i=0;i<go.column;i++) {
for(int j=0;j<go.row;j++) {
System.out.print(weightArray[i][j]+" ");
}
System.out.println();
}
//取出最大的权值
int AIi=0,AIj=0;
int weightmax=0;
for(int i=0;i<go.row;i++) {
for(int j=0;j<go.column;j++) {
if(weightmax<weightArray[i][j]) {
weightmax=weightArray[i][j];
AIi=i;
AIj=j;
System.out.println(AIi+" "+AIj);
}
}
}
//确定位置,落子
g.setColor(Color.white);
//i对应y,j对应x
countx=20+AIj*40;
county=20+AIi*40;
g.fillOval(countx-size/2, county-size/2, size, size);
//设置当前位置已经有棋子了,棋子为白子
PositonList.add(new Position(AIi,AIj));
gf.isAvail[AIi][AIj]=2;
gf.turn--;
//落子以后重置权值数组weightArray
for(int i=0;i<go.column;i++)
for(int j=0;j<go.row;j++)
gf.weightArray[i][j]=0;
if (winflag ) {
JOptionPane.showMessageDialog(null, "游戏结束" + (piece[i][j] == 1 ? "黑方胜利!" : "白方胜利!"));
canplay = false; // 游戏结束则不能在下棋
}
}
}*/
}
public Integer unionWeight(Integer a,Integer b ) {
//必须要先判断a,b两个数值是不是null
if((a==null)||(b==null)) return 0;
//一一
else if((a>=10)&&(a<=25)&&(b>=10)&&(b<=25)) return 60;
//一二、二一
else if(((a>=10)&&(a<=25)&&(b>=60)&&(b<=80))||((a>=60)&&(a<=80)&&(b>=10)&&(b<=25))) return 800;
//一三、三一、二二
else if(((a>=10)&&(a<=25)&&(b>=140)&&(b<=1000))||((a>=140)&&(a<=1000)&&(b>=10)&&(b<=25))||((a>=60)&&(a<=80)&&(b>=60)&&(b<=80)))
return 3000;
//二三、三二
else if(((a>=60)&&(a<=80)&&(b>=140)&&(b<=1000))||((a>=140)&&(a<=1000)&&(b>=60)&&(b<=80))) return 3000;
else return 0;
}
private boolean checkWin() {
boolean flag=false;
int color=piece[i][j];
// 横向五连判断
int count=1;
int m=1;
while(i+m<15&&color == piece[i+m][j]) {
count++;
m++;
}m=1;
while ( i-m>=0 &&color ==piece[i-m][j]){
count++;
m++;
}m=1;
if(count >= 5){
flag=true;
}
//纵向五连判断
int count1=1;
int m1=1;
while(j+m1<15&&color == piece[i][j+m1]) {
count1++;
m1++;
} m1=1;
while(j-m1>=0 &&color ==piece[i][j-m1]) {
count1++;
m1++;
}
if(count1 >= 5) {
flag=true;
}
//斜方向 (右上左下)
int count2=1;
int m2=1;
while(j-m2>=0&&i+m2<15&&color == piece[i+m2][j-m2]) {
count2++;
m2++;
} m2=1;
while(i-m2>=0&&j+m2<15&&color ==piece[i-m2][j+m2]) {
count2++;
m2++;
}
if(count2 >= 5) {
flag=true;
}
//斜方向(左上 右下)
int count3=1;
int m3=1;
while(i-m3>=0&&j-m3>=0&&color == piece[i-m3][j-m3]) {
count3++;
m3++;
} m3=1;
while(i+m3<15&&j+m3<15&&color ==piece[i+m3][j+m3]) {
count3++;
m3++;
}
if(count3 >= 5) {
flag=true;
}
return flag;
}
public void mousePressed(MouseEvent e) {
}
public void mouseReleased(MouseEvent e) {
}
public void mouseEntered(MouseEvent e) {
}
public void mouseExited(MouseEvent e) {
}
public void mouseDragged(MouseEvent e) {
}
public void mouseMoved(MouseEvent e) {
if(canplay) {
//获得鼠标坐标
int x=e.getX();
int y=e.getY();
Pointer pointer;
for(int i=0;i<15;i++) {
for(int j=0;j<15;j++) {
//得到每一个指示器对象
pointer=pointers[i][j];
if(pointer.isPoint(x, y)) {
pointer.setShow(true);
}else {
pointer.setShow(false);
}
}
jf.repaint();
}
}
}
}
以上是关于Java——五子棋的主要内容,如果未能解决你的问题,请参考以下文章