用面向对象的思想做一款贪吃蛇小游戏


本项目采用的是java语言,整个项目一共分为了9个类: 1.Login登录类 2.Register注册类 3.Food食物类 4.Barrier障碍物类 5.4.Snake蛇类 6.Title标头类 7.Sound音效类 8.Control游戏逻辑控制类 9.MainSnake类


一、运行效果

1.登录界面
示例:pandas 是基于NumPy 的一种工具,该工具是为了解决数据分析任务而创建的。

2.注册界面
在这里插入图片描述

3.游戏过程 在这里插入图片描述

4.结束页面
在这里插入图片描述

二、代码

1.Login登录类

import java.awt.Dimension;

import java.awt.FlowLayout;
import java.awt.HeadlessException;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Random;
import java.util.Scanner;

import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPasswordField;
import javax.swing.JTextField;
import java.sql.*;

public class Login implements ActionListener {
	// 实例化对象
	JTextField username;
	JPasswordField password;
	JFrame frame;

	public Login() {
	}

	public Login(JFrame frame, JTextField username, JPasswordField password) {
		this.frame = frame;
		this.username = username;
		this.password = password;
	}

	public void initUI() {
		// 设置登录窗口的界面:账号文本、密码文本、账号输入框、密码输入框、注册按钮、登录按钮
		frame = new JFrame();
		frame.setTitle("登录窗口");// 窗体的标题
		frame.setSize(400, 200);// 窗体的大小,单位是像素
		frame.setDefaultCloseOperation(3);// 设置窗体的关闭操作;3表示关闭窗体退出程序;2、1、0
		// 设置窗体相对于另一个组件的居中位置,参数null表示窗体相对于屏幕的中央位置
		frame.setLocationRelativeTo(null);
		frame.setResizable(false);// 禁止调整窗体大小

		// 实例化FlowLayout流式布局类的对象,指定对齐方式为居中对齐,组件之间的间隔为5个像素
		FlowLayout fl = new FlowLayout(FlowLayout.CENTER, 10, 10);
		frame.setLayout(fl);

		JLabel labName = new JLabel("账号:");
		frame.add(labName);

		// 实例化JTextField标签对象,Dimension尺寸
		username = new JTextField();
		Dimension dim1 = new Dimension(300, 30);
		// textName.setSize(dim);//setSize这方法只对顶级容器有效,其他组件使用无效。
		username.setPreferredSize(dim1);// 设置除顶级容器组件其他组件的大小
		frame.add(username);

		JLabel labpass = new JLabel("密码:");
		frame.add(labpass);

		// 实例化JPasswordField
		password = new JPasswordField();
		// 设置大小
		password.setPreferredSize(dim1);// 设置组件大小
		// 添加password到窗体上
		frame.add(password);

		JButton button1 = new JButton();
		// 设置按钮的大小
		Dimension dim2 = new Dimension(100, 30);
		button1.setSize(dim2);
		button1.setText("注册");
		frame.add(button1);
		// 实例化JButton组件
		JButton button2 = new JButton();
		button2.setSize(dim2);
		// 设置按钮的显示内容
		button2.setText("登录");
		frame.add(button2);
		frame.setVisible(true);// 设置窗体为可见

		// 对button1添加监听方法,监听是否点击这个按钮
		button1.addActionListener(this);
		// 实例化登录对象,并把登录界面中账号和密码输入框的对象传给它
		Login login = new Login(frame, username, password);
		// 登录按钮添加监听方法,对点击按钮这个动作和账号密码输入框中的信息传送
		button2.addActionListener(login);

	}

	ResultSet rs = null;
	Connection Conn = null;
	Statement statement = null;
	ResultSet rs2 = null;

	// 连接SQLServer
	public boolean ConnectionSqlServer() {

		try { // 1.加载驱动
			String driverName = "com.microsoft.sqlserver.jdbc.SQLServerDriver";
			Class.forName(driverName);
		} catch (Exception e) {
			e.printStackTrace();
			System.out.println("加载驱动失败!");
		}
		try {
			// 连接数据库
			String dbURL = "jdbc:sqlserver://localhost:1433;DatabaseName=SnakeGame用户数据库";
			String userName = "sa";// 你的数据库用户名
			String userPwd = "sqls0925@";// 你的密码
			Conn = DriverManager.getConnection(dbURL, userName, userPwd);
			return true;
		} catch (Exception e) {
			e.printStackTrace();
			System.out.print("SQL Server连接失败!");
		}
		return false;
	}

	@Override
	public void actionPerformed(ActionEvent e) {
		//注册按钮被点击,打开注册窗口
		if (e.getActionCommand().equals("注册")) {
			Register register = new Register();
			register.initUI();
			return;
		}
		try {
			if (ConnectionSqlServer()) {
				try {
					// 执行SQL语句
					// 1获得执行SQL语句的对象
					statement = Conn.createStatement();
					// 2编写SQL语句;
					String sql = "select COUNT(*) from SnakeUser where username=" + username.getText();
					// 3执行SQL:executeQuery
					ResultSet rs_num = statement.executeQuery(sql);
					// 4遍历结果集
					if (rs_num.next()) {
						// 输入的账号在数据库中为0行,账户不存在
						int i = rs_num.getInt(1);
						if (i == 0) {
							JFrame frame3 = new JFrame();
							frame3.setTitle("提示框");
							frame3.setSize(300, 80);
							frame3.setResizable(false);
							frame3.setDefaultCloseOperation(2);
							frame3.setLocationRelativeTo(null);
							FlowLayout f1 = new FlowLayout(FlowLayout.CENTER, 10, 10);
							frame3.setLayout(f1);
							JLabel label = new JLabel("账号不存在");
							frame3.add(label);
							frame3.setVisible(true);
						}
					}
					// 2编写SQL语句;
					String sql2 = "select * from SnakeUser where username=" + username.getText();
					// 3执行SQL:executeQuery
					rs2 = statement.executeQuery(sql2);
					// 4遍历结果集
					while (rs2.next()) {
						// 判断密码是否正确
						if (password.getText().equals(rs2.getString("password"))) {
							JFrame frame2 = new JFrame();
							frame2.setTitle("贪吃蛇");
							frame2.setResizable(false);
							frame2.setDefaultCloseOperation(3);
							frame2.setBounds(300, 70, 900, 720);
							Control control = new Control();
							frame2.add(control);
							frame2.setVisible(true);
							frame.dispose();
						} else {
							JFrame frame3 = new JFrame();
							frame3.setTitle("提示框");
							frame3.setSize(300, 80);
							frame3.setResizable(false);
							frame3.setDefaultCloseOperation(2);
							frame3.setLocationRelativeTo(null);
							FlowLayout f1 = new FlowLayout(FlowLayout.CENTER, 10, 10);
							frame3.setLayout(f1);
							JLabel label = new JLabel("密码不正确");
							frame3.add(label);
							frame3.setVisible(true);
						}
					}
				} catch (Exception e1) {
					e1.printStackTrace();
					System.out.print("SQL Server读取表信息失败!");
				}

			}

		} catch (HeadlessException e1) {
			// TODO Auto-generated catch block
			e1.printStackTrace();
		} finally {
			// 4.释放资源
			// 标准资源释放的代码
			if (rs != null) {
				try {
					rs.close();
				} catch (SQLException e1) {
					e1.printStackTrace();
				}
			}
			if (statement != null) {
				try {
					statement.close();
				} catch (SQLException e1) {
					e1.printStackTrace();
				}
				statement = null;
			}
			if (Conn != null) {
				try {
					Conn.close();
				} catch (SQLException e1) {
					e1.printStackTrace();
				}
				Conn = null;
			}
		}
	}

}

2.Register注册类

import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPasswordField;
import javax.swing.JTextField;
import java.sql.*;

public class Register implements ActionListener {
	JFrame frame = new JFrame();
	JTextField name2;
	JTextField password2;

	public Register() {
	}

	public Register(JFrame frame, JTextField name, JTextField password) {
		this.frame = frame;
		this.name2 = name;
		this.password2 = password;
	}

	public void initUI() {
		frame.setTitle("注册窗口");
		frame.setSize(500, 200);
		frame.setLocationRelativeTo(null);
		frame.setResizable(false);
		frame.setDefaultCloseOperation(3);

		FlowLayout f1 = new FlowLayout(FlowLayout.CENTER, 10, 20);
		frame.setLayout(f1);

		JLabel name1 = new JLabel("请输入您的账号(3-10位):");
		frame.add(name1);

		name2 = new JTextField();
		Dimension dim1 = new Dimension(300, 30);
		name2.setPreferredSize(dim1);
		frame.add(name2);

		JLabel password1 = new JLabel("请输入您的密码(3-10位):");
		frame.add(password1);

		password2 = new JTextField();
		password2.setPreferredSize(dim1);
		frame.add(password2);

		JButton button = new JButton();
		button.setText("确定");
		frame.add(button);

		frame.setVisible(true);
		// 在确定按钮上添加监听方法,监听点击这个动作和账号密码输入框中的文本
		Register re = new Register(frame, name2, password2);
		button.addActionListener(re);
	}

	Connection Conn = null;
	Statement statement = null;

	// 连接SQLServer
	public boolean ConnectionSqlServer() {
		try {
			// 1.加载驱动
			String driverName = "com.microsoft.sqlserver.jdbc.SQLServerDriver";
			Class.forName(driverName);
		} catch (Exception e) {
			e.printStackTrace();
			System.out.println("加载驱动失败!");
		}
		try {
			// 2.连接数据库
			String dbURL = "jdbc:sqlserver://localhost:1433;DatabaseName=SnakeGame用户数据库";// DatabaseName为你的数据库名称
			String userName = "sa";// 你的数据库用户名
			String userPwd = "sqls0925@";// 你的密码
			Conn = DriverManager.getConnection(dbURL, userName, userPwd);
			return true;
		} catch (Exception e) {
			e.printStackTrace();
			System.out.print("SQL Server连接失败!");
		}
		return false;
	}

	@Override
	public void actionPerformed(ActionEvent e) {
		if (ConnectionSqlServer()) {
			try {
				// 获得执行SQL语句的对象
				statement = Conn.createStatement();
				// 编写SQL语句;
				String sql = "select COUNT(*) from SnakeUser where username=" + name2.getText();
				ResultSet rs = statement.executeQuery(sql);
				if (rs.next()) {
					if (rs.getInt(1) != 0) {
						JFrame frame2 = new JFrame();
						FlowLayout f1 = new FlowLayout(FlowLayout.CENTER, 10, 10);
						frame2.setLayout(f1);
						frame2.setTitle("提示框");
						frame2.setBounds(800, 400, 200, 80);
						frame2.setResizable(false);
						JLabel exist = new JLabel();
						exist.setText("账号已存在");
						frame2.add(exist);
						frame2.setVisible(true);
						return;
					}
				}

				String values = "values('" + name2.getText() + "'," + "'" + password2.getText() + "')";
				try {
					if (name2.getText().length() < 3 || name2.getText().length() > 10
							|| password2.getText().length() < 3 || password2.getText().length() > 10) {
						JFrame frame2 = new JFrame();
						FlowLayout f1 = new FlowLayout(FlowLayout.CENTER, 10, 10);
						frame2.setLayout(f1);
						frame2.setTitle("提示");
						frame2.setBounds(800, 400, 220, 80);
						frame2.setResizable(false);
						JLabel success = new JLabel();
						success.setText("账号或密码长度不符合要求");
						frame2.add(success);
						frame2.setVisible(true);
						return;
					}
					@SuppressWarnings("unused")
					int i = statement.executeUpdate("insert into SnakeUser" + " " + values);
					JFrame frame2 = new JFrame();
					FlowLayout f1 = new FlowLayout(FlowLayout.CENTER, 10, 10);
					frame2.setLayout(f1);
					frame2.setTitle("提示");
					frame2.setBounds(800, 400, 220, 80);
					frame2.setResizable(false);
					frame2.setDefaultCloseOperation(3);
					JLabel success = new JLabel();
					success.setText("注册成功");
					frame2.add(success);
					frame2.setVisible(true);

				} catch (SQLException e1) {
					e1.printStackTrace();
					System.out.println("注册失败");
				}

			} catch (Exception e2) {
				e2.printStackTrace();
				System.out.println("数据库更改信息失败");
			}
		}
	}

}

3.Food食物类

import java.awt.Graphics;
import java.util.Random;

import javax.swing.ImageIcon;
import javax.swing.JPanel;

public class Food extends JPanel {
	public Food() {
	}

	ImageIcon food = new ImageIcon("food.png");// 引入食物图片

	public void paintComponent(Graphics g) {
		super.paintComponent(g);
		food.paintIcon(this, g, foodx, foody);// 绘制食物组件
	}
	Random r = new Random();
	public int foodx;
	public int foody;
	public void foodPosition() {// 随机生成食物位置
		foodx = 25 + 25 * r.nextInt(34);
		foody = 75 + 25 * r.nextInt(24);
	}
}

4.Barrier障碍物类

import javax.swing.*;
import java.awt.*;
import java.util.Random;

class Barrier extends JPanel {

	public Barrier() {
	}

	ImageIcon barrier = new ImageIcon("barrier.jpg");// 引入障碍图片

	public void paintComponent(Graphics g) {
		super.paintComponent(g);
		for (int i = 0; i < 10; i++) {// 随机位置上生成10个障碍物
			barrier.paintIcon(this, g, barrierX[i], barrierY[i]);
		}
	}

	Random r = new Random();
	public int barrierX[] = new int[10];
	public int barrierY[] = new int[10];

	public void barrierPosition() {
		for (int i = 0; i < 10; i++) {
			barrierX[i] = 25 + 25 * r.nextInt(34);
			barrierY[i] = 75 + 25 * r.nextInt(24);
		}
	}
}

5.Snake蛇类

import java.awt.Graphics;
import javax.swing.ImageIcon;
import javax.swing.JPanel;

public class Snake extends JPanel {
	// 引入四个方向的蛇头和身体的图片
	ImageIcon up = new ImageIcon("up.png");
	ImageIcon down = new ImageIcon("down.png");
	ImageIcon left = new ImageIcon("left.png");
	ImageIcon right = new ImageIcon("right.png");
	ImageIcon body = new ImageIcon("body.png");
	public int len;// 定义长度变量
	public int snake1[] = new int[800];// 创建800个身体长度的蛇的x坐标数组
	public int snake2[] = new int[800];// 创建800个身体长度的蛇的y坐标数组
	String direction;// 定义方向变量

	public Snake() {
	}

	public void initSnake() {
		direction = "R";// 默认蛇头方向向右
		len = 4;// 默认蛇的长度为4
		snake1[0] = 100;// 蛇头横坐标
		snake2[0] = 100;// 蛇头纵坐标
		snake1[1] = 75;// 第一节身体的横坐标
		snake2[1] = 100;// 第一节身体的纵坐标
		snake1[2] = 50;// 第二节
		snake2[2] = 100;
		snake1[3] = 25;// 第三节
		snake2[3] = 100;
	}

	public void paintComponent(Graphics g) {
		super.paintComponent(g);
		if (direction == "R") {
			right.paintIcon(this, g, snake1[0], snake2[0]);
		} else if (direction == "L") {
			left.paintIcon(this, g, snake1[0], snake2[0]);
		} else if (direction == "U") {
			up.paintIcon(this, g, snake1[0], snake2[0]);
		} else if (direction == "D") {
			down.paintIcon(this, g, snake1[0], snake2[0]);
		}
		for (int i = 1; i < len; i++) {
			body.paintIcon(this, g, snake1[i], snake2[i]);
		}
	}

	public void snakeMove() {
		// 实现身体的移动:上一节身体的位置永远是下一节身体的位置
		for (int i = len - 1; i > 0; i--) {
			snake1[i] = snake1[i - 1];
			snake2[i] = snake2[i - 1];
		}
		if (direction == "R") {// 向右移动,纵坐标不变,横坐标+25
			snake1[0] = snake1[0] + 25;// 实现头的移动
			if (snake1[0] > 850) {// 实现穿墙
				snake1[0] = 25;
			}
		} else if (direction == "L") {// 向左移动,纵坐标不变,横坐标-25
			snake1[0] = snake1[0] - 25;
			if (snake1[0] < 25) {
				snake1[0] = 850;
			}
		} else if (direction == "U") {// 向上移动,横坐标不变,纵坐标-25
			snake2[0] = snake2[0] - 25;
			if (snake2[0] < 75) {
				snake2[0] = 650;
			}
		} else if (direction == "D") {// 向下移动,横坐标不变,纵坐标+25
			snake2[0] = snake2[0] + 25;
			if (snake2[0] > 650) {
				snake2[0] = 75;
			}
		}
	}
}

6.Title标头类

import java.awt.Graphics;

import javax.swing.ImageIcon;
import javax.swing.JPanel;

public class Title extends JPanel {
	ImageIcon title = new ImageIcon("title.jpg");//引入标头图片

	public void paintComponent(Graphics g) {
		title.paintIcon(this, g, 25, 11);// 将title这个图片组件在窗体上绘制
	}
}

7.Sound音效类

import java.applet.Applet;
import java.applet.AudioClip;
import java.net.URL;

//音效的线程类
public class Sound extends Thread {
	public static final String DIE = "die.wav";
	public static final String EAT = "eat.wav";
	AudioClip ac;

	public Sound() {
	}

	public Sound(String path) {
		URL url = this.getClass().getResource("/music/" + path);
		ac = Applet.newAudioClip(url);
	}

	public void play() {
		ac.play();
	}

	@Override
	public void run() {
		play();
	}
}

8.Control游戏逻辑控制类

import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.io.IOException;
import java.io.InputStream;
import java.util.Random;

import javax.swing.ImageIcon;
import javax.swing.JPanel;
import javax.swing.Timer;
import javax.imageio.ImageIO;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.Clip;
import javax.sound.sampled.LineUnavailableException;
import javax.sound.sampled.UnsupportedAudioFileException;

public class Control extends JPanel implements KeyListener, ActionListener {
	Food food = new Food();
	Snake snake = new Snake();
	Title title = new Title();
	Barrier barrier = new Barrier();
	Sound die;
	Sound eat;
	Sound bgm;
	Timer timer;
	int score = 0;// 初始分数0分
	// 默认暂停游戏
	boolean isStarted = false;
	// 判断是否死亡
	boolean isFailed = false;
	int speed = 200;

	public Control() {
		initItem();
		this.setFocusable(true);//获取键盘事件的焦点
		this.addKeyListener(this);//处理键盘事件,敲了键盘谁来处理呢:this
		timer.start();
	}

	// 初始化物体
	public void initItem() {
		timer = new Timer(100, this);
		snake.initSnake();//初始化蛇	
		food.foodPosition();// 随机生成食物位置		
		barrier.barrierPosition();// 随机生成障碍物位置
	}

	// 方法重写 在窗体上绘制组件
	public void paintComponent(Graphics g) {
		super.paintComponent(g);
		this.setBackground(Color.white);// 设置背景色为白色
		title.paintComponent(g);// 画标头图片
		g.fillRect(25, 75, 850, 600);// 黑色背景填充游戏窗体游戏范围
		food.paintComponent(g);// 画食物
		barrier.paintComponent(g);// 画障碍物
		snake.paintComponent(g);// 画蛇
		g.setColor(Color.black);// 设置分数、长度的颜色
		g.setFont(new Font("arial", Font.BOLD, 20));
		g.drawString("len:" + snake.len, 750, 30);
		g.drawString("score:" + score, 750, 55);
		// 蛇撞到自身或者撞到障碍物死亡
		for (int j = 9; j >= 0; j--) {
			for (int i = 1; i <= snake.len; i++) {
				if ((snake.snake1[0] == barrier.barrierX[j] && snake.snake2[0] == barrier.barrierY[j])
						|| (snake.snake1[0] == snake.snake1[i] && snake.snake2[0] == snake.snake2[i])) {
					// 游戏失败
					isFailed = true;
					// 播放死亡音效
					die = new Sound(Sound.DIE);
					die.start();
					// 游戏失败isFailed==true显示文字
					g.setColor(Color.RED);// 设置game over的颜色
					g.setFont(new Font("arial", Font.BOLD, 40));
					g.drawString("Game Over", 345, 320);
					g.drawString("Press space to restart", 250, 400);
				}
			}
		}
		// 如果游戏isFailed==false再考虑游戏是否暂停
		if (!isFailed) {
			if (!isStarted) {
				g.setColor(Color.white);
				g.setFont(new Font("arial", Font.BOLD, 40));
				g.drawString("Press space to start", 250, 350);
			}
		}
	}

	@Override
	public void keyTyped(KeyEvent e) {
		// TODO Auto-generated method stub
	}

	@Override
	public void keyReleased(KeyEvent e) {
		// TODO Auto-generated method stub
	}

	@Override
	public void keyPressed(KeyEvent e) {
		if (e.getKeyCode() == KeyEvent.VK_SPACE) {
			if (isFailed) {
				isFailed = false;// 如果游戏失败,按空格重开游戏
				score=0;//分数重新置为0
				initItem();
			}
			isStarted = !isStarted;
			repaint();
		}
		if (e.getKeyCode() == KeyEvent.VK_UP) {
			snake.direction = "U";

		} else if (e.getKeyCode() == KeyEvent.VK_DOWN) {
			snake.direction = "D";

		} else if (e.getKeyCode() == KeyEvent.VK_LEFT) {
			snake.direction = "L";

		} else if (e.getKeyCode() == KeyEvent.VK_RIGHT) {
			snake.direction = "R";
		}

	}

	@Override
	public void actionPerformed(ActionEvent e) {
		// 闹钟到点后执行的方法
		if (isFailed) {
			return;// 如果游戏失败,return,接下来代码不会再执行
		}
		if (isStarted) {
			// 如果游戏开始蛇移动
			snake.snakeMove();
			// 如果蛇头位置与食物位置坐标重合
			if (food.foodx == snake.snake1[0] && food.foody == snake.snake2[0]) {
				snake.len++;// 长度+1
				score += 1;// 分数+1				
				food.foodPosition();// 蛇头碰到到食物后再次随机生成食物位置
				// 播放吞食音效
				eat = new Sound(Sound.EAT);
				eat.start();
			}
			// 重绘
			repaint();
			// 再次打开定时器
			timer.start();
		}

	}
}

9.MainSnake主函数类

import java.awt.Component;

import javax.swing.JFrame;

public class MainSnake {
	public static void main(String[] args) {
		Login login = new Login();
		login.initUI();
	}
}

三、结束语

1.该项目设计到eclipse连接数据库,步骤可参考此文章 点击即刻跳转
2.项目中的图片、音效素材私聊我即可拿

小小拙作,献丑献丑❤❤❤

  • 5
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值