java制作PVP五子棋游戏

编写五子棋游戏需要处理的问题:

①、下棋时黑白棋子颜色的交替处理

(定义Color类全局变量color来保存颜色标记,当下完一个棋子时颜色变换)

②、点击棋盘时让棋子落在离点击处最近的交叉点上

(判断点击棋盘上的坐标和棋盘上交叉点的坐标的距离)

③、不能让棋子在同一个交叉点重复下棋

      (创建int类二维数组 chess_flag[][]来记录棋盘上的下棋情况,0表示无棋子,1表示黑棋,2表示白棋。判断交叉点对应数组的标记是否为0来下棋。)

④、判断输赢

(用上述二维数组chess_flag来计算当前棋子的标记向上数和向下数后相同标记棋子数之和如果等于4,则该颜色棋子获胜,这是纵向判断,其他方向相同)

⑤、保存棋盘画面

(通过创建结点类Node来保存下棋时棋子坐标和颜色,然后保存到ArrayList类的list链表中。在下棋界面play_panel中调用paint方法中画出保存在链表中的棋子。每次下棋 都调用play_panel.repaint()方法来重绘棋盘。)

扫描二维码关注公众号,回复: 2144691 查看本文章


小知识点:

① 除了JFrame的界面大小可以用setSize方法,大部分小窗体控件用setPreferredSize(new Dimension(length,width))来确定大小。

② JOptionPane是提示框类,JOptionPane.showMessageDialog(this, "提示内容", "标题", JOptionPane.ERROR_MESSAGE);是弹出消息对话框的方法

总结:

五子棋游戏主要是对java的GUI的了解和使用。

package com.huaxin.Chess;

import java.awt.Color;
import java.awt.Dimension;
import java.awt.FlowLayout;
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 java.util.ArrayList;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JPanel;

//创建五子棋类 继承窗口类
public class Chess extends JFrame{
	
	//创建全局变量
	String cmd_jbt = new String();//创建按钮的标记
	JPanel panel_play;//创建下棋面板对象
	Color color = Color.black;//创建棋子黑白颜色标记
	int[][] chess_flag = new int[19][19]; //创建棋盘数组存放棋子信息
	int start_flag = 0;//创建开始标记 判断五子棋是否开始了
	ArrayList<Node> list = new ArrayList<Node>(); //结点链表
	//创建坐标存放数组的坐标
	int location_x =0;
	int location_y =0;
	//展示下棋界面的方法
	public void chessUI()
	{
		this.setTitle("五子棋");//创建窗口对象
		FlowLayout flowlayout = new FlowLayout();//创建流式布局对象
		this.setLayout(flowlayout);//将窗口设置为流式布局
		this.setSize(1150,860);//设置窗口大小
		
		//创建下棋面板
		 panel_play = new JPanel()
		{
			public void paint(Graphics graphics){
				super.paint(graphics);
				
				//绘制面板
				for(int i=1;i<=19;i++)
				{
					graphics.drawLine(40,i*40,760,i*40);
				}
				for(int i=1;i<=19;i++)
				{
					graphics.drawLine(i*40,40,i*40,760);
				}
				//绘制黑白结点
				for(int i=0;i<list.size();i++)
				{
					Node node = list.get(i);
					graphics.setColor(node.color);  //设置结点的颜色
					graphics.fillOval(node.x, node.y, 30, 30);  //绘制结点
				}
				
			}
		};
		//设置下棋面板背景和大小
		panel_play.setBackground(Color.lightGray);
		panel_play.setPreferredSize(new Dimension(800,800));
		
		//创建功能选择面板并设置大小
		JPanel panel_select = new JPanel();
		panel_select.setBackground(Color.gray);
		panel_select.setPreferredSize(new Dimension(280,800));
		
		//添加面板到窗体
		this.add(panel_play);
		add(panel_select);
		
		//创建功能按钮
		JButton jbt_start = new JButton("开始 / 重开");
		JButton jbt_PVP = new JButton("人人");
		JButton jbt_PVC = new JButton("人机");
		JButton jbt_regret = new JButton("悔棋");
		JButton jbt_about = new JButton("关于");
		
		//添加按钮到功能选择面板
		panel_select.add(jbt_start);	
		panel_select.add(jbt_PVP);
		panel_select.add(jbt_PVC);
		panel_select.add(jbt_regret);
		panel_select.add(jbt_about);
		
		//设置按钮的大小
		jbt_start.setPreferredSize(new Dimension(200,100));
		jbt_PVP.setPreferredSize(new Dimension(200,100));
		jbt_PVC.setPreferredSize(new Dimension(200,100));
		jbt_regret.setPreferredSize(new Dimension(200,100));
		jbt_about.setPreferredSize(new Dimension(200,100));
		
		//创建鼠标监听事件
		MouseAdapter mouse_adapter = new MouseAdapter(){
			public void mouseClicked(MouseEvent e){//鼠标点击时
				//获取点击的坐标
				int x = e.getX();
				int y = e.getY();

	
				if(x>=20&&x<=770&&y>=20&&y<=770)//判断点击的位置是否在棋盘
				{
					//判断点击的位置在交点的哪个位置并为其创建结点
					if(x%40<10&&y%40<10)//点击点的右下角
						CreatNode(x-x%40,y-y%40,x-x%40-15,y-y%40-15+0);				
						
					if(x%40<10&&y%40>10)//点击点的右上角
						CreatNode(x-x%40+0,y-y%40+40 ,x-x%40-15 , y-y%40-15+40);

					if(x%40>10&&y%40<10)//点击点的左下角
						CreatNode(x-x%40+40,y-y%40 ,x-x%40-15+40 ,y-y%40-15 );
					
					if(x%40>10&&y%40>10)//点击点的左上角
						CreatNode(x-x%40+40,y-y%4+40 ,x-x%40-15+40 , y-y%40-15+40);
					
					//判断棋子颜色并在数组中做标记
					if(color == Color.black)//如果棋子颜色为黑色
					{
						chess_flag[location_x][location_y] = 1;//在数组中给相应黑色棋子的位置做标记1
						count_chesses(location_x,location_y);//计算相连棋子数并判断输赢
					}
					if(color == Color.white)//如果棋子颜色为白色
					{
						chess_flag[location_x][location_y] = 2;//在数组中给相应白色棋子的位置做标记2
						count_chesses(location_x,location_y);//计算相连棋子数并判断输赢
					}

				}
			}
			
			//建立结点
			private void CreatNode(int i, int j, int k, int l) {
				//获取交叉点的坐标相应数组的坐标
				location_x = (i)/40-1;
				location_y = (j)/40-1;
				//System.out.println(chess_flag[location_x][location_y]);
				if(chess_flag[location_x][location_y] != 0)//判断点击位置在数组中相应的位置有没有棋子
				{
					JOptionPane.showMessageDialog(Chess.this, "该位置已有棋子,请在其他位置下棋!", "操作错误", JOptionPane.WARNING_MESSAGE);
				}
				else 
				{
					Node node = new Node(k, l, color);//创建结点对象
					list.add(node);//添加新建的结点给结点链表
					panel_play.repaint();//执行重画函数
					change_color();//改变棋子颜色
				}

			}
			
		};
		
		
		//创建悔棋动作监听对象
		ActionListener action_listener = new ActionListener(){
			public void actionPerformed(ActionEvent e) {
				if(list.size()>0)//判断棋盘是否已经下棋
				{
					if(location_x != 20){
						list.remove(list.size()-1);//去除链表中最后一个结点
						panel_play.repaint();//重绘下棋面板
						chess_flag[location_x][location_y]=0;//最后一个棋子在数组中相应变量设为0
						change_color();//改变画笔颜色	
						//将二维数组坐标设为尾结点坐标
						location_x =20;//(list.get(list.size()-1).x)/40-1;
						location_y =20;//(list.get(list.size()-1).y)/40-1;
					}
					else
					{
						JOptionPane.showMessageDialog(Chess.this, "对方正在悔棋重下,无法进行悔棋", "提示", JOptionPane.WARNING_MESSAGE);//显示关于五子棋的对话框
					}
				}
			}
		};
		
		//给开始按钮添加动作监听对象
		jbt_start.addActionListener(new ActionListener() {

			public void actionPerformed(ActionEvent e) {
				if(start_flag==0){//判断游戏是否已经开始 0为未开始 1为已经开始了
					panel_play.addMouseListener(mouse_adapter);//给下棋面板添加鼠标监听对象
					jbt_regret.addActionListener(action_listener);//给后悔按钮添加动作监听对象
					start_flag = 1;//开始标记设为1 表示游戏已经开始
				}
				Reset();//将下棋面板重置
			};
		});
		

		//给关于按钮添加动作监听对象
		jbt_about.addActionListener(new ActionListener(){
			public void actionPerformed(ActionEvent e) {
				JOptionPane.showMessageDialog(Chess.this, "作者:王锐锋", "关于五子棋", JOptionPane.WARNING_MESSAGE);//显示关于五子棋的对话框
			}
		});
		
		
		this.setDefaultCloseOperation(3);//设置窗口默认关闭操作
		this.setVisible(true);//设置窗口可视化
		
	}
	
	public void change_color()//调换棋子颜色的方法
	{
		//判断标记并设置棋子颜色
		if(color == Color.black){
			//g.setColor(Color.black);
			color = Color.white;
		}
		else if(color == Color.white){
			//
			//color_flag = 0;
			color = Color.black;
		}
	}

	
	
	public void count_chesses(int x1,int y1)//计算相连棋子数
	{
		int count_num = 1;//计算相连棋子数
		for(int i=x1-1;i>=0;i--)//计算棋子左边多少个同色棋子
		{
			if(chess_flag[i][y1]==chess_flag[x1][y1])
			{
				count_num++;
			}else	break;
		}
		for(int i=x1+1;i<=18;i++)//计算棋子右边边多少个同色棋子
		{
			if(chess_flag[i][y1]==chess_flag[x1][y1])
			{
				count_num++;
			}else	break;
		}
		checkIsWin(count_num);//判断输赢
		
		count_num =1;//重新计算相连棋子数
		for(int i=y1-1;i>=0;i--)//计算棋子上边多少个同色棋子
		{
			if(chess_flag[x1][i]==chess_flag[x1][y1])
			{
				count_num++;
			}else	break;
		}
		for(int i=y1+1;i<=18;i++)//计算棋子下边多少个同色棋子
		{
			if(chess_flag[x1][i]==chess_flag[x1][y1])
			{
				count_num++;
			}else	break;
		}
		checkIsWin(count_num);//判断输赢
		
		count_num =1;//重新计算相连棋子数
		for(int i=x1-1,j=y1-1;i>=0&&j>=0;i--,j--)//计算棋子左上边多少个同色棋子
		{
		
			if(chess_flag[i][j]==chess_flag[x1][y1])
			{
				count_num++;
			}else	break;
		}
		for(int i=x1+1,j=y1+1;i<=18&&j<=18;i++,j++)//计算棋子右下边多少个同色棋子
		{
			
			if(chess_flag[i][j]==chess_flag[x1][y1])
			{
				count_num++;
			}else	break;
		}
		checkIsWin(count_num);//判断输赢
		
		count_num =1;//重新计算相连棋子数
		for(int i=x1-1,j=y1+1;i>=0&&j<=18;i--,j++)//计算棋子左下边多少个同色棋子
		{
			
			if(chess_flag[i][j]==chess_flag[x1][y1])
			{
				count_num++;
			}else	break;
		}
		for(int i=x1+1,j=y1-1;i<=18&&j>=0;i++,j--)//计算棋子右上边多少个同色棋子
		{
			if(chess_flag[i][j]==chess_flag[x1][y1])
			{
				count_num++;
			}else	break;
		}
		checkIsWin(count_num);//判断输赢
	}
	
	private void checkIsWin(int count_num) {//判断是否赢了并重新开始下一局
		// TODO Auto-generated method stub
		if(count_num == 5&&color ==Color.black)
		{
			JOptionPane.showMessageDialog(this, "白棋获胜!!!!!", "游戏结束", JOptionPane.ERROR_MESSAGE);
			//重置所有信息
			Reset();
			JOptionPane.showMessageDialog(this, "重新开始游戏", "游戏结束", JOptionPane.WARNING_MESSAGE);
		}
		if(count_num == 5&&color ==Color.white) 
		{
			JOptionPane.showMessageDialog(this, "黑棋获胜!!!!!", "游戏结束",JOptionPane.ERROR_MESSAGE);
			//重置所有信息
			Reset();
			JOptionPane.showMessageDialog(this, "重新开始游戏", "游戏结束", JOptionPane.WARNING_MESSAGE);
		}
	}
	private void Reset() {//重置下棋板的方法
		color = Color.black;//初始化棋子颜色为黑色
		for(int i=0;i<chess_flag.length;i++)//将棋盘数组中每个变量归零
		{
			for(int j=0;j<chess_flag[i].length;j++)
			{
				chess_flag[i][j] = 0;
			}
		}
		list.clear();//清除链表中所有结点
		
		//点击对应数组坐标归零
		location_x =0;
		location_y =0;
		panel_play.repaint();//重绘下棋面板
	}
}

class Node
{
	//给结点类添加属性(交叉点在下棋面板上的坐标,棋子颜色)
		public	int x=0;
		public	int y=0;
		public	Color color;

	
	//结点类的构造函数
	public Node(int x,int y,Color color) {
		this.x = x;
		this.y =y;
		this.color = color;

	}
}




猜你喜欢

转载自blog.csdn.net/qq937654393/article/details/71330758