import javax.swing.JFrame;
public class Snake{
public static void main(String[] args){
//画出900*720的白色窗口
JFrame frame =new JFrame("沈思嘉的贪吃独角兽");
frame.setBounds(300,0,900,740);//窗体大小
frame.setResizable(false);//固定窗体,大小不可调整
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);//退出
//添加画布
SnakePanel panel=new SnakePanel();
frame.add(panel);
frame.setVisible(true);//显示窗体
}
}
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Random;
import javax.swing.ImageIcon;
import javax.swing.JPanel;
import javax.swing.Timer;
public class SnakePanel extends JPanel implements KeyListener,ActionListener{
//加载所有图片
ImageIcon title=new ImageIcon("title.png");
ImageIcon up=new ImageIcon("up1.png");
ImageIcon down=new ImageIcon("down1.png");
ImageIcon left=new ImageIcon("left2.png");
ImageIcon right=new ImageIcon("right2.png");
ImageIcon love=new ImageIcon("love.png");
ImageIcon food=new ImageIcon("food.png");
//游戏分数
int score=0;
//蛇身体的长度
int length=3;
//蛇头的方向
String direction="R";
//放蛇的数组
int[] snakex=new int[750];
int[] snakey=new int[750];
//随机产生食物
Random r=new Random();
int foodx=r.nextInt(34)*25+25;
int foody=r.nextInt(24)*25+75;
//游戏开始 关系到后面的空格键时间以及Timers是否开始
boolean isStarted=false;
//游戏结束 即蛇头是否撞到自己身体
boolean isEnded=false;
//蛇移动的原理就是不断的重画 重画的频率有timer控制,时间是毫秒
Timer timer=new Timer(200,this);//控制蛇的移动速度
public SnakePanel(){//构造函数,即给类初始化 即运行工程后的初始状态
setup();//重置 初始化
this.setFocusable(true);//选中焦点,即对画布上的按钮起作用
this.addKeyListener(this);//键盘监听 即按键盘的时候程序有反应
timer.start();//Timer类的启动,相当于定闹钟,然后工程开始repaint蛇才能运动
}
public void setup(){
direction="R";//向右为默认方向
length=3;
score=0;
snakex[0]=101;
snakey[0]=101;
snakex[1]=76;
snakey[1]=101;
snakex[2]=51;
snakey[2]=101;
isStarted=false;
isEnded=false;
}
public void paint(Graphics g){//此函数相当于一支画笔,在panel画布上或各种东西(蛇 事物 文字)
//贴图片上去,1。加载图片,2.贴上去
title.paintIcon(this,g,25,10);//贴照片
g.setColor(Color.PINK);//画笔颜色
g.fillRect(25,75,850,625);//填充指定的矩形
g.setColor(Color.BLACK);//重新定义画笔颜色
//横线
int i=75;
while(i<=700){
g.drawLine(25,i,875,i);//划线,坐标从哪到哪
i=i+25;
}
//竖线
int j=25;
while(j<=875){
g.drawLine(j,75,j,700);
j=j+25;
}
//贴独角兽头
if(direction.equals("R")){//键盘监听后对独角兽方向的判断后 在这里画出
right.paintIcon(this,g,snakex[0],snakey[0]);
}else if(direction.equals("L")){
left.paintIcon(this,g,snakex[0],snakey[0]);
}else if(direction.equals("U")){
up.paintIcon(this,g,snakex[0],snakey[0]);
}else if(direction.equals("D")){
down.paintIcon(this,g,snakex[0],snakey[0]);
}
//贴爱心
for(int m=1;m<length;m++){
love.paintIcon(this,g,snakex[m],snakey[m]);
}
//贴食物
food.paintIcon(this,g,foodx,foody);
//画开始提示语
if(!isStarted){//数据结构体判读出没开始 就在这画出下面的东西
g.setFont(new Font("arial",Font.BOLD,30));//设置画笔的字体
g.drawString("Press Space to Start/Pause",200,300);//画出文字
}
//游戏结束提示语
if(isEnded){
g.setFont(new Font("arial",Font.BOLD,30));//设置画笔的字体
g.drawString("Game Over!/Press Space to Start",200,300);
}
//游戏分数
g.setColor(Color.WHITE);
g.setFont(new Font("arial",Font.BOLD,15));
g.drawString("Score:"+score,700,25);
g.drawString("Length:"+length,700,50);
//repaint();//画板刷新
}
//这三个函数是在实现keyListener类时生成的函数 作用是监听键盘 我们是需要用第二个 即键盘按下时的反映
public void keyTyped(KeyEvent e){
}
public void keyReleased(KeyEvent e){
}
public void keyPressed(KeyEvent e){//键盘按下时 工程需要的操作
int keyCode=e.getKeyCode();//获取按键的keyCode值 每个键有不同的值
//if(keyCode==KeyEvent.VK_SPACE){//判断按键是否是空格键 VK_SPACE就是空格键默认的值
// isStarted=!isStarted;
//}
if(keyCode==KeyEvent.VK_SPACE){//判断按键是否是空格键 VK_SPACE就是空格键默认的值
if(isEnded){//如果是空格键且游戏结束了 就调用这个函数重置初始化 isEnded是false,首先就不会写出来,如果变为真则输出游戏结
束语句,如果是空格且结束为真则再继续调用重置函数,再进行进行,那么这个什么时候变为真,吃到自己的时候
setup();
//length=3;
}
else{
isStarted=!isStarted;
}
}
if(isStarted==true){
if(keyCode==40&&direction!="U"){//独角兽运动的时候不能向上一个状态的反方向运动,例如,原先向右,下一次改变的方向不能为左
。
direction="D";
}
else if(keyCode==39&&direction!="L"){
direction="R";
}
else if(keyCode==37&&direction!="R"){
direction="L";
}
else if(keyCode==38&&direction!="D"){
direction="U";
}
}
}
public void actionPerformed(ActionEvent e){//这个函数是在实现ActionListener类生成的功能,当事件发生时才调用
//定制一个闹钟,时间开始时是以闹钟响起时才开始,即paint();
//timer.start();//但我试了一下并没什么用
//身体
if(isStarted && !isEnded){
if(isStarted){
for(int m=length;m>0;m--){
snakex[m]=snakex[m-1];
snakey[m]=snakey[m-1];
}
}
//独角兽的变化
if(direction.equals("R")){
snakex[0]=snakex[0]+25;//如果等于851时直接执行了下面的语句下面的坐标为26了再运行上面贴图标的即坐标为了26图标就
在26那个位置贴了没有贴到850那个坐标上面
if(snakex[0]>851)
snakex[0]=26;
}
if(direction.equals("L")){
snakex[0]=snakex[0]-25;
if(snakex[0]<26)
snakex[0]=851;
}
if(direction.equals("U")){
snakey[0]=snakey[0]-25;
if(snakey[0]<76)
snakey[0]=676;
}
if(direction.equals("D")){
snakey[0]=snakey[0]+25;
if(snakey[0]>676)
snakey[0]=76;
}
//当独角兽吃到食物时
if(snakex[0]==foodx+1 && snakey[0]==foody+1){
length++;
score++;
foodx=r.nextInt(34)*25+25;
foody=r.nextInt(24)*25+75;
}
for(int m=1;m<length;m++){
if(snakex[0]==snakex[m]&&snakey[0]==snakey[m]){
isEnded=true;
}
}
for(int m=1;m<length;m++){
if(snakex[0]==foodx+1 && snakey[0]==foody+1){
foodx=r.nextInt(34)*25+25;
foody=r.nextInt(24)*25+75;
}
}
}
//重画
repaint();
}
}
暑假期间完成的贪吃独角兽
最新推荐文章于 2024-10-01 18:51:18 发布