
本博客记录我这个小白开始涉略Swing的界面设计咯,今天就奉献出自己学习贪吃蛇的的代码,一些也是从网上大牛那学来的,嘻嘻,就当我这个小白认真学习的见证吧! ps:Cc
SnakeView.class//关于贪吃蛇的游戏界面类
(用到了观察者observer和被观察者observable)
1 package GreedSnake;
2
3 import java.awt.BorderLayout;
4 import java.awt.Canvas;
5 import java.awt.Color;
6 import java.awt.Dimension;
7 import java.awt.FlowLayout;
8 import java.awt.Graphics;
9 import java.awt.GraphicsConfiguration;
10 import java.awt.HeadlessException;
11 import java.util.Iterator;
12 import java.util.LinkedList;
13 import java.util.Observable;
14 import java.util.Observer;
15
16 import javax.swing.JFrame;
17 import javax.swing.JLabel;
18 import javax.swing.JPanel;
19 import javax.swing.JTextField;
20 import javax.swing.UIManager;
21
22 import GreedSnake.SnakeModel.Node;
23
24 public class SnakeView extends JFrame implements Observer
25 {
26 SnakeControl control;
27 SnakeModel model;
28 Canvas gameCanvas;
29 JLabel scorelable;
30 public static final int gameWidth=600;
31 public static final int gameHeight=600;
32 public static final int nodeWidth = 10;//
33 public static final int nodeHeight = 10;
34 public SnakeView(SnakeModel model,SnakeControl control)//传入蛇SnakeModel对象以及KeyListener
35 {
36 super("My GreedSnake");
37 setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
38 this.control=control;
39 this.model=model;
40 BorderLayout layout=new BorderLayout();//边界布局,组件必须指定方向(NORTH...)
41 setLayout(layout);
42 //上面
43 scorelable=new JLabel();//添加上面的计分板
44 add(scorelable,BorderLayout.NORTH);
45 //中间
46 gameCanvas=new Canvas();//添加游戏界面,利用Canvas画板
47 gameCanvas.setSize(gameWidth+10,gameHeight+10);//设置画板的尺寸,
48 // 10代表与右边距离
49 //gameCanvas.addKeyListener(control);
50 add(gameCanvas,BorderLayout.CENTER);
51
52 JPanel panelhaha = new JPanel();
53 panelhaha.setLayout(new BorderLayout());
54 JLabel labelHelp;
55 labelHelp=new JLabel("CC PLAY Snake",JLabel.CENTER);
56 panelhaha.add(labelHelp,BorderLayout.NORTH);
57 add(panelhaha, BorderLayout.SOUTH);
58
59 this.pack();//来使得框架尽可能适应组件大小
60 this.addKeyListener(control);//添加keyListener的触发事件,控制蛇运动
61 setResizable(false);//使得窗口无法变化大小
62 setVisible(true);
63
64 }
65 public void update(Observable o, Object arg)
66 {
67 repaint();//update是observer的setchange()
68 }
69 public void repaint()
70 {
71 Graphics p=gameCanvas.getGraphics();
72 //对贪吃蛇界面进行画刷的颜色填充
73 p.setColor(Color.black);
74 p.fillRect(0,0, gameWidth, gameHeight);
75 //对蛇体进行矩阵填充节点
76 p.setColor(Color.white);
77 LinkedList snake=model.nodeSnake;
78 Iterator it=snake.iterator();//迭代器获取LinkList
79 while(it.hasNext())
80 {
81 Node n=(Node)it.next();
82 drawNode(p,n);
83 }
84 scorelable.setText("Code by CC:");
85
86 //对食物进行矩阵的填充
87 p.setColor(Color.red);
88 Node n=model.food;
89 drawNode(p, n);
90 }
91 private void drawNode(Graphics g,Node n)
92 {
93 g.fillRect(n.x*nodeWidth, n.y*nodeHeight, nodeWidth-1,nodeHeight-1);/*设置 Snake 节点Size
94 =(0,canvaswight/nodeWidth) 因为要保证每个结点能够以10为单位*/
95 }
96 public static void main(String args[])
97 {
98 SnakeModel model=new SnakeModel(60,60);
99 SnakeControl control=new SnakeControl(model);
100 SnakeView snakeView=new SnakeView(model, control);
101 model.addObserver(snakeView);//将SnakeView设置为model的一个观察者
102 (new Thread(model)).start();//为SnakeModel开一个线程
103 }
104 }
SnakeModel.class//关于蛇的系列操作以及蛇的坐标,方向设置
1 package GreedSnake;
2
3 import java.util.Arrays;
4 import java.util.LinkedList;
5 import java.util.Observable;
6 import java.util.Random;
7
8 import javax.swing.JOptionPane;
9
10 public class SnakeModel extends Observable implements Runnable
11 {
12 boolean[][]matrix;//指示当前位子是否有蛇体或者食物
13 LinkedList nodeSnake=new LinkedList();
14 Node food;
15 int score;
16 boolean pause=false;//设置游戏中断
17 //初始化60,60,画面(0,0)-(59,59)
18 int maxX;//画面的最大横坐标
19 int maxY;//画面的最大纵坐标
20 int direction=2; //指示蛇运行的方向
21 boolean running =false;//指示蛇是否在运动
22 public static final int UP=2;
23 public static final int DOWN=4;
24 public static final int LEFT=1;
25 public static final int RIGHT=3;
26 public SnakeModel(int maxX,int maxY)
27 {
28 this.maxX=maxX;
29 this.maxY=maxY;
30 reset();//初始化游戏
31 }
32 public void reset()
33 {
34 direction=SnakeModel.DOWN;
35 pause=false;
36 matrix=new boolean[maxX][];
37 for(int i=0;i<maxX;i++)
38 {
39 matrix[i]=new boolean[maxY];
40 Arrays.fill(matrix[i],false);
41 }
42
43 //Init Snake
44 int initArrayLength = maxX > 60 ? 30 : maxX / 2;//初始化蛇的长度
45 nodeSnake.clear();
46 for(int i=0;i<initArrayLength;i++)
47 {
48 int x=maxX/2+i;
49 int y=maxY/2;
50 nodeSnake.addLast(new Node(x, y));//不断向蛇尾初始化节点
51 matrix[x][y]=true;
52 }
53
54 //Create food
55 food=createfood();//获得初始化食物坐标
56 matrix[food.x][food.y]=true;
57 }
58 public void Changedirection(int Newdirection)
59 {
60 if(direction%2!=Newdirection%2)//若与当前方向相反或者一样,则不变方向
61 direction=Newdirection;
62 }
63 public boolean moveon()
64 {
65 Node n=(Node)nodeSnake.getFirst();//蛇头+direction来判断下一步
66 int x=n.x;
67 int y=n.y;
68 //根据方向判断走向
69 switch (direction)
70 {
71 case UP:
72 y--;
73 break;
74 case DOWN:
75 y++;
76 break;
77 case LEFT:
78 x--;
79 break;
80 case RIGHT:
81 x++;
82 break;
83 }
84 if((x>=0&&x<=maxX-1)&&(y>=0&&y<=maxY-1))//判断是否在画面中
85 {
86 if(matrix[x][y])
87 {
88 if(food.x==x&&food.y==y)
89 {
90 nodeSnake.addFirst(food);
91
92 food=createfood();
93 matrix[food.x][food.y]=true;
94 return true;
95 }
96 else return false;
97 }
98 else
99 {
100 //将尾巴放到头部
101 nodeSnake.addFirst(new Node(x, y));
102 matrix[x][y]=true;
103 n=(Node)nodeSnake.removeLast();
104 matrix[n.x][n.y]=false;
105 return true;
106 }
107 }
108 return false;//触到边界
109 }
110 public Node createfood()
111 {
112 int x=0;
113 int y=0;
114 do//生成食物节点的坐标
115 {
116 Random r=new Random();
117 x=r.nextInt(maxX);
118 y=r.nextInt(maxY);
119 } while (matrix[x][y]);
120 return new Node(x, y);
121 }
122 class Node
123 {
124 int x;
125 int y;
126 Node(int x,int y)
127 {
128 this.x=x;
129 this.y=y;
130 }
131 }
132 public void run()
133 {
134 running=true;
135 while(running)
136 {
137 try
138 {
139 Thread.sleep(100);
140 } catch (InterruptedException e)
141 {
142 e.printStackTrace();
143 }
144 if(!pause)
145 {
146 if(moveon())
147 {
148 // if(score>=100)
149 // {
150 // JOptionPane.showMessageDialog(null, "猪智23333333", "Game Over",
151 // JOptionPane.INFORMATION_MESSAGE);
152 // }
153 //用来判断Observer的对象是否发生更新
154 //若更新,则触发SnakeViewd的update()来重绘画面
155 setChanged();
156 notifyObservers();
157 }
158 else{
159 JOptionPane.showMessageDialog(null, "you have failed", "Game Over",
160 JOptionPane.INFORMATION_MESSAGE);//跳出结束文本框
161 break;
162 }
163 }
164 }
165 running=false;
166 }
167 public void StopSnake()
168 {
169 pause=!pause;
170 }
171 }
SnakeControl.class//关于键盘对蛇的方向操作以及中断继续游戏的操作
1 package GreedSnake;
2
3 import java.awt.event.KeyEvent;
4 import java.awt.event.KeyListener;
5
6 public class SnakeControl implements KeyListener
7 {
8 SnakeModel model;
9 public SnakeControl(SnakeModel model)
10 {
11 this.model=model;
12 }
13 public void keyPressed(KeyEvent e)
14 {
15 int keyCode=e.getKeyCode();//获取当前键盘的键值
16 if(model.running)//Snake is running
17 {
18 switch (keyCode)
19 {
20 case KeyEvent.VK_UP:
21 model.Changedirection(SnakeModel.UP);
22 break;
23 case KeyEvent.VK_DOWN:
24 model.Changedirection(SnakeModel.DOWN);
25 break;
26 case KeyEvent.VK_LEFT:
27 model.Changedirection(SnakeModel.LEFT);
28 break;
29 case KeyEvent.VK_RIGHT:
30 model.Changedirection(SnakeModel.RIGHT);
31 break;
32 case KeyEvent.VK_SPACE:
33 model.StopSnake();;
34 break;
35 }
36 }
37 if(keyCode==KeyEvent.VK_ENTER)
38 model.reset();
39 }
40 @Override
41 public void keyReleased(KeyEvent e)
42 {
43 // TODO 自动生成的方法存根
44
45 }
46 @Override
47 public void keyTyped(KeyEvent e)
48 {
49 // TODO 自动生成的方法存根
50
51 }
52
53 }