贪吃蛇游戏(Java)

首款用Java语言实现的小游戏,一些模块做得不是很好,界面的设计及整体的布局比较简单,一些应该实现的的功能没有实现,一些该有的组件没有定义出来,所以仅供参考。如果您可以提出宝贵意见,我将感激不尽!

游戏窗口的界面设置及主函数入口:

public class SnakeDemo {
	public SnakeDemo() {
		JFrame frame = new JFrame("贪吃蛇demo1.0");
		frame.setBounds(0, 0, 550, 450);// 设置窗体的大小
		SnakeGame sn = new SnakeGame();
		frame.setLocationRelativeTo(null);
		sn.setFocusable(true);// 表示Component 是否可以获得焦点
		frame.add(sn);
		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		frame.setVisible(true);
		sn.requestFocus();
	}

	public static void main(String[] args) {
		new SnakeDemo();
	}
}

程序主体,包括蛇体的绘制、蛇体的链表存储、蛇体的移动控制、食物的随机出现等方法模块:

public class SnakeGame extends JPanel {
	private final int length = 20;// 定义活动范围
	private final int width = 20;// 定义活动范围
	private final int BLOCK_SIZE = 20;// 定义单位长度
	private int SnakeLength;// 定义蛇身的长度
	private int Scores;// 定义游戏得分
	private ArrayList<SnakeBody> snake = new ArrayList<>();// 定义蛇身的集合
	private int oldDirection;// 定义蛇头的方向
	private SnakeBody newFood = new SnakeBody(1, 1, Color.GREEN);// 定义随机点
	Timer time = new Timer(400, new ThingsListener());

	public SnakeGame() {// 初始化各项数据与方法
		snake.add(new SnakeBody(width / 2, length / 2, Color.red));
		snake.add(new SnakeBody(width / 2, length / 2 + 1, Color.BLUE));
		snake.add(new SnakeBody(width / 2, length / 2 + 2, Color.blue));
		oldDirection = 1;// 定义初始方向为向上
		SnakeLength = 3;// 蛇身长度为3
		createNewFood();// 产生随机点
		time.start();
		this.addKeyListener(new KeyAdapter() {// 捕捉键盘的按键事件
			public void keyPressed(KeyEvent e) {
				int newdirection = 0;// 定义一个按下按钮后要去的新方向
				switch (e.getKeyCode()) {
				case KeyEvent.VK_UP:// 按下向上,返回1
					newdirection = 1;
					break;
				case KeyEvent.VK_DOWN:// 按下向下,返回-1
					newdirection = -1;
					break;
				case KeyEvent.VK_LEFT:// 按下相左,返回2
					newdirection = 2;
					break;
				case KeyEvent.VK_RIGHT:// 按下向右,返回-2
					newdirection = -2;
					break;
				}
				if (newdirection + oldDirection != 0) {// 不能反向运动
					oldDirection = newdirection;
					Move(newdirection);// 按此方向移动
					repaint();// 重画
				}
			}
		});
	}

	/**
	 * 移动模块 定义蛇身移动的方法 同时判断蛇是否吃到食物或自己,是否撞墙
	 * 
	 * @param newdirection
	 */
	public void Move(int newdirection) {// 定义蛇身移动的方向
		int FirstX = snake.get(0).getX();// 获取蛇第一个点的X坐标
		int FirstY = snake.get(0).getY();// 获取蛇第一个点的Y坐标

		switch (newdirection) {
		case 1:
			FirstY--;
			break;
		case -1:
			FirstY++;
			break;
		case 2:
			FirstX--;
			break;
		case -2:
			FirstX++;
			break;
		default:
			break;
		}

		if (FirstX == newFood.getX() && FirstY == newFood.getY()) {// 当碰到随机点时
			eatFood();
			Scores += 5;
			return;
		}

		for (int x = 0; x < SnakeLength; x++) {// 当碰到蛇身自己时
			if ((FirstX == snake.get(x).getX()) && (FirstY == snake.get(x).getY())) {
				Dead("你吃到自己啦(\"▔□▔)");
			}
		}

		if (FirstX < 0 || FirstX > width - 1 || FirstY < 0 || FirstY > length - 1) {
			Dead("你撞墙了");
		}

		for (int x = SnakeLength - 1; x > 0; x--) {
			snake.get(x).setX(snake.get(x - 1).getX());
			snake.get(x).setY(snake.get(x - 1).getY());
		}
		snake.get(0).setX(FirstX);
		snake.get(0).setY(FirstY);
		repaint();
	}

	/**
	 * 吃食物模块
	 */
	public void eatFood() {
		snake.add(new SnakeBody());
		SnakeLength++;
		for (int x = SnakeLength - 1; x > 0; x--) {
			snake.get(x).setX(snake.get(x - 1).getX());
			snake.get(x).setY(snake.get(x - 1).getY());
			snake.get(x).setColor(snake.get(x - 1).getColor().BLUE);
		}
		snake.get(0).setX(newFood.getX());
		snake.get(0).setY(newFood.getY());
		createNewFood();
		repaint();

	}

	/**
	 * 游戏结束模块
	 */
	public void Dead(String s) {
		Date date = new Date();
		SimpleDateFormat sd = new SimpleDateFormat();
		String str2 = sd.format(date);
		String str = s + "\n" + "所以说游戏必须结束啦";
		System.out.println(Scores);
		JOptionPane.showMessageDialog(this, str2 + "\n" + str);

		System.exit(0);
	}

	/**
	 * 创造新的随机食物的方法
	 */
	public void createNewFood() {// 创造新的随机食物的方法
		int newX = 0;
		int newY = 0;
		Boolean flag = true;
		while (flag) {
			newX = new Random().nextInt(width);
			newY = new Random().nextInt(length);

			for (int i = 0; i < SnakeLength; i++) {
				if (snake.get(i).getX() == newX && snake.get(i).getY() == newY) {
					flag = true;
					break;
				}
				flag = false;
			}
		}

		newFood.setX(newX);
		newFood.setY(newY);
		this.setBackground(Color.WHITE);
	}

	/**
	 * 创建一个内部类,设置一个监听器事件
	 *
	 */
	class ThingsListener implements ActionListener {// 设置一个监听器事件
		public void actionPerformed(ActionEvent e) {
			Move(oldDirection);
			repaint();
		}
	}

	/**
	 * 设置窗口属性
	 */
	protected void paintComponent(Graphics g) {
		super.paintComponent(g);
		g.setColor(Color.gray);// 画出网格线,颜色为灰色
		for (int i = 1; i < width; i++) {
			g.drawLine(0, BLOCK_SIZE * i, length * BLOCK_SIZE, BLOCK_SIZE * i);
		}
		for (int i = 1; i < length; i++) {
			g.drawLine(BLOCK_SIZE * i, 0, BLOCK_SIZE * i, BLOCK_SIZE * width);
		}
		g.setColor(newFood.getColor().GREEN);
		g.fillOval(newFood.getX() * BLOCK_SIZE, newFood.getY() * BLOCK_SIZE, BLOCK_SIZE, BLOCK_SIZE);
		g.setColor(newFood.getColor().black);
		g.drawRect(0, 0, width * BLOCK_SIZE, length * BLOCK_SIZE);
		g.drawString("当前分数:" + Scores, 410, 20);
		g.drawString("当前蛇身长度:" + SnakeLength, 410, 40);

		for (int x = 0; x < SnakeLength; x++) { // 画出蛇体
			g.setColor(snake.get(x).getColor());
			g.fillOval(snake.get(x).getX() * BLOCK_SIZE, snake.get(x).getY() * BLOCK_SIZE, BLOCK_SIZE, BLOCK_SIZE);
		}
	}
}

蛇身集合中的各个元素点的定义:

package SnakeGame3;

import java.awt.Color;

public class SnakeBody {// 定义蛇身集合中的各个元素点
	private int x;
	private int y;
	private Color color;

	public SnakeBody() {
		super();

	}

	public SnakeBody(int x, int y, Color color) {
		super();
		this.x = x;
		this.y = y;
		this.color = color;
	}

	public int getX() {
		return x;
	}

	public void setX(int x) {
		this.x = x;
	}

	public int getY() {
		return y;
	}

	public void setY(int y) {
		this.y = y;
	}

	public Color getColor() {
		return color;
	}

	public void setColor(Color color) {
		this.color = color;
	}

}

此游戏有待改进……
继续努力、继续学习、继续敲代码……
这是一条不归路……

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Doctor_96

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值