Java——五子棋(2)
上次我们五子棋判断输赢有小伙伴私信我说数组会越界的情况,我今天又加以改进了一下,现在不会报错啦。而且我又加上了重新开始游戏的功能。下次会把悔棋和复盘还有多线程的时间控制加上,我们慢慢来。
代码:
窗体类:
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];
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.piece =mouse.piece ;
jf.message =mouse.message ;
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 paint(Graphics g) {
super.paint(g);
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); //画棋盘竖线
}
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 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 javax.swing.JFrame;
import javax.swing.JOptionPane;
public class GameMouse implements MouseListener, ActionListener {
int[][] piece = new int[15][15];
public int turn = 1; // 判断下黑棋还是白棋
boolean canplay = true; // 游戏结束后不能在下棋了
String message="黑方先行";
//保存最多拥有多少时间(秒)
int maxTime=0;
JFrame jf;
public Graphics g;
int x = 0;
int y = 0;
int i = 0;
int j = 0;
public GameMouse(Graphics g, JFrame jf) {
this.g = g;
this.jf = jf;
}
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("认输")) {
int result = JOptionPane.showConfirmDialog(null, "是否认输?");
if (result == 0) {
if (turn == 1) {
JOptionPane.showMessageDialog(null, "游戏结束,黑方认输,白方获胜!");
} else if (turn == 2) {
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;
}
}
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++;
message="轮到黑方";
} else if (turn == 2) { // 下白棋
g.setColor(Color.white);
g.fillOval(tempx - 20, tempy - 20, 40, 40);
piece[i][j] = 2;
turn--;
message="轮到白方";
}
boolean winflag = this.checkWin(); // 传递判断输赢方法的布尔数据
if (winflag == true) {
JOptionPane.showMessageDialog(null, "游戏结束" + (piece[i][j] == 1 ? "黑方胜利!" : "白方胜利!"));
canplay = false; // 游戏结束则不能在下棋
}
} else {
JOptionPane.showMessageDialog(null, "当前位置已经有子");
}
} else {
JOptionPane.showMessageDialog(null, "请在棋盘上落子");
}
}
}
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) {
}
}