按照狂神贪吃蛇教程做出的成品程序,和大家分享
使用CSDN这么久,第一次自己写文章,如有低级错误,请多包涵。
我最近在学习JavaSE进阶,按照狂神 (B站ID:遇见狂神说) 推荐的学习路径,学习到了GUI部分,受益匪浅。如果你也在自学Java,不妨去关注up,他的讲课风格很好,而且涉及全面,从Java基础,到MVC,再到SpringBoot,值得一看。
这篇文章的目的是分享一下狂神贪吃蛇项目的全部代码,其中包含我做出改进的部分,也有我个人的疑惑,希望和大家分享。
这个贪吃蛇项目实现了简单的GUI界面和键盘监听用户交互,美中不足是比较简陋,而且不是完全的面向对象项目。由于经验与理解尚不足,我暂时没有能力将它更加完善。如果您有好的意见,欢迎与我联系。
启动类:
package com.zcy.JavaSE.GUI.Snake;
import javax.swing.*;
/**
* @author 睿智的仓鼠
*
*-学习自B站up 遇见狂神说,代码非原创,仅供学习参考!
*
*-基础功能:
*1.键盘方向键控制小蛇移动
*2.空格键暂停游戏
*
*-新增功能:
*1.小蛇运动时无法回头直接吃自己
*2.增加了难度机制,蛇的长度越长,难度越高
*3.按c键进入作弊模式
*
*-未解决部分:
*1.无法通过修改timer的参数,来根据难度调整小蛇运动的速度
*
*/
//主启动类
public class StartGame {
public static void main(String[] args) {
new MainFrame();
}
}
主窗口类:
package com.zcy.JavaSE.GUI.Snake;
import javax.swing.JFrame;
import javax.swing.WindowConstants;
//创建主窗口
public class MainFrame{
public MainFrame(){
init();
}
public void init(){
JFrame frame = new JFrame();
frame.setSize(915, 745);
frame.setResizable(false);//窗口不可拉伸
frame.setTitle("贪吃蛇小游戏");
frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
frame.add(new GamePanel());
frame.setVisible(true);
}
}
游戏面板:
package com.zcy.JavaSE.GUI.Snake;
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.KeyAdapter;
import java.awt.event.KeyEvent;
import java.util.Random;
import javax.swing.JPanel;
import javax.swing.Timer;
//游戏面板
public class GamePanel extends JPanel implements ActionListener{
//定义游戏数据
int panel_Width;//游戏界面宽度
int panel_Height;//游戏界面高度
int snake_Speed = 200;//刷新时间(毫秒),越大越慢
//定义蛇的数据结构
int length; //蛇的长度
int[] snake_X = new int[600]; //蛇的x坐标
int[] snake_Y = new int[600]; //蛇的y坐标
String snake_Orientation; //蛇头朝向
//食物的坐标
int food_X;
int food_Y;
Random random = new Random();
//定义游戏状态:开始、暂停
boolean isStrat = false; //默认暂停状态
//游戏失败
boolean isFail = false;
//游戏积分
int score;
int food_Value;//吃一个食物给几分
//游戏难度
int level;
//cheat
boolean cheat = false;
//定时器
Timer timer = new Timer(snake_Speed, this); //刷新时间(毫秒), 监听的目标对象
//构造器
public GamePanel() {
init();
//获得焦点和键盘事件
this.setFocusable(true); //获得焦点事件
this.addKeyListener(new keyboardListener());
timer.start();//游戏一开始,定时器就启动
}
//初始化方法
public void init(){
panel_Width = 850;
panel_Height = 600;
length = 3;
snake_X[0] = 100;snake_Y[0] = 100; //头的坐标
snake_X[1] = 75;snake_Y[1] = 100; //第一节身体的坐标
snake_X[2] = 50;snake_Y[2] = 100; //第二节身体的坐标
snake_Orientation = "right"; //初始头的方向为右
//食物随机分布在界面上
food_X = 25 + 25*random.nextInt(33);//生成1到34的随机数
food_Y = 75 + 25*random.nextInt(23);
score = 0;
food_Value = 5;
level = 1;
}
//绘制面板
@Override
protected void paintComponent(Graphics g) { //paintComponent无需调用,自动执行
super.paintComponent(g);//清屏
//绘制静态面板
this.setBackground(Color.lightGray);
//画上方广告栏
Data.header.paintIcon(this, g, 25, 11);//在哪个组件画, 用哪个画笔画, X, Y
//画下方游戏界面
g.fillRect(25, 75, panel_Width, panel_Height);
//画积分
g.setColor(Color.white);
g.setFont(new Font("微软雅黑", Font.BOLD, 15)); //设置字体
g.drawString("长度:"+length, 750, 25);
g.drawString("分数:"+score, 750, 40);
g.drawString("难度:"+level, 750, 55);
//画食物
Data.food.paintIcon(this, g, food_X, food_Y);
//画小蛇
if (snake_Orientation.equals("right")){
Data.right.paintIcon(this, g, snake_X[0], snake_Y[0]);//画朝右的头部
}else if(snake_Orientation.equals("left")){
Data.left.paintIcon(this, g, snake_X[0], snake_Y[0]);//画朝左的头部
}else if(snake_Orientation.equals("up")){
Data.up.paintIcon(this, g, snake_X[0], snake_Y[0]);//画朝上的头部
}else if(snake_Orientation.equals("down")){
Data.down.paintIcon(this, g, snake_X[0], snake_Y[0]);//画朝下的头部
}
for (int i = 1; i < length; i++) {
Data.body.paintIcon(this, g, snake_X[i], snake_Y[i]);//画每一节身体
}
//游戏状态
if (isStrat == false){
g.setColor(Color.white);
g.setFont(new Font("微软雅黑", Font.BOLD, 40)); //设置字体
g.drawString("按下空格开始游戏", 300, 300);
}
//游戏失败
if (isFail == true){
g.setColor(Color.red);
g.setFont(new Font("微软雅黑", Font.BOLD, 40)); //设置字体
g.drawString("失败,按下空格重新开始", 220, 300);
}
}
//键盘监听器
class keyboardListener extends KeyAdapter{
@Override
public void keyPressed(KeyEvent e) {
int keyCode = e.getKeyCode();//获得按下的键
//空格
if (keyCode == KeyEvent.VK_SPACE){ //按下空格
if (isFail == true){
//空格控制重新开始
isFail = false;
init();
}else {
//空格控制游戏暂停
isStrat = !isStrat; //isStart取反
}
repaint();
}
//控制小蛇移动
if (keyCode == KeyEvent.VK_UP){
if (snake_Orientation != "down"){
snake_Orientation = "up"; //蛇头变向
}
}else if (keyCode == KeyEvent.VK_DOWN){
if (snake_Orientation != "up"){
snake_Orientation = "down";
}
}else if (keyCode == KeyEvent.VK_LEFT){
if (snake_Orientation != "right"){
snake_Orientation = "left";
}
}else if (keyCode == KeyEvent.VK_RIGHT){
if (snake_Orientation != "left"){
snake_Orientation = "right";
}
}
if (keyCode == KeyEvent.VK_C){
cheat = !cheat;
}
}
}
//事件监听,通过固定的时间来刷新
@Override
public void actionPerformed(ActionEvent e) {
if (isStrat == true && isFail == false){ //游戏开始状态,则小蛇开始运动
//身体跟随移动
for (int i = length-1; i > 0; i--) {//向前移动一节(每个身体都到上一节身体的坐标)
//新生成的身体不可见
snake_X[length] = -50;
snake_Y[length] = -50;
snake_X[i] = snake_X[i-1];
snake_Y[i] = snake_Y[i-1];
}
//头部运动判断,只需要控制头部的运动,其他身体都会跟着动
if (snake_Orientation == "up"){
snake_Y[0] = snake_Y[0]-25;
if (snake_Y[0] < 75){//边界判断
snake_Y[0] = panel_Height+50;
}
}else if (snake_Orientation == "down"){
snake_Y[0] = snake_Y[0]+25;
if (snake_Y[0] > panel_Height+50){//边界判断
snake_Y[0] = 75;
}
}else if (snake_Orientation == "left"){
snake_X[0] = snake_X[0]-25;
if (snake_X[0] < 25){//边界判断
snake_X[0] = panel_Width;
}
}else if (snake_Orientation == "right"){
snake_X[0] = snake_X[0]+25;
if (snake_X[0] > panel_Width){//边界判断
snake_X[0] = 25;
}
}
//吃食物
if (snake_X[0] == food_X && snake_Y[0] == food_Y){
//身体变长
length++;
//分数增加
score += food_Value;
//重新生成食物
food_X = 25 + 25*random.nextInt(34);
food_Y = 75 + 25*random.nextInt(24);
}
//失败判定,头碰到身体就算失败
if (cheat == false){
for (int i = 1; i < length; i++) { //遍历所有身体坐标
if (snake_X[0] == snake_X[i] && snake_Y[0] == snake_Y[i]){
isFail = true;
break;
}
}
}
if (length > 4 && length < 13){
level = 2;
timer.stop();
snake_Speed = 1000;
}
repaint();
}
timer.start();//定时器开始
}
}
数据部分:
package com.zcy.JavaSE.GUI.Snake;
import java.net.URL;
import javax.swing.ImageIcon;
public class Data {
public static URL headerURL = Data.class.getResource("statics/header.png");
public static ImageIcon header = new ImageIcon(headerURL);
public static URL upURL = Data.class.getResource("statics/up.png");
public static URL downURL = Data.class.getResource("statics/down.png");
public static URL leftURL = Data.class.getResource("statics/left.png");
public static URL rightURL = Data.class.getResource("statics/right.png");
public static ImageIcon up = new ImageIcon(upURL);
public static ImageIcon down = new ImageIcon(downURL);
public static ImageIcon left = new ImageIcon(leftURL);
public static ImageIcon right = new ImageIcon(rightURL);
public static URL bodyURL = Data.class.getResource("statics/body.png");
public static ImageIcon body = new ImageIcon(bodyURL);
public static URL foodURL = Data.class.getResource("statics/food.png");
public static ImageIcon food = new ImageIcon(foodURL);
}
图片素材保存目录:
Snake.statics
图片素材下载地址:
链接:百度网盘 下载地址
提取码:qbm4
初来乍到,请多关照。
我会写更多文章来分享我觉得有意义的项目,记录学习历程。