?一.?程序基本思路:
1.寫窗口、棋盤面板、控制面板;
2.繪制棋盤;
3.繪制棋子;
4.添加組件功能;
5.判斷輸贏;
6.悔棋;
7.復(fù)盤。
二.實(shí)際操作
1.創(chuàng)建窗口、添加面板
package teachGoBang;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class GoBang {
public void drawUI() {
JFrame jf = new JFrame("五子棋");//創(chuàng)建窗口
jf.setSize(980,900);//設(shè)置窗口大小
jf.setLocationRelativeTo(null);//居中顯示
jf.setDefaultCloseOperation(3);//設(shè)置窗口后臺(tái)關(guān)閉
jf.setLayout(new BorderLayout());//將窗體設(shè)為邊框布局
JPanel chesspanel = new JPanel();//創(chuàng)建棋盤對(duì)象
jf.setBackground(Color.WHITE);//設(shè)置棋盤顏色
jf.add(chesspanel,BorderLayout.CENTER);//將面板添加到窗體中間
Mouse mouse = new Mouse();//創(chuàng)建鼠標(biāo)對(duì)象
//直接在面板后創(chuàng)建鼠標(biāo)對(duì)象便于對(duì)象在類之間的傳遞
JPanel buttonpanel = new JPanel();//創(chuàng)建操控面板
buttonpanel.setBackground(Color.GRAY);//設(shè)置棋盤顏色
buttonpanel.setPreferredSize(new Dimension(180,900));//設(shè)置控制面板大小
jf.add(buttonpanel,BorderLayout.EAST);//將面板添加到窗體右側(cè)布局
String[] button = {"開始","人機(jī)","悔棋","認(rèn)輸","復(fù)盤"};//創(chuàng)建按鈕數(shù)組
for(int i=0;i<button.length;i++) {
JButton jbu = new JButton(button[i]);//創(chuàng)建按鈕對(duì)象,并賦給其數(shù)組值
jbu.setPreferredSize(new Dimension(160,100));//設(shè)置按鈕大小
jbu.setFont(new Font("思源宋體",Font.BOLD,18));//設(shè)置按鈕字體
buttonpanel.add(jbu);//給操控面板添加按鈕組件
jbu.addActionListener(mouse);//給按鈕添加鼠標(biāo)監(jiān)聽器
}
jf.setVisible(true);//設(shè)置窗體課件
mouse.setGraphics(chesspanel.getGraphics());//創(chuàng)建畫筆對(duì)象并傳遞給Mouse類
chesspanel.addMouseListener(mouse);//給棋盤添加鼠標(biāo)監(jiān)聽器
}
public static void main(String[]args) {
GoBang go = new GoBang();
go.drawUI();
}
}
效果圖:
?2.繪制棋盤
? 為了棋盤線在窗體刷新后仍能保存,我們直接重寫chesspanel的paint方法,將棋盤繪制寫在paint方法中。為了調(diào)用方便,我們先寫一個(gè)接口,用于保存繪制棋盤要用的數(shù)據(jù)。
package teachGoBang;
public interface Basic {
public int x0 = 50, y0 = 50, size = 50, line = 15;
//x0,y0圍棋盤線的起始點(diǎn),size為行距,line為行數(shù)
}
package teachGoBang;
import java.awt.Graphics;
import javax.swing.JPanel;
//寫一個(gè)MyPanel類繼承類,重寫paint方法
public class MyPanel extends JPanel implements Basic{
public void paint(Graphics g) {
super.paint(g);//先將父類自帶的paint方法再寫一遍
for (int i = 0; i < line; i++) {
g.drawLine(x0, y0 + i * size, x0 + (line - 1) * size, y0 + i * size);
g.drawLine(x0 + i * size, y0, x0 + i * size, y0 + (line - 1) * size);
}
}
}
同時(shí)要記得將先前的chesspanel對(duì)象的類名改為MyPanel
MyPanel chesspanel = new MyPanel();//創(chuàng)建棋盤對(duì)象
效果圖
?3.繪制棋子
? 棋子繪制寫在鼠標(biāo)類中,通過(guò)鼠標(biāo)點(diǎn)擊位置獲取棋子坐標(biāo)。繪制后的棋子要保存到數(shù)組中,然后在MyPanel類的paint方法中再繪制一次棋子,完成已繪制棋子的保存。
package teachGoBang;
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 lqz3.Chess;
//在鼠標(biāo)類中直接去繼承MouseAdapter類而不是使用接口可以不用重寫所有方法
public class Mouse extends MouseAdapter implements ActionListener, Basic {
private Graphics g;// 定義畫筆
private int x, y, x1, y1;
private int[][] chessArr = new int[line][line];// 定義二維數(shù)組,用于保存棋盤坐標(biāo)對(duì)應(yīng)的棋子顏色
private int count = 0;// 定義計(jì)數(shù)器記錄棋子個(gè)數(shù)
private Color color;
public void setGraphics(Graphics g) {
this.g = g;
}
public int[][] getchessArr(){
return chessArr;
}
public void actionPerformed(ActionEvent e) {
}
public void mouseClicked(MouseEvent e) {
int x = e.getX();// 鼠標(biāo)點(diǎn)擊處獲取x、y坐標(biāo)
int y = e.getY();
// 獲取落子坐標(biāo),此處進(jìn)行判斷讓獲取的坐標(biāo)位于棋盤線交點(diǎn)處
if ((x - x0) % size > size / 2) {
x1 = (x - x0) / size + 1;
} else if ((x - x0) % size <= size / 2) {
x1 = (x - x0) / size;
}
if ((y - y0) % size > size / 2) {
y1 = (y - y0) / size + 1;
} else if ((y - y0) % size <= size / 2) {
y1 = (y - y0) / size;
}
// 判斷棋子是否會(huì)越出棋盤界
if (0 <= x1 && x1 <= 14 && 0 <= y1 && y1 <= 14) {
// 判斷只有空位置才能下棋
if (chessArr[y1][x1] == 0) {
// 加for循環(huán)是為了給棋子添加3D效果
for (int i = 0; i < 50; i++) {
// count為雙數(shù)下黑棋,為單數(shù)下白棋
//下完黑棋在數(shù)組中存入1,白棋存入-1
if (count % 2 == 0) {
color = new Color(5 * i, 5 * i, 5 * i);// 3d效果
g.setColor(color);// 設(shè)置畫筆顏色
g.fillOval(x1 * size + x0 + i / 2 - 25, y1 * size + y0 + i / 2 - 25, 50 - i, 50 - i);
chessArr[y1][x1] = 1;// 記錄棋盤上每顆棋子的顏色(實(shí)際是記入1、-1)
} else {
color = new Color(155 + 2 * i, 155 + 2 * i, 155 + 2 * i);
g.setColor(color);
g.fillOval(x1 * size + x0 + i / 2 - 25, y1 * size + y0 + i / 2 - 25, 50 - i, 50 - i);
chessArr[y1][x1] = -1;
}
}
count++;//每下完一顆棋,計(jì)數(shù)器加1
}
}else {
System.out.print("超出棋盤邊界");
}
}
}
接下來(lái)要在MyPanel的paint方法中重繪棋子。先在兩個(gè)類中寫set和get方法,再將chessArr數(shù)組傳遞到MyPanel類中,由于GoBang類中同時(shí)出現(xiàn)chesspanel和mouse對(duì)象,因此在GoBang中傳遞該數(shù)組。為了防止MyPanel中出現(xiàn)重繪棋盤時(shí)要用到chessArr數(shù)組而chessArr數(shù)組還沒(méi)傳過(guò)來(lái)的情況發(fā)生,我們直接在創(chuàng)建chesspanel對(duì)象后就把數(shù)組傳過(guò)去
Mouse mouse = new Mouse();//創(chuàng)建鼠標(biāo)對(duì)象
chesspanel.setchseeArr(mouse.getchessArr());//傳遞數(shù)組
public void paint(Graphics g) {
super.paint(g);// 先將父類自帶的paint方法再寫一遍
//繪制棋盤
for (int i = 0; i < line; i++) {
g.drawLine(x0, y0 + i * size, x0 + (line - 1) * size, y0 + i * size);
g.drawLine(x0 + i * size, y0, x0 + i * size, y0 + (line - 1) * size);
}
//繪制棋子
for (int i = 0; i < chessArr.length; i++) {
for (int j = 0; j < chessArr[0].length; j++) {
int chesscolor = chessArr[i][j];//取出棋子顏色對(duì)應(yīng)的值
if (chesscolor != 0) {
if (chesscolor == 1) {//下黑棋
for (int a = 0; a < 50; a++) {
g.setColor(new Color(5 * a, 5 * a, 5 * a));
g.fillOval(j * size + x0 + a / 2 - 25, i * size + y0 + a / 2 - 25, 50 - a, 50 - a);
}
} else {//下白棋
for (int a = 0; a < 50; a++) {
g.setColor(new Color(155 + 2 * a, 155 + 2 * a, 155 + 2 * a));
g.fillOval(j * size + x0 + a / 2 - 25, i * size + y0 + a / 2 - 25, 50 - a, 50 - a);
}
}
}
}
}
}
效果圖
?此步驟重點(diǎn)有:用計(jì)數(shù)器單雙決定棋色、棋子要下在交點(diǎn)處、用二維數(shù)組保存棋色對(duì)應(yīng)值、傳遞二維數(shù)組、實(shí)現(xiàn)棋子重繪。
4.添加組件功能
? ?我們先寫“開始”和“認(rèn)輸”這兩個(gè)功能。
開始:
在鼠標(biāo)類中
private String button;
private boolean start=false;//定義布爾值,點(diǎn)擊開始后start=true,判斷輸贏后start=false
在下棋前加入判斷條件?
//下棋前添加判斷條件:是否按了“開始”
if (start == true) {
// 判斷棋子是否會(huì)越出棋盤界
if (0 <= x1 && x1 <= 14 && 0 <= y1 && y1 <= 14) {
點(diǎn)擊開始后要要清空棋盤,因此我們?cè)贛ouse類中寫一個(gè)清空棋盤的方法。
為此我們要將chesspanel對(duì)象傳入Mouse類中:
private boolean start = false;// 定義布爾值,點(diǎn)擊開始后start=true,判斷輸贏后start=false
private MyPanel chesspanel;
//通過(guò)構(gòu)造方法,傳入chesspanel
public Mouse(MyPanel chesspanel) {
this.chesspanel = chesspanel;
}
在GoBang類創(chuàng)建mouse對(duì)象時(shí)傳入chesspanel
Mouse mouse = new Mouse(chesspanel);//創(chuàng)建鼠標(biāo)對(duì)象,并傳入chesspanel
接著在Mouse中寫一個(gè)clean方法:
public void clean() {
//遍歷二維數(shù)組,讓所有棋子顏色歸零
for(int i=0;i<chessArr.length;i++) {
for(int j=0;j<chessArr[i].length;j++) {
chessArr[i][j] = 0;
}
}
//執(zhí)行重繪方法,除去所有棋子
chesspanel.paint(g);
}
最后對(duì)應(yīng)按鈕功能
public void actionPerformed(ActionEvent e) {
button = e.getActionCommand();// 按鈕內(nèi)容對(duì)應(yīng)鼠標(biāo)點(diǎn)擊信息
switch (button) {
case "開始"://點(diǎn)擊開始
clean();// 清空棋盤
count = 0;//計(jì)數(shù)器清零
start = true;// 允許開始
break;
}
}
認(rèn)輸:
這里的“認(rèn)輸”功能我們采用點(diǎn)擊按鈕后彈出窗口顯示游戲結(jié)束的做法,并且點(diǎn)擊“認(rèn)輸”按鈕后不能再下棋。我們直接寫一個(gè)end方法。
// 輸出游戲結(jié)束面板
public void end() {
//創(chuàng)建窗體
JFrame jy = new JFrame();
jy.setSize(500, 500);
jy.setLocationRelativeTo(null);
jy.setDefaultCloseOperation(3);
//設(shè)置流動(dòng)布局
jy.setLayout(new FlowLayout());
//添加標(biāo)簽,載入圖片
JLabel jla = new JLabel(new ImageIcon("D:\\java\\java\\10.16五子棋(游戲結(jié)束.png"));
//設(shè)置標(biāo)簽大小
jla.setPreferredSize(new Dimension(500, 500));
jy.add(jla);
jy.setVisible(true);
}
case "認(rèn)輸":
end();//彈出面板
start = false;//不能再下棋
break;
5.判斷輸贏
由于判斷輸贏代碼量較大,我們直接新建一個(gè)Win類,在該類中寫判斷輸贏的方法。
同樣需要把chessArr傳入Win類
public class Win {
private int[][] chessArr;//定義chessArr數(shù)組
//構(gòu)造方法初始化chessArr數(shù)組
public Win(int[][] chessArr) {
this.chessArr = chessArr;
}
}
private boolean start = false;// 定義布爾值,點(diǎn)擊開始后start=true,判斷輸贏后start=false
private MyPanel chesspanel;
Win win = new Win(chessArr);//創(chuàng)建win對(duì)象并傳入chessArr
判斷輸贏的思路是:分為水平、豎直、左上-右下、右上-左下四條軸寫四個(gè)方法,每條軸又分正負(fù)兩個(gè)方向;每條軸設(shè)定一個(gè)計(jì)數(shù)器,通過(guò)for循環(huán)遍歷同方向棋子,當(dāng)棋子同色,計(jì)數(shù)器+1,最后返回計(jì)數(shù)器的值,當(dāng)計(jì)數(shù)器大于等于5時(shí),決出勝負(fù)。
// 判斷水平方向
public int countchessX(int x1, int y1) {
int chess = 1;// 設(shè)置計(jì)數(shù)器記錄同色棋子
// 往右側(cè)方向
for (int i = x1 + 1; i < chessArr.length; i++) {
if (chessArr[y1][x1] == chessArr[y1][i]) {
chess++;// 如果右側(cè)棋子同色,則計(jì)數(shù)器加1
} else {// 不同色則退出循環(huán)
break;
}
}
// 往左側(cè)方向
for (int i = x1 - 1; i >= 0; i--) {
if (chessArr[y1][x1] == chessArr[y1][i]) {
chess++;
} else {
break;
}
}
return chess;// 返回chess值用于判斷輸贏
}
// 判斷豎直方向
public int countchessY(int x1, int y1) {
int chess = 1;
for (int i = y1 + 1; i < chessArr.length; i++) {
if (chessArr[y1][x1] == chessArr[i][x1]) {
chess++;
} else {
break;
}
}
for (int i = y1 - 1; i >= 0; i--) {
if (chessArr[y1][x1] == chessArr[i][x1]) {
chess++;
} else {
break;
}
}
return chess;
}
// 判斷左上、右下方向
public int countchessM(int x1, int y1) {
int chess = 1;
// 右下方向
for (int i = x1 + 1, j = y1 + 1; i < chessArr.length && j < chessArr.length; i++, j++) {
if (chessArr[y1][x1] == chessArr[j][i]) {
chess++;
} else {
break;
}
}
// 左上方向
for (int i = x1 - 1, j = y1 - 1; i >= 0 && j >= 0; i--, j--) {
if (chessArr[y1][x1] == chessArr[j][i]) {
chess++;
} else {
break;
}
}
return chess;
}
// 判斷右上、左下方向
public int countchessN(int x1, int y1) {
int chess = 1;
// 右上方向
for (int i = x1 + 1, j = y1 - 1; i < chessArr.length && j >= 0; i++, j--) {
if (chessArr[y1][x1] == chessArr[j][i]) {
chess++;
} else {
break;
}
}
// 左下方向
for (int i = x1 - 1, j = y1 + 1; i >= 0 && j < chessArr.length; i--, j++) {
if (chessArr[y1][x1] == chessArr[j][i]) {
chess++;
} else {
break;
}
}
return chess;
}
// 判斷輸贏
public int checkwin(int x1, int y1) {
if (countchessX(x1, y1) >= 5 || countchessY(x1, y1) >= 5 || countchessM(x1, y1) >= 5
|| countchessN(x1, y1) >= 5) {
// 用最后下的棋子的顏色判斷誰(shuí)輸誰(shuí)贏。
if (chessArr[y1][x1] == 1) {//最后下黑棋
return 1;//返回1
} else if (chessArr[y1][x1] == -1) {//最后下白棋
return -1;//返回-1
}
}
return 0;
}
在Mouse類中寫一個(gè)判斷輸贏的方法,每下完一顆棋執(zhí)行一次該方法。
public void checkwin() {
//如果以滿足勝負(fù)條件
if(win.checkwin(x1, y1)==1||win.checkwin(x1, y1)==-1) {
end();//執(zhí)行結(jié)束游戲方法
}
}
}
count++;// 每下完一顆棋,計(jì)數(shù)器加1
checkwin();//每下完一顆棋,判斷一次輸贏
}
6.悔棋
悔棋思路:先創(chuàng)建一個(gè)棋子類存入棋子對(duì)象的坐標(biāo)、顏色,再創(chuàng)建一個(gè)一維數(shù)組按順序存入一個(gè)個(gè)棋子對(duì)象,接著寫一個(gè)悔棋方法:每點(diǎn)擊一次悔棋,就找出數(shù)組中最末位棋子對(duì)應(yīng)的坐標(biāo),取出該坐標(biāo)帶入chessArr并令其等于0,然后刷新面板出去該棋子。
package teachGoBang;
import java.awt.Color;
//創(chuàng)建棋子類
public class ChessR {
public int x1,y1;
public Color color;
//構(gòu)造方法初始化參數(shù)
public ChessR(int x1,int y1,Color color) {
this.x1 = x1;
this.y1 = y1;
this.color = color;
}
}
private int[][] chessArr = new int[line][line];// 定義二維數(shù)組,用于保存棋盤坐標(biāo)對(duì)應(yīng)的棋子顏色
private ChessR[] chessB =new ChessR[line*line]; //定義一維數(shù)組存入棋子對(duì)象
ChessR chess = new ChessR(x1,y1,color);//創(chuàng)建棋子對(duì)象存入棋子數(shù)值
chessB[count] = chess;//以count為下標(biāo)存入棋子對(duì)象
count++;// 每下完一顆棋,計(jì)數(shù)器加1
checkwin();//每下完一顆棋,判斷一次輸贏
}
// 悔棋方法
public void regret() {
if (count > 0) {//添加判斷,有棋子時(shí)才能悔棋
ChessR chessR = chessB[--count];// 取出數(shù)組中最后一顆棋子
int x = chessR.x1;// 取出該棋子對(duì)應(yīng)的x、y值
int y = chessR.y1;
chessArr[y][x] = 0;// 清空該棋子對(duì)應(yīng)位置
chesspanel.paint(g);
}
}
7.復(fù)盤
復(fù)盤的本質(zhì)是棋子的重繪,我們?cè)趶?fù)盤前先清空前,然后設(shè)置時(shí)間間隔,通過(guò)paint方法依次繪出所下的棋子。文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-458061.html
// 復(fù)盤方法
public void repeat() {
for (int i = 0; i < count; i++) {
ChessR chess = chessB[i];// 通過(guò)循環(huán),正序取出棋子
// 設(shè)置棋子重繪時(shí)間間隔
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
//順序雙數(shù)繪黑棋,單數(shù)繪白棋
if(i%2==0) {
chessArr[chess.y1][chess.x1] = 1;
}else {
chessArr[chess.y1][chess.x1] = -1;
}
chesspanel.paint(g);//繪制棋子
}
count = 0;//計(jì)數(shù)器清零
}
以上就是用java寫一個(gè)簡(jiǎn)單的五子棋程序的全過(guò)程,下一章將在五子棋中加入人機(jī)對(duì)戰(zhàn)的功能。文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-458061.html
到了這里,關(guān)于用Java寫一個(gè)簡(jiǎn)易五子棋游戲的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!