/*
* 贪吃蛇,采取了组件,集合的思想,
* 简单的图形界面运用+集合处理
* 贪吃蛇,采取了组件,集合的思想,
* 简单的图形界面运用+集合处理
*/
package cn.hncu.games;
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Point;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.util.Random;
import javax.swing.Icon;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JComboBox;
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.Timer;
import cn.hncu.set.MySet;
public class RetroSnaker extends JFrame{
private String dir="./images_RetroSnaker/";
private JMenu[] jmenu;
private JMenuItem[][] jmenuItem;
/*
* 菜单处理
*/
private ActionListener jmenuListener=new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
if(e.getActionCommand().equals("newGame")){
//snaker.newGame();
newGame();
}else if(e.getActionCommand().equals("break")){
if(timer==null||!timer.isRunning())
return;
timer.stop();
removeKeyListener(keyListener);
jmenuItem[0][1].setEnabled(false);
jmenuItem[0][2].setEnabled(true);
}else if(e.getActionCommand().equals("continue")){
if(timer==null||timer.isRunning())
return;
timer.restart();
addKeyListener(keyListener);
jmenuItem[0][2].setEnabled(false);
jmenuItem[0][1].setEnabled(true);
}else if(e.getActionCommand().equals("exit")){
if (timer!=null&&timer.isRunning()) {
timer.stop();
}
//System.exit(0);
dispose();
}else if(e.getActionCommand().equals("nightmare")){
delay=40;
setDifficultyLabel(2);
repaint();
}else if(e.getActionCommand().equals("hard")){
delay=100;
setDifficultyLabel(1);
repaint();
}else if(e.getActionCommand().equals("low")){
delay=600;
setDifficultyLabel(0);
repaint();
}
}
};
//private SnakerJPanel snaker;
private Timer timer;
/*
* 动态监听,移动(更新)贪吃蛇
*/
private ActionListener listener=new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
upDete();
}
};
/*
* 键盘监听,控制方向
*/
private KeyListener keyListener=new KeyListener() {
@Override
public void keyTyped(KeyEvent e) {
}
@Override
public void keyReleased(KeyEvent e) {
}
@Override
public void keyPressed(KeyEvent e) {
if(timer==null||!timer.isRunning()||mySet.size()<1)
return;
timer.stop();
int keyCode=e.getKeyCode();
switch(keyCode){
case KeyEvent.VK_DOWN:
((SnakerBody)mySet.get(0)).direction="down";
break;
case KeyEvent.VK_UP:
((SnakerBody)mySet.get(0)).direction="up";
break;
case KeyEvent.VK_LEFT:
((SnakerBody)mySet.get(0)).direction="left";
break;
case KeyEvent.VK_RIGHT:
((SnakerBody)mySet.get(0)).direction="right";
break;
}
upDete();
timer.restart();
}
};
private int delay=600;
private int score=0;
private MySet mySet=new MySet();
private JLabel snakerlabel,difficultylabel;
private SnakerBody nextSnaker;
private boolean isOver;
public RetroSnaker() {
super("简易版贪吃蛇");
setBounds(100, 20, 1200, 660);
setDefaultCloseOperation(DISPOSE_ON_CLOSE);
//菜单
JMenuBar bar=new JMenuBar();
String[] str={"游戏","选项"};
String[][] strs={{"新游戏","暂停","继续","退出"},
{"噩梦","困难","普通"}};
String[][] strs_english={{"newGame","break","continue","exit"},
{"nightmare","hard","low"}};
jmenu=new JMenu[str.length];
jmenuItem=new JMenuItem[strs.length][];
for (int i = 0; i < jmenu.length; i++) {
jmenu[i]=new JMenu(str[i]);
jmenuItem[i]=new JMenuItem[strs[i].length];
for (int j = 0; j < jmenuItem[i].length; j++) {
jmenuItem[i][j]=new JMenuItem(strs[i][j]);
jmenuItem[i][j].addActionListener(jmenuListener);
jmenuItem[i][j].setActionCommand(strs_english[i][j]);
if(jmenuItem[i][j].getActionCommand().equals("continue"))
jmenuItem[i][j].setEnabled(false);
if(jmenuItem[i][j].getActionCommand().equals("break"))
jmenuItem[i][j].setEnabled(false);
jmenu[i].add(jmenuItem[i][j]);
}
bar.add(jmenu[i]);
}
setJMenuBar(bar);
//snaker=new SnakerJPanel();
//getContentPane().add(snaker);
setBack();
setVisible(true);
}
//设置背景
private void setBack() {
getContentPane().setLayout(null);
for (int i = 0; i < 50; i++) {
for (int j = 0; j < 30; j++) {
if(i==0||j==0||i==49||j==29){
JLabel jlbwall=new JLabel(new ImageIcon(dir+"zhuqiang.jpg"));
jlbwall.setBounds(i*20, j*20, 20, 20);
getContentPane().add(jlbwall);
}
}
}
JPanel scoreP=new JPanel(){
@Override
public void paint(Graphics g) {
super.paint(g);
g.setColor(Color.red);
g.setFont(new Font("叶根友毛笔行书2.0版", Font.ITALIC, 20));
g.drawString("游戏得分:", 20, 20);
g.drawString("游戏难度:", 20, 120);
g.setFont(new Font("叶根友毛笔行书2.0版", Font.ITALIC, 80));
g.drawString(""+score, 40, 80);
g.drawImage(Toolkit.getDefaultToolkit().createImage(dir+"she.jpg"),0,150,200,500,this);
}
};
scoreP.setBounds(1000, 0, 200, 660);
getContentPane().add(scoreP);
scoreP.setLayout(null);
difficultylabel=new JLabel();
setDifficultyLabel(0);
difficultylabel.setBounds(20, 100, 140, 200);
scoreP.add(difficultylabel);
JLabel shelabel=new JLabel(new ImageIcon(dir+"she.jpg"));
shelabel.setBounds(20, 300, 160, 300);
scoreP.add(shelabel);
}
/*
* 难度标签
*/
private void setDifficultyLabel(int num) {
String[] strlabel={"low.png","hard.png","nightmare.png"};
Icon img=new ImageIcon(dir+strlabel[num]);
difficultylabel.setIcon(img);
}
/*
* 游戏初始化处理
*/
private void newGame() {
if(timer!=null&&timer.isRunning())
timer.stop();
//初始化设置
isOver=true;
removeKeyListener(keyListener);
addKeyListener(keyListener);
jmenuItem[0][1].setEnabled(true);
jmenuItem[0][2].setEnabled(false);
jmenuItem[1][0].setEnabled(false);
jmenuItem[1][1].setEnabled(false);
jmenuItem[1][2].setEnabled(false);
score=0;
// 自制集合MySet(文章后有集合链接),
// 清空集合,将蛇头加入
for (int i = 0; i < mySet.size(); i++) {
JLabel snakercomp=((SnakerBody)mySet.get(i)).snaker;
getContentPane().remove(snakercomp);
}
mySet.removeAll();
//头部标签设置位置,图片
JLabel snakerhead=new JLabel(new ImageIcon(dir+"longtou.png"));
mySet.add(new SnakerBody(new Point(20, 20), "right", snakerhead));
snakerhead.setBounds(20, 20, 20, 20);
getContentPane().add(snakerhead);
//boxDifficulty.setSelectedIndex(boxDifficulty.getSelectedIndex());
timer=new Timer(delay, listener);
timer.start();
nextSnaker=nextBody();
repaint();
}
/*
* 下一个蛇身出现的随机处理
*/
private SnakerBody nextBody() {
Random random=new Random();
int x,y;
//while(true)使随机出现的新点不在蛇身
while (true) {
x = random.nextInt(49) * 20;
y = random.nextInt(29) * 20;
if(x==0||y==0)
continue;
boolean flag=true;
for (int i = 0; i < mySet.size(); i++) {
SnakerBody body=((SnakerBody)mySet.get(i));
if(x==body.point.x&&y==body.point.y){
flag=false;
break;
}
}
if(flag)
break;
}
if(snakerlabel!=null)
getContentPane().remove(snakerlabel);
snakerlabel=new JLabel(new ImageIcon(dir+"longshen.png"));
snakerlabel.setBounds(x, y, 20, 20);
getContentPane().add(snakerlabel);
return new SnakerBody(new Point(x, y), "", snakerlabel);
}
//更新贪吃蛇
private void upDete() {
if(mySet.size()<1||!isOver)
return;
//先移除所有组件
for (int i = 0; i < mySet.size(); i++) {
JLabel snakercomp=((SnakerBody)mySet.get(i)).snaker;
getContentPane().remove(snakercomp);
}
//移动位置,在集合中处理(由尾到头,使位置向上个进行改变)
SnakerBody lastend=new SnakerBody((SnakerBody)mySet.get(mySet.size()-1));
for (int i = mySet.size()-1; i > 0; i--) {
SnakerBody last=((SnakerBody)mySet.get(i-1));
SnakerBody body=((SnakerBody)mySet.get(i));
body.point.x=last.point.x;
body.point.y=last.point.y;
body.direction=last.direction;
}
//头部处理
SnakerBody head=((SnakerBody)mySet.get(0));
String state=head.direction;
if(state.equals("down"))
head.point.y+=20;
else if(state.equals("up"))
head.point.y-=20;
else if(state.equals("left"))
head.point.x-=20;
else if(state.equals("right"))
head.point.x+=20;
//判断是否结束
boolean flag=isGameOver(head);
//添加
if(head.point.x==nextSnaker.point.x&&head.point.y==nextSnaker.point.y){
addNextSnaker(lastend);
}
//添加组件显示
int i = 0;
if(flag)
i=1;
for (; i < mySet.size(); i++) {
SnakerBody snakerb=((SnakerBody)mySet.get(i));
JLabel snakercomp=snakerb.snaker;
snakercomp.setLocation(snakerb.point);
getContentPane().add(snakercomp);
}
repaint();
}
private boolean isGameOver(SnakerBody head) {
//撞自身结束
for (int k = 1; k < mySet.size(); k++) {
SnakerBody bodynum=(SnakerBody)mySet.get(k);
if(head.point.x==bodynum.point.x&&head.point.y==bodynum.point.y){
overMessags();
return true;
}
}
//撞墙结束
int i=head.point.x/20;
int j=head.point.y/20;
if(!(i<=0||j<=0||i>=49||j>=29))
return false;
else
overMessags();
return true;
}
/*
* 结束游戏显示
*/
private void overMessags() {
int option=JOptionPane.showConfirmDialog(this, "得分:"+score+"。是否再来一次?", "游戏结束", JOptionPane.YES_NO_CANCEL_OPTION);
if(option==JOptionPane.OK_OPTION)
newGame();
else if(option==JOptionPane.NO_OPTION){
if (timer!=null&&timer.isRunning()) {
timer.stop();
}
//System.exit(0);
dispose();
}else{
timer.stop();
isOver=false;
removeKeyListener(keyListener);
jmenuItem[0][1].setEnabled(false);
jmenuItem[0][2].setEnabled(false);
jmenuItem[1][0].setEnabled(true);
jmenuItem[1][1].setEnabled(true);
jmenuItem[1][2].setEnabled(true);
}
}
/*
* 吃到,添加一个蛇身
*/
private void addNextSnaker(SnakerBody lastend) {
nextSnaker.direction=lastend.direction;
nextSnaker.point.x=lastend.point.x;
nextSnaker.point.y=lastend.point.y;
mySet.add(nextSnaker);
score+=1;
nextSnaker=nextBody();
}
/*
* 集合的封装类
* 将标签,位置,方向封装成一个类
*/
private class SnakerBody{
private Point point;
private String direction;
private JLabel snaker;
public SnakerBody(Point point,String direction,JLabel snaker){
this.point=point;
this.direction=direction;
this.snaker=snaker;
}
public SnakerBody(SnakerBody snakerlast){
this.point=new Point(snakerlast.point);
this.direction=snakerlast.direction;
this.snaker=snakerlast.snaker;
}
}
public static void main(String[] args) {
new RetroSnaker();
}
}