Java beginner's gobang game implementation tutorial
- 2021-11-24 01:25:59
- OfStack
This article shares the specific code of Java to realize 5 sub-chess games for your reference, the specific contents are as follows
1. Creation of graphical interface
1.1 Creating an JFrame Form Container
1) The JFrame form needs to be set to the basic size, layout, default closure, and most importantly, visible.
1.2 Add components on JFrame to draw chessboard pieces and game operations.
1) Drawing of chessboard pieces: Customize a class to inherit JPanel, and rewrite the method of drawing chessboard and pieces into paint () method, so that when the form changes (zooming in, zooming out, moving and other operations, the chessboard pieces will not disappear and the chess game will be saved).
2) Regret chess, throw in the towel and other operations are realized by adding mouse monitoring through JButton button.
2. Implementation of key points
Use six classes to implement the underlying logic, UI, DrawChessBoard, GameMouse, QiZi, Location, and AI.
2.1 Draw chess pieces at the click position on the chessboard
1) Add mouse monitoring to the chessboard to obtain the coordinates of the click position
The UI class initializes the graphical interface in 1 and adds GameMouse listening to the DrawChessBoard class. In this way, when the mouse clicks on the chessboard, you can get the pixel coordinates clicked by the mouse on the chessboard by rewriting mouseClicked () of GameMouse class.
2) Coordinates are converted to coordinates in a 2-digit group
Save the position of all pieces on the chessboard by using int [] [] memory 2-dimensional array in QiZi class, so that the pixel coordinates are converted into coordinates in 2-dimensional array, and the corresponding values of pieces' colors are attached, so that the positions of all pieces on the chessboard can be saved.
3) Draw pieces on the chessboard
By traversing the non-zero values of int [] [] memory 2-dimensional array in QiZi class paint () method, you can call the brush method at the corresponding position to draw black and white chess pieces.
2.2 Judge Win or Lose
1) After playing chess pieces, the chess playing position is saved in int [] [] memory 2-dimensional array of QiZi class, and the number of continuous chess pieces in four directions can be calculated with this point as the center. If the number reaches five, the winner can be determined by generating pop-up windows of JOptionPane class.
2.2 Realization of regretting chess function and prompting the last falling position function
1) Every time you successfully drop a chess piece, you can create an Location object with the coordinates of the chess pieces, and add the object to the ArrayList or Stack container of QiZi class. When the mouse clicks on the regretful chess Button, clear the value of the corresponding position of int [] [] memory 2-dimensional array of QiZi class (change it to 0), and then redraw the chess pieces on the chessboard to complete the regretful chess effect.
2) At the same time, the position of the last falling child in the container can be found, and the last falling child prompt can be drawn on the corresponding coordinates of the chessboard.
2.3 Beginning, Realization of Giving Up
1) Start the game, that is, reset the game, and clear the corresponding attributes of chess pieces, such as int [] [] memory2-dimensional array (i.e. chess score), owener=1 (reset to white), and clear the chess pieces on the chessboard.
2) If you throw in the towel, you can judge the current value of QiZi. owner, judge the one party that loses and give a prompt.
2.4 Implementation of AI
1) When AI is black by default, it is necessary to call AI to play black chess after the white square falls, so call AI method in if branch where white chess needs to be played in GameMouse
2) Whether AI is powerful or not depends on its design. Here, an idea is provided: set up a chess type comparison table and assign values to different chess types (such as 1111, which represents Bai Zi 4 companies and has higher weight). When it is AI's turn, the total weight of each vacancy on the chessboard in 8 directions can be calculated according to this table, and it can be settled at the place with the largest weight. The weight setting of different chess in the chess type comparison table can be obtained by analyzing a large number of chess games such as python, so as to train AI. The more reasonable the weight setting, the stronger AI will be.
3. Other functions
The animation effect and sound effect can be realized by opening up different threads, while the network battle can increase the network communication related modules.
4. Source code
package wuziqi925;
import javax.swing.*;
import java.awt.*;
public class GameUI {
public static void main(String[] args) {
GameUI gameUI=new GameUI();
gameUI.showUI();
}
public void showUI(){
// Create a chess piece object
QiZi qizi=new QiZi();
// Get a form
JFrame jFrame=new JFrame();
jFrame.setSize(1000,795);
jFrame.setDefaultCloseOperation(3);
jFrame.setLocationRelativeTo(null);
jFrame.setLayout(null);
jFrame.setTitle("5 Sub-chess ");
jFrame.setResizable(false);
// Form to add a chessboard panel
DrawChessBoard chessBoard=new DrawChessBoard(qizi);
jFrame.add(chessBoard);
chessBoard.setSize(760,760);
chessBoard.setBackground(Color.ORANGE);
// Test JFrame Frame pixel size, Insets[top=32,left=3,bottom=3,right=3]
//System.out.println(jFrame.getInsets());
// Form adds an option panel to draw a chessboard
JPanel bp=new JPanel();
bp.setSize(236,760);
bp.setBackground(Color.lightGray);
bp.setLocation(760,0);
bp.setLayout(null);
jFrame.add(bp);
// Options panel add button
JButton start=new JButton(" Begin ");
start.setBackground(Color.white);
start.setFont(new Font(" Chinese running letters ",Font.BOLD,20));
start.setBounds(40,350,150,50);
JButton quit=new JButton(" To throw in the towel ");
quit.setBackground(Color.white);
quit.setFont(new Font(" Chinese running letters ",Font.BOLD,20));
quit.setBounds(40,440,150,50);
JButton undo=new JButton(" Regret chess ");
undo.setBackground(Color.white);
undo.setFont(new Font(" Chinese running letters ",Font.BOLD,20));
undo.setBounds(40,530,150,50);
bp.add(start);
bp.add(quit);
bp.add(undo);
// Select Mode Options
ButtonGroup bg=new ButtonGroup();
JRadioButton rrdz=new JRadioButton(" Player battle ");
JRadioButton rjdz=new JRadioButton(" Man-machine battle ");
rrdz.setSize(120,30);
rrdz.setLocation(55,60);
rrdz.setFont(new Font(" Chinese running letters ",Font.BOLD,20));
rrdz.setVisible(true);
rjdz.setSize(120,30);
rjdz.setLocation(55,90);
rjdz.setFont(new Font(" Chinese running letters ",Font.BOLD,20));
rjdz.setVisible(true);
bg.add(rjdz);
bg.add(rrdz);
bp.add(rjdz);
bp.add(rrdz);
bp.setVisible(true);
// Set the form visible
jFrame.setVisible(true);
AI ai=new AI(qizi,chessBoard);
// Gets the mouse listener and brush of the chessboard and adds the brush to the mouse
Graphics g1=chessBoard.getGraphics();
GameMouse gameMouse=new GameMouse(qizi,chessBoard,ai);
chessBoard.addMouseListener(gameMouse);
start.addActionListener(gameMouse);
quit.addActionListener(gameMouse);
undo.addActionListener(gameMouse);
rrdz.addActionListener(gameMouse);
rjdz.addActionListener(gameMouse);
}
}
package wuziqi925;
import javax.swing.*;
import java.awt.*;
public class DrawChessBoard extends JPanel {
QiZi qiZi;
private static int LINE_NUM = 15;
private static int MARGIN_WIDTH = 30;
public static int CELL_SIZE = 50;
public DrawChessBoard(QiZi qiZi) {
this.qiZi = qiZi;
}
@Override
public void paint(Graphics g) {
super.paint(g);
// Draw a chessboard
for (int i = 0; i < LINE_NUM; i++) {
g.drawLine(MARGIN_WIDTH, MARGIN_WIDTH + i * CELL_SIZE, MARGIN_WIDTH + (LINE_NUM - 1) * CELL_SIZE, MARGIN_WIDTH + i * CELL_SIZE);
g.drawLine(MARGIN_WIDTH + i * CELL_SIZE, MARGIN_WIDTH, MARGIN_WIDTH + i * CELL_SIZE, MARGIN_WIDTH + (LINE_NUM - 1) * CELL_SIZE);
}
// Draw points on a chessboard
g.fillOval(CELL_SIZE*3+22,CELL_SIZE*3+22,16,16);
g.fillOval(CELL_SIZE*11+22,CELL_SIZE*3+22,16,16);
g.fillOval(CELL_SIZE*3+22,CELL_SIZE*11+22,16,16);
g.fillOval(CELL_SIZE*11+22,CELL_SIZE*11+22,16,16);
// Draw chess pieces
int[][] a = qiZi.memory;
for (int i = 0; i < a.length; i++) {
for (int j = 0; j < a[i].length; j++) {
if (a[i][j] == 1) {
g.setColor(Color.white);
g.fillOval(CELL_SIZE * i + 7, CELL_SIZE * j + 7, 46, 46);
} else if (a[i][j] == 2) {
g.setColor(Color.black);
g.fillOval(CELL_SIZE * i + 7, CELL_SIZE * j + 7, 46, 46);
}
}
}
// Draw the last 1 On the position of the chess pieces 10 Character frame
if (qiZi.arr.size() > 0) {
Graphics2D g1=(Graphics2D)g;
g1.setColor(Color.red);
g1.setStroke(new BasicStroke(3.0f));
Location l = qiZi.arr.get(qiZi.arr.size() - 1);
g1.drawLine(CELL_SIZE * l.x + MARGIN_WIDTH - 8, CELL_SIZE * l.y + MARGIN_WIDTH, CELL_SIZE * l.x + MARGIN_WIDTH + 8, CELL_SIZE * l.y + MARGIN_WIDTH);
g1.drawLine(CELL_SIZE * l.x + MARGIN_WIDTH, CELL_SIZE * l.y + MARGIN_WIDTH - 8, CELL_SIZE * l.x + MARGIN_WIDTH, CELL_SIZE * l.y + MARGIN_WIDTH + 8);
}
}
}
package wuziqi925;
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
public class GameMouse implements MouseListener, ActionListener {
QiZi qizi;
DrawChessBoard drawChessBoard;
AI ai;
public GameMouse() {
}
public GameMouse( QiZi qiZi, DrawChessBoard drawChessBoard,AI ai) {
this.qizi = qiZi;
this.drawChessBoard=drawChessBoard;
this.ai=ai;
}
@Override
public void mouseClicked(MouseEvent e) {
int cellSize= DrawChessBoard.CELL_SIZE;
int x=e.getX();
int xx=0;
int y=e.getY();
int yy=0;
// Draw chess pieces in the click position , And convert the sub-position into a chess piece in 2 Coordinates in Dimensional Array
if (qizi.owner==1) {
if ((x - 30) % cellSize > 25 & (y - 30) % cellSize > 25) {
xx=(x - 30) / cellSize + 1;
yy=(y - 30) / cellSize + 1;
} else if ((x - 30) % cellSize > 25 & (y - 30) % cellSize < 25) {
xx=(x - 30) / cellSize + 1;
yy=(y - 30) / cellSize;
} else if ((x - 30) % cellSize < 25 & (y - 30) % cellSize > 25) {
xx=(x - 30) / cellSize;
yy=(y - 30) / cellSize + 1;
} else if ((x - 30) % cellSize < 25 & (y - 30) % cellSize < 25) {
xx=(x - 30) / cellSize;
yy=(y - 30) / cellSize;
}
if(qizi.memory[xx][yy]==0) {// Judge childless
qizi.x=xx;
qizi.y=yy;
qizi.memory[qizi.x][qizi.y] = qizi.owner;// Place the chess pieces and put them into the container
Location location=new Location(qizi);// Record the position order of the chess pieces just laid
qizi.arr.add(location);
drawChessBoard.repaint();// Draw the chess piece just laid
qizi.judgeWinner();// Judge winning or losing
qizi.owner=2;// Exchange chess rights
}
if (ai.state){
ai.initiateAI();
}
}else {
qizi.owner=2;
if ((x - 30) % cellSize > 25 & (y - 30) % cellSize > 25) {
xx=(x - 30) / cellSize + 1;
yy=(y - 30) / cellSize + 1;
} else if ((x - 30) % cellSize > 25 & (y - 30) % cellSize < 25) {
xx=(x - 30) / cellSize + 1;
yy=(y - 30) / cellSize;
} else if ((x - 30) % cellSize < 25 & (y - 30) % cellSize > 25) {
xx=(x - 30) / cellSize;
yy=(y - 30) / cellSize + 1;
} else if ((x - 30) % cellSize < 25 & (y - 30) % cellSize < 25) {
xx=(x - 30) / cellSize;
yy=(y - 30) / cellSize;
}
if(qizi.memory[xx][yy]==0) {
qizi.x=xx;
qizi.y=yy;
qizi.memory[qizi.x][qizi.y] = qizi.owner;// Place the chess pieces and put them into the container
Location location=new Location(qizi);// Record the position order of the chess pieces just laid
qizi.arr.add(location);
drawChessBoard.repaint();// Draw the chess piece just laid
qizi.judgeWinner();// Judge winning or losing
qizi.owner=1;// Exchange chess rights
}
}
}
@Override
public void actionPerformed(ActionEvent e) {
int cellSize= DrawChessBoard.CELL_SIZE;
String s=e.getActionCommand();
JOptionPane tc=new JOptionPane();
// Realization of regret chess function
if (s.equals(" Regret chess ")){
if (qizi.arr.size()>0) {
Location l = qizi.arr.get(qizi.arr.size() - 1);
qizi.memory[l.x][l.y] = 0;
qizi.arr.remove(qizi.arr.size() - 1);
if (qizi.owner == 1) {
qizi.owner = 2;
} else if (qizi.owner == 2) {
qizi.owner = 1;
}
}else {
tc.showMessageDialog(null," There is no chess to destroy, please play chess! ");
}
// Refresh the chessboard
drawChessBoard.repaint();
}
if (s.equals(" Begin ")){
qizi.owner=1;
qizi.memory=new int[15][15];
qizi.arr.clear();
qizi.win=false;
drawChessBoard.repaint();
}
if(s.equals(" To throw in the towel ")){
int whiteCount=0;
int blackCount=0;
for (int i = 0; i < qizi.memory.length; i++) {
for (int j = 0; j < qizi.memory[i].length; j++) {
if (qizi.memory[i][j]==1){
whiteCount++;
}else if (qizi.memory[i][j]==2){
blackCount++;
}
}
}
if (whiteCount==blackCount){
tc.showMessageDialog(null,qizi.owner==1 ?" Black surrender , Bai Fangsheng! ":" White surrender , Black wins! ");
}else if(whiteCount>blackCount){
tc.showMessageDialog(null," Black surrender , Bai Fangsheng! ");
}else {
tc.showMessageDialog(null," White surrender , Black wins! ");
}
}
if (s.equals(" Man-machine battle ")){
ai.state=true;
}
if (s.equals(" Player battle ")){
ai.state=false;
}
}
@Override
public void mousePressed(MouseEvent e) {
}
@Override
public void mouseReleased(MouseEvent e) {
}
@Override
public void mouseEntered(MouseEvent e) {
}
@Override
public void mouseExited(MouseEvent e) {
}
}
package wuziqi925;
import javax.swing.*;
import java.util.ArrayList;
public class QiZi {
int x;
int y;
int owner=1;//1 It stands for white, 2 It stands for black
int[][] memory;
ArrayList <Location>arr;
boolean win=false;
public QiZi() {
memory=new int[15][15];
arr=new ArrayList<>(50);
}
public void judgeWinner() {
JOptionPane tc=new JOptionPane();
int count1=0;
int count2=0;
int count3=0;
int count4=0;
// Vertical direction detection
for (int i = y-1; i >-1 ; i--) {
if (memory[x][i]==owner){
count1++;
}else {
break;
}
}
for (int i = y+1; i <15; i++) {
if (memory[x][i]==owner){
count1++;
}else {
break;
}
}
if (count1 > 3){
tc.showMessageDialog(null,owner==1?" Bai Fangsheng ":" Black side wins ");
win=true;
return;
}
// Horizontal direction detection
for (int i = x-1; i >-1 ; i--) {
if (memory[i][y]==owner){
count2++;
}else {
break;
}
}
for (int i = x+1; i <15; i++) {
if (memory[i][y]==owner){
count2++;
}else {
break;
}
}
if (count2 > 3){
tc.showMessageDialog(null,owner==1?" Bai Fangsheng ":" Black side wins ");
win=true;
return;
}
// In \ Directional detection
int yy=y;
for (int i = x+1; i <15; i++) {
if(yy==14){
break;
}
yy++;
if (memory[i][yy]==owner){
count3++;
}else {
break;
}
}
yy=y;
for (int i = x-1; i >-1; i--) {
if (yy==0){
break;
}
yy--;
if (memory[i][yy]==owner){
count3++;
}else {
break;
}
}
if (count3 > 3){
tc.showMessageDialog(null,owner==1?" Bai Fangsheng ":" Black side wins ");
win=true;
return;
}
// In / Directional detection
yy=y;
for (int i = x+1; i <15; i++) {
if(yy==0){
break;
}
yy--;
if (memory[i][yy]==owner){
count4++;
}else {
break;
}
}
yy=y;
for (int i = x-1; i >-1; i--) {
if(yy==14){
break;
}
yy++;
if (memory[i][yy]==owner){
count4++;
}else {
break;
}
}
if (count4 > 3){
tc.showMessageDialog(null,owner==1?" Bai Fangsheng ":" Black side wins ");
win=true;
return;
}
}
}
package wuziqi925;
public class Location {
QiZi qiZi;
int x;
int y;
public Location(QiZi qiZi) {
// Record chess score
x=qiZi.x;
y=qiZi.y;
}
public Location(int x, int y) {
this.x = x;
this.y = y;
}
}
package wuziqi925;
import java.util.*;
public class AI {
boolean state=false;//true For on false For off
QiZi qiZi;
// Storing chess weights
private HashMap<String,Integer> playValueTable=new HashMap<>();
// Store the weight of each downloadable point
private HashMap<Location,Integer> locationsAndValues=new HashMap<>();
DrawChessBoard drawChessBoard;
int AIDO=0;
public AI(QiZi qiZi,DrawChessBoard drawChessBoard){
this.drawChessBoard=drawChessBoard;
this.qiZi=qiZi;
//1 Chess pieces (players) representing this direction are white, 2 Chess pieces representing black square in this direction ( AI )
playValueTable.put("22221",100);
playValueTable.put("2222",100);
playValueTable.put("11112",99);
playValueTable.put("1111",0);
playValueTable.put("2221",40);
playValueTable.put("222",45);
playValueTable.put("1112",35);
playValueTable.put("111",46);
playValueTable.put("22",25);
playValueTable.put("221",20);
playValueTable.put("11",15);
playValueTable.put("112",10);
playValueTable.put("21",5);
playValueTable.put("2",10);
playValueTable.put("1",8);
playValueTable.put("12",2);
}
public void initiateAI(){
if (qiZi.win){
return;
}
int chessValue=0;
// Traverse the chessboard to find an empty point
for (int i = 0; i <qiZi.memory.length; i++) {
for (int j = 0; j < qiZi.memory[i].length; j++) {
// Calculation qiZi.memory[i][j] Weight of the (empty point) position, save ij Site
if (qiZi.memory[i][j]==0){
Location l=new Location(i,j);
chessValue=countValue(i,j);
locationsAndValues.put(l,chessValue);
}
}
}
//System.out.println(chessValue);
// Judge the point with the largest weight , Gets the coordinate value of this point and passes it in qiZi.memory
// According to value Right HashMap<Location,Integer> locationsAndValues Sort to find the maximum value
Set<Map.Entry<Location,Integer>> set=locationsAndValues.entrySet();
List<Map.Entry<Location,Integer>> list=new ArrayList<>(set);
list.sort(new Comparator<Map.Entry<Location, Integer>>() {
@Override
public int compare(Map.Entry<Location, Integer> o1, Map.Entry<Location, Integer> o2) {
return o2.getValue()-o1.getValue();
}
});
// Take the maximum after sorting // Obtain the empty point coordinates corresponding to the maximum weight value
Map.Entry<Location,Integer> maxSet=list.get(0);
Location toDo=maxSet.getKey();
qiZi.x= toDo.x;
qiZi.y= toDo.y;
qiZi.memory[qiZi.x][qiZi.y]=qiZi.owner;
Location location=new Location(qiZi);// Record the position order of the chess pieces just laid
qiZi.arr.add(location);
drawChessBoard.repaint();// Draw the chess piece just laid
qiZi.judgeWinner();// Judge winning or losing
qiZi.owner=1;// Exchange chess rights
System.out.println(++AIDO);
locationsAndValues.clear();
}
private int countValue(int i,int j) {
int totalValue=0;
StringBuilder s1=new StringBuilder();
StringBuilder s2=new StringBuilder();
StringBuilder s3=new StringBuilder();
StringBuilder s4=new StringBuilder();
StringBuilder s5=new StringBuilder();
StringBuilder s6=new StringBuilder();
StringBuilder s7=new StringBuilder();
StringBuilder s8=new StringBuilder();
//8 Go in a direction to judge
//North
for (int k = j-1; k >-1 ; k--) {
if (qiZi.memory[i][k]==1){
s1.append(1);
}else if (qiZi.memory[i][k]==2) {
s1.append(2);
}else {
break;
}
}
int count1=playValueTable.get(s1.toString())==null?0:playValueTable.get(s1.toString());
totalValue+=count1;
//South
for (int k = j+1; k <15; k++) {
if (qiZi.memory[i][k]==1){
s2.append(1);
}else if (qiZi.memory[i][k]==2) {
s2.append(2);
}else {
break;
}
}
int count2=playValueTable.get(s2.toString())==null?0:playValueTable.get(s2.toString());
totalValue+=count2;
//West
for (int k = i-1; k >-1 ; k--) {
if (qiZi.memory[k][j]==1){
s3.append(1);
}else if (qiZi.memory[k][j]==2) {
s3.append(2);
}else {
break;
}
}
int count3=playValueTable.get(s3.toString())==null?0:playValueTable.get(s3.toString());
totalValue+=count3;
//East
for (int k = i+1; k <15; k++) {
if (qiZi.memory[k][j]==1){
s4.append(1);
}else if (qiZi.memory[k][j]==2) {
s4.append(2);
}else {
break;
}
}
int count4=playValueTable.get(s4.toString())==null?0:playValueTable.get(s4.toString());
totalValue+=count4;
//SE
int yy=j;
for (int k = i+1; k < 15; k++) {
if(yy==14){
break;
}
yy++;
if (qiZi.memory[k][yy]==1){
s5.append(1);
}else if (qiZi.memory[k][yy]==2) {
s5.append(2);
}else {
break;
}
}
int count5=playValueTable.get(s5.toString())==null?0:playValueTable.get(s5.toString());
totalValue+=count5;
//NW
yy=j;
for (int k = i-1; k >-1; k--) {
if(yy==0){
break;
}
yy--;
if (qiZi.memory[k][yy]==1){
s6.append(1);
}else if (qiZi.memory[k][yy]==2) {
s6.append(2);
}else {
break;
}
}
int count6=playValueTable.get(s6.toString())==null?0:playValueTable.get(s6.toString());
totalValue+=count6;
//NE
yy=j;
for (int k = i+1; k <15; k++) {
if(yy==0){
break;
}
yy--;
if (qiZi.memory[k][yy]==1){
s7.append(1);
}else if (qiZi.memory[k][yy]==2) {
s7.append(2);
}else {
break;
}
}
int count7=playValueTable.get(s7.toString())==null?0:playValueTable.get(s7.toString());
totalValue+=count6;
//SW
yy=j;
for (int k = i-1; k >-1; k--) {
if(yy==14){
break;
}
yy++;
if (qiZi.memory[k][yy]==1){
s8.append(1);
}else if (qiZi.memory[k][yy]==2) {
s8.append(2);
}else {
break;
}
}
int count8=playValueTable.get(s8.toString())==null?0:playValueTable.get(s8.toString());
totalValue+=count8;
return totalValue;
}
}