J2ME貪吃蛇源代碼——200行左右,包含詳細(xì)注釋 package snake;import javax.microedition.midlet.*;
創(chuàng)新互聯(lián)公司專業(yè)IDC數(shù)據(jù)服務(wù)器托管提供商,專業(yè)提供成都服務(wù)器托管,服務(wù)器租用,達(dá)州主機(jī)托管,達(dá)州主機(jī)托管,成都多線服務(wù)器托管等服務(wù)器托管服務(wù)。
import javax.microedition.lcdui.*;public class SnakeMIDlet extends MIDlet {
SnakeCanvas displayable = new SnakeCanvas();
public SnakeMIDlet() {
Display.getDisplay(this).setCurrent(displayable);
}public void startApp() {}public void pauseApp() {}public void destroyApp(boolean unconditional) {}}//文件名:SnakeCanvas.javapackage snake;import java.util.*;
import javax.microedition.lcdui.*;/**
* 貪吃蛇游戲
*/
public class SnakeCanvas extends Canvas implements Runnable{
/**存儲(chǔ)貪吃蛇節(jié)點(diǎn)坐標(biāo),其中第二維下標(biāo)為0的代表x坐標(biāo),第二維下標(biāo)是1的代表y坐標(biāo)*/
int[][] snake = new int[200][2];
/**已經(jīng)使用的節(jié)點(diǎn)數(shù)量*/
int snakeNum;
/**貪吃蛇運(yùn)動(dòng)方向,0代表向上,1代表向下,2代表向左,3代表向右*/
int direction;
/*移動(dòng)方向*/
/**向上*/
private final int DIRECTION_UP = 0;
/**向下*/
private final int DIRECTION_DOWN = 1;
/**向左*/
private final int DIRECTION_LEFT = 2;
/**向右*/
private final int DIRECTION_RIGHT = 3;/**游戲區(qū)域?qū)挾?/
int width;
/**游戲區(qū)域高度*/
int height;/**蛇身單元寬度*/
private final byte SNAKEWIDTH = 4;/**是否處于暫停狀態(tài),true代表暫停*/
boolean isPaused = false;
/**是否處于運(yùn)行狀態(tài),true代表運(yùn)行*/
boolean isRun = true;/**時(shí)間間隔*/
private final int SLEEP_TIME = 300;
/**食物的X坐標(biāo)*/
int foodX;
/**食物的Y坐標(biāo)*/
int foodY;
/**食物的閃爍控制*/
boolean b = true;
/**Random對(duì)象*/
Random random = new Random();
public SnakeCanvas() {
//初始化
init();
width = this.getWidth();
height = this.getHeight();
//啟動(dòng)線程
new Thread(this).start();
}/**
* 初始化開始數(shù)據(jù)
*/
private void init(){
//初始化節(jié)點(diǎn)數(shù)量
snakeNum = 7;
//初始化節(jié)點(diǎn)數(shù)據(jù)
for(int i = 0;i snakeNum;i++){
snake[i][0] = 100 - SNAKEWIDTH * i;
snake[i][1] = 40;
}
//初始化移動(dòng)方向
direction = DIRECTION_RIGHT;
//初始化食物坐標(biāo)
foodX = 100;
foodY = 100;
}protected void paint(Graphics g) {
//清屏
g.setColor(0xffffff);
g.fillRect(0,0,width,height);
g.setColor(0);//繪制蛇身
for(int i = 0;i snakeNum;i++){
g.fillRect(snake[i][0],snake[i][1],SNAKEWIDTH,SNAKEWIDTH);
}
//繪制食物
if(b){
g.fillRect(foodX,foodY,SNAKEWIDTH,SNAKEWIDTH);
}
}private void move(int direction){
//蛇身移動(dòng)
for(int i = snakeNum - 1;i 0;i--){
snake[i][0] = snake[i - 1][0];
snake[i][1] = snake[i - 1][1];
}//第一個(gè)單元格移動(dòng)
switch(direction){
case DIRECTION_UP:
snake[0][1] = snake[0][1] - SNAKEWIDTH;
break;
case DIRECTION_DOWN:
snake[0][1] = snake[0][1] + SNAKEWIDTH;
break;
case DIRECTION_LEFT:
snake[0][0] = snake[0][0] - SNAKEWIDTH;
break;
case DIRECTION_RIGHT:
snake[0][0] = snake[0][0] + SNAKEWIDTH;
break;
}
}
/**
* 吃掉食物,自身增長(zhǎng)
*/
private void eatFood(){
//判別蛇頭是否和食物重疊
if(snake[0][0] == foodX snake[0][1] == foodY){
snakeNum++;
generateFood();
}
}
/**
* 產(chǎn)生食物
* 說(shuō)明:食物的坐標(biāo)必須位于屏幕內(nèi),且不能和蛇身重合
*/
private void generateFood(){
while(true){
foodX = Math.abs(random.nextInt() % (width - SNAKEWIDTH + 1))
/ SNAKEWIDTH * SNAKEWIDTH;
foodY = Math.abs(random.nextInt() % (height - SNAKEWIDTH + 1))
/ SNAKEWIDTH * SNAKEWIDTH;
boolean b = true;
for(int i = 0;i snakeNum;i++){
if(foodX == snake[i][0] snake[i][1] == foodY){
b = false;
break;
}
}
if(b){
break;
}
}
}
/**
* 判斷游戲是否結(jié)束
* 結(jié)束條件:
* 1、蛇頭超出邊界
* 2、蛇頭碰到自身
*/
private boolean isGameOver(){
//邊界判別
if(snake[0][0] 0 || snake[0][0] (width - SNAKEWIDTH) ||
snake[0][1] 0 || snake[0][1] (height - SNAKEWIDTH)){
return true;
}
//碰到自身
for(int i = 4;i snakeNum;i++){
if(snake[0][0] == snake[i][0]
snake[0][1] == snake[i][1]){
return true;
}
}
return false;
}/**
* 事件處理
*/
public void keyPressed(int keyCode){
int action = this.getGameAction(keyCode);
//改變方向
switch(action){
case UP:
if(direction != DIRECTION_DOWN){
direction = DIRECTION_UP;
}
break;
case DOWN:
if(direction != DIRECTION_UP){
direction = DIRECTION_DOWN;
}
break;
case LEFT:
if(direction != DIRECTION_RIGHT){
direction = DIRECTION_LEFT;
}
break;
case RIGHT:
if(direction != DIRECTION_LEFT){
direction = DIRECTION_RIGHT;
}
break;
case FIRE:
//暫停和繼續(xù)
isPaused = !isPaused;
break;
}
}/**
* 線程方法
* 使用精確延時(shí)
*/
public void run(){
try{
while (isRun) {
//開始時(shí)間
long start = System.currentTimeMillis();
if(!isPaused){
//吃食物
eatFood();
//移動(dòng)
move(direction);
//結(jié)束游戲
if(isGameOver()){
break;
}
//控制閃爍
b = !b;
}
//重新繪制
repaint();
long end = System.currentTimeMillis();
//延時(shí)
if(end - start SLEEP_TIME){
Thread.sleep(SLEEP_TIME - (end - start));
}
}
}catch(Exception e){}
}
}
package games;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import java.util.*;
import static java.lang.Math.*;//靜態(tài)導(dǎo)入
/*
* 此類是貪吃蛇的簡(jiǎn)單實(shí)現(xiàn)方法
* 自己可以加入在開始時(shí)的設(shè)置,比如
* 選關(guān),初始的蛇的長(zhǎng)度等等
*/
public class Snake extends JPanel {
private static final long serialVersionUID = 1L;
private Direction dir;// 要走的方向
private int blockWidth = 10;// 塊大小
private int blockSpace = 2;// 塊之間的間隔
private long sleepTime;// 重畫的進(jìn)間間隔
private MySnake my;
private int total;// 代表蛇的長(zhǎng)度
private Rectangle food;// 代表蛇的食物
private volatile boolean go;
private int round;// 表示第幾關(guān)
public Snake(JFrame jf) {
initOther();
// 為頂級(jí)窗口類JFrame添加事件處理函數(shù)
jf.addKeyListener(new KeyAdapter() {
public void keyReleased(KeyEvent ke) {
int code = ke.getKeyCode();
if (code == KeyEvent.VK_RIGHT) {
if (dir != Direction.WEST)
dir = Direction.EAST;
}
else if (code == KeyEvent.VK_LEFT) {
if (dir != Direction.EAST)
dir = Direction.WEST;
}
else if (code == KeyEvent.VK_UP) {
if (dir != Direction.SOUTH)
dir = Direction.NORTH;
}
else if (code == KeyEvent.VK_DOWN) {
if (dir != Direction.NORTH)
dir = Direction.SOUTH;
} else if (code == KeyEvent.VK_ENTER) {
if (!go)
initOther();
}
}
});
this.setBounds(300, 300, 400, 400);
this.setVisible(true);
}
// 隨機(jī)生成一個(gè)食物的位置
private void makeFood() {
int x = 40 + (int) (random() * 30) * 12;
int y = 10 + (int) (random() * 30) * 12;
food = new Rectangle(x, y, 10, 10);
}
// 做一些初始化的工作
private void initOther() {
dir = Direction.EAST;
sleepTime = 500;
my = new MySnake();
makeFood();
total = 3;
round = 1;
new Thread(new Runnable() {
public void run() {
go = true;
while (go) {
try {
Thread.sleep(sleepTime);
repaint();
} catch (Exception exe) {
exe.printStackTrace();
}
}
}
}).start();
}
// 處理多少關(guān)的函數(shù)
private void handleRound() {
if (total == 6) {
round = 2;
sleepTime = 300;
} else if (total == 10) {
round = 3;
sleepTime = 200;
} else if (total == 15) {
round = 4;
sleepTime = 100;
} else if (total == 18) {
round = 5;
sleepTime = 50;
} else if (total == 20) {
round = 6;
sleepTime = 20;
} else if (total 21) {
round = 7;
sleepTime = 15;
}
}
// 把自己的組件全部畫出來(lái)
public void paintComponent(Graphics g) {
g.setColor(Color.PINK);
g.fillRect(0, 0, this.getWidth(), this.getHeight());
g.setColor(Color.BLACK);
g.drawRect(40, 10, 358, 360);
if (go) {
my.move();
my.draw(g);
g.setFont(new Font("黑體", Font.BOLD, 20));
g.drawString("您的得分:" + (total * 10) + " 第" + round + "關(guān)", 40,
400);
} else {
g.setFont(new Font("黑體", Font.BOLD, 20));
g.drawString("游戲結(jié)束,按回車(ENTER)鍵重玩!", 40, 440);
}
g.setColor(Color.RED);
g.fillRect(food.x, food.y, food.width, food.height);
}
private class MySnake {
private ArrayListRectangle list;
public MySnake() {
list = new ArrayListRectangle();
list.add(new Rectangle(160 + 24, 130, 10, 10));
list.add(new Rectangle(160 + 12, 130, 10, 10));
list.add(new Rectangle(160, 130, 10, 10));
}
// 蛇移動(dòng)的方法
public void move() {
if (isDead()) {
go = false;
return;
}
if (dir == Direction.EAST) {
Rectangle rec = list.get(0);
Rectangle rec1 = new Rectangle(rec.x
+ (blockWidth + blockSpace), rec.y, rec.width,
rec.height);
list.add(0, rec1);
} else if (dir == Direction.WEST) {
Rectangle rec = list.get(0);
Rectangle rec1 = new Rectangle(rec.x
- (blockWidth + blockSpace), rec.y, rec.width,
rec.height);
list.add(0, rec1);
} else if (dir == Direction.NORTH) {
Rectangle rec = list.get(0);
Rectangle rec1 = new Rectangle(rec.x, rec.y
- (blockWidth + blockSpace), rec.width, rec.height);
list.add(0, rec1);
} else if (dir == Direction.SOUTH) {
Rectangle rec = list.get(0);
Rectangle rec1 = new Rectangle(rec.x, rec.y
+ (blockWidth + blockSpace), rec.width, rec.height);
list.add(0, rec1);
}
if (isEat()) {
handleRound();
makeFood();
} else {
list.remove(list.size() - 1);
}
}
// 判斷是否吃到了食物
private boolean isEat() {
if (list.get(0).contains(food)) {
total++;
return true;
} else
return false;
}
// 判斷是否死了,如果碰壁或者自己吃到自己都算死了
private boolean isDead() {
Rectangle temp = list.get(0);
if (dir == Direction.EAST) {
if (temp.x == 388)
return true;
else {
Rectangle comp = new Rectangle(temp.x + 12, temp.y, 10, 10);
for (Rectangle rec : list) {
if (rec.contains(comp))
return true;
}
}
return false;
} else if (dir == Direction.WEST) {
if (temp.x == 40)
return true;
else {
Rectangle comp = new Rectangle(temp.x - 12, temp.y, 10, 10);
for (Rectangle rec : list) {
if (rec.contains(comp))
return true;
}
}
return false;
} else if (dir == Direction.NORTH) {
if (temp.y == 10)
return true;
else {
Rectangle comp = new Rectangle(temp.x, temp.y - 12, 10, 10);
for (Rectangle rec : list) {
if (rec.contains(comp))
return true;
}
}
return false;
} else if (dir == Direction.SOUTH) {
if (temp.y == 358)
return true;
else {
Rectangle comp = new Rectangle(temp.x, temp.y + 12, 10, 10);
for (Rectangle rec : list) {
if (rec.contains(comp))
return true;
}
}
return false;
} else {
return false;
}
}
// 把自己畫出來(lái)
public void draw(Graphics g) {
for (Rectangle rec : list) {
g.fillRect(rec.x, rec.y, rec.width, rec.height);
}
}
}
public static void main(String arsg[]) {
JFrame jf = new JFrame("貪吃蛇");
Snake s = new Snake(jf);
jf.getContentPane().add(s, BorderLayout.CENTER);
jf.setBounds(300, 300, 500, 500);
jf.setVisible(true);
jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
}
// 定義一個(gè)枚舉,在此也可以用接口或者常量值代替
enum Direction {
EAST, SOUTH, WEST, NORTH;
}
三個(gè)文件,樓主看好:
運(yùn)行可以,但是并不能鼓吹是一個(gè)具有好的風(fēng)格的代碼,。
//文件一
package greedysnake_cx;
public class Node {
int x=0;
int y=0;
int nodewidth;
int nodeheight;
Node(int x,int y){
this.x=x;
this.y=y;
}
}
//文件二
package greedysnake_cx;
/**
* 實(shí)現(xiàn)一個(gè)greedysnake的模型,具有功能:
* 1)移動(dòng),moveOn()----從director參數(shù)中獲取方向信息,如果方向定義的下一個(gè)點(diǎn)的邏輯值是true,檢查是不是food,是則將food添加到
* 列表的頭部,snake繼續(xù)移動(dòng),不是則停止移動(dòng)(撞到蛇尾巴了)
* 2)加速,speedUp()----將現(xiàn)成的停滯時(shí)間間隔interval按照一定的比率 speedRate進(jìn)行擴(kuò)大
* 3)減速,speedDown()----....
*
* 該類實(shí)現(xiàn)Runnable接口,
* */
//定義snake的模型
import java.util.*;
import javax.swing.*;
public class SnakeModel implements Runnable {
private GreedSnake gs;
//給每一個(gè)矩陣點(diǎn)確立一個(gè)boolean值
boolean[][] matrix;
private int maxX;
private int maxY;
//設(shè)置一個(gè)節(jié)點(diǎn)的列表;
LinkedList nodeArray = new LinkedList();
Node food=null;
int direction=UP;
int score=0;
//定義方向
public final static int LEFT=1;
public final static int UP=2;
public final static int RIGHT=3;
public final static int DOWN=4;
private int interval=200; //停頓時(shí)間的間隔
boolean pause=false; //定義暫停
private double speedRate=0.5; //定義速度的變更幅度
//constructor
public SnakeModel(GreedSnake gs,int maxx,int maxy){
this.gs=gs;
this.maxX=maxx;
this.maxY=maxy;
//this.matrix=null;
////////////////////////////////////////////////////////////////////
//init matrix[][];
matrix=new boolean[maxX][]; //***********************不初始化是不行滴
for(int i=0;imaxX;i++){
matrix[i]=new boolean[maxY];//將矩陣的每一行定義成列的集合
Arrays.fill(matrix[i], false);///使用java.util.Arrays的static方法fill,將matrix[]數(shù)組里面的元素全部定義成false
//至此,矩陣?yán)锩嫠械狞c(diǎn)的boolean值都是flase
//for(int j=0;jmaxY;j++){
//matrix[i][j]=false;
//}
}
////////////////////////////////////////////////////////////////////
//init nodeArray
int initlength=10;
for(int i=0;iinitlength;i++){
//確保snake出現(xiàn)在屏幕的中央 assure that the greedy snake appears in the center of the model
//snake的長(zhǎng)度由maxX來(lái)確定
int x=maxX/2+i;
int y=maxY/2;
nodeArray.addFirst(new Node(x,y));
matrix[x][y]=true;
}
//////////////////////////////////////////////////////////////////////
//創(chuàng)建食物
food=createFood();
System.out.println("some test!");
matrix[food.x][food.y]=true;
}//end constructor
//snake動(dòng)起
public boolean moveOn(){
Node head=(Node)nodeArray.getFirst();
int x=head.x;
int y=head.y;
switch(direction){
case LEFT:
x--;break;
case UP:
y--;break;
case RIGHT:
x++;break;
case DOWN:
y++;break;
default:
}
if((x = 0 x maxX) (y = 0 y maxY)){
if(matrix[x][y]){//當(dāng)蛇頭轉(zhuǎn)至一個(gè)bool值為true的點(diǎn)時(shí)
if(x==food.xy==food.y){//該點(diǎn)是食物
nodeArray.addFirst(food);
//吃掉補(bǔ)上
food=createFood();
matrix[food.x][food.y]=true;
score+=10;
return true;
}
else //該點(diǎn)不是食物,(蛇尾巴)
return false;
}
else{
nodeArray.addFirst(new Node(x,y));
matrix[x][y]=true;
Node nn=(Node)nodeArray.removeLast();//移除并且返回列表中的最后一個(gè)元素
matrix[nn.x][nn.y]=false;
return true;
}
}
return false;
}//end moveOn
public void run() {
boolean running=true;
while(running){
try{
Thread.sleep(interval);
}
catch(InterruptedException e){
e.printStackTrace();
}
if(!pause){
if(moveOn()){
gs.repaint();
}
else{
JOptionPane.showMessageDialog(null, "sorry myboy,GAME OVER!", "message", JOptionPane.INFORMATION_MESSAGE);
running=false;
}
}
}
/*boolean running=true;
while(running){
try{
Thread.sleep(interval);
}
catch (InterruptedException e){
e.printStackTrace();
}
if(!pause){
if(moveOn()){
gs.repaint();
}
else{
JOptionPane.showMessageDialog(null,"i am sorry ,you failed!","message",JOptionPane.INFORMATION_MESSAGE);
break;
}
}
}//end while
running=false;//當(dāng)且僅當(dāng)失敗退出的時(shí)候;
*/
}
//獲取當(dāng)前游戲得分
public int getScore(){
return this.score;
}
//加速
public void speedUp(){
interval*=speedRate;
}
//減速
public void speedDown(){
interval/=speedRate;
}
//設(shè)置暫停
public void chagePause(){
pause=!pause;
}
//設(shè)置方向
public void chageDirection(int newdirection){
if(direction % 2 != newdirection % 2){
direction=newdirection;
}
}
//生成食物
private Node createFood() {
/*
* 創(chuàng)建一個(gè)隨機(jī)數(shù)的生成器,這個(gè)是java.util.Random類
* 與java.lang.Math類中的random()方法有不一樣的地方,彼方法返回一個(gè)0-1之間的隨機(jī)數(shù)
* */
Random random=new Random();
int foodx=random.nextInt(maxX);
int foody=random.nextInt(maxY);
Node food=new Node(foodx,foody);
return food;
}
}
//文件三
package greedysnake_cx;
/**
* 在repaint()方法中,繪畫上下文對(duì)象是從canvas對(duì)象使用getContentPane()獲取的!!
* */
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.util.*;
public class GreedSnake implements KeyListener{
Canvas canvas;
private JLabel jlabel;
private JPanel jpanel;
private JFrame jframe;
SnakeModel snakemodel;
private final static int canvaswidth=400;
private final static int canvasheight=300;
private final static int nodewidth=10;
private final static int nodeheight=10;
//construction
GreedSnake(){
jframe=new JFrame("The Greed Sanke!");
jframe.setLayout(new BorderLayout());
Container cp=jframe.getContentPane();
//在jframe面板中添加各種組件
jlabel=new JLabel("welcome");
jlabel.setText("Welcome my friend! Enjoy your self!");
cp.add(jlabel,BorderLayout.NORTH);
canvas=new Canvas();
canvas.setSize(canvaswidth,canvasheight);
canvas.addKeyListener(this); //給空白面板添加鍵盤時(shí)間監(jiān)聽器!
cp.add(canvas,BorderLayout.CENTER);
jpanel=new JPanel();
jpanel.setLayout(new BorderLayout());
JLabel label=new JLabel("Pass enter or 'r' or 's' to start",JLabel.CENTER);
jpanel.add(label,BorderLayout.NORTH);
JLabel label2=new JLabel("Pass space to pause this game!",JLabel.CENTER);
jpanel.add(label2,BorderLayout.CENTER);
JLabel label3=new JLabel("Pass pageUp or pageDown to up or down the speed of the snake!",JLabel.CENTER);
jpanel.add(label3,BorderLayout.SOUTH);
cp.add(jpanel,BorderLayout.SOUTH);
//給頂層容器設(shè)置時(shí)間監(jiān)聽、可視化、關(guān)閉按鈕的設(shè)定
jframe.addKeyListener(this);
jframe.pack();
jframe.setVisible(true);
jframe.setResizable(false);
jframe.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
begin();
}//end construction
public void begin(){
//開啟一個(gè)SnakeModel的進(jìn)程,并且開始改進(jìn)程
snakemodel=new SnakeModel(this,canvaswidth/nodewidth,canvasheight/nodeheight);
(new Thread(snakemodel)).start();
}
void repaint(){
int score=snakemodel.getScore();
jlabel.setText("您的得分是:"+score);
Graphics g=canvas.getGraphics();///pay attention!
g.setColor(Color.white);
g.fillRect(0, 0, canvaswidth, canvasheight);
g.setColor(Color.blue);
LinkedList list=snakemodel.nodeArray;
for(int i=0;ilist.size();i++){
Node nn=(Node)list.get(i);
paintingNode(g,nn);
}
//繪制food
g.setColor(Color.green);
Node foodnode=new Node(snakemodel.food.x,snakemodel.food.y);
paintingNode(g,foodnode);
}
public void paintingNode(Graphics gg,Node n){
/*
* 使用Graphics 的fillRect方法,填充一個(gè)矩形,
* 矩形的起點(diǎn)需要乘以一個(gè)NODE的長(zhǎng)寬,以避免重疊
* */
gg.fillRect(n.x*nodewidth, n.y*nodeheight,nodewidth-1,nodeheight-1);
}
public void keyPressed(KeyEvent e) {//按下某一個(gè)鍵時(shí),調(diào)用此方法
int keycode=e.getKeyCode();
/* if(keycode==KeyEvent.VK_ENTER||keycode==KeyEvent.VK_R){
begin();
}*/
switch(keycode){
case KeyEvent.VK_LEFT:
snakemodel.chageDirection(SnakeModel.LEFT);
break;
case KeyEvent.VK_UP:
snakemodel.chageDirection(SnakeModel.UP);
break;
case KeyEvent.VK_RIGHT:
snakemodel.chageDirection(SnakeModel.RIGHT);
break;
case KeyEvent.VK_DOWN:
snakemodel.chageDirection(SnakeModel.DOWN);
break;
case KeyEvent.VK_PAGE_DOWN:
snakemodel.speedDown();
break;
case KeyEvent.VK_PAGE_UP:
snakemodel.speedUp();
break;
case KeyEvent.VK_ENTER:
case KeyEvent.VK_R:
begin();
break;
case KeyEvent.VK_SPACE:
case KeyEvent.VK_P:
snakemodel.chagePause();
default:
}//end switch
}//end keyPressed
public void keyReleased(KeyEvent e) {//釋放某一個(gè)鍵時(shí),調(diào)用此方法
}
public void keyTyped(KeyEvent e) {//鍵入某一個(gè)鍵時(shí),調(diào)用此方法!
}
//main
public static void main(String[] args){
GreedSnake gs=new GreedSnake();
}
}
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.image.BufferedImage;
import java.util.ArrayList;
import java.util.List;
import javax.swing.JFrame;
public class InterFace extends JFrame {
/**
* WIDTH:寬
* HEIGHT:高
* SLEEPTIME:可以看作蛇運(yùn)動(dòng)的速度
* L = 1,R = 2, U = 3, D = 4 左右上下代碼
*/
public static final int WIDTH = 800, HEIGHT = 600, SLEEPTIME = 200, L = 1,R = 2, U = 3, D = 4;
BufferedImage offersetImage= new BufferedImage(WIDTH, HEIGHT,BufferedImage.TYPE_3BYTE_BGR);;
Rectangle rect = new Rectangle(20, 40, 15 * 50, 15 * 35);
Snake snake;
Node node;
public InterFace() {
//創(chuàng)建"蛇"對(duì)象
snake = new Snake(this);
//創(chuàng)建"食物"對(duì)象
createNode();
this.setBounds(100, 100, WIDTH, HEIGHT);
//添加鍵盤監(jiān)聽器
this.addKeyListener(new KeyAdapter() {
public void keyPressed(KeyEvent arg0) {
System.out.println(arg0.getKeyCode());
switch (arg0.getKeyCode()) {
//映射上下左右4個(gè)鍵位
case KeyEvent.VK_LEFT:
snake.dir = L;
break;
case KeyEvent.VK_RIGHT:
snake.dir = R;
break;
case KeyEvent.VK_UP:
snake.dir = U;
break;
case KeyEvent.VK_DOWN:
snake.dir = D;
}
}
});
this.setTitle("貪吃蛇 0.1 By : Easy");
this.setDefaultCloseOperation(EXIT_ON_CLOSE);
this.setVisible(true);
//啟動(dòng)線程,開始執(zhí)行
new Thread(new ThreadUpadte()).start();
}
public void paint(Graphics g) {
Graphics2D g2d = (Graphics2D) offersetImage.getGraphics();
g2d.setColor(Color.white);
g2d.fillRect(0, 0, WIDTH, HEIGHT);
g2d.setColor(Color.black);
g2d.drawRect(rect.x, rect.y, rect.width, rect.height);
//如果蛇碰撞(吃)到食物,則創(chuàng)建新食物
if (snake.hit(node)) {
createNode();
}
snake.draw(g2d);
node.draw(g2d);
g.drawImage(offersetImage, 0, 0, null);
}
class ThreadUpadte implements Runnable {
public void run() {
//無(wú)限重繪畫面
while (true) {
try {
Thread.sleep(SLEEPTIME);
repaint(); //
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
/**
* 創(chuàng)建食物
*/
public void createNode() {
//隨機(jī)食物的出現(xiàn)位置
int x = (int) (Math.random() * 650) + 50,y = (int) (Math.random() * 500) + 50;
Color color = Color.blue;
node = new Node(x, y, color);
}
public static void main(String args[]) {
new InterFace();
}
}
/**
* 節(jié)點(diǎn)類(包括食物和蛇的身軀組成節(jié)點(diǎn))
*/
class Node {
int x, y, width = 15, height = 15;
Color color;
public Node(int x, int y, Color color) {
this(x, y);
this.color = color;
}
public Node(int x, int y) {
this.x = x;
this.y = y;
this.color = color.black;
}
public void draw(Graphics2D g2d) {
g2d.setColor(color);
g2d.drawRect(x, y, width, height);
}
public Rectangle getRect() {
return new Rectangle(x, y, width, height);
}
}
/**
* 蛇
*/
class Snake {
public ListNode nodes = new ArrayListNode();
InterFace interFace;
int dir=InterFace.R;
public Snake(InterFace interFace) {
this.interFace = interFace;
nodes.add(new Node(20 + 150, 40 + 150));
addNode();
}
/**
* 是否碰撞到食物
* @return true 是 false 否
*/
public boolean hit(Node node) {
//遍歷整個(gè)蛇體是否與食物碰撞
for (int i = 0; i nodes.size(); i++) {
if (nodes.get(i).getRect().intersects(node.getRect())) {
addNode();
return true;
}
}
return false;
}
public void draw(Graphics2D g2d) {
for (int i = 0; i nodes.size(); i++) {
nodes.get(i).draw(g2d);
}
move();
}
public void move() {
nodes.remove((nodes.size() - 1));
addNode();
}
public synchronized void addNode() {
Node nodeTempNode = nodes.get(0);
//如果方向
switch (dir) {
case InterFace.L:
//判斷是否會(huì)撞墻
if (nodeTempNode.x = 20) {
nodeTempNode = new Node(20 + 15 * 50, nodeTempNode.y);
}
nodes.add(0, new Node(nodeTempNode.x - nodeTempNode.width,
nodeTempNode.y));
break;
case InterFace.R:
//判斷是否會(huì)撞墻
if (nodeTempNode.x = 20 + 15 * 50 - nodeTempNode.width) {
nodeTempNode = new Node(20 - nodeTempNode.width, nodeTempNode.y);
}
nodes.add(0, new Node(nodeTempNode.x + nodeTempNode.width,
nodeTempNode.y));
break;
case InterFace.U:
//判斷是否會(huì)撞墻
if (nodeTempNode.y = 40) {
nodeTempNode = new Node(nodeTempNode.x, 40 + 15 * 35);
}
nodes.add(0, new Node(nodeTempNode.x, nodeTempNode.y - nodeTempNode.height));
break;
case InterFace.D:
//判斷是否會(huì)撞墻
if (nodeTempNode.y = 40 + 15 * 35 - nodeTempNode.height) {
nodeTempNode = new Node(nodeTempNode.x,40 - nodeTempNode.height);
}
nodes.add(0, new Node(nodeTempNode.x, nodeTempNode.y + nodeTempNode.height));
break;
}
}
}
//package main;
import java.awt.Color;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStreamReader;
import javax.swing.ImageIcon;
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;
public class TanChiShe implements KeyListener,ActionListener{
/**
* @param args
*/
int max = 300;//蛇長(zhǎng)最大值
final int JianJu = 15; //設(shè)定蛇的運(yùn)動(dòng)網(wǎng)格間距(窗口最大32*28格)
byte fangXiang = 4; //控制蛇的運(yùn)動(dòng)方向,初始為右
int time = 500; //蛇的運(yùn)動(dòng)間隔時(shí)間
int jianTime = 2;//吃一個(gè)減少的時(shí)間
int x,y;//蛇的運(yùn)動(dòng)坐標(biāo),按網(wǎng)格來(lái)算
int x2,y2;//暫存蛇頭的坐標(biāo)
int jiFenQi = 0;//積分器
boolean isRuned = false;//沒運(yùn)行才可設(shè)級(jí)別
boolean out = false;//沒開始運(yùn)行?
boolean run = false;//暫停運(yùn)行
String JiBie = "中級(jí)";
JFrame f = new JFrame("貪吃蛇 V1.0");
JPanel show = new JPanel();
JLabel Message = new JLabel("級(jí)別:中級(jí) 蛇長(zhǎng):5 時(shí)間500ms 分?jǐn)?shù):00");
// JButton play = new JButton("開始");
JLabel sheTou;
JLabel shiWu;
JLabel sheWei[] = new JLabel[max];
static int diJi = 4; //第幾個(gè)下標(biāo)的蛇尾要被加上
ImageIcon shang = new ImageIcon("tuPian\\isSheTouUp.png");//產(chǎn)生四個(gè)上下左右的蛇頭圖案
ImageIcon xia = new ImageIcon("tuPian\\isSheTouDown.png");
ImageIcon zhuo = new ImageIcon("tuPian\\isSheTouLeft.png");
ImageIcon you = new ImageIcon("tuPian\\isSheTouRight.png");
JMenuBar JMB = new JMenuBar();
JMenu file = new JMenu("開始游戲");
JMenuItem play = new JMenuItem(" 開始游戲 ");
JMenuItem pause = new JMenuItem(" 暫停游戲 ");
JMenu hard = new JMenu("游戲難度");
JMenuItem gao = new JMenuItem("高級(jí)");
JMenuItem zhong = new JMenuItem("中級(jí)");
JMenuItem di = new JMenuItem("低級(jí)");
JMenu about = new JMenu(" 關(guān)于 ");
JMenuItem GF = new JMenuItem("※高分榜");
JMenuItem ZZ = new JMenuItem("關(guān)于作者");
JMenuItem YX = new JMenuItem("關(guān)于游戲");
JMenuItem QK = new JMenuItem("清空記錄");
static TanChiShe tcs = new TanChiShe();
public static void main(String[] args) {
// TanChiShe tcs = new TanChiShe();
tcs.f();
}
public void f(){
f.setBounds(250,100,515,530);
f.setLayout(null);
f.setAlwaysOnTop(true);//窗口始終保持最前面
f.setBackground(new Color(0,0,0));
f.setDefaultCloseOperation(0);
f.setResizable(false);
f.setVisible(true);
// f.getContentPane().setBackground(Color.BLACK);
f.addWindowListener(new WindowAdapter(){
public void windowClosing(WindowEvent e){
System.exit(0);//退出程序
}
});
f.setJMenuBar(JMB);
JMB.add(file);
file.add(play);
file.add(pause);
JMB.add(hard);
hard.add(gao);
hard.add(zhong);
hard.add(di);
JMB.add(about);
about.add(GF);
GF.setForeground(Color.blue);
about.add(ZZ);
about.add(YX);
about.add(QK);
QK.setForeground(Color.red);
f.add(show);
show.setBounds(0,f.getHeight()-92,f.getWidth(),35);
// show.setBackground(Color.green);
// f.add(play);
// play.setBounds(240,240,80,25);
play.addActionListener(this);
pause.addActionListener(this);
gao.addActionListener(this);
zhong.addActionListener(this);
di.addActionListener(this);
GF.addActionListener(this);
ZZ.addActionListener(this);
YX.addActionListener(this);
QK.addActionListener(this);
show.add(Message);
Message.setForeground(Color.blue);
f.addKeyListener(this);
// show.addKeyListener(this);
play.addKeyListener(this);
sheChuShi();
}
public void sheChuShi(){//蛇初始化
sheTou = new JLabel(you);//用向右的圖來(lái)初始蛇頭
f.add(sheTou);
sheTou.setBounds(JianJu*0,JianJu*0,JianJu,JianJu);
// System.out.println("ishere");
shiWu = new JLabel("■");
f.add(shiWu);
shiWu.setBounds(10*JianJu,10*JianJu,JianJu,JianJu);
for(int i=0;i=diJi;i++) {
sheWei[i] = new JLabel("■");
f.add(sheWei[i]);
sheWei[i].setBounds(-1*JianJu,0*JianJu,JianJu,JianJu);
}
while(true){
if(out == true){
yunXing();
break;
}
try{
Thread.sleep(200);
}catch(Exception ex){
ex.printStackTrace();
}
}
}
public void sheJiaChang(){//蛇的長(zhǎng)度增加
if(diJi max){
sheWei[++diJi] = new JLabel(new ImageIcon("tuPian\\isSheWei.jpg"));
f.add(sheWei[diJi]);
sheWei[diJi].setBounds(sheWei[diJi-1].getX(),sheWei[diJi-1].getY(),JianJu,JianJu);
// System.out.println("diJi "+diJi);
}
}
public void pengZhuanJianCe(){//檢測(cè)蛇的碰撞情況
if(sheTou.getX()0 || sheTou.getY()0 ||
sheTou.getX()f.getWidth()-15 || sheTou.getY()f.getHeight()-105 ){
gameOver();
// System.out.println("GameOVER");
}
if(sheTou.getX() == shiWu.getX() sheTou.getY() == shiWu.getY()){
out: while(true){
shiWu.setLocation((int)(Math.random()*32)*JianJu,(int)(Math.random()*28)*JianJu);
for(int i=0;i=diJi;i++){
if(shiWu.getX()!= sheWei[i].getX() shiWu.getY()!=sheWei[i].getY()
sheTou.getX()!=shiWu.getX() sheTou.getY()!= shiWu.getY()){//如果食物不在蛇身上則退出循環(huán),產(chǎn)生食物成功
break out;
}
}
}
sheJiaChang();
// System.out.println("吃了一個(gè)");
if(time100 ){
time -= jianTime;
}
else{}
Message.setText("級(jí)別:"+JiBie+" 蛇長(zhǎng):"+(diJi+2)+" 時(shí)間:"+time+"ms 分?jǐn)?shù):"+(jiFenQi+=10)+"");
}
for(int i=0;i=diJi;i++){
if(sheTou.getX() == sheWei[i].getX() sheTou.getY() == sheWei[i].getY()){
gameOver();
// System.out.println("吃到尾巴了");
}
}
}
public void yunXing(){
while(true){
while(run){
if(fangXiang == 1){//上
y-=1;
}
if(fangXiang == 2){//下
y+=1;
}
if(fangXiang == 3){//左
x-=1;
}
if(fangXiang == 4){//右
x+=1;
}
x2 = sheTou.getX();
y2 = sheTou.getY();
sheTou.setLocation(x*JianJu,y*JianJu); //設(shè)置蛇頭的坐標(biāo) 網(wǎng)格數(shù)*間隔
for(int i=diJi;i=0;i--){
if(i==0){
sheWei[i].setLocation(x2,y2);
// System.out.println(i+" "+sheTou.getX()+" "+sheTou.getY());
}
else{
sheWei[i].setLocation(sheWei[i-1].getX(),sheWei[i-1].getY());
// System.out.println(i+" "+sheWei[i].getX()+" "+sheWei[i].getY());
}
}
pengZhuanJianCe();
try{
Thread.sleep(time);
}catch(Exception e){
e.printStackTrace();
}
}
Message.setText("級(jí)別:"+JiBie+" 蛇長(zhǎng):"+(diJi+2)+" 時(shí)間:"+time+"ms 分?jǐn)?shù):"+(jiFenQi+=10)+"");
try{
Thread.sleep(200);
}catch(Exception e){
e.printStackTrace();
}
}
}
public void gameOver(){//游戲結(jié)束時(shí)處理
int in = JOptionPane.showConfirmDialog(f,"游戲已經(jīng)結(jié)束!\n是否要保存分?jǐn)?shù)","提示",JOptionPane.YES_NO_OPTION);
if(in == JOptionPane.YES_OPTION){
// System.out.println("YES");
String s = JOptionPane.showInputDialog(f,"輸入你的名字:");
try{
FileInputStream fis = new FileInputStream("GaoFen.ini");//先把以前的數(shù)據(jù)讀出來(lái)加到寫的數(shù)據(jù)前
InputStreamReader isr = new InputStreamReader(fis);
BufferedReader br = new BufferedReader(isr);
String s2,setOut = "";
while((s2=br.readLine())!= null){
setOut =setOut+s2+"\n";
}
FileOutputStream fos = new FileOutputStream("GaoFen.ini");//輸出到文件流
s = setOut+s+":"+jiFenQi+"\n";
fos.write(s.getBytes());
}catch(Exception e){}
}
System.exit(0);
}
public void keyTyped(KeyEvent arg0) {
// TODO 自動(dòng)生成方法存根
}
public void keyPressed(KeyEvent arg0) {
// System.out.println(arg0.getSource());
if(arg0.getKeyCode() == KeyEvent.VK_UP){//按上下時(shí)方向的值相應(yīng)改變
if(fangXiang != 2){
fangXiang = 1;
// sheTou.setIcon(shang);//設(shè)置蛇的方向
}
// System.out.println("UP");
}
if(arg0.getKeyCode() == KeyEvent.VK_DOWN){
if(fangXiang != 1){
fangXiang = 2;
// sheTou.setIcon(xia);
}
// System.out.println("DOWN");
}
if(arg0.getKeyCode() == KeyEvent.VK_LEFT){//按左右時(shí)方向的值相應(yīng)改變
if(fangXiang != 4){
fangXiang = 3;
// sheTou.setIcon(zhuo);
}
// System.out.println("LEFT");
}
if(arg0.getKeyCode() == KeyEvent.VK_RIGHT){
if(fangXiang != 3){
fangXiang = 4;
// sheTou.setIcon(you);
}
// System.out.println("RIGHT");
}
}
public void keyReleased(KeyEvent arg0) {
// TODO 自動(dòng)生成方法存根
}
public void actionPerformed(ActionEvent arg0) {
// TODO 自動(dòng)生成方法存根
JMenuItem JI = (JMenuItem)arg0.getSource();
if(JI == play){
out = true;
run = true;
isRuned = true;
gao.setEnabled(false);
zhong.setEnabled(false);
di.setEnabled(false);
}
if(JI == pause){
run = false;
}
if(isRuned == false){//如果游戲還沒運(yùn)行,才可以設(shè)置級(jí)別
if(JI == gao){
time = 200;
jianTime = 1;
JiBie = "高級(jí)";
Message.setText("級(jí)別:"+JiBie+" 蛇長(zhǎng):"+(diJi+2)+" 時(shí)間:"+time+"ms 分?jǐn)?shù):"+jiFenQi);
}
if(JI == zhong){
time = 400;
jianTime = 2;
JiBie = "中級(jí)";
Message.setText("級(jí)別:"+JiBie+" 蛇長(zhǎng):"+(diJi+2)+" 時(shí)間:"+time+"ms 分?jǐn)?shù):"+jiFenQi);
}
if(JI == di){
time = 500;
jianTime = 3;
JiBie = "低級(jí)";
Message.setText("級(jí)別:"+JiBie+" 蛇長(zhǎng):"+(diJi+2)+" 時(shí)間:"+time+"ms 分?jǐn)?shù):"+jiFenQi);
}
}
if(JI == GF){
try{
FileInputStream fis = new FileInputStream("GaoFen.ini");
InputStreamReader isr = new InputStreamReader(fis);
BufferedReader br = new BufferedReader(isr);
String s,setOut = "";
while((s=br.readLine())!= null){
setOut =setOut+s+"\n";
}
if(setOut.equals("")){
JOptionPane.showMessageDialog(f,"暫無(wú)保存記錄!","高分榜",JOptionPane.INFORMATION_MESSAGE);
}
else{
JOptionPane.showMessageDialog(f,setOut);
}
}catch(Exception e){
e.printStackTrace();
}
}
if(JI == ZZ){//關(guān)于作者
JOptionPane.showMessageDialog(f,"軟件作者:申志飛\n地址:四川省綿陽(yáng)市\(zhòng)nQQ:898513806\nE-mail:shenzhifeiok@126.com","關(guān)于作者",JOptionPane.INFORMATION_MESSAGE);
}
if(JI == YX){//關(guān)于游戲
JOptionPane.showMessageDialog(f,"貪吃蛇游戲\n游戲版本 V1.0","關(guān)于游戲",JOptionPane.INFORMATION_MESSAGE);
}
if(JI == QK){
try{
int select = JOptionPane.showConfirmDialog(f,"確實(shí)要清空記錄嗎?","清空記錄",JOptionPane.YES_OPTION);
if(select == JOptionPane.YES_OPTION){
String setOut = "";
FileOutputStream fos = new FileOutputStream("GaoFen.ini");//輸出到文件流
fos.write(setOut.getBytes());
}
}catch(Exception ex){}
}
}
}
//是我自己寫的,本來(lái)里面有圖片的,但無(wú)法上傳,所以把圖片去掉了,里面的ImageIcon等語(yǔ)句可以去掉。能正常運(yùn)行。
public
class
Snake
implements
Data//蛇類實(shí)現(xiàn)了data接口
{
public
Snake()
{
array.add(new
Point(10,
10));//
array.add(new
Point(10,
11));//
array.add(new
Point(10,
12));//
array.add(new
Point(10,
13));//
array.add(new
Point(10,
14));//這五句話是構(gòu)造一個(gè)蛇,這條蛇由五個(gè)坐標(biāo)點(diǎn)連成
currentFlag
=UPFLAG
;//當(dāng)前的運(yùn)動(dòng)方向設(shè)為向上
lifeFlag
=
true;//當(dāng)前蛇的生命設(shè)為活著
}
public
void
move()//蛇的運(yùn)動(dòng)函數(shù)
{
tair
=
(Point)array.get(array.size()
-
1);//得到蛇的尾巴
int
len
=
array.size()
-
2;
for(int
i
=
len;
i
=
0;
i--)//這個(gè)for循環(huán)把蛇的每一個(gè)點(diǎn)都坐標(biāo)偏移即運(yùn)動(dòng)了
{
Point
leftPoint
=
(Point)array.get(i);
Point
rightPoint
=
(Point)array.get(i
+
1);
rightPoint.x
=
leftPoint.x;
rightPoint.y
=
leftPoint.y;//每一個(gè)右邊的點(diǎn)等于其左邊的點(diǎn),像蛇那樣的一縮一張的運(yùn)動(dòng)
}
}
public
void
moveHeadLeft()//把蛇的頭部轉(zhuǎn)向左邊
{
if(currentFlag
==
RIGHTFLAG
||
currentFlag
==
LEFTFLAG)//如果運(yùn)動(dòng)方向設(shè)為向左或向右則不執(zhí)行
{
return;
}
move();
Point
point
=
(Point)(array.get(0));
//得到蛇頭部
point.x
=
point.x
-
1;//蛇頭部橫坐標(biāo)減一,縱坐標(biāo)不變
point.y
=
point.y;
if(point.x
LEFT)//如果蛇頭部不能再左,就不執(zhí)行
{
lifeFlag
=
false;
}
currentFlag
=
LEFTFLAG;//將蛇運(yùn)動(dòng)方向改為左
}