有關五子棋人人對戰的代碼,以及其他一些我想說的話請參考
https://blog.csdn.net/HNU_Csee_wjw/article/details/80356800
由於某些原因,這裏我給出的AI算法算是比較簡單的,所以導致了電腦其實並沒有很強,甚至你玩的多了還可以發現電腦的“致命缺點”,由於我只是藉助這個項目來做一個java的入門練習,且我還在讀研,所以本人並不準備對AI的算法進行改進。但是我仍然歡迎各位朋友對我的代碼進行改進,切實有效的,請聯繫我索要紅包~
五子棋遊戲接口:
public interface WZQConfig {
/*
* 起始位置X
*/
public static final int START_X = 60;
/*
* 起始位置Y
*/
public static final int START_Y = 60;
/*
* 五子棋盤線條數
*/
public static final int H_LINE = 15;
/*
* 五子棋盤豎線條數
*/
public static final int V_LINE = 15;
/*
* 五子棋盤格子大小
*/
public static final int SIZE = 60;
/*
* 儲存棋子的x位置信息
*/
public static final int[][] bx = new int[17][17];
public static final int[][] bx_lastStep = new int[17][17];
public static final int[][] weightArray = new int [17][17];
}
界面類:
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
/*
* 五子棋的界面類,該類繼承JFrame,然後實現WZQConfig接口
*/
import javax.swing.JPanel;
public class WZQFrame extends JPanel implements WZQConfig {
public void WZQFrame() {
// WZQFrame ui = new WZQFrame();
JFrame jf = new javax.swing.JFrame();
jf.setTitle("五子棋");
jf.setDefaultCloseOperation(3);
jf.setSize(1246, 1080);
jf.setLocationRelativeTo(null);
jf.setResizable(false);
jf.setLayout(new FlowLayout());
this.setLayout(new FlowLayout());
this.setPreferredSize(new Dimension(1030, 1080));
// this.setBackground(Color.CYAN);
// 把面板對象添加到窗體上
jf.add(this);
JPanel jp1 = new JPanel();
jp1.setPreferredSize(new Dimension(200, 1080));
jp1.setLayout(new FlowLayout());
jf.add(jp1);
LoginListener ll = new LoginListener();
String[] str = { "悔棋", "重新開始" };
for (int i = 0; i < str.length; i++) {
JButton jbu1 = new JButton(str[i]);
jbu1.setPreferredSize(new Dimension(150, 80));
jbu1.setFont(new Font("楷體", Font.BOLD,20));//設置字體
jp1.add(jbu1);
jbu1.addActionListener(ll);
}
jf.setVisible(true);
Graphics g = this.getGraphics();
this.addMouseListener(ll);
ll.setG(g);
ll.setU(this);
}
/*
* 重寫窗體繪製容器的方法
*/
public void paint(Graphics g) {
super.paint(g);
ImageIcon im2 = new ImageIcon(this.getClass().getResource("2.jpg"));
g.drawImage(im2.getImage(), 0, 0, 1030, 1080, null);
for (int i = 1; i < 17; i++) {
Graphics2D g2 = (Graphics2D) g;
g2.setStroke(new BasicStroke(4));
g2.drawLine(START_X, START_Y * i, START_X + SIZE * V_LINE, START_Y
* i);// 橫線
g2.drawLine(START_X * i, START_Y, START_X * i, START_Y + SIZE
* V_LINE);// 豎線
g2.setStroke(new BasicStroke(8));
// 畫邊框
g2.drawLine(35, 35, 990, 35);
g2.drawLine(35, 990, 990, 990);
g2.drawLine(35, 35, 35, 990);
g2.drawLine(990, 35, 990, 990);
}
for (int k = 0; k < 17; k++) {
for (int k1 = 0; k1 < 17; k1++) {
if (bx[k][k1] == 1) {
g.setColor(Color.BLACK);
g.fillOval(Math.abs(k * SIZE - 25),
Math.abs(k1 * SIZE - 25), 50, 50);
} else if (bx[k][k1] == 2) {
g.setColor(Color.WHITE);
g.fillOval(Math.abs(k * SIZE - 25),
Math.abs(k1 * SIZE - 25), 50, 50);
}
}
}
}
public static void main(String[] args) {
WZQFrame l = new WZQFrame();
l.WZQFrame();
}
}
控制器/監聽類:
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.util.HashMap;
import java.util.Random;
import javax.swing.JButton;
import javax.swing.JOptionPane;
public class LoginListener implements MouseListener, WZQConfig, ActionListener {
private int x, y;// 鼠標點擊的位置
private int x1, y1, xx, yy, x2, y2;// 鼠標點擊附近格子交點的座標
private Graphics g;
private int a = 0, i = 0, j = 0, count1 = 0;// count統計當前下的棋子數
private String Str;// 定義全局變量獲取按鈕上的字符串
private JButton jbu1, jbu2;
private int GetX[] = new int[256];
private int GetY[] = new int[256];
WZQFrame ui;
HashMap<String,Integer> map = new HashMap<String,Integer>();
public LoginListener(){
// 活一連
map.put("010", 20);
map.put("020", 20);
map.put("01", 20);
map.put("02", 20);
map.put("10", 20);
map.put("20", 20);
// 活二連
map.put("0110", 100);
map.put("0220", 100);
map.put("011", 100);
map.put("110", 100);
map.put("022", 100);
map.put("220", 100);
// 活三連
map.put("01110", 500);
map.put("02220", 500);
map.put("1110", 500);
map.put("0111", 500);
map.put("2220", 500);
map.put("0222", 500);
// 活四連
map.put("011110", 10000);
map.put("022220", 10000);
map.put("01111", 10000);
map.put("11110", 10000);
map.put("02222", 10000);
map.put("22220", 10000);
// 死一連
map.put("012", 10);
map.put("021", 10);
map.put("120", 10);
map.put("210", 10);
// 死二連
map.put("0112", 70);
map.put("0221", 70);
map.put("2110", 70);
map.put("1220", 70);
// 死三連
map.put("01112", 200);
map.put("02221", 200);
map.put("21110", 200);
map.put("12220", 200);
// 死四連
map.put("011112", 10000);
map.put("022221", 10000);
map.put("211110", 10000);
map.put("122220", 10000);
}
public void setG(Graphics g) {
this.g = g;
}
public void setT(JButton b) {
jbu1 = b;
}
public void setU(WZQFrame u) {
ui = u;
}
public void mouseClicked(MouseEvent e) {
}
public void mousePressed(MouseEvent e) {
}
public void mouseReleased(MouseEvent e) {
x = e.getX();
y = e.getY();
x1 = Math.abs(x - START_X);
y1 = Math.abs(y - START_Y);
xx = x1 % SIZE;
if (xx >= SIZE / 2) {
x1 = (x1 / SIZE) + 2;
} else {
x1 = (x1 / SIZE) + 1;
}
yy = y1 % SIZE;// 判斷橫座標是否超過格子長度的一半(防止玩家點偏)
if (yy >= SIZE / 2) {
y1 = (y1 / SIZE) + 2;
} else {
y1 = (y1 / SIZE) + 1;
}
g.setColor(Color.BLACK);
if (bx[x1][y1] == 0) {
bx[x1][y1] = 1;// 表示黑棋
g.fillOval(Math.abs(x1 * SIZE - 25), Math.abs(y1 * SIZE - 25), 50,
50);
count1++;// 所下棋子數加一
GetX[count1] = x1;// 記錄第count1步的棋子x值
GetY[count1] = y1;// 記錄第count1步的棋子y值
if (CheckRow(x1, y1) >= 5) {
JOptionPane.showMessageDialog(null, "BLACK WIN!!");
}
if (CheckList(x1, y1) >= 5) {
JOptionPane.showMessageDialog(null, "BLACK WIN!!");
}
if (UpperRight(x1, y1) >= 5) {
JOptionPane.showMessageDialog(null, "BLACK WIN!!");
}
if (UpperLeft(x1, y1) >= 5) {
JOptionPane.showMessageDialog(null, "BLACK WIN!!");
}
}
g.setColor(Color.WHITE);
WZQAI();// 遍歷棋盤
AIcount();// 電腦計算應該下棋的座標
if (bx[x1][y1] == 0) {
bx[x1][y1] = 2;// 表示白棋
if(x1==0)
{g.fillOval(Math.abs((x1+1)* SIZE - 25), Math.abs((y1+1) * SIZE - 25), 50,
50);}
else
{
g.fillOval(Math.abs(x1* SIZE - 25), Math.abs(y1 * SIZE - 25), 50,
50);
}
count1++;// 所下棋子數加一
GetX[count1] = x1;// 記錄第count1步的棋子x值
GetY[count1] = y1;// 記錄第count1步的棋子y值
if (CheckRow(x1, y1) >= 5) {
JOptionPane.showMessageDialog(null, "WHITE WIN!!");
}
if (CheckList(x1, y1) >= 5) {
JOptionPane.showMessageDialog(null, "WHITE WIN!!");
}
if (UpperRight(x1, y1) >= 5) {
JOptionPane.showMessageDialog(null, "WHITE WIN!!");
}
if (UpperLeft(x1, y1) >= 5) {
JOptionPane.showMessageDialog(null, "WHITE WIN!!");
}
}
// 清空權值數組
for (int r = 0; r < weightArray.length; r++) {
for (int c = 0; c < weightArray.length; c++) {
weightArray[r][c] = 0;
}
}
}
public void actionPerformed(ActionEvent e) {
setT(jbu1);
Str = e.getActionCommand();// 讀取點擊按鈕上的字符串
if ("悔棋".equals(Str)) {
if (g.getColor() == Color.BLACK) {
g.setColor(Color.WHITE);
}
if (g.getColor() == Color.WHITE) {
g.setColor(Color.BLACK);
}
Regret();
ui.repaint();
} else if ("重新開始".equals(Str)) {
Restart();
ui.repaint();
}
}
public void mouseEntered(MouseEvent e) {
}
public void mouseExited(MouseEvent e) {
}
public int CheckRow(int x, int y)// 橫着五子連成一條直線
{
int count = 0;
for (int i = x + 1; i < bx.length; i++)// 向右判斷是否棋子一樣
{
if (bx[i][y] == bx[x][y])
count++;
else
break;
}
for (int i = x; i >= 0; i--)// 向右判斷是否棋子一樣
{
if (bx[i][y] == bx[x][y])
count++;
else
break;
}
return count;
}
public int CheckList(int x, int y)// 豎着五子連成一條直線
{
int count = 0;
for (int i = y + 1; i < bx.length; i++)// 向下判斷是否棋子一樣
{
if (bx[x][i] == bx[x][y])
count++;
else
break;
}
for (int i = y; i >= 0; i--)// 向上判斷是否棋子一樣
{
if (bx[x][i] == bx[x][y])
count++;
else
break;
}
return count;
}
public int UpperRight(int x, int y)// 右上到左下五子連成一條直線
{
int count = 0;
for (int i = x + 1, j = y - 1; i < bx.length && j >= 0; i++, j--)// 向下判斷是否棋子一樣
{
if (bx[i][j] == bx[x][y])
count++;
else
break;
}
for (int i = x, j = y; i >= 0 && j < bx.length; i--, j++)// 向上判斷是否棋子一樣
{
if (bx[i][j] == bx[x][y])
count++;
else
break;
}
return count;
}
public int UpperLeft(int x, int y)// 左上到右下五子連成一條直線
{
int count = 0;
for (int i = x - 1, j = y - 1; i >= 0 && j >= 0; i--, j--)// 向下判斷是否棋子一樣
{
if (bx[i][j] == bx[x][y])
count++;
else
break;
}
for (int i = x, j = y; i < bx.length && j < bx.length; i++, j++)// 向上判斷是否棋子一樣
{
if (bx[i][j] == bx[x][y])
count++;
else
break;
}
return count;
}
public void Regret() {// 悔棋
assert count1 >= 2;
bx[GetX[count1]][GetY[count1]] = 0;
bx[GetX[count1-1]][GetY[count1-1]] = 0;
if (count1 > 0) {
count1 = count1 - 2;
}
}
public void Restart() {// 重新開始
{
for (int k = 0; k <= count1; k++) {
bx[GetX[k]][GetY[k]] = 0;
}
}
count1 = 0;
for (int i1 = 0; i1 < bx.length; i1++) {
for (int j1 = 0; j1 < bx.length; j1++) {
bx[i][j] = 0;
}
}
}
public void WZQAI() {
// 這兩個循環遍歷整個存儲棋子的數組
for (int r = 0; r < bx.length; r++) {
for (int c = 0; c < bx[r].length; c++) {
if (bx[r][c] == 0) {// 判斷是否是空位
int ch = 0;// 存儲第一次出現棋子的變量
String chessCode = "0";// 存儲統計棋子相連情況的變量
/*
* 橫向向左 左面的棋子在chessCode爲左方, 右面的棋子在chessCode爲右方
*/
for (int c1 = c - 1; c1 >= 0; c1--) {
if (bx[r][c1] == 0) {// 判斷是否是空位
if (c1 + 1 == c) {// 判斷是否是相鄰的
break;
} else {// 判斷是否不是相鄰的
chessCode = bx[r][c1] + chessCode;// 記錄棋子相連的情況
break;
}
} else {// 判斷是否是棋子
if (ch == 0) {// 判斷是否是第一次出現棋子
chessCode = bx[r][c1] + chessCode;// 記錄棋子相連的情況
ch = bx[r][c1];// 存儲第一次的棋子
} else if (ch == bx[r][c1]) {// 判斷是否是一樣顏色的棋子
chessCode = bx[r][c1] + chessCode;// 記錄棋子相連的情況
} else {
chessCode = bx[r][c1] + chessCode;// 記錄棋子相連的情況
break;
}
}
}
// 根據棋子相連的情況,獲取HashMap中存儲的權值
Integer weight = map.get(chessCode);
if(null==weight){
System.out.println(" get one null.....");
}
else{
int a;
a=weight.intValue();
// 存儲入到權值數組中
weightArray[r][c] += a;
}
ch = 0;// 重置到初始狀態
chessCode = "0";// 重置到初始狀態
/*
* 橫向向右 左面的棋子在chessCode爲左方, 右面的棋子在chessCode爲右方
*/
for (int c2 = c + 1; c2 <= 15; c2++) {// 判斷是是空位
if (bx[r][c2] == 0) {// 判斷空位相鄰的
if (c2 - 1 == c) {
break;
} else {// 判斷空位是不相鄰的
chessCode = chessCode + bx[r][c2];// 記錄棋子相連的情況
}
}
// 判斷是棋子
else {// 判斷是第一次出現棋子
if (ch == 0) {
chessCode = chessCode + bx[r][c2];// 記錄棋子相連的情況
ch = bx[r][c2];// 儲存第一次出現的棋子
} else if (ch == bx[r][c2])// 判斷棋子的顏色一樣
{
chessCode = chessCode + bx[r][c2];
}// 記錄棋子的連接情況
else {// 相鄰棋子顏色不一樣
chessCode = chessCode + bx[r][c2];
break;
}
}
weight = map.get(chessCode);
if(null==weight){
System.out.println(" get one null.....");
}
else{
int a;
a=weight.intValue();
// 存儲入到權值數組中
weightArray[r][c] += a;
}
ch = 0;// 重置到初始狀態
chessCode = "0";// 重置到初始狀態
}
/*
* 豎向向上 上面的棋子在chessCode爲左方, 下面的棋子在chessCode爲右方
*/
for (int r1 = r - 1; r1 >= 0; r1--) {
if (bx[r1][c] == 0) {// 判斷是否是空位
if (r1 + 1 == r) {// 判斷是否是相鄰的
break;
} else {// 判斷是否不是相鄰的
chessCode = bx[r1][c] + chessCode;// 記錄棋子相連的情況
break;
}
} else {// 判斷是否是棋子
if (ch == 0) {// 判斷是否是第一次出現棋子
chessCode = bx[r1][c] + chessCode;// 記錄棋子相連的情況
ch = bx[r1][c];// 存儲第一次的棋子
} else if (ch == bx[r1][c]) {// 判斷是否是一樣顏色的棋子
chessCode = bx[r1][c] + chessCode;// 記錄棋子相連的情況
} else {
chessCode = bx[r1][c] + chessCode;// 記錄棋子相連的情況
break;
}
}
}
// 根據棋子相連的情況,獲取HashMap中存儲的權值
weight = map.get(chessCode);
if(null==weight){
System.out.println(" get one null.....");
}
else{
int a;
a=weight.intValue();
// 存儲入到權值數組中
weightArray[r][c] += a;
}
ch = 0;// 重置到初始狀態
chessCode = "0";// 重置到初始狀態
/*
* 豎向向下 上面的棋子在chessCode爲左方, 下面的棋子在chessCode爲右方
*/
for (int r2 = r + 1; r2 <= 15; r2++) {// 判斷是是空位
if (bx[r2][c] == 0) {// 判斷空位相鄰的
if (r2 - 1 == r) {
break;
} else {// 判斷空位是不相鄰的
chessCode = chessCode + bx[r2][c];// 記錄棋子相連的情況
}
}
// 判斷是棋子
else {// 判斷是第一次出現棋子
if (ch == 0) {
chessCode = chessCode + bx[r][c];// 記錄棋子相連的情況
ch = bx[r2][c];// 儲存第一次出現的棋子
} else if (ch == bx[r2][c])// 判斷棋子的顏色一樣
{
chessCode = chessCode + bx[r2][c];
}// 記錄棋子的連接情況
else {// 相鄰棋子顏色不一樣
chessCode = chessCode + bx[r2][c];
break;
}
}
weight = map.get(chessCode);
if(null==weight){
System.out.println(" get one null.....");
}
else{
int a;
a=weight.intValue();
// 存儲入到權值數組中
weightArray[r][c] += a;
}
ch = 0;// 重置到初始狀態
chessCode = "0";// 重置到初始狀態
}
/*
* 左斜向上 左上面的棋子在chessCode爲左方, 右下面的棋子在chessCode爲右方
*/
for (int r1 = r - 1, c1 = c - 1; c1 >= 0 && r1 >= 0; c1--, r1--) {
if (bx[r1][c1] == 0) {// 判斷是否是空位
if (c1 + 1 == c && r1 + 1 == c) {// 判斷是否是相鄰的
break;
} else {// 判斷是否不是相鄰的
chessCode = bx[r1][c1] + chessCode;// 記錄棋子相連的情況
break;
}
} else {// 判斷是否是棋子
if (ch == 0) {// 判斷是否是第一次出現棋子
chessCode = bx[r1][c1] + chessCode;// 記錄棋子相連的情況
ch = bx[r1][c1];// 存儲第一次的棋子
} else if (ch == bx[r1][c1]) {// 判斷是否是一樣顏色的棋子
chessCode = bx[r1][c1] + chessCode;// 記錄棋子相連的情況
} else {
chessCode = bx[r1][c1] + chessCode;// 記錄棋子相連的情況
break;
}
}
}
// 根據棋子相連的情況,獲取HashMap中存儲的權值
weight = map.get(chessCode);
if(null==weight){
System.out.println(" get one null.....");
}
else{
int a;
a=weight.intValue();
// 存儲入到權值數組中
weightArray[r][c] += a;
}
ch = 0;// 重置到初始狀態
chessCode = "0";// 重置到初始狀態
/*
* 左斜向下 左上面的棋子在chessCode爲左方, 右下面的棋子在chessCode爲右方
*/
for (int r1 = r + 1, c1 = c + 1; c1 <= 15 && r1 <= 15; c1++, r1++) {
if (bx[r1][c1] == 0) {// 判斷是否是空位
if (c1 - 1 == c && r1 - 1 == c) {// 判斷是否是相鄰的
break;
} else {// 判斷是否不是相鄰的
chessCode = chessCode + bx[r1][c1];// 記錄棋子相連的情況
break;
}
} else {// 判斷是否是棋子
if (ch == 0) {// 判斷是否是第一次出現棋子
chessCode = chessCode + bx[r1][c1];// 記錄棋子相連的情況
ch = bx[r1][c1];// 存儲第一次的棋子
} else if (ch == bx[r1][c1]) {// 判斷是否是一樣顏色的棋子
chessCode = chessCode + bx[r1][c1];// 記錄棋子相連的情況
} else {
chessCode = chessCode + bx[r1][c1];// 記錄棋子相連的情況
break;
}
}
}
/*
* 右斜向上 左下面的棋子在chessCode爲左方, 右上面的棋子在chessCode爲右方
*/
for (int r1 = r - 1, c1 = c + 1; c1 <= 15 && r1 >= 0; c1++, r1--) // 行r,列c
{
if (bx[r1][c1] == 0) {// 判斷是否是空位
if (c1 - 1 == c && r1 + 1 == c) {// 判斷是否是相鄰的
break;
} else {// 判斷是否不是相鄰的
chessCode = chessCode + bx[r1][c1];// 記錄棋子相連的情況
break;
}
} else {// 判斷是否是棋子
if (ch == 0) {// 判斷是否是第一次出現棋子
chessCode = chessCode + bx[r1][c1];// 記錄棋子相連的情況
ch = bx[r1][c1];// 存儲第一次的棋子
} else if (ch == bx[r1][c1]) {// 判斷是否是一樣顏色的棋子
chessCode = chessCode + bx[r1][c1];// 記錄棋子相連的情況
} else {
chessCode = chessCode + bx[r1][c1];// 記錄棋子相連的情況
break;
}
}
weight = map.get(chessCode);
if(null==weight){
System.out.println(" get one null.....");
}
else{
int a;
a=weight.intValue();
// 存儲入到權值數組中
weightArray[r][c] += a;
}
ch = 0;// 重置到初始狀態
chessCode = "0";// 重置到初始狀態
}
/*
* 右斜向下 左下面的棋子在chessCode爲左方, 右上面的棋子在chessCode爲右方
*/
for (int r1 = r + 1, c1 = c - 1; c1 >= 0 && r1 <= 15; c1--, r1++) // 行r,列c
{
if (bx[r1][c1] == 0) {// 判斷是否是空位
if (c1 + 1 == c && r1 - 1 == c) {// 判斷是否是相鄰的
break;
} else {// 判斷是否不是相鄰的
chessCode = bx[r1][c1] + chessCode;// 記錄棋子相連的情況
break;
}
} else {// 判斷是否是棋子
if (ch == 0) {// 判斷是否是第一次出現棋子
chessCode = bx[r1][c1] + chessCode;// 記錄棋子相連的情況
ch = bx[r1][c1];// 存儲第一次的棋子
} else if (ch == bx[r1][c1]) {// 判斷是否是一樣顏色的棋子
chessCode = bx[r1][c1] + chessCode;// 記錄棋子相連的情況
} else {
chessCode = bx[r1][c1] + chessCode;// 記錄棋子相連的情況
break;
}
}
}
// 根據棋子相連的情況,獲取HashMap中存儲的權值
weight = map.get(chessCode);
if(null==weight){
System.out.println(" get one null.....");
}
else{
int a;
a=weight.intValue();
// 存儲入到權值數組中
weightArray[r][c] += a;
}
ch = 0;// 重置到初始狀態
chessCode = "0";// 重置到初始狀態
}
}
}
}
public void AIcount() {// 電腦統計應該下棋的座標
int max = -1;// 儲存權值的最大值
int rx = 0;// 儲存最大值處的行座標
int cx = 0;// 儲存最大值處的列座標
int k = 0;
// 最大值的座標爲x1,y1
for (int r = 0; r < weightArray.length; r++) {
for (int c = 0; c < weightArray.length; c++) {
if (weightArray[r][c] > max) {
System.out.println("weightArray=" + weightArray[r][c]);
max = weightArray[r][c];
rx = r;
cx = c;
} else {
continue;
}
}
}
x1 = rx;
y1 = cx;
x2 = rx * SIZE - 25;
y2 = cx * SIZE - 25;
}
}