贪吃蛇(修改Ⅰ版)

修改:1、添加了菜单栏,并进行了监听

2、添加了通关的条件

3、添加了背景音乐(音频文件连接:http://yunpan.cn/cQjY4PzpkfSdz (提取码:2726))

4、美观了蛇身

class SnakeMain代码:

import java.applet.Applet;

import java.applet.AudioClip;

import java.awt.Color;

import java.awt.event.ActionEvent;

import java.awt.event.ActionListener;

import java.awt.event.MouseEvent;

import java.awt.event.MouseMotionListener;

import java.net.MalformedURLException;

import java.net.URL;

import javax.swing.JButton;

import javax.swing.JDialog;

import javax.swing.JFrame;

import javax.swing.JLabel;

import javax.swing.JMenu;

import javax.swing.JMenuBar;

import javax.swing.JMenuItem;

import javax.swing.JOptionPane;

import javax.swing.JPanel;

import javax.swing.JTextField;

public class SnakeMain extends JFrame implements ActionListener {

private static JLabel scoreLabel;

private JButton  stop,start;

static SnakeModel snake;

AudioClip snakeSong;

public static void main(String[] args) {

new SnakeMain();

}

public SnakeMain() {

super("贪吃蛇");

this.setBounds(300, 100, 400, 400);

this.setDefaultCloseOperation(EXIT_ON_CLOSE);

this.setResizable(false);

this.getContentPane().setBackground(Color.white);

JPanel p = new JPanel();

this.getContentPane().add(p, "North");

p.setBackground(Color.WHITE);

scoreLabel=new JLabel();

scoreLabel.setText("score:"+0);

stop = new JButton("stop");

start = new JButton("start");

//添加菜单

JMenuBar menuBar=new JMenuBar();

setJMenuBar(menuBar);

JMenu menuGame=new JMenu("GAMES");

menuBar.add(menuGame);

JMenuItem newGames=new JMenuItem("New");

JMenuItem JStop=new JMenuItem("Stop");

JMenuItem GoOn=new JMenuItem("GoOn");

JMenuItem Exit=new JMenuItem("Exit");

menuGame.add(newGames);

menuGame.insertSeparator(1);

menuGame.add(JStop);

menuGame.insertSeparator(10);

menuGame.add(GoOn);

menuGame.insertSeparator(20);

menuGame.add(Exit);

JMenu menuHlep=new JMenu("HELP");

menuBar.add(menuHlep);

JMenuItem regarding=new JMenuItem("Regarding");

menuHlep.add(regarding);

//添加音乐

new Thread(new Runnable() {

@Override

public void run() {

try {

snakeSong=Applet.newAudioClip(new URL("file:" + "image/snakeSongs/song1.wav"));

snakeSong.loop();

snakeSong.play();

} catch (MalformedURLException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

}

}).start();

// 让这些组件丢失焦点

// scoreField.setFocusable(false);

stop.setFocusable(false);

start.setFocusable(false);

//添加组件到面板p

p.add(scoreLabel);

p.add(stop);

p.add(start);

snake = new SnakeModel(400);// 500为刷新时间

this.getContentPane().add(snake); // 把蛇加入到面板中 (蛇的运行范围:0<=x<=380

// 0<=y<=330)

Control control = new Control(snake); // 控制蛇

// 进行监听

stop.addActionListener(this);

start.addActionListener(this);

this.addKeyListener(control);

//菜单项加监听

newGames.addActionListener(this);

JStop.addActionListener(this);

GoOn.addActionListener(this);

Exit.addActionListener(this);

regarding.addActionListener(this);

// 显示

this.setVisible(true);

}

public static void re() { // 刷新分数框

scoreLabel.setText("score:" + SnakeModel.getScore());

if(SnakeModel.getScore()==100){

SnakeModel.stop();

int a=JOptionPane.showConfirmDialog(null, "Restart or Exit?!","Congratulations to patience!!!",  JOptionPane.YES_NO_OPTION);

if(a==JOptionPane.OK_OPTION){

snake.reStart();

}else{

System.exit(0);

}

}

}

public static  void gameOver() {// 游戏结束

// JOptionPane.showMessageDialog(null, "Game Over!!!ReStart?Please press R");

int a=JOptionPane.showConfirmDialog(null, "Restart or Exit?!", "Game Over!!!", JOptionPane.YES_NO_OPTION);

if(a==JOptionPane.OK_OPTION){

snake.reStart();

}else{

System.exit(0);

}

}

@Override

public void actionPerformed(ActionEvent e) {

if (e.getSource() == stop||e.getActionCommand().equals("Stop")) {

SnakeModel.stop();

}

if (e.getSource() == start||e.getActionCommand().equals("GoOn")) {

SnakeModel.start();

}

if(e.getActionCommand().equals("New")){

snake.reStart();

}

if(e.getActionCommand().equals("Exit")){

System.exit(0);

}

if(e.getActionCommand().equals("Regarding")){

JOptionPane.showConfirmDialog(null," BlogID:http://blog.csdn.net/xionghui2013 ","The APP", JOptionPane.YES_OPTION);

}

}

}

class SnakeModel 代码:

import java.awt.Canvas;

import java.awt.Color;

import java.awt.Graphics;

import java.awt.event.ActionEvent;

import java.awt.event.ActionListener;

import java.util.Random;

import javax.swing.Timer;

import cn.hncu.xh.Snake.snakePoint.point;

/*

* 思路: 利用动态数组装蛇模型,蛇身的点都只跟着蛇头(即:数组的第一个元素)动,

*     每 repaint()一次,就把动态数组里面的蛇全部数出来。

*     每吃一个食物时,就添加在蛇头,蛇头往后移动一步,然后蛇身跟着移动。

* 注意:在蛇吃到食物时,要避免捆绑!!!

*/

public class SnakeModel extends Canvas implements ActionListener {

private snakePoint[] snakePoint; // 装蛇的数组

private static Timer timer; // 定时器

private static int score = 0; // 分数

private int Dx, Dy;// 蛇头所在坐标

private int Px, Py; // 食物的坐标

static final int LEFT = 1;

static final int UP = 2;

static final int DOWN = 4;

static final int RIGHT = 3;

int direction = 4; // 初始方向为向下移动

boolean isFrist = true; // 控制第一个食物的位置

boolean isOne = true; // 控制每次刷新一次蛇只能按一次键盘

boolean food; // 控制没吃到一个食物才去刷新食物的坐标

public SnakeModel(int delay) {// 构造蛇模型

this.snakePoint = new snakePoint[600]; // 用来装蛇头

snakePoint[1] = new snakePoint(100, 100);// 画蛇头

// 使用定时器

timer = new Timer(delay, this);

}

public static int getScore() { // 获取分数

return score;

}

class snakePoint { // 蛇身(每条蛇由很多蛇身构成)

int x, y;

public snakePoint(int x, int y) {

this.x = x;

this.y = y;

}

snakePoint(snakePoint p) {

this.x = p.x;

this.y = p.y;

}

}

@Override

public void paint(Graphics g) {

// 食物

creatFood();

// 每走一次就让数组自动移动一次

if (score != 0) {

for (int i = score + 2; i > 1; i--) {

snakePoint[i] = new snakePoint(snakePoint[i - 1]);

}

}

switch (direction) {// 判断蛇头的走向

case UP:

snakePoint[1].y -= 10;

break;

case DOWN:

snakePoint[1].y += 10;

break;

case LEFT:

snakePoint[1].x -= 10;

break;

case RIGHT:

snakePoint[1].x += 10;

break;

}

// 吃到了食物

// 要考虑食物的坐标不可能与蛇头坐标重合

if (snakePoint[1].x <= Px + 7 && snakePoint[1].x >= Px - 5

&& snakePoint[1].y <= Py + 7 && snakePoint[1].y >= Py - 5) {

score++; // 分数加一

food = true; // 刷新食物

SnakeMain.re(); // 刷新分数

timer.setDelay((timer.getDelay() - 4) <= 0 ? 20

: timer.getDelay() - 4); // 每次吃到食物后就会加速蛇的移动速度

// System.out.println(timer.getDelay());

// 吃掉一个食物后,在蛇头增加一个长度

for (int j = score + 1; j > 1; j--) {

snakePoint[j] = new snakePoint(snakePoint[j - 1]);

}

// 让蛇头往移动方向走一步

switch (direction) {// 判断蛇头的走向

case UP:

this.snakePoint[1].y -= 10;

break;

case DOWN:

this.snakePoint[1].y += 10;

break;

case LEFT:

this.snakePoint[1].x -= 10;

break;

case RIGHT:

this.snakePoint[1].x += 10;

break;

}

}

g.setColor(Color.RED);// 食物为红色

g.fill3DRect(Px, Py, 10, 10,true);// 画食物

g.setColor(Color.black);

g.draw3DRect(Px, Py, 10, 10,true);

// 画蛇,把蛇从数组中画出来

for (int i = 1; i <= score + 1; i++) {

g.setColor(Color.GREEN);

g.fill3DRect(snakePoint[i].x, snakePoint[i].y, 10, 10, true);

g.setColor(Color.blue);

g.draw3DRect(snakePoint[i].x, snakePoint[i].y, 10, 10, true);

// g.fillRect(snakePoint[i].x, snakePoint[i].y, 10, 10);

}

}

private void creatFood() {

if (isFrist) {

Px = legal(380);// 获得合法的x值,

Py = legal(300);// 获得合法的y值,即与x组合成食物坐标后不在蛇身上

isFrist = false;

return;

}

// 下一个食物坐标

if (food) {

Px = legal(380);// 同上

Py = legal(300);

food = false;

}

// System.out.println(Px);

// System.out.println(Py);

}

private int legal(int i) {

Random r = new Random(); // 生成随机数

if (i == 380) { // 生成食物的y坐标

while (true) {

int n = (r.nextInt(37) + 1) * 10;

for (int j = 1; j <= score + 1; j++) { // 每次都要与蛇身进行匹配,避免食物出现在蛇身上;下同

if (snakePoint[j].x != n && j == (score + 1)) {

return n;

}

}

}

}

if (i == 300) { // 生成食物的x坐标

while (true) {

int n = (r.nextInt(29) + 1) * 10;

for (int j = 1; j <= score + 1; j++) {

if (snakePoint[j].y != n && j == (score + 1)) {

return n;

}

}

}

}

return 0;

}

@Override

public void actionPerformed(ActionEvent e) {

isOver();// 判断是否结束游戏

repaint();

isOne = true;

// System.out.println(snakePoint[1].x+"  "+snakePoint[1].y);

}

private void isOver() {

if (isCondition()) {// isCondition()//判断是否结束的所有条件放在里面

timer.stop();

SnakeMain.gameOver(); // 游戏结束,弹出对话框

}

}

private boolean isCondition() { // 游戏结束的条件

// 出界(撞墙)

if (snakePoint[1].x <= 0 || snakePoint[1].x >= 380

|| snakePoint[1].y <= 0 || snakePoint[1].y >= 300) {

return true;

}

// 蛇头吃到蛇身了

for (int i = 2; i <= score + 1; i++) {

if (snakePoint[1].x == snakePoint[i].x

&& snakePoint[1].y == snakePoint[i].y) {

return true;

}

}

return false;

}

public void changeDirection(int newDirection) { // 改变方向

if (direction % 2 != newDirection % 2 && isOne) {// 改变的方向不能与原来的方向相同或相反

direction = newDirection;

isOne = false;

}

}

public static void stop() {

timer.stop();

}

public static void start() {

timer.start();

}

// 重置所有的数据

public void reStart() {

score = 0;

SnakeMain.re();

direction = 4;

isFrist = true;

isOne = true;

food = false;

// snakePoint=null;

snakePoint[1].x = 100;

snakePoint[1].y = 100;

creatFood();

}

}

class Control代码:

import java.awt.event.KeyEvent;

import java.awt.event.KeyListener;

public class Control implements KeyListener {  //对键盘进行监听

SnakeModel snake=null;

public Control(SnakeModel snake) {

this.snake=snake;

}

@Override

public void keyPressed(KeyEvent e) {

if(e.getKeyCode()==KeyEvent.VK_UP){

snake.changeDirection(SnakeModel.UP);

}

if(e.getKeyCode()==KeyEvent.VK_DOWN){  //监听按键↓,向下移动

snake.changeDirection(SnakeModel.DOWN);

}

if(e.getKeyCode()==KeyEvent.VK_LEFT){  //监听按键←,向左移动

snake.changeDirection(SnakeModel.LEFT);

}

if(e.getKeyCode()==KeyEvent.VK_RIGHT){    //监听按键↑,向上移动

snake.changeDirection(SnakeModel.RIGHT);

}

if(e.getKeyCode()==KeyEvent.VK_RIGHT){   //监听按键→,向右移动

snake.changeDirection(SnakeModel.RIGHT);

}

// if(e.getKeyCode()==KeyEvent.VK_R){//监听按键R,重置

// snake.reStart();

// }

}

@Override

public void keyTyped(KeyEvent e) {
}

@Override

public void keyReleased(KeyEvent e) {}

}

时间: 2024-11-06 20:43:13

贪吃蛇(修改Ⅰ版)的相关文章

原生js写的贪吃蛇网页版游戏

<html> <head> <meta http-equiv="Content-Type" content="text/html; charset=gb2312" /> <title>原生js写的贪吃蛇网页版游戏</title> </head> <body><div><A href="http://www.999jiujiu.com/">h

c/c++ 贪吃蛇控制台版

贪吃蛇控制台版(操作系统win7 64位:编译环境gcc, vs2017通过,其它环境未测试 不保证一定通过) 运行效果: #include <iomanip> #include <windows.h> #include <conio.h> using namespace std; HANDLE hOut = GetStdHandle(STD_OUTPUT_HANDLE);//全局句柄 class snake; void Init_Console();//控制台初始化

贪吃蛇 android版 里面自己实现了简单的事件系统

游戏预览 游戏是用SurfaceView开发的 流畅 和体验还是挺好 CanvasState 游戏的主要业务类 package bill; import java.util.ArrayList; import java.util.Collections; import java.util.EventListener; import java.util.EventListenerProxy; import java.util.HashMap; import java.util.Iterator;

Java版贪吃蛇(比较完善的版本)

很认真的写的一个java版的贪吃蛇游戏,图形界面,支持菜单操作,键盘监听,可加速,减速,统计得分,设定运动速度,设定游戏背景颜色等!应该没有Bug了,因为全被我修改没了.哈哈. 下面是项目各包及类的层次关系: 游戏的主要运行界面截图如下: 下面是部分代码,详细源码见此链接:http://pan.baidu.com/s/1bnubnzh //Snake类: package com.huowolf.entities; import java.awt.Color; import java.awt.Gr

Qt版贪吃蛇游戏

Qt版贪吃蛇游戏 转载请标明出处:牟尼的专栏 http://blog.csdn.net/u012027907 最近在学习Qt,用了一个多月的时间掌握了Qt中最基本的知识,也完成了<Qt版音乐播放器>.<Qt版贪吃蛇游戏>.<Qt版双人俄罗斯方块>以及<Qt版科学计算器>等,之前在VC下写过这些程序,所以在Qt下只是改变了显示等语句,我写过<C++版贪吃蛇游戏>.<VC版贪吃蛇游戏>,当时将与显示等无关的东西封装起来,在Qt下直接用,只

Java版贪吃蛇小游戏的实现

使用的IDE eclipse JDK版本 1.6 辅助类 Coordinate.java package com.nn.util; /** *坐标点 */ public class Coordinate { public int x; public int y; public Coordinate(int newX, int newY) { x = newX; y = newY; } public boolean equals(Coordinate other) { if (x == other

控制台小游戏-贪吃蛇,c++和c#版

说是c++版,其实只是用到了c++的cout和cin而已.这是我做的第二个控制台游戏,基本上每一行代码都加上了注释. 游戏嘛,我觉得重要的是了解他的思想,所以后期学了面向对象之后这个游戏的代码我也没有重新封装. 下面请看图 代码如下:我是用dev c++写的 1 //注释. ---星辰 2 3 #include <iostream> 4 #include<Windows.h> 5 #include<ctime> 6 #include<cstdlib> 7 #

OC版贪吃蛇

昨天写了一个js版贪吃蛇,今天突然想写一个OC版的,来对比一下两种语言的区别 oc版功能,适配所有尺寸iphone,可暂停,可设置地图和蛇的比例,可加速 对比一下会发现js版的相对OC版的会简单一些,有想看js版的可以看我上一篇随笔 程序中没用到任何素材,效果图如下: github源码地址:https://github.com/masterChunlinHan/snake_OC 下面开始,跟js版一样,为了方便学习,所有代码都写在一个controller中,所以头文件中什么也不用写 #impor

假期休闲,来发贪吃蛇!(Win32控制台版)

假期无事,整理电脑文件的时候发现了以前大二时做的坦克小游戏,心血来潮,决定再来一发贪吃蛇. 游戏玩法不必多说,主要是算法实现和绘制过程. 首先,利用一个二维数组 mp[][] 来存储地图信息,其中的值表示: 0:空 1:被蛇覆盖 2:食物 有了这个地图数组,生成随机食物的时候就可以避免生成到蛇身上. 那蛇的身体如何存储呢?也很简单,用队列(存储每一个小格的坐标信息). 队列的头尾方向与蛇的头尾方向正好相反. 蛇每走一步,在蛇头方向的下一位置画一个小方格,同时把该位置放置到队列尾端.取出队列第一个