Java五子棋小游戏

本文介绍了作者使用Java编写五子棋小游戏的过程,包括棋盘界面的创建、人人对战和人机对战的实现。游戏逻辑涉及棋子下落、判断输赢、悔棋、重新开始和认输功能。在人机对战中,采用了权值法让机器选择最佳落子位置,通过不断调整权值提高AI智能性。
摘要由CSDN通过智能技术生成

五子棋可能大家都玩过或者听说过,规则非常简单:双方分别使用黑白两色的棋子,下在棋盘(15*15)直线与横线的交叉点上,先形成5子连线者获胜。
最近,我用Java写了一个五子棋小游戏,现在和大家分享一下。

首先我创建了四个类,分别为:
在这里插入图片描述
ChessUI,创建窗口,负责游戏的界面;
ChessPosition,包含两个参数,分别为棋子的x,y坐标;
ChessBoardListener,监听器类,当监听到鼠标的动作时,调用ChessBoard中的方法以做出响应。
ChessBoard,负责管理棋子,包括下棋,悔棋,重新开始,判断输赢等。

首先来实现游戏的界面:

public class ChessUI extends JPanel{
   
	
	Graphics p;
	BufferedImage bgImage;//棋盘的背景图片
	AlphaComposite ac;  //用以设置透明度
	ChessBoard qz = new ChessBoard(this);

	public void initUI() {
   
		
		JFrame frame = new JFrame();
		frame.setSize(534,614);//设置窗口大小
		frame.setLocationRelativeTo(null);//设置窗口在屏幕居中
		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);//关闭窗口即结束程序
		frame.setTitle("五子棋");//设置
		
		//创建鼠标监听器对象
		ChessBoardListener cblisten = new ChessBoardListener(qz);
 
		//创建南边功能面板并添加到窗体的南面
		JPanel southPanel = new JPanel();
		southPanel.setPreferredSize(new Dimension(45,45));
		frame.add(southPanel,BorderLayout.SOUTH);

//		//创建西边功能面板并添加到窗体的西边
//		JPanel westPanel = new JPanel();
//		westPanel.setPreferredSize(new Dimension(45,500));
//		frame.add(westPanel,BorderLayout.WEST);

		//创建中间绘图区域面板并添加窗体的中间
		frame.add(this,BorderLayout.CENTER);
		this.setBackground(Color.white);
		this.addMouseListener(cblisten);//添加鼠标监听器
		
		//设置一个字符数组来存储图形按钮上的文字
		String[] text = {
   "重新开始","悔棋","认输","人人对战","人机对战"};
		for(int i=0; i<text.length;i++) {
   
			//创建按钮
			JButton btn = new JButton(text[i]);
			btn.setPreferredSize(new Dimension(90,35));
			//添加按钮到南面板
			southPanel.add(btn);
			btn.addActionListener(cblisten);//给按钮加上动作监听器
		}
		
		try {
   
			bgImage = ImageIO.read(new File("C:/Users/background.png"));//给棋盘添加背景图片
		} catch (IOException e) {
   
			e.printStackTrace();
		}
//		ac = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.1f);//设置透明度
		frame.setVisible(true);//设置窗体可见		
		//获取画布
		Graphics2D p = (Graphics2D) this.getGraphics();
		p.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_ON);
//		((Graphics2D) p).setComposite(ac);//设置透明度
		System.out.println(p);//
		cblisten.setGraphics(p);	
		qz.init();
	}
	
	public void paint(Graphics g) {
   //重绘,每次缩小放大窗体时棋盘和棋子能够再次被画出来
		super.paint(g);
		g.drawImage(bgImage, 0, 0, 512, 512, this);
			
		if(qz!=null) {
   
			qz.drawChessBorad(g);
			qz.drawChess(g);
		}		
	}	
	public static void main (String[] args) {
   		
		ChessUI pl = new ChessUI();		
		pl.initUI();
		
	}
}

值得注意的是,getGraphics这一步要在setVisible后,要不然会报出空指针异常。
在这里插入图片描述
效果如下图所示:
在这里插入图片描述
接下来分人人对战,人机对战两部分来讲述。
人人对战的算法相对来说简单一点,所以先来说说人人对战。

分为下棋和判断输赢两部分:
先说下棋:
鼠标在棋盘上点击一下,就在棋盘上画一颗棋子,这里需要对鼠标监听器获取的x,y坐标处理一下,使鼠标点击后棋子画在离获取的坐标最近的格子的正中间,因为我们做不到每一次点击都点在精准的棋盘线交叉点上。

为了使黑白子轮流下棋,我用了一个标志位flag来标志,当flag为1时下的棋为黑色,flag为2时下的棋为白色。一开始初始化flag为1,规定了黑子先下。下完一颗棋子后就反转标志位,就可实现黑白子轮流下棋。

创建一个大小为15*15的二维数组,用来保存棋盘上棋子的值,初始化为0后,下了一颗黑棋就把数组对应的位置的值置为1,下白棋则置为2,同时每下一颗棋子就将其放入ArrayList中,方便后续的悔棋。

public void humanAndhuman(Graphics g, int rowh, int rowl){
   
		
		if(this.allchess[rowh][rowl]==0){
   
			if(this.flag==1) {
   
				g.setColor(Color.black);
				g.fillOval((rowh+1)*gap-radius, (rowl+1)*gap-radius, 2*radius, 2*radius);
				this.list.add(new ChessPosition(rowh,rowl));
				this.allchess[rowh][rowl] = 1;			
				this.flag = 2;
			}
			else if(this.flag==2){
   
				g.setColor(Color.white);
				g.fillOval((rowh+1)*gap-radius, (rowl+1)*gap-radius, 2*radius, 2*radius);
				this.list.add(new ChessPosition(rowh,rowl));
				this.allchess[rowh][rowl] = 2;
				this.flag = 1;
			}
		}
		checkWin(rowh,rowl);
	}

判断输赢:
每下完一步棋,就要判断一下是否分出胜负。判断胜负的规则非常简单,就是看棋盘上有没有相同颜色的棋子连成5颗或以上,先连成5颗的一方胜利。

所以判断输赢的算法这样来写:
从当前棋子的位置开始,分为四个方向:横向、竖向、左斜、右斜,每个方向都要判断是否有5颗或以上相同颜色的棋子连成一线。举个例子,定义一个变量count来计数,初始化为1(即当前棋子自身),检查横向时,先向左开始检查,遇到相同颜色的棋子时count自加一,直到遇到颜色不同的棋子或者到了棋盘边界,接着从当前棋子位置的右边开始检查,遇到相同颜色的棋子时count自加一,直到遇到颜色不同的棋子或者到了棋盘边界,最后判断count是否大于等于5,若是,获取当前棋子的颜色,若是黑色则弹出“黑方胜利,白方失败”这样的弹窗。

另外,设置一个标志位gameover,初始化为1,意思是允许下棋,当分出胜负后,设置gameover为0,就不能再下棋或者悔棋了。

public void 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值