想好自己准备设计的风格之后,首先搭建基本框架,做出GUI界面,然后构建游戏区具体内容,最后逐步添加遗漏和需要的功能设置。
我的snake思路:
首先编先一个MainFrame类:搭建整个游戏界面
(1) 定义三个级别商量,beginner,middle,expert:public static final int beginner=1,middle=2,expert=3;变量名均为大写
(2)定义菜单相关属性:接着定义个menubar和一个menu给menu起名字叫“难度”,然后添加JradioButtonMenuItem初级中级高级
private JRadioButtonMenuItem miBegin = new JRadioButtonMenuItem("初级");
private JRadioButtonMenuItem miMiddle = new JRadioButtonMenuItem("中级");
private JRadioButtonMenuItem miHard = new JRadioButtonMenuItem("高级");
(3)定义控制面板的属性
private JToolBar toolBar = new JToolBar();
private JButton jbtStart = new JButton("开始");//游戏开始按钮
private JButton jbtPause= new JButton("暂停");//游戏暂停按钮
private JButton jbtStop = new JButton("结束");//游戏退出按钮
private JButton jbtHelp = new JButton("帮助");//帮助按钮
(4) 定义游戏区
Private PlayPanel playPanel=new playPanel();
另建立一个PlayPanel extends Jpanel:
定义状态栏相关属性:
private JLabel jlScore = new JLabel("0");
private JLabel jlThroughBody = new JLabel("0");
private JLabel jlThroughWall = new JLabel("0");
private int score = 0;//当前得分
private int throughBody = 0;
private int throughWall = 0;
定义游戏区相关属性:
private static final int ROWS = 30;//游戏区行数
private static final int COLS = 50;//游戏区列数
private JButton[][] playBlocks;//游戏区的所有方块
定义蛇身相关属性
????????????????
private int length = 3;//蛇身的初始长度
private int[] rows = new int[ROWS*COLS];//记录蛇身每个方块的行号
private int[] columes = new int[ROWS*COLS];//记录蛇身每个方块的列号
public static final int UP = 1, LEFT = 2, DOWN = 3, RIGHT = 4;//贪食蛇运动方向
private int direction = RIGHT;
private int lastdirection = RIGHT;
?????????????????
private boolean lost = false;
public boolean isLost(){
return lost;
}
//设置蛇的运行方向
public void setSnakeDirection(int direction){
this.direction = direction;
}
//构造状态栏
JPanel statusPane = new JPanel();//状态栏面板
statusPane.add( new JLabel("得分:"));
statusPane.add(jlScore);
statusPane.add(new JLabel("穿身宝物:"));
statusPane.add(jlThroughBody);
statusPane.add(new JLabel("穿墙宝物:"));
statusPane.add(jlThroughWall);
//构造游戏区面板
JPanel showPane = new JPanel();//显示蛇身运动的游戏区面板
showPane.setLayout(new GridLayout(ROWS,COLS,0,0));
//设置边框
showPane.setBorder(BorderFactory.createEtchedBorder());
//创建并初始化游戏区方块
playBlocks = new JButton[ROWS][COLS];
for (int i = 0; i < ROWS; i++) {
for (int j = 0; j < COLS; j++) {
playBlocks[i][j] = new JButton();
playBlocks[i][j].setBackground(Color.LIGHT_GRAY);
playBlocks[i][j].setVisible(false);
playBlocks[i][j].setEnabled(false);
showPane.add(playBlocks[i][j]);
}
}
this.setLayout(new BorderLayout());
this.add(statusPane,BorderLayout.NORTH);
this.add(showPane,BorderLayout.CENTER);
定义一个createSnake类创建Snake
length=3;//蛇身初始长度
score = 0;//当前得分
throughBody = 0;//穿身宝物数
throughWall = 0; //穿墙宝物数
lost=false;//游戏结束标志
direction = RIGHT;//蛇身运动方向
lastdirection = RIGHT; //蛇身在改变运动方向前的运动方向
初始化蛇身的位置
for (int i = 0; i <= length; i++) {
rows[i] = 1;
columes[i] = length - i;
}
显示蛇身
for (int i = 0; i <= length; i++) {
playBlocks[rows[i]][columes[i]].setBackground(Color.green);
playBlocks[rows[i]][columes[i]].setVisible(true);
}
创建一个moveSnake类
去掉尾巴
playBlocks[rows[length]][columes[length]].setVisible(false); playBlocks[rows[length]][columes[length]].setBackground(Color.lightGray);
//移动除蛇头外蛇身
for (int i = length; i > 0; i--) {
rows[i] = rows[i - 1];
columes[i] = columes[i - 1];
}
//根据蛇身运动方向,决定蛇头位置
switch (direction) {
case UP:{
if (lastdirection == DOWN)
rows[0] += 1;
else {
rows[0] -= 1;
lastdirection = UP;
}
break;
}
case LEFT: {
if (lastdirection == RIGHT)
columes[0] += 1;
else {
columes[0] -= 1;
lastdirection = LEFT;
}
break;
}
case DOWN: {
if (lastdirection == UP)
rows[0] -= 1;
else {
rows[0] += 1;
lastdirection = DOWN;
}
break;
}
case RIGHT: {
if (lastdirection == LEFT)
columes[0] -= 1;
else {
columes[0] += 1;
lastdirection = RIGHT;
}
break;
}
}
//处理蛇头碰到墙壁时操作
if (rows[0] >= ROWS || rows[0] < 0 || columes[0] >= COLS || columes[0] < 0 ){
//处理有穿墙宝物时的穿墙操作
if (throughWall != 0) {
//更改穿墙宝物数,并更新状态栏
throughWall--;
jlThroughWall.setText(Integer.toString(throughWall));
//当蛇头碰到右侧墙壁时,蛇头从左侧墙壁重新进入
if (rows[0] >= ROWS) {
rows[0] = 0;
}
//当蛇头碰到左侧墙壁时,蛇头从右侧墙壁重新进入
else if (rows[0] < 0) {
rows[0] = ROWS - 1;
}
//当蛇头碰到底部墙壁时,蛇头从顶部墙壁重新进入
else if (columes[0] >= COLS) {
columes[0] = 0;
}
//当蛇头碰到顶部墙壁时,蛇头从底部墙壁重新进入
else if (columes[0] < 0) {
columes[0] = COLS - 1;
}
} //当没有穿墙宝物时,游戏结束
else {
lost = true;
return;
}
}
//蛇头碰到蛇身时的处理操作
if (playBlocks[rows[0]][columes[0]].getBackground().equals(Color.green)) {
if (throughBody != 0) {
throughBody--;
jlThroughBody.setText(Integer.toString(throughBody));
}
else {
lost = true;
return;
}
}
//蛇头吃完食物后,蛇身加长,并随机显示下一个食物或宝物
if (playBlocks[rows[0]][columes[0]].getBackground().equals(Color.yellow)
||playBlocks[rows[0]][columes[0]].getBackground().equals(Color.blue)
||playBlocks[rows[0]][columes[0]].getBackground().equals(Color.red)) {
length++;
createFood();
//更新状态栏
score += 100;
jlScore.setText(Integer.toString(score));
//获得穿墙宝物时的操作
if (playBlocks[rows[0]][columes[0]].getBackground().equals(Color.blue)) {
throughBody++;
jlThroughBody.setText(Integer.toString(throughBody));
}
//获得穿身宝物时的操作
if (playBlocks[rows[0]][columes[0]].getBackground().equals(Color.red)) {
throughWall++;
jlThroughWall.setText(Integer.toString(throughWall));
}
}
//显示蛇头
playBlocks[rows[0]][columes[0]].setBackground(Color.green);
playBlocks[rows[0]][columes[0]].setVisible(true);
// 在游戏区内随机放置食物
public void createFood(){
int x = 0;//食物行号
int y = 0;//食物列号
//随机生成食物位置,如果新位置是蛇身时,重新生成食物位置
do{
//随机生成食物的行
x = (int) (Math.random() * ROWS);
// 随机生成食物的列
y = (int) (Math.random() * COLS);
}while (playBlocks[x][y].isVisible()) ;
//生成随机数,用于决定食物的类型
int random = (int) (Math.random() * 10);
//当随机数小于7时,生成普通食物
if (random < 7) {
playBlocks[x][y].setBackground(Color.yellow);
}//当随机数介于7~9之间时,生成穿身宝物
else if (random < 9) {
playBlocks[x][y].setBackground(Color.blue);
}//当随机数大于等于9时,生成红色
else {
playBlocks[x][y].setBackground(Color.red);
}
playBlocks[x][y].setVisible(true);
}
最后清空游戏区
public void clear(){
for (int i = 0; i < ROWS; i++) {
for (int j = 0; j < COLS; j++) {
playBlocks[i][j].setBackground(Color.LIGHT_GRAY);
playBlocks[i][j].setVisible(false);
}
}
}
(5) 定义其他如:
SnakeThread thread = new SnakeThread();//游戏主线程
private boolean isPause = false;//游戏暂停标志
private boolean isEnd = true;//游戏结束标志
private int level = BEGINNER;//当前游戏级别
private int speed = 300;
private HelpDialog dlgHelp =null;
(6) 编写MainFrame构造方法:布局界面添加监听器
this.setJMenuBar(menuBar);
menuBar.add(mLevel);
ButtonGroup group = new ButtonGroup();
group.add(miBegin);
group.add(miMiddle);
group.add(miHard);
mLevel.add(miBegin);
mLevel.add(miMiddle);
mLevel.add(miHard);
miBegin.setSelected(true);
Container contentPane = this.getContentPane();
contentPane.add(toolBar,BorderLayout.NORTH);
toolBar.add(jbtStart);
toolBar.add(jbtPause);
toolBar.add(jbtStop);
toolBar.add(jbtHelp);
contentPane.add(playPane,BorderLayout.CENTER);
// 设置按钮初始状态
jbtStart.setFocusable(false);
jbtPause.setFocusable(false);
jbtStop.setFocusable(false);
jbtHelp.setFocusable(false);
jbtPause.setEnabled(false);
jbtStop.setEnabled(false);
MainFrameActionListener actionListener = new MainFrameActionListener();
jbtStart.addActionListener(actionListener);
jbtPause.addActionListener(actionListener);
jbtStop.addActionListener(actionListener);
jbtHelp.addActionListener(actionListener);
miBegin.addActionListener(actionListener);
miMiddle.addActionListener(actionListener);
miHard.addActionListener(actionListener);
MainFrameKeyListener keyListener = new MainFrameKeyListener();
this.addKeyListener(keyListener);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
(7) 编写一个线程SnakeThread extends Thread
public void run() {
while (true) {
try {
//停顿
Thread.sleep(speed);
//当游戏处于正常运行状态,则移动蛇身
if (!isEnd && !isPause) {
playPane.moveSnake();
if(playPane.isLost()){
isEnd = true;
//记着这个东西
JOptionPane.showMessageDialog(null, "游戏结束!");
isPause = false;
playPane.clear();
jbtStart.setEnabled(true);
jbtPause.setText("暂停");
jbtPause.setEnabled(false);
jbtStop.setEnabled(false);
}
}
}
catch (Exception ex){}
}
}
(8) 完成MainFrameActionListener implements ActionListener:
public void actionPerformed(ActionEvent e){
//当用户点击开始时执行
if(e.getSource()==jbtStart){
//初始化状态
isEnd = false;
isPause = false;
//创建贪食蛇
playPane.createSnake();
//随机摆放食物
playPane.createFood();
try {
//启动游戏
thread.start();
}
catch (Exception ex) {
}
jbtStart.setEnabled(false);
jbtPause.setEnabled(true);
jbtStop.setEnabled(true);
}else if(e.getSource()==jbtPause){
if (isPause == true ) {
jbtPause.setText("暂停");
}else if (isPause == false) {
jbtPause.setText("继续");
}
isPause = !isPause;
}else if(e.getSource()==jbtStop){
isEnd = true;
isPause = false;
playPane.clear();
jbtStart.setEnabled(true);
jbtPause.setText("暂停");
jbtPause.setEnabled(false);
jbtStop.setEnabled(false);
}else if(e.getSource()==jbtHelp){
if(dlgHelp==null)
dlgHelp=new HelpDialog();
//明白下面这些东西
Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
Dimension frameSize = dlgHelp.getSize();
if (frameSize.height > screenSize.height) {
frameSize.height = screenSize.height;
}
if (frameSize.width > screenSize.width) {
frameSize.width = screenSize.width;
}
dlgHelp.setLocation((screenSize.width - frameSize.width) / 2, (screenSize.height - frameSize.height) / 2);
dlgHelp.setVisible(true);
}else if(e.getSource()==miBegin){
speed=300;
}else if(e.getSource()==miMiddle){
speed=200;
}else if(e.getSource()==miHard){
speed=100;
}
}
(9) 编写MainFrameKeyListener extends KeyAdapter
//判断游戏状态
if (!isEnd && !isPause) {
//根据用户按键,设置蛇运动方向
if (e.getKeyCode() == KeyEvent.VK_UP) {
playPane.setSnakeDirection(PlayPanel.UP);
}
if (e.getKeyCode() == KeyEvent.VK_DOWN) {
playPane.setSnakeDirection(PlayPanel.DOWN);
}
if (e.getKeyCode() == KeyEvent.VK_LEFT) {
playPane.setSnakeDirection(PlayPanel.LEFT);
}
if (e.getKeyCode() == KeyEvent.VK_RIGHT) {
playPane.setSnakeDirection(PlayPanel.RIGHT);
}
}
}
另编写一个HelpDialog类如:
public class HelpDialog extends JDialog {
JPanel panel1 = new JPanel();
BorderLayout borderLayout1 = new BorderLayout();
JTextArea jTextArea1 = new JTextArea();
private String help = "游戏说明:/n1 :方向键控制蛇移动的方向."+
"/n2 :按开始键开始游戏."+
"/n3 :按暂停键可以暂停游戏,再按暂停键能继续玩游戏."+
"/n4 :黄色为普通食物,吃一个得100分."+
"/n5 :青色为穿身宝物,吃一个得100分,该宝物允许玩家穿过一次蛇身"+
"/n6 :红色为穿墙宝物,吃一个得100分,该宝物允许玩家穿过一次墙壁."+
"/n7 :当分数到达一定时,会自动升级.当到达最高级别时就没有升级了.";
GridBagLayout gridBagLayout1 = new GridBagLayout();
public HelpDialog(Frame frame, String title, boolean modal) {
super(frame, title, modal);
try {
jbInit();
pack();
}
catch(Exception ex) {
ex.printStackTrace();
}
}
public HelpDialog() {
this(null, "", false);
}
private void jbInit() throws Exception {
panel1.setLayout(borderLayout1);
jTextArea1.setBackground(SystemColor.control);
jTextArea1.setEditable(false);
jTextArea1.setText(help);
this.setResizable(false);
this.setTitle("帮助");
this.getContentPane().setLayout(gridBagLayout1);
getContentPane().add(panel1, new GridBagConstraints(0, 0, 1, 1, 1.0, 1.0
,GridBagConstraints.CENTER, GridBagConstraints.BOTH, new Insets(0, 0, 0, 0), 45, 83));
panel1.add(jTextArea1, BorderLayout.CENTER);
}
}
创建一个Snake类,调用游戏
package snake;
import java.awt.*;
public class Snake {
//Construct the application
public Snake() {
MainFrame frame = new MainFrame();
frame.setTitle("贪食蛇游戏-作者:07502班支健丞");
frame.setSize(760,574);
frame.setResizable(false);
//Center the window
//Toolkit是一个工具类.不需要实例化.getDefaultToolkit()是他的一个静态方法.这个方法的 返回值(在此处为对象)还有一个方法getScreenSize(),最后的这个方法返回一个Dimension类型的对象.是返回当先分辨率的.
Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
Dimension frameSize = frame.getSize();
if (frameSize.height > screenSize.height) {
frameSize.height = screenSize.height;
}
if (frameSize.width > screenSize.width) {
frameSize.width = screenSize.width;
}
frame.setLocation((screenSize.width - frameSize.width) / 2, (screenSize.height - frameSize.height) / 2);
frame.setVisible(true);
}
//Main method
public static void main(String[] args) {
new Snake();
}
}