100字范文,内容丰富有趣,生活中的好帮手!
100字范文 > 五子棋(人人对战 人机对战均可)

五子棋(人人对战 人机对战均可)

时间:2024-01-15 22:28:45

相关推荐

五子棋(人人对战 人机对战均可)

这是我第一次做个人项目,虽然难度不大,但也还是花了挺多时间的。

第一步建立了棋子类,用于定义棋子。

import java.awt.Color;import java.awt.Graphics;public class Chess implements ChessInterface {protected Color color;public int x, y;public Chess(int x, int y, Color color) {this.x = x;this.y = y;this.color = color;}public void draw(Graphics g) {g.setColor(color);g.fillOval(X + x * Size - Size / 2, Y + y * Size - Size / 2, Size, Size);}}

第二步画棋盘,同时将监听器也进行绑定,我将监听器绑定在了按键而非棋盘上。重写paint方法用于重绘。这里要注意的一点是,最好创建一个接口保存棋盘的间距、行数、列数等信息,方便之后修改。同时在这个接口中,还声明了一个二维数组用于保存棋局(棋子的颜色)。第二个二维数组是之后人机对战用到的,之后再详述。棋盘代码如下:

public class ChessPane extends JPanel implements ChessInterface {/*** */private static final long serialVersionUID = 1L;Chess chess[] = new Chess[100];public static void main(String[] args) {ChessPane chesspanel = new ChessPane();chesspanel.showUI();}// 创建窗体对象public void showUI() {JFrame jf = new JFrame();jf.setSize(800, 660);jf.setTitle("五子棋");// 设置进程的方法jf.setDefaultCloseOperation(3);// 设置居中显示jf.setLocationRelativeTo(null);jf.getContentPane().setBackground(Color.WHITE);jf.setLayout(new BorderLayout());// this.setBackground(Color.BLUE);jf.add(this, BorderLayout.CENTER);JPanel pan = new JPanel();pan.setBackground(Color.DARK_GRAY);pan.setPreferredSize(new Dimension(150, 0));jf.add(pan, BorderLayout.EAST);// 添加监听器ChessListener mouse = new ChessListener();this.addMouseListener(mouse);mouse.setC(chess);mouse.setP(this);String button[] = { "开始游戏", "悔 棋", "认 输", "人机对战", "双人对战" };for (int i = 0; i < button.length; i++) {JButton jbu = new JButton(button[i]);pan.add(jbu);jbu.addActionListener(mouse);}jf.setVisible(true);Graphics g = this.getGraphics();mouse.setGr(g);}public void paint(Graphics g) {super.paint(g);// 画棋盘for (int i = 0; i < 15; i++) {g.drawLine(X, Y + i * Size, X + (Coloum - 1) * Size, Y + i * Size);g.drawLine(X + i * Size, Y, X + i * Size, Y + (Row - 1) * Size);}// 画棋子for (int i = 0; i < chess.length; i++) {Chess ch = chess[i];if (ch != null)ch.draw(g);}}}

接口代码:

public interface ChessInterface {//棋子和棋盘的大小public static final int Size=40;public static final int X=30;public static final int Y=30;public static final int Row=15;public static final int Coloum=15;//存棋子public static final int[][]array=new int[Row][Coloum];public static final int[][]chessValue=new int[Row][Coloum];}

接下来是监听器部分,由于功能比较多,所以写的有些混乱,请多包涵。

几个功能的实现思想如下:

1)双人对战:通过监听器获取点击坐标,但是要注意把坐标进行转换,才能让棋子落在棋盘的交叉点处。通过一个num变量用于计数,从而判定棋子的颜色。用filloval函数绘制棋子,注意的是要将棋子保存进数组,因为要进行重绘。(事实上,每下一颗棋子就进行了一次重绘)。

2)开始游戏:这个按钮的意思是重新开始游戏,其实只要明白“下子就是重绘”这一原理,就很好解决了。只需要将保存棋子的数组清空,棋盘就无法进行重绘,也就是重新开始新的一轮游戏了。

3)悔棋:悔棋的原理同 2),之前提到用num来计数,只需要更改num值,就能对数组中保存的值进行修改,也就是对棋局进行修改。

4)人机对战:人机对战有很多种实现方式,小白采用的是最简单的权值表法,也就是遍历整个棋盘,根据之前设定的权值生成每一个位置的权值表,选取权值最大的位置下子。这里又创建了一个二维数组,用于存储每个格子的权值。

首先,设立权值;然后,根据权值建立每个可能位置的权值表(八个方位,权值进行累加);通过循环找到权值最大的位置,然后下子(这里要注意的是,不同的方向要记得及时把之前累加的权值清零。);下子之后,把整个棋盘的权值表清零(二维数组清零)这里还有一个小细节,由于我把监听器绑定在按键上,所以是通过获取按键上的字符串来判断当前的功能的,建议还是将不同的功能写成函数进行调用,这样就能提高代码复用。可以通过设定一个变量来控制代码的运行。

package com.fzj.Chess0421;import java.awt.Color;import java.awt.Graphics;import java.awt.event.ActionEvent;import java.awt.event.ActionListener;import java.awt.event.MouseAdapter;import java.awt.event.MouseEvent;import java.awt.event.MouseListener;import java.awt.event.MouseMotionListener;import java.util.HashMap;import javax.swing.JOptionPane;import javax.swing.JPanel;public class ChessListener extends MouseAdapterimplements ChessInterface, MouseListener, ActionListener, MouseMotionListener {private int x, y, i = 0;private Graphics g;private int num = 0;Chess[] chess;private String str;Color chessc;CheckWin win = new CheckWin();ChessPane cp;public void setGr(Graphics gr) {g = gr;}public void setC(Chess[] c) {chess = c;}public void setP(ChessPane p) {cp = p;}public void mouseReleased(MouseEvent e) {x = e.getX();y = e.getY();int row = 1;int line = 1;// 判断棋子的位置int a = (x - X) / Size;// 取商int b = (x - X) % Size;// 取余数if (b <= (Size / 2)) {row = a;} else {row = a + 1;}int c = (y - Y) / Size;// 取商int d = (y - Y) % Size;// 取余数if (d <= (Size / 2)) {line = c;} else {line = c + 1;}if (array[row][line] == 0) {if (num % 2 == 0) {g.setColor(Color.black);array[row][line] = 1;} else {g.setColor(Color.white);array[row][line] = 2;}g.fillOval(X + row * Size - Size / 2, Y + line * Size - Size / 2, Size, Size);Chess ch = new Chess(row, line, g.getColor());chess[num] = ch;num++;if (i == 1) {AI();}win.isWin(row, line);}}public void restart(){for (int i = 0; i < chess.length; i++) {chess[i] = null;}for (int i = 0; i < array.length; i++) {for (int j = 0; j < array.length; j++) {array[i][j] = 0;}}num = 0;cp.paint(g);}public void actionPerformed(ActionEvent e) {str = e.getActionCommand();if ("开始游戏".equals(str)) {restart();}if ("悔 棋".equals(str)) {if(i==2){if (num > 0) {num--;x = chess[num].x;y = chess[num].y;array[x][y] = 0;chess[num] = null;cp.repaint();}}}if ("人机对战".equals(str)) {restart();i = 1;// 人先下(黑子),并判断输赢// AI();}if ("双人对战".equals(str)) {restart();i = 0;// 人先下(黑子),并判断输赢// AI();}}HashMap<String, Integer> hm = new HashMap<String, Integer>();public ChessListener() {//blackhm.put("1", 10);hm.put("11", 100);hm.put("111", 5000);hm.put("1111", 8000);hm.put("12", 5);hm.put("112", 80);hm.put("1112", 3000);hm.put("11112", 10000);hm.put("21", 11);hm.put("211", 110);hm.put("2111", 1100);hm.put("21111", 11000);//whitehm.put("2", 20);hm.put("22", 200);hm.put("222", 4500);hm.put("2222", 10000);hm.put("221", 100);hm.put("2221", 3000);hm.put("22221", 12000);hm.put("122", 5);hm.put("1222", 500);hm.put("12222", 10000);}public void AI() {// 人先下(黑子),并判断输赢// 建立权值// 水平方向for (int i = 0; i < array.length; i++) {for (int j = 0; j < array[i].length; j++) {if (array[i][j] == 0) {String code = "";int color = 0;// 向右for (int k = i + 1; k < array.length; k++) {if (array[k][j] == 0) {break;} else {if (color == 0) {color = array[k][j];code += array[k][j];} else if (array[k][j] == color) {code += array[k][j];} else {code += array[k][j];break;}}}// 根据code取出对应的权值Integer value1 = hm.get(code);if (value1 != null) {chessValue[i][j] += value1;}// 向左code = "";color = 0;// 向左for (int k = i; k > 0; k--) {if (array[k][j] == 0) {break;} else {if (color == 0) {color = array[k][j];code += array[k][j];} else if (array[k][j] == color) {code += array[k][j];} else {code += array[k][j];break;}}}value1 = hm.get(code);if (value1 != null) {chessValue[i][j] += value1;}// 垂直方向// 向上color = 0;code = "";for (int k = j + 1; k < array.length; k++) {if (array[i][k] == 0) {break;} else {if (color == 0) {color = array[i][k];code += array[i][k];} else if (array[i][k] == color) {code += array[i][k];} else {code += array[i][k];break;}}}// 根据code取出对应的权值Integer value11 = hm.get(code);if (value11 != null) {chessValue[i][j] += value11;}// 向下color = 0;code = "";for (int k = j; k > 0; k--) {if (array[i][k] == 0) {break;} else {if (color == 0) {color = array[i][k];code += array[i][k];} else if (array[i][k] == color) {code += array[i][k];} else {code += array[i][k];break;}}}value1 = hm.get(code);if (value1 != null) {chessValue[i][j] += value1;}code = "";color = 0;//右斜//向下for (int k = 0; k < (array.length - i)&&k<(array.length-j); k++) {if (array[i + k][j + k] == 0) {break;} else {if (color == 0) {color = array[i + k][j + k];code += array[i + k][j + k];} else if (array[i + k][j + k] == color) {code += array[i + k][j + k];} else {code += array[i + k][j + k];break;}}}value1 = hm.get(code);if (value1 != null) {chessValue[i][j] += value1;}code = "";color = 0;// 向上for (int k = 0; (j - k) > 0 && (i - k) > 0; k++) {if (array[i - k][j - k] == 0) {break;} else {if (color == 0) {color = array[i - k][j - k];code += array[i - k][j - k];} else if (array[i - k][j - k] == color) {code += array[i - k][j - k];} else {code += array[i - k][j - k];break;}}}value1 = hm.get(code);if (value1 != null) {chessValue[i][j] += value1;}code = "";color = 0;// 向下for (int k = 0; (i - k) > 0 && k > (array.length - j); k++) {if (array[i - k][j + k] == 0) {break;} else {if (color == 0) {color = array[i - k][j + k];code += array[i - k][j + k];} else if (array[i - k][j + k] == color) {code += array[i - k][j + k];} else {code += array[i - k][j + k];break;}}}value1 = hm.get(code);if (value1 != null) {chessValue[i][j] += value1;}code = "";color = 0;// for (int k = 0; k < (array.length - i) && (j - k) > 0; k++) {if (array[i + k][j - k] == 0) {break;} else {if (color == 0) {color = array[i + k][j - k];code += array[i + k][j - k];} else if (array[i + k][j - k] == color) {code += array[i + k][j - k];} else {code += array[i + k][j - k];break;}}}value1 = hm.get(code);if (value1 != null) {chessValue[i][j] += value1;}}}}// 找到权值最大的位置,并下子int max = 0;int x1 = 0;int y1 = 0;for (int a = 0; a < chessValue.length; a++) {for (int b = 0; b < chessValue.length; b++) {if (chessValue[a][b] > max) {max = chessValue[a][b];x1 = a;y1 = b;}}}for (int a = 0; a < chessValue.length; a++) {for (int b = 0; b < chessValue.length; b++) {System.out.print(chessValue[a][b] + " ");}System.out.println();}System.out.println();// System.out.println("x1="+x1+" y1="+y1);g.setColor(Color.white);g.fillOval(X + x1 * Size - Size / 2, Y + y1 * Size - Size / 2, Size, Size);array[x1][y1] = 2;Chess ch = new Chess(x1, y1, Color.white);chess[num] = ch;num++;win.isWin(x1, y1);// 清空权值表for (int a = 0; a < chessValue.length; a++) {for (int b = 0; b < chessValue.length; b++) {chessValue[a][b] = 0;}}}}

接下来,也是比较重要的一步,判断输赢,我专门建立了一个类用于判断输赢,只需要创建一个对象,就能调用判定的方法。其实判定其实很简单,用一个变量进行计数,再采用一个循环,同色则+1,异色或无子则break,也是对八个方位进行判定,代码如下:

import javax.swing.JOptionPane;public class CheckWin implements ChessInterface {public void isWin(int x,int y){if(horizontal(x,y)>=5||vertical(x,y)>=5||westnorth(x,y)>=5||eastnorth(x,y)>=5){if(array[x][y]==1)JOptionPane.showMessageDialog(null, "black win");else if(array[x][y]==2)JOptionPane.showMessageDialog(null, "white win");}}public int horizontal(int x, int y) {int count = 0;for (int i = x + 1; i < array.length; i++) {if (array[i][y] == array[x][y]) {count++;} elsebreak;}for (int i = x; i >= 0; i--) {if (array[i][y] == array[x][y]) {count++;} elsebreak;}return count;}public int vertical(int x, int y) {int count = 0;for (int i = y + 1; i < array.length; i++) {if (array[x][i] == array[x][y]) {count++;} elsebreak;}for (int i = y; i >= 0; i--) {if (array[x][i] == array[x][y]) {count++;} elsebreak;}return count;}public int westnorth(int x, int y) {int count = 0;for (int i = 0; i <(array.length-x)&&i<(array.length-x); i++) {if (array[x+i][y+i] == array[x][y]) {count++;} elsebreak;}for (int i = 1; (x-i)>=0&&(y-i)>=0; i++) {if (array[x-i][y-i] == array[x][y]) {count++;} elsebreak;}return count;}public int eastnorth(int x, int y) {int count = 0;for (int i = 0; i <(array.length-x)&&(y-i)>0; i++) {if (array[x+i][y-i] == array[x][y]) {count++;} elsebreak;}for (int i = 1; (x-i)>=0&&i <(array.length-y); i++) {if (array[x-i][y+i] == array[x][y]) {count++;} elsebreak;}return count;}}

至此,一个简陋的五子棋就完成了。

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。