package sj.Gobang_V04;
import java.awt.Point;
import java.util.ArrayList;
/**
* 游戏属性接口
*
* @author Songjie_xuan
* @time 2014-09-30
*
*/
public interface Gobang_Attribute {
public static int sPoint_X = 30, sPoint_Y = 30;// 棋盘线条绘制起点
public static int lattice_Size = 30;// 棋盘单元格大小
public static int crosswise_Num = 15, vertical_Num = 15;// 棋盘标准15*15
public static int piece_Size = 26;// 棋子大小
// 枚举定义落子标记数据类型
public static enum judge_Null {
WHITE, EMPTY, BLACK
};
// 判断落子点是否为空的数组
public static judge_Null[] cPoint_Mark = new judge_Null[vertical_Num
* crosswise_Num];
// 创建ArrayList对象,存放所有落子点坐标
static ArrayList<Point> cPoint_List = new ArrayList<Point>();
// 权值数组,存放权值
public static int[] values = new int[vertical_Num * crosswise_Num];
}
package sj.Gobang_V04;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Graphics;
import java.awt.Point;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
/**
* 游戏窗体类
*
* @author Songjie_xuan
* @time 2014-09-30
*
*/
@SuppressWarnings("serial")
public class Gobang_Frame extends JFrame implements Gobang_Attribute {
// 游戏Panel尺寸
private int GPANEL_W = lattice_Size * (vertical_Num - 1) + 60;
private int GPANEL_H = lattice_Size * (vertical_Num - 1) + 60;
// 按钮Panel尺寸
private int BPANEL_W = lattice_Size * (vertical_Num - 1) + 60;
private int BPANEL_H = 40;
// 游戏窗体尺寸
private int GFRAME_W = lattice_Size * (vertical_Num - 1) + 80;
private int GFRAME_H = GPANEL_H + BPANEL_H + 45;
private JButton star_Btn, end_Btn, pre_Btn;
/**
* 构造方法设置游戏窗体
*/
public Gobang_Frame() {
this.setTitle("我的五子棋");
this.setSize(GFRAME_W, GFRAME_H);
this.setResizable(false);
this.setLocationRelativeTo(null);
this.setDefaultCloseOperation(3);
// 设置窗体布局
this.setLayout(new FlowLayout());
// 添加游戏Panel
JPanel g_Panel = new Game_Panel();
g_Panel.setBackground(Color.DARK_GRAY);
g_Panel.setPreferredSize(new Dimension(GPANEL_W, GPANEL_H));
this.add(g_Panel);
// 添加按钮Panel
JPanel b_Panel = btn_Panel();
this.add(b_Panel);
this.setVisible(true);
// 从g_Panel上获取棋子绘制区域(画布)
Graphics g = g_Panel.getGraphics();
Gobang_Listener g_Listener = new Gobang_Listener(g);
g_Panel.addMouseListener(g_Listener);
// while (true) {
// this.update(this.getGraphics());
// // try {
// // Thread.sleep(100);
// // } catch (InterruptedException e) {
// // // TODO Auto-generated catch block
// // e.printStackTrace();
// // }
// }
}
/**
* 设置按钮Panel的方法
*
* @return=>返回JPanel对象
*/
public JPanel btn_Panel() {
// 设置按钮Panel
JPanel panel = new JPanel();
panel.setPreferredSize(new Dimension(BPANEL_W, BPANEL_H));
panel.setBackground(Color.LIGHT_GRAY);// 设置背景色
panel.setLayout(new FlowLayout());// 设置布局
// 创建游戏按钮对象
star_Btn = new JButton("开始游戏");
end_Btn = new JButton("结束游戏");
pre_Btn = new JButton("保存游戏");
// 给按钮装上监听器
Btn_Listener btn_Lis = new Btn_Listener();
star_Btn.addActionListener(btn_Lis);
end_Btn.addActionListener(btn_Lis);
pre_Btn.addActionListener(btn_Lis);
// 将游戏按钮添加到Panel上
panel.add(star_Btn);
panel.add(pre_Btn);
panel.add(end_Btn);
return panel;
}
/**
* 游戏Panel类
*
* @author Songjie_xuan
*
*/
class Game_Panel extends JPanel {
/**
* 重绘界面的方法
*
* @param g
* =>重绘区域
*/
public void paint(Graphics g) {
// 调用父类重绘方法正确绘制组件
super.paint(g);
// 重绘棋盘
draw_Board(g);
// 重绘棋子
draw_Piece(g);
}
/**
* 绘制棋子
*
* @param g
* =>绘制区域
*/
private void draw_Piece(Graphics g) {
// 遍历棋盘所有交点
for (int index = 0; index < cPoint_List.size(); index++) {
Point p = cPoint_List.get(index);
if (cPoint_Mark[index] != judge_Null.EMPTY) {
if (cPoint_Mark[index] == judge_Null.BLACK) {
g.setColor(Color.BLACK);
} else {
g.setColor(Color.WHITE);
}
g.fillOval(p.x - piece_Size / 2, p.y - piece_Size / 2,
piece_Size, piece_Size);
}
}
}
/**
* 绘制棋盘线条
*
* @param g
* =>绘制区域
*/
private void draw_Board(Graphics g) {
// 设置棋盘线条颜色为白色
g.setColor(Color.WHITE);
int i = 0;
// 绘制横线
for (i = 0; i < crosswise_Num; i++) {
g.drawLine(sPoint_X, sPoint_Y + i * lattice_Size, sPoint_X
+ lattice_Size * (vertical_Num - 1), sPoint_Y + i
* lattice_Size);
}
// 绘制竖线
for (i = 0; i < vertical_Num; i++) {
g.drawLine(sPoint_X + i * lattice_Size, sPoint_Y, sPoint_X + i
* lattice_Size, sPoint_Y + lattice_Size
* (crosswise_Num - 1));
}
g.fillOval(120 - 4, 120 - 4, 8, 8);
g.fillOval(360 - 4, 120 - 4, 8, 8);
g.fillOval(120 - 4, 360 - 4, 8, 8);
g.fillOval(360 - 4, 360 - 4, 8, 8);
g.fillOval(240 - 4, 240 - 4, 8, 8);
}
}
/**
* 按钮监听器类
*
* @author Songjie_xuan
*
*/
class Btn_Listener implements ActionListener {
public void actionPerformed(ActionEvent e) {
String btn_Str = e.getActionCommand();
if ("开始游戏".equals(btn_Str)) {
create_List();
star_Btn.setText("暂停游戏");
} else if ("暂停游戏".equals(btn_Str)) {
star_Btn.setText("继续游戏");
} else if ("继续游戏".equals(btn_Str)) {
star_Btn.setText("暂停游戏");
}
if ("结束游戏".equals(btn_Str)) {
star_Btn.setText("开始游戏");
}
}
/**
* 开始游戏,所有可以落子的点坐标存放到ArrayList对象中 并标记为空位
*/
public void create_List() {
// 获取所有交点的坐标存入cPoint_List
for (int i = 0; i < vertical_Num; i++) {
for (int j = 0; j < crosswise_Num; j++) {
// 计算所有落子位置的(x,y)坐标
int cPoint_X = sPoint_X + j * lattice_Size;
int cPoint_Y = sPoint_Y + i * lattice_Size;
// 落子位置坐标存放到数组中
cPoint_List.add(new Point(cPoint_X, cPoint_Y));
}
}
for (int i = 0; i < cPoint_List.size(); i++) {
cPoint_Mark[i] = judge_Null.EMPTY;
}
}
}
}
package sj.Gobang_V04;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Point;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
/**
* 游戏界面监听器类
*
* @author Songjie_xuan
* @time 2014-10-02
*
*/
public class Gobang_Listener extends MouseAdapter implements Gobang_Attribute {
private Graphics g;
Gobang_Robot gr = new Gobang_Robot();
Gobang_Listener(Graphics g) {
this.g = g;
}
/**
* 绘制棋子的方法
*
* @param x
* =>绘制棋子的中心点x坐标
* @param y
* =>绘制棋子的中心点y坐标
*/
public void draw_Piece(int x, int y, int index, judge_Null jn) {
// 根据jn的值判定需要绘制白子,还是黑子
if (jn == judge_Null.BLACK) {
g.setColor(Color.BLACK);
cPoint_Mark[index] = jn;
} else if (jn == judge_Null.WHITE) {
g.setColor(Color.WHITE);
cPoint_Mark[index] = jn;
}
g.fillOval(x - piece_Size / 2, y - piece_Size / 2, piece_Size,
piece_Size);
}
/**
* 判赢方法
*
* @param index
* =>当前落子点的小标
* @return=>返回boolean值
*/
private boolean judge_Win(int index) {
int c1 = 0;
int c2 = 0;
int count = 0;
// **横向检测**
// 检测前要判断查找范围
for (int i = 0; i < 15; i++) {
if (index >= 15 * i && index < 15 * i + 15) {
c1 = 15 * i + 15;
c2 = 15 * i;
// System.out.println(c);
break;
}
}
// 横向开始检测
for (int i = index; i < c1; i++) {
if (cPoint_Mark[index] == cPoint_Mark[i]) {
count++;
} else {
break;
}
}
for (int i = index - 1; i >= c2; i--) {
if (cPoint_Mark[index] == cPoint_Mark[i]) {
count++;
} else {
break;
}
}
// 横向检测结束,如果count还小于5,于是从新置为0
if (count < 5) {
count = 0;
}
// 纵向检测
for (int i = index; i < vertical_Num * vertical_Num; i += 15) {
if (cPoint_Mark[index] == cPoint_Mark[i]) {
count++;
} else {
break;
}
}
for (int i = index - 15; i >= 0; i -= 15) {
if (cPoint_Mark[index] == cPoint_Mark[i]) {
count++;
} else {
break;
}
}
// 纵向检测结束,如果count还小于5,于是从新置为0
if (count < 5) {
count = 0;
}
// 主对角线斜向检测
for (int i = index; i < vertical_Num * vertical_Num; i += 15) {
if (cPoint_Mark[index] == cPoint_Mark[i]) {
count++;
i++;
} else {
break;
}
}
for (int i = index - 16; i >= 0; i -= 15) {
if (cPoint_Mark[index] == cPoint_Mark[i]) {
count++;
i--;
} else {
break;
}
}
// 主对角线斜向检测结束,如果count还小于5,于是从新置为0
if (count < 5) {
count = 0;
}
// 副对角线检测
for (int i = index; i < vertical_Num * crosswise_Num; i += 14) {
if (cPoint_Mark[index] == cPoint_Mark[i]) {
count++;
} else {
break;
}
}
for (int i = index - 14; i >= 0; i -= 14) {
if (cPoint_Mark[index] == cPoint_Mark[i]) {
count++;
} else {
break;
}
}
// 如果count大于等于5,表示获胜
if (count >= 5) {
count = 0;
return true;
}
return false;
}
public void mouseReleased(MouseEvent e) {
// 获取当前鼠标点击位置
int mouse_X = e.getX();
int mouse_Y = e.getY();
// System.out.println("<"+mouse_X+" "+mouse_Y+">");
for (int index = 0; index < cPoint_List.size(); index++) {
Point p = cPoint_List.get(index);
if (Math.abs(mouse_X - p.x) <= 3 * lattice_Size / 7
&& Math.abs(mouse_Y - p.y) <= 3 * lattice_Size / 7) {
if (cPoint_Mark[index] == judge_Null.EMPTY) {
// 玩家落子
draw_Piece(p.x, p.y, index, judge_Null.BLACK);
// 每次落子都检查是否获胜
if (judge_Win(index)) {
javax.swing.JOptionPane
.showMessageDialog(null, "黑棋获胜!");
// 获胜后清空棋盘
for (int i = 0; i < cPoint_Mark.length; i++) {
cPoint_Mark[i] = judge_Null.EMPTY;
}
break;
}
// **计算机落子**
// 首先计算最优落子位置
gr.select_PutPoint();
// 根据位置绘制白子
draw_Piece(gr.p.x, gr.p.y, gr.index, judge_Null.WHITE);
// 每次落子都检查是否获胜
if (judge_Win(gr.index)) {
javax.swing.JOptionPane
.showMessageDialog(null, "白棋获胜!");
for (int i = 0; i < cPoint_List.size(); i++) {
cPoint_Mark[i] = judge_Null.EMPTY;
}
break;
}
} else {
javax.swing.JOptionPane.showMessageDialog(null,
"此处有子,不能落子!");
}
}
}
}
}
package sj.Gobang_V04;
import java.awt.Point;
/**
* 五子棋计算机类
*
* @author Songjie_xuan
* @time 2014-10-04
*
*/
public class Gobang_Robot implements Gobang_Attribute {
Point p;
int index;
// 选择落子点
public void select_PutPoint() {
// 遍历所有交点
for (int i = 0; i < cPoint_List.size(); i++) {
// 选择被标记为judge_Null.EMPTY的点
if (cPoint_Mark[i] == judge_Null.EMPTY) {
// 如果为空则计算权值存放到values数组中
values[i] = count_Values(i);
} else {
// 不为空的点权值赋为0
values[i] = 0;
}
}
int temp = 0;
// 遍历所有交点
for (int i = 0; i < values.length; i++) {
// 找出权值最大的点,获取该点的下标
if (temp < values[i]) {
temp = values[i];
}
}
// 遍历所有交点
for (int i = 0; i < values.length; i++) {
// 找出权值最大的点,获取该点及其下标
if (temp == values[i]) {
index = i;
p = cPoint_List.get(i);
}
}
}
/**
* 计算权值
*/
private int count_Values(int i) {
int values = 10 * i;
return 1000;
}
}
package sj.Gobang_V04;
/**
* 五子棋启动类
*
* @author Songjie_xuan
* @time 2014-09-30
*
*/
public class Gobang_Test {
public static void main(String[] args) {
new Gobang_Frame();
}
}