這篇文章給大家分享的是有關java如何實現簡易的五子棋游戲的內容。小編覺得挺實用的,因此分享給大家做個參考,一起跟隨小編過來看看吧。
本文實例為大家分享了java實現簡易五子棋游戲的具體代碼,供大家參考,具體內容如下
先上效果圖

1、五子棋游戲分析:
五子棋作為較為普遍且簡易的娛樂游戲,受到眾多人的熱愛,且五子棋AI也是一個較為容易實現的AI。下面我們先來分析游戲規則。(哈哈,雖然大家都知道,但我還是想寫寫)雙方分別使用黑白兩色棋子,下在棋盤橫線交叉處,先連成五子者勝利。(黑棋禁手啥的規則在我的程序里沒加,就不贅述了)。
2、程序分析:
(1)首先,五子棋開始,我們需要一個棋盤,15*15的棋盤,需要黑白棋子。
(2)其次,我們需要實現棋子順序的改變,就是實現先下黑棋,再下白棋,然后實現一個基本的修正功能,就是通過點擊交叉點周圍的位置,使棋子下到交叉處。
(3)再之后呢,有了棋子棋盤,(其實這個時候已經能進行下棋了,自己判斷勝負,哈哈),但是呢,我們接下來需要加一個判斷輸贏的功能。
(4)接下來,我們就來豐富我們的五子棋游戲,加一些功能鍵,例如重新開始,悔棋,認輸,計時啥啥啥的。
(5)最后來一個高級點的,就是實現人機對戰,實現AI下棋。
1、棋盤棋子模塊
棋盤嘛就用直線畫就好,橫線15條,豎線15條,棋子也就兩個,可以畫得花哨一點,比如3D棋子,也可以簡單一點就用填充圓就好。博主畫了一個黑色3D棋子,白的沒畫。(這里繼承了我之前的一個畫板,實現直線的重繪,可以去翻一翻我的之前有關畫板的博客)。創建一個二維數組,存放棋子,用1代表黑棋,2代表白棋,0代表沒棋。用count變量來計算到誰下棋了,以及記錄下了第幾顆棋子了。
以下是窗體代碼
public void outUI(){
//設置標題
this.setTitle("五子棋");
this.setSize(1680,1380);
this.setLayout(null);
JButton btn = new JButton();
JButton btn1 = new JButton();
JButton btn2 = new JButton();
JButton btn3 = new JButton();
JButton btn4 = new JButton();
btn.setBounds(1340, 780, 210, 65);
btn1.setBounds(1340,860,210, 65);
btn2.setBounds(1340,940,210, 65);
btn3.setBounds(320,1200,210, 65);
btn4.setBounds(780,1200,210, 65);
//獲取一個圖片
ImageIcon square=new ImageIcon(this.getClass().getResource("JButton1.jpg"));
ImageIcon square1=new ImageIcon(this.getClass().getResource("JButton.jpg"));
ImageIcon square2=new ImageIcon(this.getClass().getResource("JButton2.jpg"));
ImageIcon square3=new ImageIcon(this.getClass().getResource("JButton3.jpg"));
ImageIcon square4=new ImageIcon(this.getClass().getResource("JButton4.jpg"));
//設置圖片的大小
square.setImage(square.getImage().getScaledInstance(210, 65, 0));
square1.setImage(square1.getImage().getScaledInstance(210, 65, 0));
square2.setImage(square2.getImage().getScaledInstance(210, 65, 0));
square3.setImage(square3.getImage().getScaledInstance(210, 65, 0));
square4.setImage(square4.getImage().getScaledInstance(210, 65, 0));
//把圖片放到按鈕上
btn.setIcon(square);
btn1.setIcon(square1);
btn2.setIcon(square2);
btn3.setIcon(square3);
btn4.setIcon(square4);
btn.setText("開始");
btn1.setText("悔棋");
btn2.setText("認輸");
btn3.setText("人機對戰");
btn4.setText("人人對戰");
this.add(btn);
this.add(btn1);
this.add(btn2);
this.add(btn3);
this.add(btn4);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setVisible(true);
MyGameListen bn=new MyGameListen();
this.addMouseListener(bn);
btn.addActionListener(bn);
btn1.addActionListener(bn);
btn2.addActionListener(bn);
btn3.addActionListener(bn);
btn4.addActionListener(bn);
Graphics f= this.getGraphics();
AI Ai=new AI();
AI2 Ai2=new AI2();
AIPlus Ai3=new AIPlus();
bn.ai=Ai;
bn.ai2=Ai2;
bn.ai3=Ai3;
bn.f1=f;
Ai.f1=f;
Ai2.f1=f;
Ai3.f1=f;
bn.sn=this;
Ai.arr2=bn.arr;
Ai2.arr2=bn.arr;
Ai3.arr=bn.arr;
arragain=bn.arr;
showtime a=new showtime();
a.count1=bn.count;
}
int[][] arragain;
@Override
public void paint(Graphics g) {
// TODO Auto-generated method stub
super.paint(g);
//加背景圖
ImageIcon square5=new ImageIcon(this.getClass().getResource("game.jpeg"));
ImageIcon square6=new ImageIcon(this.getClass().getResource("title.jpg"));
square5.setImage(square5.getImage().getScaledInstance( 1200,1162,0));
square6.setImage(square6.getImage().getScaledInstance( 366,683,0));
g.drawImage(square5.getImage(),40,60,this);
g.drawImage(square6.getImage(),1280,100,366,683,this);
for(int i=1;i<=15;i++)
{
g.drawLine(80, i*80, 1200, i*80);
g.drawLine(i*80,80,i*80,1200);
}
g.drawLine(60,60 , 1220, 60);
g.drawLine(60,60 , 60, 1220);
g.drawLine(60, 1220, 1220,1220);
g.drawLine(1220, 1220, 1220,60);
g.fillOval(630, 630, 20, 20);
g.fillOval(310, 950, 20, 20);
g.fillOval(310, 310, 20, 20);
g.fillOval(950, 950, 20, 20);
g.fillOval(950, 310, 20, 20);
// 繪制棋盤
MyGameListen bn1=new MyGameListen();
bn1.f1=g;
for(int i=0;i<arragain.length;i++) {
for(int j=0;j<arragain.length;j++)
{
if(arragain[i][j]==1)
{
Blackchessman(i*80-40,j*80-40,g);
}
else if(arragain[i][j]==2)
{
whitechessman(i*80-40,j*80-40,g);
}
}
}
}
public void Blackchessman(int x,int y,Graphics g)
{
for(int i=0;i<80;i++)
{
Color c=new Color(i*3,i*3,i*3);
g.setColor(c);
g.fillOval(x+i/3, y+i/3, 80-i, 80-i);
}
}
public void whitechessman(int x,int y,Graphics g)
{
g.setColor(Color.white);
g.fillOval(x,y,80,80);
}以下是鼠標監聽器的代碼,這里有部分變量沒有給出,在文章末尾會附上完整代碼
public void mousePressed(MouseEvent e)
{
x1=e.getX();y1=e.getY();
m=correct(x1);
n=correct(y1);
if(x1<=1240&&y1<=1240)
{
if(arr[m/80][n/80]==0)
{
if(count%2!=0)
{
x1=e.getX();y1=e.getY();
m=correct(x1);
n=correct(y1);
Blackchessman(m-40,n-40);
arr[m/80][n/80]=1;
arr1[m/80][n/80]=count;
count++;
if( gobangiswin.isWin(arr, m/80, n/80)) {
JOptionPane.showMessageDialog(null, "黑棋WIN??!");
}
//ai下棋
if(who==2) {
ai3.playchess();
arr[ai3.q][ai3.w]=2;
arr1[ai3.q][ai3.w]=count;
count++;
if( gobangiswin.isWin(arr,ai3.q ,ai3.w )) {
JOptionPane.showMessageDialog(null, "白棋WIN??!");
}
}
}
else
{
x1=e.getX();y1=e.getY();
m=correct(x1);
n=correct(y1);
whitechessman(m-40,n-40);
arr[m/80][n/80]=2;
arr1[m/80][n/80]=count;
count++;
if( gobangiswin.isWin(arr, m/80, n/80)) {
JOptionPane.showMessageDialog(null, "白棋WIN??!");
}
}
}
else
return;
}
else {
return;}
}2、位置修正
這個功能其實有很多種實現的方法,可以根據自己的棋盤位置啥的進行修正。
public int correct(int x)
{
a=x/80;
b=x%80;
if(b<=40)
{
return a*80;
}
else
return (a+1)*80;
}3、輸贏判斷
輸贏判斷的思路,大概是以下思路,通過點擊,下了最后一顆棋子以后,判斷該棋子是否使游戲結束了,就是下完這顆棋子后是否成功構成五子連珠。因為輸贏的判斷你 只需要判斷最后一步即可,因為輸贏的勝負就在最后一步。所以,通過判斷最后一顆棋子的八個方向是否構成五子連珠即可。
以下是判斷輸贏的代碼。
public class GobangIsWin {
//判斷輸贏函數
// 橫向
public int left_right(int[][] arr,int x,int y) {
int con=1;
//向右遍歷
for(int i=x+1;i<arr.length;i++)
{
if(arr[x][y]==arr[i][y]){
con++;
}
else
break;
}
//向左遍歷
for(int i=x-1;i>0&&i<arr.length;i--)
{
if(arr[x][y]==arr[i][y]) {
con++;
}
else
break;
}
return con;
}
// 縱向
public int high_low(int[][] arr,int x,int y)
{
int con=1;
//向下遍歷
for(int i=y+1;i<arr[0].length;i++)
{
if(arr[x][y]==arr[x][i]) {
con++;
}
else
break;
}
//向上遍歷
for(int i=y-1;i>0&&i<arr[0].length;i--)
{
if(arr[x][y]==arr[x][i]) {
con++;
}
else
break;
}
return con;
}
// 左斜
public int towQudrant_three(int[][] arr,int x,int y)
{
int con=1;
int i=x,j=y;
//向右上遍歷
for(int m=i+1,k=j-1;m<arr.length&&k>0&&m<i+5&&k>j-5;k--,m++)
{
if(x==15||y==1) {
break;
}
else if(arr[x][y]==arr[m][k])
con++;
else
break;
}
//向左下遍歷
for(int m=i-1,k=j+1;k<arr.length&&m>0&&k<i+5&&m>j-5;k++,m--)
{
if(x==1||y==15) {
break;
}
if(arr[x][y]==arr[m][k])
con++;
else
break;
}
return con;
}
// 右斜
public int one_fourwin(int[][] arr,int x,int y)
{
int con=1;
int i=x,j=y;
//向左上遍歷
for(int m=i-1,k=j-1;m>0&&k>0&&m>i-5&&k>j-5;k--,m--)
{
if(x==1||y==1) {
break;
}
if(arr[x][y]==arr[m][k])
con++;
else
break;
}
//向右下遍歷
for(int m=i+1,k=j+1;k<arr.length&&m<arr.length&&m<i+5&&k<j+5;k++,m++)
{
if(x==15||y==15) {
break;
}
if(arr[x][y]==arr[m][k])
con++;
else
break;
}
return con;
}
public boolean isWin(int[][] arr,int x,int y) {
if(left_right(arr, x, y)>=5||high_low(arr, x, y)>=5||towQudrant_three(arr, x, y)>=5||one_fourwin(arr, x, y)>=5) {
return true;
}else {
return false;
}
}
}4、我們再來加一點功能,這里有悔棋,重新開始,認輸的功能。
重新開始:我們清空我們存放棋子的數組即可,然后重新繪制棋盤,將之前的棋盤覆蓋即可。
public void start() {
sn.repaint();
for(int i=0;i<arr.length;i++)
{
for(int j=0;j<arr.length;j++) {
arr[i][j]=0;
}
}
count=1;
}悔棋:悔棋的思路:悔棋,我們可以和開始一樣,先把之前的棋盤覆蓋掉,然后去除存放數組里的最后一個棋子即可,然后在新的棋盤上重新放下棋子(除了最后一個棋子)。
public void huiqi()
{
sn.repaint();
//去除最后一顆棋子
for(int i=0;i<arr1.length;i++)
{
for(int j=0;j<arr1.length ;j++)
{
if(arr1[i][j]==count-1)
{
arr1[i][j]=0;
arr[i][j]=0;
}
if(arr1[i][j]==count-2&&who==2)
{
arr1[i][j]=0;
arr[i][j]=0;
}
}
}
//重放棋子
for(int i=0;i<arr.length;i++)
{
for(int j=0;j<arr.length ;j++)
{
if(arr[i][j]==1)
{
Blackchessman(i*80-40,j*80-40);
}
else if(arr[i][j]==2)
{
whitechessman(i*80-40,j*80-40);
}
}
}
//控制下一顆棋子顏色
if(who==2) {
count=count-2;
}
else if(who==1)
{
count=count-1;
}
}認輸功能:這個很簡單就不說了,判斷一下到誰下點擊了認輸就誰輸就好。
5、最后來一個高級的,實現AI的功能,人機對戰。
這里有很多種實現人工智能的方法:
(1)權值法
(2)博弈樹
(3)機器學習
博主現在水平有限,只會權值算法,等博主學會后面兩種方法再來加~
權值法:這里用到了權值表,創建一個新的二維數組chessvalue[][]用于存放該點的權值。
HashMap<String,Integer> map = new HashMap<String,Integer>();
map.put("1",10);
map.put("11",100);
map.put("111",1000);
map.put("1111",10000);這里的HashMap類是一種特殊的類,可以通過map.get(),將字符串放進get方法中,通過比較map中的所有字符串,找到與之相對應的權值,并返回這個值,這里指的注意的是,這里返回的數據類型不是int型,而是Integer型,但是不必擔心,這個類型也能實現累加。
接下來是查找棋型,通過查找該位置的八個方向的棋型,并對八個方向的權值進行累加。最后通過找出最大的權值的位置,將棋子下到這個位置就好,這樣就基本實現AI功能了。
保存棋局的方法:通過String類型的拼接功能實現棋局的保存。
注:在寫這部分AI的時候,對于部分棋型沒有考慮到,難度水平大概處于低階至中階,對于部分難以通過遍歷八個方向進行查找的,采用了聯合算法。例如,對于“22022”這樣的棋型,顯然需要通過左右兩邊的棋型綜合考慮,這里采用了聯合算法,遍歷完左右(上下)后進行一次聯合判斷。
AI代碼
public class AIPlus {
int arr[][]=null;
int weightArray[][]=new int [16][16];
Graphics f1=null;
//棋子相連情況的劃分
HashMap<String,Integer> map = new HashMap<String,Integer>();//設置不同落子情況和相應權值的數組
public AIPlus() {
//被堵住
map.put("01", 17);//眠1連
map.put("02", 12);//眠1連
map.put("001", 17);//眠1連
map.put("002", 12);//眠1連
map.put("0001", 17);//眠1連
map.put("0002", 12);//眠1連
map.put("0102",17);//眠1連,15
map.put("0201",12);//眠1連,10
map.put("0012",15);//眠1連,15
map.put("0021",10);//眠1連,10
map.put("01002",19);//眠1連,15
map.put("02001",14);//眠1連,10
map.put("00102",17);//眠1連,15
map.put("00201",12);//眠1連,10
map.put("00012",15);//眠1連,15
map.put("00021",10);//眠1連,10
map.put("01000",21);//活1連,15
map.put("02000",16);//活1連,10
map.put("00100",19);//活1連,15
map.put("00200",14);//活1連,10
map.put("00010",17);//活1連,15
map.put("00020",12);//活1連,10
map.put("00001",15);//活1連,15
map.put("00002",10);//活1連,10
//被堵住
map.put("0101",65);//眠2連,40
map.put("0202",60);//眠2連,30
map.put("0110",65);//眠2連,40
map.put("0220",60);//眠2連,30
map.put("011",65);//眠2連,40
map.put("022",60);//眠2連,30
map.put("0011",65);//眠2連,40
map.put("0022",60);//眠2連,30
map.put("01012",65);//眠2連,40
map.put("02021",60);//眠2連,30
map.put("01102",65);//眠2連,40
map.put("02201",60);//眠2連,30
map.put("00112",65);//眠2連,40
map.put("00221",60);//眠2連,30
map.put("01010",75);//活2連,40
map.put("02020",70);//活2連,30
map.put("01100",75);//活2連,40
map.put("02200",70);//活2連,30
map.put("00110",75);//活2連,40
map.put("00220",70);//活2連,30
map.put("00011",75);//活2連,40
map.put("00022",70);//活2連,30
//被堵住
map.put("0111",1500);//眠3連,100
map.put("0222",1400);//眠3連,80
map.put("01112",1500);//眠3連,100
map.put("02221",1400);//眠3連,80
map.put("01101",10000);//活3連,130
map.put("02202",8000);//活3連,110
map.put("01011",10000);//活3連,130
map.put("02022",8000);//活3連,110
map.put("01110", 10000);//活3連
map.put("02220", 8000);//活3連
map.put("01111",300000);//4連,300
map.put("02222",350000);//4連,280
}
public void printArray(int[][] arr) {
for(int i=1;i<arr.length;i++)
{
for(int j=1;j<arr.length ;j++)
{
System.out.print(arr[i][j]+" ");
}
System.out.println();
}
}
public Integer unionWeight(Integer a,Integer b ) {
//必須要先判斷a,b兩個數值是不是null
if((a==null)||(b==null)) return 0;
//一一
else if((a>=10)&&(a<=25)&&(b>=10)&&(b<=25)) return 60;
//一二、二一
else if(((a>=10)&&(a<=25)&&(b>=60)&&(b<=80))||((a>=60)&&(a<=80)&&(b>=10)&&(b<=25))) return 800;
//一三、三一、二二
else if(((a>=10)&&(a<=25)&&(b>=140)&&(b<=1000))||((a>=140)&&(a<=1000)&&(b>=10)&&(b<=25))||((a>=60)&&(a<=80)&&(b>=60)&&(b<=80)))
return 300000;
//二三、三二
else if(((a>=60)&&(a<=80)&&(b>=140)&&(b<=1000))||((a>=140)&&(a<=1000)&&(b>=60)&&(b<=80))) return 300000;
else return 0;
}
public void getvalue() {
for(int i=0;i<arr.length;i++) {
for(int j=0;j<arr[i].length;j++) {
//首先判斷當前位置是否為空
if(arr[i][j]==0) {
//往左延伸
String ConnectType="0";
int jmin=Math.max(0, j-4);
for(int positionj=j-1;positionj>=jmin;positionj--) {
//依次加上前面的棋子
ConnectType=ConnectType+arr[i][positionj];
}
//從數組中取出相應的權值,加到權值數組的當前位置中
Integer valueleft=map.get(ConnectType);
if(valueleft!=null) weightArray[i][j]+=valueleft;
//往右延伸
ConnectType="0";
int jmax=Math.min(14, j+4);
for(int positionj=j+1;positionj<=jmax;positionj++) {
//依次加上前面的棋子
ConnectType=ConnectType+arr[i][positionj];
}
//從數組中取出相應的權值,加到權值數組的當前位置中
Integer valueright=map.get(ConnectType);
if(valueright!=null) weightArray[i][j]+=valueright;
//聯合判斷,判斷行
weightArray[i][j]+=unionWeight(valueleft,valueright);
//往上延伸
ConnectType="0";
int imin=Math.max(0, i-4);
for(int positioni=i-1;positioni>=imin;positioni--) {
//依次加上前面的棋子
ConnectType=ConnectType+arr[positioni][j];
}
//從數組中取出相應的權值,加到權值數組的當前位置中
Integer valueup=map.get(ConnectType);
if(valueup!=null) weightArray[i][j]+=valueup;
//往下延伸
ConnectType="0";
int imax=Math.min(14, i+4);
for(int positioni=i+1;positioni<=imax;positioni++) {
//依次加上前面的棋子
ConnectType=ConnectType+arr[positioni][j];
}
//從數組中取出相應的權值,加到權值數組的當前位置中
Integer valuedown=map.get(ConnectType);
if(valuedown!=null) weightArray[i][j]+=valuedown;
//聯合判斷,判斷列
weightArray[i][j]+=unionWeight(valueup,valuedown);
//往左上方延伸,i,j,都減去相同的數
ConnectType="0";
for(int position=-1;position>=-4;position--) {
if((i+position>=0)&&(i+position<=14)&&(j+position>=0)&&(j+position<=14))
ConnectType=ConnectType+arr[i+position][j+position];
}
//從數組中取出相應的權值,加到權值數組的當前位置
Integer valueLeftUp=map.get(ConnectType);
if(valueLeftUp!=null) weightArray[i][j]+=valueLeftUp;
//往右下方延伸,i,j,都加上相同的數
ConnectType="0";
for(int position=1;position<=4;position++) {
if((i+position>=0)&&(i+position<=14)&&(j+position>=0)&&(j+position<=14))
ConnectType=ConnectType+arr[i+position][j+position];
}
//從數組中取出相應的權值,加到權值數組的當前位置
Integer valueRightDown=map.get(ConnectType);
if(valueRightDown!=null) weightArray[i][j]+=valueRightDown;
//聯合判斷,判斷行
weightArray[i][j]+=unionWeight(valueLeftUp,valueRightDown);
//往左下方延伸,i加,j減
ConnectType="0";
for(int position=1;position<=4;position++) {
if((i+position>=0)&&(i+position<=14)&&(j-position>=0)&&(j-position<=14))
ConnectType=ConnectType+arr[i+position][j-position];
}
//從數組中取出相應的權值,加到權值數組的當前位置
Integer valueLeftDown=map.get(ConnectType);
if(valueLeftDown!=null) weightArray[i][j]+=valueLeftDown;
//往右上方延伸,i減,j加
ConnectType="0";
for(int position=1;position<=4;position++) {
if((i-position>=0)&&(i-position<=14)&&(j+position>=0)&&(j+position<=14))
ConnectType=ConnectType+arr[i-position][j+position];
}
//從數組中取出相應的權值,加到權值數組的當前位置
Integer valueRightUp=map.get(ConnectType);
if(valueRightUp!=null) weightArray[i][j]+=valueRightUp;
//聯合判斷,判斷行
weightArray[i][j]+=unionWeight(valueLeftDown,valueRightUp);
}
}
}
}
int q=0,w=0;
public void playchess()
{
getvalue();
//取出最大的權值
int weightmax=0;
for(int i=0;i<arr.length;i++) {
for(int j=0;j<arr.length;j++) {
if(weightmax<weightArray[i][j]) {
weightmax=weightArray[i][j];
q=i;
w=j;
}
}
}
whitechessman(q*80-40, w*80-40);
for(int i=0;i<weightArray.length;i++)
{
for(int j=0;j<weightArray.length;j++) {
weightArray[i][j]=0;
}
}
}
public void whitechessman(int x,int y)
{
f1.setColor(Color.white);
f1.fillOval(x,y,80,80);
}
}感謝各位的閱讀!關于“java如何實現簡易的五子棋游戲”這篇文章就分享到這里了,希望以上內容可以對大家有一定的幫助,讓大家可以學到更多知識,如果覺得文章不錯,可以把它分享出去讓更多的人看到吧!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。