贪吃蛇游戏 1.0

编译环境:Visual Studio 2019

注:使用了Easyx 图形库。Easyx下载 Easyx官网

Easyx 图形库安装教程:https://blog.csdn.net/weixin_43919932/article/details/102996507

说明:此贪吃蛇游戏为第一版,使用了库中提供的简单的描线绘图功能所设计,不含资源包。可直接测试运行,贪吃蛇游戏 2.0在此基础上增加了贴图功能,界面相对部分优化。另外,为方便测试,在代码初始位置预留属性框中各属性参数均可自由调整

 

直接上代码:

#define _CRT_SECURE_NO_WARNINGS
#define _CRT_NON_CONFORMING_SWPRINTFS
#undef UNICODE
#undef _UNICODE	
#include <stdio.h>
#include <stdlib.h>
#include <graphics.h>
#include <conio.h>
#include <time.h>
#include <windows.h>

/*--------------------------------属 性---------------------------*/
#define WIDE 1200		/* 窗口大小  WIDE * HIGH像素   	 */
#define HIGH 700
#define FORM 200		/*	设置文字边框宽度  */
#define SIZE 40				//每节蛇的尺寸
#define LEN 100				//蛇的最长长度
#define COLOUR RGB(rand()%255,rand()%255,rand()%255)	//彩色

static int speed = 100;		//速度(控制刷新的时间间隔)

enum Direction { right = 77, left = 75, down = 80, up = 72, Esc = 27 };//枚举方向值


/*---------------------------资源-------------------------------------*/
//蛇
typedef struct _snake
{
	int x[LEN];				//坐标—X
	int y[LEN];				//坐标—Y
	int len;				//长度
	int count;				//分数
	int direction;			//方向
}Snake;

//食物
typedef struct _food
{
	int x;
	int y;
	int flg;
}Food;


/************************************************************/
//变量
Snake snake;		//蛇
Food  food;			//食物
//函数
void Form();			//文字提示框
void Init_Snake();		//初始化蛇
void Init_Food();		//初始化食物
void ShowSnake();		//贴图画蛇
void ShowFood();		//贴图画食物
void MoveSnake();		//蛇的移动
void KeyDown();			//控制
void EatFood();			//吃食物
int GameOver();			//游戏结束




void Form()
{
	setlinecolor(BLACK);					//画线颜色
	setfillcolor(WHITE);
	fillrectangle(0, 0, WIDE, HIGH - 1);	//边框

	setfillcolor(RGB(254, 236, 232));		//右侧文字框背景色
	fillrectangle(WIDE - FORM, 0, WIDE, HIGH / 3);	//上提示框,实时显示分数
	fillrectangle(WIDE - FORM, HIGH / 3, WIDE, HIGH);	//下提示框,操作手册
	setbkmode(TRANSPARENT);		//文字透明方式
	settextcolor(LIGHTBLUE);	//文字颜色
	TCHAR  str[3][50];
	_stprintf(str[0], _T("   得分:%4d 分"), snake.count);
	_stprintf(str[1], _T("   速度:%4d 级"), (100 - speed) / 20);
	_stprintf(str[2], _T("   长度:%4d 节"), snake.len);
	for (int i = 0; i < 3; ++i)
	{
		outtextxy(WIDE - FORM + 10, i * 20 + 20, str[i]);	//指定位置输出字符串
	}

	TCHAR  str2[10][50];
	_stprintf(str2[0], _T("提示:一枚果实10分 "));
	_stprintf(str2[1], _T("      撞到墙,或撞到自己"));
	_stprintf(str2[2], _T("      游戏游戏"));
	_stprintf(str2[3], _T("      "));
	_stprintf(str2[4], _T("按键:Esc : 强制退出游戏"));
	_stprintf(str2[5], _T("          1 : 加速 "));
	_stprintf(str2[6], _T("          0 : 减速"));
	_stprintf(str2[7], _T("      空格: 暂停"));
	for (int i = 0; i < 8; i++)
	{
		outtextxy(WIDE - FORM + 10, HIGH / 3 + i * 20 + 20, str2[i]);	//指定位置输出字符串
	}


}

int main()
{

	initgraph(WIDE, HIGH);		//初始化窗口大小
	setbkcolor(WHITE);			//背景颜色

	Init_Snake();				//初始化蛇
	Init_Food();				//初始化食物

	while (true)//强退
	{
		if (food.flg == 0)
		{
			Init_Food();		//初始化食物
		}
		cleardevice();			//刷新窗口

		BeginBatchDraw();		//这个函数用于开始批量绘图。执行后,任何绘图操作都将暂时不输出到屏幕上,防止闪屏
		Form();					//打印表框

		if (_kbhit())
		{
			KeyDown();			//玩家控制蛇移动
		}
		ShowSnake();			//画蛇
		ShowFood();				//画食物
		EndBatchDraw();			// 结束批量绘制,并执行未完成的绘制任务

		EatFood();
		MoveSnake();			//蛇移动

		if (GameOver() == 1)		//游戏结束条件
		{
			break;
		}
		Sleep(speed);			//控制速度
	}

	getchar();
	closegraph();
	return 0;
}
/*--------------------------蛇的功能函数--------------------------*/
//初始化蛇
void Init_Snake()
{
	//初始化前三节蛇
	snake.x[0] = SIZE * 2;
	snake.y[0] = 0;

	snake.x[1] = SIZE;
	snake.y[1] = 0;

	snake.x[2] = 0;
	snake.y[2] = 0;

	snake.len = 3;
	snake.count = 0;
	snake.direction = right;	//默认向右
}
//初始化食物
void Init_Food()
{
	srand((unsigned int)time(NULL));//随机种子
label:
	int x = (WIDE - FORM) / SIZE;	//预留 FORM 像素显示信息
	int y = HIGH / SIZE;
	food.x = rand() % x * SIZE;	// *10 保证食物地址为整数,与蛇头比较
	food.y = rand() % y * SIZE;
	//检查食物是否在蛇身上
	int i = 0;
	while (i < snake.len)
	{
		if (food.x == snake.x[i] && food.y == snake.y[i])
		{
			goto label;
		}
		++i;
	}
	food.flg = 1;
}
//贴图画蛇
void ShowSnake()
{
	for (int i = 0; i < snake.len; ++i)
	{
		setlinecolor(BLACK);	//设置画线颜色
		setfillcolor(GREEN);	//设置填充颜色
		fillrectangle(snake.x[i], snake.y[i], snake.x[i] + SIZE, snake.y[i] + SIZE);
		/*  左上、右下坐标*/
	}

}
//贴图画食物
void ShowFood()
{
	setfillcolor(COLOUR);	//设置填充颜色--彩色食物
	fillrectangle(food.x, food.y, food.x + SIZE, food.y + SIZE);
}
//蛇的移动
void MoveSnake()
{
	//把蛇的后一节坐标移动到前一节的坐标位置
	for (int i = snake.len - 1; i > 0; --i)
	{
		snake.x[i] = snake.x[i - 1];
		snake.y[i] = snake.y[i - 1];
	}
	//单独移动蛇头,根据蛇的方向移动
	switch (snake.direction)
	{
	case right:
		snake.x[0] += SIZE;
		break;
	case left:
		snake.x[0] -= SIZE;
		break;
	case up:
		snake.y[0] -= SIZE;
		break;
	case down:
		snake.y[0] += SIZE;
		break;
	default:
		break;
	}
}



/*getch函数从控制台读取单个字符而不回显,函数不能去读取CTRL+C,当读取一个
	功能键或方向键,函数必须调用两次(这就说明可以用这个函数去监控功能键
	和方向键),第一次调用返回0或0xe0,第二次返回实际的键代码*/
	//控制
void KeyDown()
{
	char tmp = _getch();		//接受_getch()的第一个返回值
	switch (tmp)
	{
	case '1':		// 1 加速
		if (speed > 20)
		{
			speed -= 20;
		}
		return;
		break;
	case '0':		// 0 减速
		if (speed < 200)
		{
			speed += 20;
		}
		return;
		break;
	default:
		break;
	}
	char key = _getch();		//接受键盘键入的值
	switch (key)
	{
	case right:
		if (snake.direction != left)	//不能相反方向移动
			snake.direction = right;
		break;
	case left:
		if (snake.direction != right)
			snake.direction = left;
		break;
	case up:
		if (snake.direction != down)
			snake.direction = up;
		break;
	case down:
		if (snake.direction != up)
			snake.direction = down;
		break;
	case Esc:	//强退
	{
		TCHAR s[] = _T("即将退出游戏,是(Y)/否(N)");
		setfillcolor(LIGHTCYAN);
		fillrectangle(0, 0, WIDE - FORM, HIGH);
		setbkmode(TRANSPARENT);			//文字透明方式
		settextcolor(LIGHTBLUE);		//文字颜色
		outtextxy(WIDE * 3 / 10, HIGH / 2, s);	//指定位置输出字符串
		char ch = getchar();
		if (ch == 'Y' || ch == 'y')	exit(0);

	}
	break;
	case ' ':		//暂停
		while (true)
		{
			if (_kbhit())
			{
				char ch = _getch();
				if (_getch() == ' ')	break;
			}

		}

		break;

	default:
		break;

	}
	fflush(stdin);
}



//吃食物
void EatFood()
{
	if (food.x == snake.x[0] && food.y == snake.y[0])
	{
		++snake.len;
		snake.count += 10;	//一个食物十分
		food.flg = 0;
	}

}



//死亡
int GameOver()
{
	for (int i = 1; i < snake.len; i++)
	{
		//撞自己
		if (snake.x[i] == snake.x[0] && snake.y[i] == snake.y[0])
		{
			TCHAR s[100];
			_stprintf(s, _T("咬到自己了 GameOver!\n您的分数为%d分"), snake.count);

			setfillcolor(WHITE);		//背景填充颜色
			fillrectangle(0, 0, WIDE - FORM, HIGH);
			setbkmode(TRANSPARENT);		//文字透明方式
			settextcolor(LIGHTBLUE);	//文字颜色
			outtextxy(WIDE * 2 / 10, HIGH / 2, s);	//指定位置输出字符串

			return 1;
		}
		//撞墙
		else if (snake.x[i]<0 || snake.x[0]>WIDE - FORM - SIZE ||		//横坐标出界
			snake.y[i]<0 || snake.y[0]>HIGH - SIZE)		//纵坐标出界
		{
			TCHAR s[100];
			_stprintf(s, _T("你撞墙了 GameOver!\n您的分数为%d分"), snake.count);

			setfillcolor(WHITE);		//背景填充颜色
			fillrectangle(0, 0, WIDE - FORM, HIGH);
			setbkmode(TRANSPARENT);		//文字透明方式
			settextcolor(LIGHTBLUE);	//文字颜色
			outtextxy(WIDE * 2 / 10, HIGH / 2, s);	//指定位置输出字符串
			return 1;
		}
		//通关
		else if (snake.len == LEN)		//最长长度
		{
			TCHAR s[100];
			_stprintf(s, _T("恭喜 通关 GameOver!\n您的分数为%d分"), snake.count);

			setfillcolor(WHITE);		//背景填充颜色
			fillrectangle(0, 0, WIDE - FORM, HIGH);
			setbkmode(TRANSPARENT);		//文字透明方式
			settextcolor(LIGHTBLUE);	//文字颜色
			outtextxy(WIDE * 2 / 10, HIGH / 2, s);	//指定位置输出字符串
			return 1;
		}
	}
	return 0;
}

效果如下:

 

  • 6
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论
好的,以下是一个简单的安卓贪吃蛇游戏的全部代码: 1. activity_main.xml ```xml <?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent"> <TextView android:id="@+id/score_textview" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Score: 0" android:textSize="24sp" android:layout_alignParentTop="true" android:layout_alignParentEnd="true" android:layout_marginTop="16dp" android:layout_marginEnd="16dp" /> <FrameLayout android:id="@+id/game_frame" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_below="@id/score_textview" android:background="@android:color/darker_gray" /> <Button android:id="@+id/start_button" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Start" android:layout_centerInParent="true" /> </RelativeLayout> ``` 2. SnakeGameView.java ```java import android.content.Context; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.graphics.Point; import android.graphics.Rect; import android.view.SurfaceHolder; import android.view.SurfaceView; import java.util.ArrayList; import java.util.List; import java.util.Random; public class SnakeGameView extends SurfaceView implements Runnable { private final int BLOCK_SIZE = 50; private final int NUM_BLOCKS_WIDE = 10; private final int NUM_BLOCKS_HIGH = 20; private Thread gameThread = null; private SurfaceHolder surfaceHolder; private volatile boolean playing; private boolean paused = true; private Canvas canvas; private Paint paint; private long fps; private int score; private int highScore[] = new int[4]; private enum Direction { UP, RIGHT, DOWN, LEFT } private Direction direction = Direction.RIGHT; private int[] snakeXs; private int[] snakeYs; private int snakeLength; private List<Point> apples = new ArrayList<>(); private int numApples; public SnakeGameView(Context context) { super(context); surfaceHolder = getHolder(); paint = new Paint(); snakeXs = new int[200]; snakeYs = new int[200]; numApples = 0; highScore[0] = 0; highScore[1] = 0; highScore[2] = 0; highScore[3] = 0; newGame(); } @Override public void run() { while (playing) { long frameStartTime = System.currentTimeMillis(); if (!paused) { update(); draw(); } long timeThisFrame = System.currentTimeMillis() - frameStartTime; if (timeThisFrame > 0) { fps = 1000 / timeThisFrame; } } } public void pause() { playing = false; try { gameThread.join(); } catch (InterruptedException e) { // Error } } public void resume() { playing = true; gameThread = new Thread(this); gameThread.start(); } private void newGame() { snakeLength = 1; snakeXs[0] = NUM_BLOCKS_WIDE / 2; snakeYs[0] = NUM_BLOCKS_HIGH / 2; spawnApple(); score = 0; } private void spawnApple() { Random random = new Random(); int appleX = random.nextInt(NUM_BLOCKS_WIDE - 1) + 1; int appleY = random.nextInt(NUM_BLOCKS_HIGH - 1) + 1; for (Point apple : apples) { if (apple.x == appleX && apple.y == appleY) { spawnApple(); } } apples.add(new Point(appleX, appleY)); numApples++; } private void eatApple(int appleIndex) { snakeLength++; apples.remove(appleIndex); score += 10; spawnApple(); } private void moveSnake() { for (int i = snakeLength; i > 0; i--) { snakeXs[i] = snakeXs[i-1]; snakeYs[i] = snakeYs[i-1]; } switch (direction) { case UP: snakeYs[0]--; break; case RIGHT: snakeXs[0]++; break; case DOWN: snakeYs[0]++; break; case LEFT: snakeXs[0]--; break; } } private boolean detectDeath() { boolean dead = false; if (snakeXs[0] == -1 || snakeXs[0] >= NUM_BLOCKS_WIDE || snakeYs[0] == -1 || snakeYs[0] >= NUM_BLOCKS_HIGH) { dead = true; } for (int i = snakeLength - 1; i > 0; i--) { if (i > 4 && snakeXs[0] == snakeXs[i] && snakeYs[0] == snakeYs[i]) { dead = true; } } return dead; } private void update() { if (snakeXs[0] == apples.get(0).x && snakeYs[0] == apples.get(0).y) { eatApple(0); } moveSnake(); if (detectDeath()) { newGame(); } } private void draw() { if (surfaceHolder.getSurface().isValid()) { canvas = surfaceHolder.lockCanvas(); canvas.drawColor(Color.BLACK); paint.setColor(Color.WHITE); paint.setTextSize(40); canvas.drawText("Score: " + score, 10, 50, paint); for (Point apple : apples) { paint.setColor(Color.RED); canvas.drawRect(apple.x * BLOCK_SIZE, apple.y * BLOCK_SIZE, (apple.x + 1) * BLOCK_SIZE, (apple.y + 1) * BLOCK_SIZE, paint); } for (int i = 0; i < snakeLength; i++) { if (i == 0) { paint.setColor(Color.GREEN); } else { paint.setColor(Color.WHITE); } canvas.drawRect(snakeXs[i] * BLOCK_SIZE, snakeYs[i] * BLOCK_SIZE, (snakeXs[i] + 1) * BLOCK_SIZE, (snakeYs[i] + 1) * BLOCK_SIZE, paint); } surfaceHolder.unlockCanvasAndPost(canvas); } } public void pauseGame() { paused = true; } public void startGame() { paused = false; } public void moveRight() { if (direction != Direction.LEFT) { direction = Direction.RIGHT; } } public void moveLeft() { if (direction != Direction.RIGHT) { direction = Direction.LEFT; } } public void moveUp() { if (direction != Direction.DOWN) { direction = Direction.UP; } } public void moveDown() { if (direction != Direction.UP) { direction = Direction.DOWN; } } } ``` 3. MainActivity.java ```java import android.os.Bundle; import android.os.Handler; import android.os.Message; import android.support.v7.app.AppCompatActivity; import android.view.MotionEvent; import android.view.View; import android.widget.Button; import android.widget.Toast; public class MainActivity extends AppCompatActivity implements View.OnTouchListener, View.OnClickListener { private SnakeGameView snakeGameView; private Button startButton; private final int MOVE_RIGHT = 0; private final int MOVE_LEFT = 1; private final int MOVE_UP = 2; private final int MOVE_DOWN = 3; private Handler handler = new Handler(new Handler.Callback() { @Override public boolean handleMessage(Message msg) { switch (msg.what) { case MOVE_RIGHT: snakeGameView.moveRight(); break; case MOVE_LEFT: snakeGameView.moveLeft(); break; case MOVE_UP: snakeGameView.moveUp(); break; case MOVE_DOWN: snakeGameView.moveDown(); break; } return true; } }); @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); snakeGameView = findViewById(R.id.game_frame); snakeGameView.setOnTouchListener(this); startButton = findViewById(R.id.start_button); startButton.setOnClickListener(this); } @Override protected void onResume() { super.onResume(); snakeGameView.resume(); } @Override protected void onPause() { super.onPause(); snakeGameView.pause(); } @Override public boolean onTouch(View view, MotionEvent motionEvent) { switch (motionEvent.getAction()) { case MotionEvent.ACTION_DOWN: if (motionEvent.getX() >= snakeGameView.getWidth() * 3 / 4) { handler.sendEmptyMessage(MOVE_RIGHT); } else if (motionEvent.getX() <= snakeGameView.getWidth() / 4) { handler.sendEmptyMessage(MOVE_LEFT); } else if (motionEvent.getY() <= snakeGameView.getHeight() / 4) { handler.sendEmptyMessage(MOVE_UP); } else if (motionEvent.getY() >= snakeGameView.getHeight() * 3 / 4) { handler.sendEmptyMessage(MOVE_DOWN); } break; } return true; } @Override public void onClick(View view) { if (view.getId() == R.id.start_button) { startButton.setVisibility(View.INVISIBLE); snakeGameView.startGame(); } } } ``` 这些代码实现了一个简单的安卓贪吃蛇游戏,并且可以通过触摸屏幕或者按钮控制贪吃蛇的移动方向。当贪吃蛇触碰到边界或自身时,游戏会重新开始,并记录最高分数。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

我叫RT

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值