想好自己準備設計的風格之後,首先搭建基本框架,做出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();
}
}