求VS得贪吃蛇源代码!谢谢大神 还有个问题在VS中写#include<Windows.h>应输入预处理器指令

JavaScript016

求VS得贪吃蛇源代码!谢谢大神 还有个问题在VS中写#include<Windows.h>应输入预处理器指令,第1张

// Snake.cpp

#include <windows.h>

#include <tchar.h>

#include <atlimage.h>

#include <deque>

using namespace std

#include <Mmsystem.h>

#pragma comment( lib,"winmm.lib" )

const UINT MAX_LOADSTRING = 40

TCHAR szTitle[MAX_LOADSTRING] = "贪吃蛇 js简化版1.1"

TCHAR szWindowClass[MAX_LOADSTRING] = "Snake"

ATOM MyRegisterClass(HINSTANCE hInstance)

LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM)

const UINT BMP_WIDTH = 600

const UINT BMP_HEGITH = 600

HWND g_hWnd

HDC g_hDC

HDC g_hBufDC

HBITMAP g_hBufBmp

CImage g_Bg //背景图

CImage g_Snake //蛇图

CImage g_Food //食物图

CImage g_Head //蛇头图

CImage g_Rear //蛇尾图

CImage g_Shibai //死亡图

deque<POINT> g_SnakeDeque //蛇位置队列

POINT g_FoodPos //食物位置

int iSnakeDir //蛇位置方向

enum DIR_ENUM { DIR_UP,DIR_DN,DIR_LT,DIR_RT }  //枚举4个方向

int iKey  //记录玩家按下的按键值

int iLife = 3 //三条生命

bool bIsDie = false //是否死亡过

bool bAtc = false

POINT ptHead

void GameInit() //游戏初始化

void GameFrame() //游戏帧

void InputProcess() //输入处理

void LogicProcess() //逻辑处理

void WndDrawProcess() //窗口图形绘制

//判断pt点是否在蛇身

bool IsInSnake( POINT pt )

{

for (UINT i=0i<g_SnakeDeque.size()i++)

{

if (g_SnakeDeque[i].x == pt.x && g_SnakeDeque[i].y == pt.y)

{

return true

}

}

return false

}

//随机食物位置

void FoodRand()

{

do 

{

g_FoodPos.x = rand()%20*30  //宽600,最多有20个30,随机一下

g_FoodPos.y = rand()%20*30

} while (IsInSnake(g_FoodPos))

}

void GameInit()

{

g_hDC = GetDC(g_hWnd)

g_hBufDC = CreateCompatibleDC(g_hDC)

g_hBufBmp = CreateCompatibleBitmap(g_hDC,BMP_WIDTH,BMP_HEGITH)

SelectObject(g_hBufDC,g_hBufBmp)

ReleaseDC(g_hWnd,g_hDC)

g_Bg.Load("bg.png")

g_Snake.Load("snake.png")

g_Food.Load("food.png")

g_Head.Load("head.png")

g_Rear.Load("rear.png")

g_Shibai.Load("sbai.png")

POINT ptSnake = {300,300} //定义蛇位置

g_SnakeDeque.push_back(ptSnake)//位置加入队列中

iSnakeDir = rand()%4 //随机蛇运动方向

mciSendString( "open bg.mp3 alias bgMusic",NULL,0,NULL ) //发送MIC命令:打开bgMusic.mp3文件,并命名为 bgMusic 记住这名字很重要

mciSendString( "play bgMusic from 0 repeat",NULL,0,NULL )//从0开始播放bgMusic,并重复播放 其他的命令还算有stop,pause等

//以此类推,先读取了吃到食物和死亡的音乐,在指定位置播放

mciSendString( "open eat.wav alias eatMusic",NULL,0,NULL ) //同上(能支持CD,MP3,wav,midi,avi等格式,不支持rm或rmvb或ogg等)

mciSendString( "open die.wav alias dieMusic",NULL,0,NULL ) //同上

srand( timeGetTime() ) //随机种子,使得每次随机不一样

FoodRand()

}

void GameFrame()

{

static  int iStep = timeGetTime() //速度限制一下

if( timeGetTime()-iStep > 300 ) //300毫秒移动一次,想快点可以改,也可以作为难度递增,改小此值

{

iStep = timeGetTime()

InputProcess()

LogicProcess()

}

WndDrawProcess()

}

void InputProcess() //输入处理

{

//控制蛇运动

if( iKey == VK_UP ) //如果按下“上”键,其他按键可以自己改,VK_开头,如果是字母或数字按键,则对应ASCII码

{

if( iSnakeDir == DIR_LT || iSnakeDir == DIR_RT ) //若蛇正往左右走时才能改变

{

iSnakeDir = DIR_UP

}

}

else if(  iKey == VK_DOWN ) //以此类推

{

if( iSnakeDir == DIR_LT || iSnakeDir == DIR_RT )

{

iSnakeDir = DIR_DN

}

}

else if(  iKey == VK_LEFT )

{

if( iSnakeDir == DIR_UP || iSnakeDir == DIR_DN )

{

iSnakeDir = DIR_LT

}

}

else if(  iKey == VK_RIGHT )

{

if( iSnakeDir == DIR_UP || iSnakeDir == DIR_DN )

{

iSnakeDir = DIR_RT

}

}

//蛇运动,其实蛇的运动就是蛇头根据方向往前走一步,而蛇尾去掉一步,

//如果转化为算法就是在队列前根据方向加入一个节点,去掉队列最后一个节点,好好理解,算法的重要性

ptHead = g_SnakeDeque.front() //获取第一个节点

if( iSnakeDir == DIR_UP )

{

ptHead.y -= 30

}

else if( iSnakeDir == DIR_DN )

{

ptHead.y += 30

}

else if( iSnakeDir == DIR_LT )

{

ptHead.x -= 30

}

else if( iSnakeDir == DIR_RT )

{

ptHead.x += 30

}

}

void LogicProcess() //逻辑处理

{

//蛇出界了或者蛇吃到自己身体了,需要死掉

if( ptHead.x < 0 || ptHead.x >= 600 || ptHead.y <0 || ptHead.y >= 600 || IsInSnake(ptHead) )

{

mciSendString( "play dieMusic from 0",NULL,0,NULL ) //播放死亡音乐

g_SnakeDeque.clear() //全清

POINT ptSnake = {300,300} //定义蛇的位置

g_SnakeDeque.push_back( ptSnake ) //放入蛇的节点中

iSnakeDir = rand()%4 //随机蛇运动方向

iLife-- //死亡,生命减1

if( iLife <= 0 )

{

bIsDie = true

g_hDC = GetDC(g_hWnd)

g_Shibai.Draw(g_hDC,0,0)

ReleaseDC(g_hWnd,g_hDC)

int ret = MessageBox(g_hWnd,"3次生命已用完 \n 是否重新开始程序!","提示",MB_OKCANCEL)

if (ret == IDOK)

{

FoodRand()

return

}

DestroyWindow(g_hWnd) //摧毁关闭窗口

return

}

}

else if( ptHead.x==g_FoodPos.x && ptHead.y==g_FoodPos.y ) //蛇吃到食物

{

mciSendString( "play eatMusic from 0",NULL,0,NULL ) //播放吃到食物音乐

g_SnakeDeque.push_front( ptHead ) //新的位置加入蛇头,蛇头往前移动

//g_SnakeDeque.pop_back() //和正常行走最大的不同

FoodRand() //重新随机食物

}

else //无出界,无吃到自身,无吃到食物,正常行走

{

g_SnakeDeque.push_front( ptHead ) //新的位置加入蛇头,蛇头往前移动

g_SnakeDeque.pop_back() //删除最后节点,蛇尾往前收

}

}

void WndDrawProcess() //绘图处理

{

RECT rc = {0,0,BMP_WIDTH,BMP_HEGITH}

FillRect(g_hBufDC,&rc,(HBRUSH)GetStockObject(WHITE_BRUSH))

g_Bg.Draw(g_hBufDC,0,0)//绘制背景

g_hDC = GetDC(g_hWnd)

for( UINT i=0 i<g_SnakeDeque.size() i++ ) //遍历蛇的节点,绘画蛇的样子

{

if( i== 0 )

{

g_Head.Draw( g_hBufDC, g_SnakeDeque[i].x, g_SnakeDeque[i].y ) //绘画蛇头

}

else if( i == g_SnakeDeque.size()-1 )

{

g_Rear.Draw( g_hBufDC, g_SnakeDeque[i].x, g_SnakeDeque[i].y ) //绘画蛇尾

}

else

{

g_Snake.Draw( g_hBufDC, g_SnakeDeque[i].x, g_SnakeDeque[i].y ) //绘画蛇身,把蛇的样子画到指点位置节点上

}

}

//绘画食物

g_Food.Draw( g_hBufDC, g_FoodPos.x, g_FoodPos.y )

if (bIsDie)

{

iLife = 3

bIsDie = false

}

//绘画生命数

char sz[32] = {0}

for( int i=0 i<iLife i++ )

{

strcat_s( sz, " ★") //根据生命数,加入红心

}

SetTextColor( g_hBufDC, RGB(255,0,0) )//设置字体颜色为红色

SetBkMode( g_hBufDC,TRANSPARENT ) //设置字体背景颜色为透明

TextOut( g_hBufDC,0,0,sz,strlen(sz)) //输出字体

BitBlt(g_hDC,0,0,BMP_WIDTH,BMP_HEGITH,g_hBufDC,0,0,SRCCOPY)

ReleaseDC(g_hWnd,g_hDC)

}

int APIENTRY _tWinMain(HINSTANCE hInstance,

   HINSTANCE /*hPrevInstance*/,

   LPTSTR    /*lpCmdLine*/,

   int       nCmdShow)

{

MSG msg

MyRegisterClass(hInstance)

int iW = 600+GetSystemMetrics(SM_CXFIXEDFRAME)*2

int iH = 600+GetSystemMetrics(SM_CYFIXEDFRAME)*2+GetSystemMetrics(SM_CYCAPTION)

int iX = (GetSystemMetrics(SM_CXSCREEN)-iW)/2

int iY = (GetSystemMetrics(SM_CYSCREEN)-iH)/2

g_hWnd = CreateWindow(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW,

iX, iY, iW, iH, NULL, NULL, hInstance, NULL)

if (!g_hWnd)

{

return FALSE

}

GameInit()

ShowWindow(g_hWnd, nCmdShow)

UpdateWindow(g_hWnd)

ZeroMemory(&msg,sizeof(MSG))

while (msg.message != WM_QUIT)

{

if (PeekMessage(&msg, NULL, 0, 0,PM_REMOVE))

{

TranslateMessage(&msg)

DispatchMessage(&msg)

}

else if(!bAtc)

{

GameFrame()

}

else

{

::WaitMessage()

}

}

return (int) msg.wParam

}

ATOM MyRegisterClass(HINSTANCE hInstance)

{

WNDCLASSEX wcex

wcex.cbSize = sizeof(WNDCLASSEX)

wcex.style = CS_HREDRAW | CS_VREDRAW

wcex.lpfnWndProc = WndProc

wcex.cbClsExtra = 0

wcex.cbWndExtra = 0

wcex.hInstance = hInstance

wcex.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_SNAKE))

wcex.hCursor = LoadCursor(NULL, IDC_ARROW)

wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1)

wcex.lpszMenuName = NULL

wcex.lpszClassName = szWindowClass

wcex.hIconSm = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL))

return RegisterClassEx(&wcex)

}

LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)

{

switch (message)

{

case WM_KILLFOCUS:

bAtc = true

break

case WM_SETFOCUS:

bAtc = false

break

case WM_KEYDOWN:

iKey = wParam //玩家按下按键是捕获按键值

break

case WM_DESTROY:

DeleteObject(g_hBufBmp)

DeleteDC(g_hBufDC)

PostQuitMessage(0)

break

default:

return DefWindowProc(hWnd, message, wParam, lParam)

}

return 0

}

贪吃蛇

import java.awt.*

import java.awt.event.*

public class GreedSnake //主类

{

/**

* @param args

*/

public static void main(String[] args) {

// TODO Auto-generated method stub

new MyWindow()

}

}

class MyPanel extends Panel implements KeyListener,Runnable//自定义面板类,继承了键盘和线程接口

{

Button snake[]//定义蛇按钮

int shu=0//蛇的节数

int food[]//食物数组

boolean result=true//判定结果是输 还是赢

Thread thread//定义线程

static int weix,weiy//食物位置

boolean t=true//判定游戏是否结束

int fangxiang=0//蛇移动方向

int x=0,y=0//蛇头位置

MyPanel()

{

setLayout(null)

snake=new Button[20]

food=new int [20]

thread=new Thread(this)

for(int j=0j<20j++)

{

food[j]=(int)(Math.random()*99)//定义20个随机食物

}

weix=(int)(food[0]*0.1)*60//十位*60为横坐标

weiy=(int)(food[0]%10)*40//个位*40为纵坐标

for(int i=0i<20i++)

{

snake[i]=new Button()

}

add(snake[0])

snake[0].setBackground(Color.black)

snake[0].addKeyListener(this)//为蛇头添加键盘监视器

snake[0].setBounds(0,0,10,10)

setBackground(Color.cyan)

}

public void run() //接收线程

{

while(t)

{

if(fangxiang==0)//向右

{

try

{

x+=10

snake[0].setLocation(x, y)//设置蛇头位置

if(x==weix&&y==weiy) //吃到食物

{

shu++

weix=(int)(food[shu]*0.1)*60

weiy=(int)(food[shu]%10)*40

repaint()//重绘下一个食物

add(snake[shu])//增加蛇节数和位置

snake[shu].setBounds(snake[shu-1].getBounds())

}

thread.sleep(100)//睡眠100ms

}

catch(Exception e){}

}

else if(fangxiang==1)//向左

{

try

{

x-=10

snake[0].setLocation(x, y)

if(x==weix&&y==weiy)

{

shu++

weix=(int)(food[shu]*0.1)*60

weiy=(int)(food[shu]%10)*40

repaint()

add(snake[shu])

snake[shu].setBounds(snake[shu-1].getBounds())

}

thread.sleep(100)

}

catch(Exception e){}

}

else if(fangxiang==2)//向上

{

try

{

y-=10

snake[0].setLocation(x, y)

if(x==weix&&y==weiy)

{

shu++

weix=(int)(food[shu]*0.1)*60

weiy=(int)(food[shu]%10)*40

repaint()

add(snake[shu])

snake[shu].setBounds(snake[shu-1].getBounds())

}

thread.sleep(100)

}

catch(Exception e){}

}

else if(fangxiang==3)//向下

{

try

{

y+=10

snake[0].setLocation(x, y)

if(x==weix&&y==weiy)

{

shu++

weix=(int)(food[shu]*0.1)*60

weiy=(int)(food[shu]%10)*40

repaint()

add(snake[shu])

snake[shu].setBounds(snake[shu-1].getBounds())

}

thread.sleep(100)

}

catch(Exception e){}

}

int num1=shu

while(num1>1)//判断是否咬自己的尾巴

{

if(snake[num1].getBounds().x==snake[0].getBounds().x&&snake[num1].getBounds().y==snake[0].getBounds().y)

{

t=false

result=false

repaint()

}

num1--

}

if(x<0||x>=this.getWidth()||y<0||y>=this.getHeight())//判断是否撞墙

{

t=false

result=false

repaint()

}

int num=shu

while(num>0) //设置蛇节位置

{

snake[num].setBounds(snake[num-1].getBounds())

num--

}

if(shu==15) //如果蛇节数等于15则胜利

{

t=false

result=true

repaint()

}

}

}

public void keyPressed(KeyEvent e) //按下键盘方向键

{

if(e.getKeyCode()==KeyEvent.VK_RIGHT)//右键

{

if(fangxiang!=1)//如果先前方向不为左

fangxiang=0

}

else if(e.getKeyCode()==KeyEvent.VK_LEFT)

{ if(fangxiang!=0)

fangxiang=1

}

else if(e.getKeyCode()==KeyEvent.VK_UP)

{ if(fangxiang!=3)

fangxiang=2

}

else if(e.getKeyCode()==KeyEvent.VK_DOWN)

{ if(fangxiang!=2)

fangxiang=3

}

}

public void keyTyped(KeyEvent e)

{

}

public void keyReleased(KeyEvent e)

{

}

public void paint(Graphics g) //在面板上绘图

{

int x1=this.getWidth()-1

int y1=this.getHeight()-1

g.setColor(Color.red)

g.fillOval(weix, weiy, 10, 10)//食物

g.drawRect(0, 0, x1, y1)//墙

if(t==false&&result==false)

g.drawString("GAME OVER!", 250, 200)//输出游戏失败

else if(t==false&&result==true)

g.drawString("YOU WIN!", 250, 200)//输出游戏成功

}

}

class MyWindow extends Frame implements ActionListener//自定义窗口类

{

MyPanel my

Button btn

Panel panel

MyWindow()

{

super("GreedSnake")

my=new MyPanel()

btn=new Button("begin")

panel=new Panel()

btn.addActionListener(this)

panel.add(new Label("begin后请按Tab键选定蛇"))

panel.add(btn)

panel.add(new Label("按上下左右键控制蛇行动"))

add(panel,BorderLayout.NORTH)

add(my,BorderLayout.CENTER)

setBounds(100,100,610,500)

setVisible(true)

validate()

addWindowListener(new WindowAdapter()

{

public void windowClosing(WindowEvent e)

{

System.exit(0)

}

})

}

public void actionPerformed(ActionEvent e)//按下begin按钮

{

if(e.getSource()==btn)

{

try

{

my.thread.start()//开始线程

my.validate()

}

catch(Exception ee){}

}

}

}

用MVC方式实现的贪吃蛇游戏,共有4个类。运行GreedSnake运行即可。主要是观察者模式的使用,我已经添加了很多注释了。

1、

/*

* 程序名称:贪食蛇

* 原作者:BigF

* 修改者:algo

* 说明:我以前也用C写过这个程序,现在看到BigF用Java写的这个,发现虽然作者自称是Java的初学者,

* 但是明显编写程序的素养不错,程序结构写得很清晰,有些细微得地方也写得很简洁,一时兴起之

* 下,我认真解读了这个程序,发现数据和表现分开得很好,而我近日正在学习MVC设计模式,

* 因此尝试把程序得结构改了一下,用MVC模式来实现,对源程序得改动不多。

* 我同时也为程序增加了一些自己理解得注释,希望对大家阅读有帮助。

*/

package mvcTest

/**

* @author WangYu

* @version 1.0

* Description:

* </pre>

* Create on :Date :2005-6-13 Time:15:57:16

* LastModified:

* History:

*/

public class GreedSnake {

public static void main(String[] args) {

SnakeModel model = new SnakeModel(20,30)

SnakeControl control = new SnakeControl(model)

SnakeView view = new SnakeView(model,control)

//添加一个观察者,让view成为model的观察者

model.addObserver(view)

(new Thread(model)).start()

}

}

-------------------------------------------------------------

2、

package mvcTest

//SnakeControl.java

import java.awt.event.KeyEvent

import java.awt.event.KeyListener

/**

* MVC中的Controler,负责接收用户的操作,并把用户操作通知Model

*/

public class SnakeControl implements KeyListener{

SnakeModel model

public SnakeControl(SnakeModel model){

this.model = model

}

public void keyPressed(KeyEvent e) {

int keyCode = e.getKeyCode()

if (model.running){ // 运行状态下,处理的按键

switch (keyCode) {

case KeyEvent.VK_UP:

model.changeDirection(SnakeModel.UP)

break

case KeyEvent.VK_DOWN:

model.changeDirection(SnakeModel.DOWN)

break

case KeyEvent.VK_LEFT:

model.changeDirection(SnakeModel.LEFT)

break

case KeyEvent.VK_RIGHT:

model.changeDirection(SnakeModel.RIGHT)

break

case KeyEvent.VK_ADD:

case KeyEvent.VK_PAGE_UP:

model.speedUp()

break

case KeyEvent.VK_SUBTRACT:

case KeyEvent.VK_PAGE_DOWN:

model.speedDown()

break

case KeyEvent.VK_SPACE:

case KeyEvent.VK_P:

model.changePauseState()

break

default:

}

}

// 任何情况下处理的按键,按键导致重新启动游戏

if (keyCode == KeyEvent.VK_R ||

keyCode == KeyEvent.VK_S ||

keyCode == KeyEvent.VK_ENTER) {

model.reset()

}

}

public void keyReleased(KeyEvent e) {

}

public void keyTyped(KeyEvent e) {

}

}

-------------------------------------------------------------

3、

/*

*

*/

package mvcTest

/**

* 游戏的Model类,负责所有游戏相关数据及运行

* @author WangYu

* @version 1.0

* Description:

* </pre>

* Create on :Date :2005-6-13 Time:15:58:33

* LastModified:

* History:

*/

//SnakeModel.java

import javax.swing.*

import java.util.Arrays

import java.util.LinkedList

import java.util.Observable

import java.util.Random

/**

* 游戏的Model类,负责所有游戏相关数据及运行

*/

class SnakeModel extends Observable implements Runnable {

boolean[][] matrix// 指示位置上有没蛇体或食物

LinkedList nodeArray = new LinkedList()// 蛇体

Node food

int maxX

int maxY

int direction = 2// 蛇运行的方向

boolean running = false// 运行状态

int timeInterval = 200// 时间间隔,毫秒

double speedChangeRate = 0.75// 每次得速度变化率

boolean paused = false// 暂停标志

int score = 0// 得分

int countMove = 0// 吃到食物前移动的次数

// UP and DOWN should be even

// RIGHT and LEFT should be odd

public static final int UP = 2

public static final int DOWN = 4

public static final int LEFT = 1

public static final int RIGHT = 3

public SnakeModel( int maxX, int maxY) {

this.maxX = maxX

this.maxY = maxY

reset()

}

public void reset(){

direction = SnakeModel.UP// 蛇运行的方向

timeInterval = 200// 时间间隔,毫秒

paused = false// 暂停标志

score = 0// 得分

countMove = 0// 吃到食物前移动的次数

// initial matirx, 全部清0

matrix = new boolean[maxX][]

for (int i = 0i <maxX++i) {

matrix[i] = new boolean[maxY]

Arrays.fill(matrix[i], false)

}

// initial the snake

// 初始化蛇体,如果横向位置超过20个,长度为10,否则为横向位置的一半

int initArrayLength = maxX >20 ? 10 : maxX / 2

nodeArray.clear()

for (int i = 0i <initArrayLength++i) {

int x = maxX / 2 + i//maxX被初始化为20

int y = maxY / 2//maxY被初始化为30

//nodeArray[x,y]: [10,15]-[11,15]-[12,15]~~[20,15]

//默认的运行方向向上,所以游戏一开始nodeArray就变为:

// [10,14]-[10,15]-[11,15]-[12,15]~~[19,15]

nodeArray.addLast(new Node(x, y))

matrix[x][y] = true

}

// 创建食物

food = createFood()

matrix[food.x][food.y] = true

}

public void changeDirection(int newDirection) {

// 改变的方向不能与原来方向同向或反向

if (direction % 2 != newDirection % 2) {

direction = newDirection

}

}

/**

* 运行一次

* @return

*/

public boolean moveOn() {

Node n = (Node) nodeArray.getFirst()

int x = n.x

int y = n.y

// 根据方向增减坐标值

switch (direction) {

case UP:

y--

break

case DOWN:

y++

break

case LEFT:

x--

break

case RIGHT:

x++

break

}

// 如果新坐标落在有效范围内,则进行处理

if ((0 <= x &&x <maxX) &&(0 <= y &&y <maxY)) {

if (matrix[x][y]) { // 如果新坐标的点上有东西(蛇体或者食物)

if (x == food.x &&y == food.y) { // 吃到食物,成功

nodeArray.addFirst(food)// 从蛇头赠长

// 分数规则,与移动改变方向的次数和速度两个元素有关

int scoreGet = (10000 - 200 * countMove) / timeInterval

score += scoreGet >0 ? scoreGet : 10

countMove = 0

food = createFood()// 创建新的食物

matrix[food.x][food.y] = true// 设置食物所在位置

return true

} else // 吃到蛇体自身,失败

return false

} else { // 如果新坐标的点上没有东西(蛇体),移动蛇体

nodeArray.addFirst(new Node(x, y))

matrix[x][y] = true

n = (Node) nodeArray.removeLast()

matrix[n.x][n.y] = false

countMove++

return true

}

}

return false// 触到边线,失败

}

public void run() {

running = true

while (running) {

try {

Thread.sleep(timeInterval)

} catch (Exception e) {

break

}

if (!paused) {

if (moveOn()) {

setChanged()// Model通知View数据已经更新

notifyObservers()

} else {

JOptionPane.showMessageDialog(null,

"you failed",

"Game Over",

JOptionPane.INFORMATION_MESSAGE)

break

}

}

}

running = false

}

private Node createFood() {

int x = 0

int y = 0

// 随机获取一个有效区域内的与蛇体和食物不重叠的位置

do {

Random r = new Random()

x = r.nextInt(maxX)

y = r.nextInt(maxY)

} while (matrix[x][y])

return new Node(x, y)

}

public void speedUp() {

timeInterval *= speedChangeRate

}

public void speedDown() {

timeInterval /= speedChangeRate

}

public void changePauseState() {

paused = !paused

}

public String toString() {

String result = ""

for (int i = 0i <nodeArray.size()++i) {

Node n = (Node) nodeArray.get(i)

result += "[" + n.x + "," + n.y + "]"

}

return result

}

}

class Node {

int x

int y

Node(int x, int y) {

this.x = x

this.y = y

}

}

------------------------------------------------------------

4、

package mvcTest

//SnakeView.java

import javax.swing.*

import java.awt.*

import java.util.Iterator

import java.util.LinkedList

import java.util.Observable

import java.util.Observer

/**

* MVC模式中得Viewer,只负责对数据的显示,而不用理会游戏的控制逻辑

*/

public class SnakeView implements Observer {

SnakeControl control = null

SnakeModel model = null

JFrame mainFrame

Canvas paintCanvas

JLabel labelScore

public static final int canvasWidth = 200

public static final int canvasHeight = 300

public static final int nodeWidth = 10

public static final int nodeHeight = 10

public SnakeView(SnakeModel model, SnakeControl control) {

this.model = model

this.control = control

mainFrame = new JFrame("GreedSnake")

Container cp = mainFrame.getContentPane()

// 创建顶部的分数显示

labelScore = new JLabel("Score:")

cp.add(labelScore, BorderLayout.NORTH)

// 创建中间的游戏显示区域

paintCanvas = new Canvas()

paintCanvas.setSize(canvasWidth + 1, canvasHeight + 1)

paintCanvas.addKeyListener(control)

cp.add(paintCanvas, BorderLayout.CENTER)

// 创建底下的帮助栏

JPanel panelButtom = new JPanel()

panelButtom.setLayout(new BorderLayout())

JLabel labelHelp

labelHelp = new JLabel("PageUp, PageDown for speed", JLabel.CENTER)

panelButtom.add(labelHelp, BorderLayout.NORTH)

labelHelp = new JLabel("ENTER or R or S for start", JLabel.CENTER)

panelButtom.add(labelHelp, BorderLayout.CENTER)

labelHelp = new JLabel("SPACE or P for pause", JLabel.CENTER)

panelButtom.add(labelHelp, BorderLayout.SOUTH)

cp.add(panelButtom, BorderLayout.SOUTH)

mainFrame.addKeyListener(control)

mainFrame.pack()

mainFrame.setResizable(false)

mainFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE)

mainFrame.setVisible(true)

}

void repaint() {

Graphics g = paintCanvas.getGraphics()

//draw background

g.setColor(Color.WHITE)

g.fillRect(0, 0, canvasWidth, canvasHeight)

// draw the snake

g.setColor(Color.BLACK)

LinkedList na = model.nodeArray

Iterator it = na.iterator()

while (it.hasNext()) {

Node n = (Node) it.next()

drawNode(g, n)

}

// draw the food

g.setColor(Color.RED)

Node n = model.food

drawNode(g, n)

updateScore()

}

private void drawNode(Graphics g, Node n) {

g.fillRect(n.x * nodeWidth,

n.y * nodeHeight,

nodeWidth - 1,

nodeHeight - 1)

}

public void updateScore() {

String s = "Score: " + model.score

labelScore.setText(s)

}

public void update(Observable o, Object arg) {

repaint()

}

}

希望采纳