Java贪吃蛇游戏(坐标方法)

最近研究一个大大的贪吃蛇代码,自己开始试着写了写,已经对贪吃蛇的移动及规则方面的算法了解,主要是绘图方面有很大的困难,因为贪吃蛇的代码中将蛇的身体定义成多个坐标点,所以在绘图的过程中就必须要把这样的点给放大,与此同时蛇的移动范围又要在panel面板尺寸的基础上进行缩小,这样才使得游戏中设的移动不出问题。废话不说,上代码.楼主实力有限,本想添加背景音乐并且利用图片来修改蛇的身体和食物,结果没有成功,只是用圆形替代食物。

Snake.java

import java.util.*;
import javax.swing.*;
public class Snake {
int len,wid;
static int up=1;
static int down=3;
static int left=2;
static int right=4;
int direction=4;
LinkedList snakeList = new LinkedList();
Node food;
Snakepanel pane;
boolean al[][];
static boolean run=true;
public Snake(Snakepanel pane,int x,int y)
{
len=x;
wid=y;
this.pane=pane;
al=new boolean[x][y];
for(int i=0;i<x;i++)
{
for(int j=0;j<y;j++)
al[i][j]=false;
}//设定边界,除蛇身以及食物以外的地方布尔值为false,
int length = len > 20 ? 10 : len / 2;//蛇身的初始长度
for(int i=0;i<length;i++)
{
int a=x/10+i;
int b=y/10;//设置了蛇头的朝向
snakeList.addFirst(new Node(a,b));//设置蛇身,蛇头朝右方向
}
food=createfood();
al[food.x][food.y]=true;//food及蛇身的bool值设成true,其余的为false
};
public void move(){
Node n=(Node)snakeList.getFirst();
int x=n.x;
int y=n.y;
if(direction==4)
x++;
if(direction==2)
x--;
if(direction==3)
y++;
if(direction==1)
y--;
if((0<=x&&x<=pane.len/15-1)&&(0<=y&&y<=pane.wid/15-2))//判断是否在蛇移动的范围内,这里wid/15-2是因为初始化panel面板时,因大小范围产生点误差,造成蛇与边界还有一点距离时提示越界,因此做了调整

{
if(al[x][y])
{
if(x==food.x&&y==food.y)
{
snakeList.addFirst(food);//吃到食物时,蛇向头部添加食物的座标点,增长蛇身
food =createfood();//重新产生食物
al[food.x][food.y] = true;//食物bool值重设为true
}
else 
{
JOptionPane.showMessageDialog(null, "GameOver");
System.exit(0);//蛇撞到自身
}
}
else 
{
snakeList.addFirst(new Node(x,y));
al[x][y]=true;
Node l=(Node)snakeList.getLast();
snakeList.removeLast();
al[l.x][l.y]=false;//蛇身移动,队头增加,队尾删除
}
}
else
{
JOptionPane.showMessageDialog(null, "GameOver");
System.exit(0);
}
pane.repaint();//重绘组件,也就是在应用中蛇能移动的原理
}
public Node createfood()
{
int x=0,y=0;
do {
Random r = new Random();
x = r.nextInt(len-10);
y = r.nextInt(wid-10);//食物产生的范围是,左上角坐标原点~(蛇移动的范围横坐标-10,蛇移动的范围横纵坐标-10)


} while (al[x][y]);//排除食物产生在蛇身的可能
return new Node(x, y);
}
public void changeDirection(int newdirection)
{
if(direction%2!=newdirection%2)
{
direction=newdirection;
}//保证蛇不能回头
}

}


Node.java

public class Node {
int x,y;
public Node(int x,int y)
{
this.x=x;
this.y=y;

}
}//整个界面是由点组成的


Snakepanel.java

import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.util.*;
public class Snakepanel extends JPanel implements KeyListener {//键盘事件接口
int len=400;
int wid=500;//面板大小
int rectx=15;
int recty=15;//倍数设置
int count=1;
Snake snake;
Node n;
public Snakepanel()
{
snake=new Snake(this,len/rectx,wid/recty);//蛇的实例化,并且蛇移动范围设置为面板大小的15分之一倍
setBackground(Color.BLACK);//面板背景设为黑色
setSize(len,wid);
setFocusable(true);//设置焦点
addKeyListener(this);//添加键盘事件
}
public void paintComponent(Graphics g) {
super.paintComponent(g);//打印容器中每个组件
LinkedList list = snake.snakeList;
Iterator it = list.iterator();//创建迭代器对象
g.setColor(Color.white);//Graphics g设置颜色为白色
while (it.hasNext()) {
n = (Node) it.next();//迭代器访问线性表元素
drawNode(g, n);//调用迭代器并绘制蛇身颜色
}
g.setColor(Color.WHITE);
Node f = snake.food;
drawCircle(g, f);//绘制食物颜色,修改成圆形
}
public void keyPressed(KeyEvent e) {//实现键盘事件接口
int keycode = e.getKeyCode();
if (keycode == KeyEvent.VK_ENTER) {
begin();
} else if (keycode == KeyEvent.VK_UP) {
snake.changeDirection(Snake.up);
} else if (keycode == KeyEvent.VK_DOWN) {
snake.changeDirection(Snake.down);
} else if (keycode == KeyEvent.VK_LEFT) {
snake.changeDirection(Snake.left);
} else if (keycode == KeyEvent.VK_RIGHT) {
snake.changeDirection(Snake.right);

}


public void keyReleased(KeyEvent e) {
}


public void keyTyped(KeyEvent e) {
}//上述两种方法不需要实现,但必须空处理


public void drawNode(Graphics g, Node n) {
g.fillRect(n.x*rectx , n.y*recty , rectx-2, recty-2);
}//定义绘制方法

public void drawCircle(Graphics g, Node n) {
g.fillArc(n.x*rectx , n.y*recty , rectx-2, recty-2,0,360);
}
public void begin() {
if(count==1)
{
Snake.run = true;
SnakeThread thread = new SnakeThread(snake);
thread.start();
count++;
}//调用线程实现蛇体移动,已经修正按回车加速的BUG
}
}



SnakeThread.java
public class SnakeThread extends Thread {//创建使蛇移动的线程
Snake snake;


public SnakeThread(Snake s) {
snake = s;
}


public void run() {
Snake.run = true;


while (Snake.run) {
try {
snake.move();
sleep(150);//休眠时间,影响游戏速度
} catch (InterruptedException e) {
}
}
}
}

Snakeframe.java

import javax.swing.*;
import java.awt.*;
public class Snakeframe extends JFrame{
public Snakeframe() {
setSize(400, 505);//窗口大小设置
setTitle("贪吃蛇");
this.setLocation(360, 150);//窗口位置设置
Snakepanel panel = new Snakepanel();
add(panel, BorderLayout.CENTER);
}
}

Play.java

import javax.swing.*;
public class Play {
public static void main(String args[]) {
Snakeframe frame = new Snakeframe();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setResizable(false);//窗口是否可以改变大小
frame.setVisible(true);//显示窗口
JOptionPane.showMessageDialog(null, "回车键开始\n上,下,左,右控制蛇的方向");
}
}



  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值