java实现简易的五子棋游戏

这篇文章主要为大家详细介绍了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

以下是鼠标监听器的代码,这里有部分变量没有给出,在文章末尾会附上完整代码

public void mousepressed(MouseEvent e) { x1=e.getX();y1=e.getY(); m=correct(x1); n=correct(y1); if(x1

2、位置修正

这个功能其实有很多种实现的方法,可以根据自己的棋盘位置啥的进行修正。

public int correct(int x) { a=x/80; b=x%80; if(b

3、输赢判断

输赢判断的思路,大概是以下思路,通过点击,下了最后一颗棋子以后,判断该棋子是否使游戏结束了,就是下完这颗棋子后是否成功构成五子连珠。因为输赢的判断你 只需要判断最后一步即可,因为输赢的胜负就在最后一步。所以,通过判断最后一颗棋子的八个方向是否构成五子连珠即可。

以下是判断输赢的代码

public class GobangIsWin { //判断输赢函数 // 横向 public int left_right(int[][] arr,int x,int y) { int con=1; //向右遍历 for(int i=x+1;i0&&i0&&i0&&mj-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;k0&&kj-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=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

悔棋:悔棋的思路:悔棋,我们可以和开始一样,先把之前的棋盘覆盖掉,然后去除存放数组里的最后一个棋子即可,然后在新的棋盘上重新放下棋子(除了最后一个棋子)。

public void huiqi() { sn.repaint(); //去除最后一颗棋子 for(int i=0;i

认输功能:这个很简单就不说了,判断一下到谁下点击了认输就谁输就好。

5、最后来一个高级的,实现AI的功能,人机对战。

这里有很多种实现人工智能的方法

(1)权值法

(2)博弈树

(3)机器学习

博主现在水平有限,只会权值算法,等博主学会后面两种方法再来加~

权值法:这里用到了权值表,创建一个新的二维数组chessvalue[][]用于存放该点的权值。

HashMap map = new HashMap(); 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 map = new HashMap();//设置不同落子情况和相应权值的数组 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=10)&&(a=10)&&(b=10)&&(a=60)&&(b=60)&&(a=10)&&(b=10)&&(a=140)&&(b=140)&&(a=10)&&(b=60)&&(a=60)&&(b=60)&&(a=140)&&(b=140)&&(a=60)&&(b=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 positi+1;positionj=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 positi+1;positioni=-4;position--) { if((i+position>=0)&&(i+position=0)&&(j+position=0)&&(i+position=0)&&(j+position=0)&&(i+position=0)&&(j-position=0)&&(i-position=0)&&(j+position

三、总结

本次是第一次做游戏类的项目,仍然存在许多不足,但是很开心最后成功了,然后最后AI部分的权值表以及联合算法借鉴了其他博主的思路,如有侵权,请联系我删除。后期我会再加上博弈树算法的思想。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持编程之家。

相关文章

HashMap是Java中最常用的集合类框架,也是Java语言中非常典型...
在EffectiveJava中的第 36条中建议 用 EnumSet 替代位字段,...
介绍 注解是JDK1.5版本开始引入的一个特性,用于对代码进行说...
介绍 LinkedList同时实现了List接口和Deque接口,也就是说它...
介绍 TreeSet和TreeMap在Java里有着相同的实现,前者仅仅是对...
HashMap为什么线程不安全 put的不安全 由于多线程对HashMap进...