本项目采用的是java语言,整个项目一共分为了9个类: 1.Login登录类 2.Register注册类 3.Food食物类 4.Barrier障碍物类 5.4.Snake蛇类 6.Title标头类 7.Sound音效类 8.Control游戏逻辑控制类 9.MainSnake类
目录
一、运行效果
1.登录界面
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.项目中的图片、音效素材私聊我即可拿
小小拙作,献丑献丑❤❤❤