初始化游戏界面:
蛇的长度为2,分数为0,用上下左右控制蛇的移动方向
每吃掉一个随机生成的食物后长度加1,分数加10
当蛇走出上下左右的边界或吃到自己的身体时游戏结束,再次按下空格键重新开始游戏
每段身体的节点类Node:
import java.util.Random;
//节点坐标
public class Node {
private int x;
private int y;
public Node(){
}
public Node(int x,int y){
this.x = x;
this.y = y;
}
//随机生成节点坐标
public void random(){
Random random = new Random();
this.x = random.nextInt(40)+2;//每个格子的位置,从2到42,像素为30到630
this.y = random.nextInt(40)+2;
}
public void setX(int x){
this.x = x;
}
public int getX(){
return this.x;
}
public void setY(int y){
this.y = y;
}
public int getY(){
return this.y;
}
}
初始化蛇类:
package 贪吃蛇.GameDemo02;
import java.util.LinkedList;
//蛇身
public class Snake {
//蛇的身体
private LinkedList<Node> body = new LinkedList<>();
//控制蛇头的方向
private String fx = "left";
//蛇是否活着
public static boolean isLiving = true;
//初始化蛇身长度为4及身体坐标位置
public Snake(){
body.add(new Node(16,20));
body.add(new Node(17,20));
}
//控制蛇的移动,先在蛇头方向的前面新加一个节点,然后在删除最后一个节点,循环调用实现蛇的动态移动
public void move(){
if (isLiving){//为true时蛇才移动
Node head = body.getFirst();//接收蛇头
if (fx.equals("up")){
body.addFirst(new Node(head.getX(),head.getY() - 1));//在蛇头的前面添加新节点
}
if (fx.equals("down")){
body.addFirst(new Node(head.getX(),head.getY() + 1));
}
if (fx.equals("left")){
body.addFirst(new Node(head.getX() - 1,head.getY()));
}
if (fx.equals("right")){
body.addFirst(new Node(head.getX() + 1,head.getY()));
}
body.removeLast();//删除最后一个节点
//判断蛇是否撞墙
head = body.getFirst();//蛇头
if (head.getX() < 0 || head.getX() >= 40 || head.getY() < 2 || head.getY() >= 42){
isLiving = false;
}
//判断蛇头是否碰到蛇尾
for (int i = 1; i < body.size(); i++){
Node node = body.get(i);
if (head.getX() == node.getX() && head.getY() == node.getY()){
isLiving = false;
}
}
}
}
public void setBody(LinkedList<Node> body){
this.body = body;
}
public LinkedList<Node> getBody(){
return this.body;
}
public void setFx(String fx){
this.fx = fx;
}
public String getFx(){
return this.fx;
}
public void eat() {
Node head = body.getFirst();//接收蛇头
if (fx.equals("up")){
body.addFirst(new Node(head.getX(),head.getY() - 1));//在蛇头的前面添加新节点
}
if (fx.equals("down")){
body.addFirst(new Node(head.getX(),head.getY() + 1));
}
if (fx.equals("left")){
body.addFirst(new Node(head.getX() - 1,head.getY()));
}
if (fx.equals("right")){
body.addFirst(new Node(head.getX() + 1,head.getY()));
}
}
}
游戏主类:
import javax.swing.*;
import java.awt.*;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.util.LinkedList;
import java.util.Timer;
import java.util.TimerTask;
public class MainJFrame {
JFrame frame = new JFrame("贪吃蛇");
private Snake snake;//蛇
JPanel p;//画板
LinkedList<Node> body;//存放蛇的所有节点
private Timer timer = new Timer();;//实现蛇移动的动态效果
boolean isStart = false;//游戏初始化暂停
private Node food;//食物
private int length = 2;
private int score = 0;//得分
public MainJFrame(){
initJFrame();//初始化窗体参数
initGameJPanel();//初始化游戏棋盘
init();//初始化蛇和食物
initTimer();//实现蛇移动的动态效果
frame.addKeyListener(listener);//按下键盘控制蛇移动的方向
}
//初始化蛇和食物
public void init(){
snake = new Snake();//初始化蛇
food = new Node();//初始化食物
food.random();
}
//键盘按键事件
KeyListener listener = new KeyAdapter() {
@Override
public void keyPressed(KeyEvent e) {
int keyCode = e.getKeyCode();
if (keyCode == 32){//空格键
if (!Snake.isLiving){
init();//重新开始游戏
Snake.isLiving = true;
}else{
isStart = !isStart;
}
}
if (snake.getFx().equals("up") || snake.getFx().equals("down")){//蛇头朝上或下时只能往左右移动
if (keyCode == KeyEvent.VK_LEFT){
snake.setFx("left");
}
if (keyCode == KeyEvent.VK_RIGHT){
snake.setFx("right");
}
}
if (snake.getFx().equals("left") || snake.getFx().equals("right")){//蛇头朝左或右时只能往上下左右移动
if (keyCode == KeyEvent.VK_UP){
snake.setFx("up");
}
if (keyCode == KeyEvent.VK_DOWN){
snake.setFx("down");
}
}
}
};
//初始化窗体参数
private void initJFrame(){
frame.setBounds(700,250,610,670);//窗体位置及大小
frame.setVisible(true);//窗体可见
frame.setResizable(false);//窗体大小不可变
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);//单击关闭
}
//初始化游戏棋盘
private void initGameJPanel(){
p = new JPanel(){
@Override
public void paint(Graphics g) {
if (!isStart){//游戏运行
g.setColor(Color.blue);
g.setFont(new Font("微软雅黑",Font.BOLD,40));
g.drawString("游戏暂停按空格键开始",100,300);
}
if (isStart){
g.clearRect(0,0,610,640);
//绘制蛇身
body = snake.getBody();//获取蛇的所有节点
for (Node node : body){
g.fillRect(node.getX() * 15,node.getY() * 15,15,15);
}
}
//绘制40条横线和竖线,每个格子为15*15的像素,窗体宽610高640
for (int i = 2; i <= 42; i++){
g.setColor(Color.black);
g.drawLine(0,i * 15,600,i * 15);
}
for (int i = 0; i <= 40; i++){
g.drawLine(i * 15,30,i * 15,630);
}
//绘制食物
g.setColor(Color.red);
g.fillRect(food.getX() * 15,food.getY() * 15,15,15);
if (Snake.isLiving == false){
g.setFont(new Font("微软雅黑",Font.BOLD,40));
g.drawString("蛇已死请按空格键重新开始游戏",25,300);
}
//绘制得分
g.setColor(Color.blue);
g.setFont(new Font("微软雅黑",Font.BOLD,25));
g.drawString("长度:"+length,200,25);
g.drawString("分数:"+score,300,25);
}
};
frame.add(p);//添加游戏棋盘
}
//实现蛇移动的动态效果
public void initTimer(){
//初始化定时任务
TimerTask timerTask = new TimerTask() {
@Override
public void run() {
if (isStart){
snake.move();//调用蛇的移动
//判断蛇是否与食物重合,吃食物身体变长
Node head = snake.getBody().getFirst();//获取蛇头
if (head.getX() == food.getX() && head.getY() == food.getY()){
snake.eat();
length++;
score += 10;
food.random();//吃完食物刷新食物
}
}
p.repaint();//重绘游戏界面
}
};
//每100毫秒执行一次定时任务
timer.scheduleAtFixedRate(timerTask,0,280);
}
public static void main(String[] args) {
new MainJFrame();//运行游戏
}
}