贪吃蛇
代码展示
主类
package com.luffy.snake;
import javax.swing.*;
/**
*
* 贪吃蛇主程序
*
* */
public class StartGame {
public static void main(String[] args) {
JFrame jFrame = new JFrame();
//给窗口添加一个主面板
jFrame.add(new GamePanel());
//设置窗口的基本属性
jFrame.setBounds(10,10,930,740);
jFrame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
jFrame.setResizable(false);
jFrame.setVisible(true);
}
}
数据类
package com.luffy.snake;
import javax.swing.*;
import java.net.URL;
/**
*
* 贪吃蛇数据类
*
* */
public class Data {
//相对路径 tx.jpg
//绝对路径 / 相当于当前目录
//这里是相对路径,使用相对路径拿到资源设置为URL对象
public static URL headerURL = Data.class.getResource("statics/header.png");//计时板
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 URL bodyURL = Data.class.getResource("statics/body.png");//身体
public static URL foodURL = Data.class.getResource("statics/food.png");//食物
//将拿到的图片资源转换成图片标签
public static ImageIcon header = new ImageIcon(headerURL);
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 ImageIcon body = new ImageIcon(bodyURL);
public static ImageIcon food = new ImageIcon(foodURL);
}
面板类
package com.luffy.snake;
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.util.Random;
/**
*
* 贪吃蛇主面板
*
* */
public class GamePanel extends JPanel implements KeyListener, ActionListener {
//定义蛇的数据结构
int length;//蛇的长度
int[] snakeX = new int[600];//蛇的x坐标 25 * 25
int[] snakeY = new int[500];//蛇的y坐标 25 * 25
boolean isStart = false;//游戏状态
String fx;//蛇的方向
Timer timer = new Timer(100,this);//定时器
Random random = new Random();//食物随机值
int foodX;//食物X坐标
int foodY;//食物Y坐标
boolean isFail;//失败状态
int score;//分数
//构造器
public GamePanel(){
init();//初始化数据
this.setFocusable(true);//获得焦点
this.addKeyListener(this);//启动键盘监听
timer.start();//启动定时器
}
//初始化方法
public void init(){
length = 3;//长度
snakeX[0] = 100 ; snakeY[0] = 100;//蛇头
snakeX[1] = 75 ; snakeY[1] = 100;//第一个身体
snakeX[2] = 50 ; snakeY[2] = 100;//第二个身体
fx = "R";//方向
foodX = 25 + 25 * random.nextInt(34);//食物随机X值
foodY = 75 + 25 * random.nextInt(23);//食物随机Y值
isFail = false;//是否失败
score = 0;//积分
}
//绘制面板,我们游戏中的所有东西,都是用这个画笔来画
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);//调用一次清屏一次
setPanelProperty(g);//设置面板初始属性
setHeadDirection(g);//根据按下方向键设置蛇头部的方向
initSnakeBody(g);//初始加载蛇的两个身体
gameState(g);//游戏开始状态
refurbishData(g);//刷新数据
ifFail(g);//游戏失败提示文字
}
//键盘监听事件
@Override
public void keyPressed(KeyEvent e) {
int keyCode = e.getKeyCode();//获取键盘监听值
ifGameStateOperation(keyCode);//判断游戏失败状态操作
setDirectionValue(keyCode);//根据按下的方向设置方向值
}
//定时器监听事件
@Override
public void actionPerformed(ActionEvent e) {
//如果游戏状态不是暂停,并且游戏失败状态不为true
if(isStart && isFail == false){
eatFood();//判断小蛇是否吃到食物,吃到就增长身体并且刷新食物位置
bodyMove();//身体移动
headMove();//头移动
collideBodyFail();//碰撞身体失败
}
timer.start();//重启定时器刷新页面
}
@Override
public void keyTyped(KeyEvent e) {
}
@Override
public void keyReleased(KeyEvent e) {
}
//设置面板初始属性
public void setPanelProperty(Graphics g){
this.setBackground(Color.WHITE);//设置面板为白色
Data.header.paintIcon(this,g,25,11);//将标题栏画入
g.fillRect(25,75,850,600);//画一个游戏场景的矩形
Data.food.paintIcon(this,g,foodX,foodY);//将食物第一次画在游戏上
}
//根据按下方向键设置蛇头部的方向
public void setHeadDirection(Graphics g){
if(fx.equals("R")){//右
Data.right.paintIcon(this,g,snakeX[0],snakeY[0]);
}else if(fx.equals("L")){//左
Data.left.paintIcon(this,g,snakeX[0],snakeY[0]);
}else if(fx.equals("U")){//上
Data.up.paintIcon(this,g,snakeX[0],snakeY[0]);
}else if(fx.equals("D")){//下
Data.down.paintIcon(this,g,snakeX[0],snakeY[0]);
}
}
//初始加载蛇的两个身体
public void initSnakeBody(Graphics g){
for (int i = 1; i < length; i++) {
Data.body.paintIcon(this,g,snakeX[i],snakeY[i]);
}
}
//游戏开始状态
public void gameState(Graphics g){
if(isStart == false){
g.setColor(Color.white);
g.setFont(new Font("微软雅黑",Font.BOLD,40));
g.drawString("按下空格开始游戏!",300,350);
}
}
//刷新数据
public void refurbishData(Graphics g){
g.setColor(Color.white);
g.setFont(new Font("微软雅黑",Font.BOLD,10));
g.drawString("长度:" + length,750,30);
g.drawString("分数:" + score,750,50);
}
//游戏失败提示文字
public void ifFail(Graphics g){
if(isFail){//true为失败
g.setColor(Color.red);
g.setFont(new Font("微软雅黑",Font.BOLD,40));
g.drawString("游戏失败,按下任意键重新开始!",175,350);
}
}
//判断游戏失败状态操作
public void ifGameStateOperation(int keyCode){
if(isFail){
//失败按下空格键重新初始化开始界面
if(keyCode == KeyEvent.VK_SPACE){
init();
}
}else{
//没有失败如果按的是空格则暂停游戏
if(keyCode == KeyEvent.VK_SPACE){
isStart = !isStart;
repaint();//重绘画面
}
}
}
//根据按下的方向设置方向值
public void setDirectionValue(int keyCode){
if(keyCode == KeyEvent.VK_UP){
if(fx == "D"){
fx = "D";
}else{
fx = "U";
}
}else if(keyCode == KeyEvent.VK_DOWN){
if(fx == "U"){
fx = "U";
}else{
fx = "D";
}
}else if(keyCode == KeyEvent.VK_LEFT){
if(fx == "R"){
fx = "R";
}else{
fx = "L";
}
}else if(keyCode == KeyEvent.VK_RIGHT){
if(fx == "L"){
fx = "L";
}else{
fx = "R";
}
}
}
//吃食物
public void eatFood(){
//判断小蛇是否吃到食物,吃到就增长身体并且刷新食物位置
if(snakeX[0] == foodX && snakeY[0] == foodY){
length++;
score = score + 10;
foodX = 25 + 25 * random.nextInt(34);
foodY = 75 + 25 * random.nextInt(23);
}
}
//身体移动
public void bodyMove(){
//身体随着长度而往头的方向依次前进移动
for(int i=length-1; i > 0; i--){
snakeX[i] = snakeX[i-1];
snakeY[i] = snakeY[i-1];
}
}
//头移动
public void headMove(){
//头根据按下后修改的方向键进行移动
if(fx.equals("U")){
snakeY[0] = snakeY[0] - 25;//小蛇的头往右25像素
if(snakeY[0] < 100){isFail = true;}//边界判断
repaint();//重绘画面
}else if(fx.equals("D")){
snakeY[0] = snakeY[0] + 25;//小蛇的头往右25像素
if(snakeY[0] > 625){isFail = true;}//边界判断
repaint();//重绘画面
}else if(fx.equals("L")){
snakeX[0] = snakeX[0] - 25;//小蛇的头往右25像素
if(snakeX[0] < 50){isFail = true;}//边界判断
repaint();//重绘画面
}else if(fx.equals("R")){
snakeX[0] = snakeX[0] + 25;//小蛇的头往右25像素
if(snakeX[0] > 845){isFail = true;}//边界判断
repaint();//重绘画面
}
}
//碰撞身体失败
public void collideBodyFail(){
//从身体开始判断
for(int i = 1; i < length; i++){
//循环全部身体,如果头撞到随意一个身体,将游戏失败状态改为true
if(snakeX[0] == snakeX[i] && snakeY[0] == snakeY[i]){
isFail = true;
}
}
}
}
心得
跟着狂神视频学的,后面自己多写了一点代码,不让头部往身体的方向转,碰到边缘就死亡等