C语言小游戏之贪吃蛇

PSP

任务开始时间结束时间中断时间delta时间
画素材12.07 18:1312.07 18:280min15min
设计接口12.08 15:1312.08 15:380min25min
写代码12.08 15:4012.08 17:310min101min
写代码12.08 18:4012.08 19:420min62min

WBS

任务估计用时实际用时
搜集素材25min15min
设计分析50min25min
编码显示图片30min63min
编码使蛇运动60min38min
编码碰撞检测30min62min+

演示

在这里插入图片描述

代码(已完成)

#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
#include <time.h>
#include <windows.h>
#include <math.h>
#include <graphics.h>
#include <easyx.h>

// 引用 Windows Multimedia API
#pragma comment(lib,"Winmm.lib")

struct node {
	int 			x;
	int				y;
	struct node*    next;
};

typedef struct node  node_t;
typedef struct node* nodeptr_t;

#define High 1000  // 游戏画面尺寸
#define Width 750

IMAGE img_bk; // 背景图片
IMAGE img_wall; // 背景图片
int head_x, head_y; // 蛇头位置
int targetx, targety; // 目标位置
IMAGE img_target, img_headup, img_headdown, img_headleft, img_headright, img_body; // 蛇头蛇身图片
int score = 0; // 得分
nodeptr_t snakelist; // 蛇链表

int station; // 方向, 1上,2下,3左,4右。
int isGameOver = 0; // 游戏是否结束

// 初始化
void Init();

void UpdateWhthoutEat(); // 更新画面
// 显示
void Show();
void Input();
void GenerateTarget();
bool EatDetect();
bool TargetDetect();
void UpdateWhthEat();

int main() {
	Init();
	GenerateTarget();
	while (1)
	{
		Show();  // 显示画面
		bool iseat = EatDetect();
		if (iseat)
			UpdateWhthEat();
		else
			UpdateWhthoutEat();
		bool isover = TargetDetect();
		if (isover)
			isGameOver = 1;
		Input();
	}
	return 0;
}

void Init()
{
	//mciSendString(L"open sources/game_music.mp3 alias bkmusic", NULL, 0, NULL);//打开背景音乐
	//mciSendString(L"play bkmusic repeat", NULL, 0, NULL);  // 循环播放
	initgraph(Width, High);
	loadimage(&img_bk, L"sources/background.png");
	loadimage(&img_headup, L"sources/head_up.png");
	loadimage(&img_headdown, L"sources/head_down.png");
	loadimage(&img_headleft, L"sources/head_left.png");
	loadimage(&img_headright, L"sources/head_right.png");
	loadimage(&img_body, L"sources/body.png");
	loadimage(&img_target, L"sources/target.png");
	loadimage(&img_wall, L"sources/wall.png");

	head_x = Width / 2;
	head_y = Width / 2;

	station = 1;
	targetx = 0;
	targety = 0;

	snakelist = (nodeptr_t)malloc(sizeof(node_t));
	snakelist->next = nullptr;
	snakelist->x = 0;
	snakelist->y = 0;

	int newbody_x = head_x;
	int newbody_y = head_y;

	nodeptr_t temptail = snakelist;

	for (int i = 0; i < 3; ++i)
	{
		nodeptr_t temp = (nodeptr_t)malloc(sizeof(node_t));
		temp->x = newbody_x;
		temp->y = newbody_y;
		newbody_y = newbody_y + 25;
		temptail->next = temp;
		temptail = temptail->next;
	}
	temptail->next = nullptr;
	BeginBatchDraw();
}


// 键盘输入
void Input()
{
	if (_kbhit())
	{
		char keyboard = _getch();
		if (keyboard == 'w' && station != 2) {
			station = 1;
		}
		if (keyboard == 's' && station != 1)
		{
			station = 2;
		}
		if (keyboard == 'a' && station != 4)
		{
			station = 3;
		}
		if (keyboard == 'd' && station != 3)
		{
			station = 4;
		}
	}
}
// 更新
void UpdateWhthoutEat()
{
	if (station == 1)
	{
		head_y = head_y - 25;
	}
	if (station == 2)
	{
		head_y = head_y + 25;
	}
	if (station == 3)
	{
		head_x = head_x - 25;
	}
	if (station == 4)
	{
		head_x = head_x + 25;
	}
	nodeptr_t temptail = snakelist;
	while (temptail->next->next != nullptr)
		temptail = temptail->next;
	temptail->next->next = snakelist->next;
	snakelist->next = temptail->next;
	temptail->next = nullptr;
	snakelist->next->x = head_x;
	snakelist->next->y = head_y;
	return;
}

void UpdateWhthEat()
{
	if (station == 1)
	{
		head_y = head_y - 25;
	}
	if (station == 2)
	{
		head_y = head_y + 25;
	}
	if (station == 3)
	{
		head_x = head_x - 25;
	}
	if (station == 4)
	{
		head_x = head_x + 25;
	}
	nodeptr_t temp = (nodeptr_t)malloc(sizeof(node_t));
	temp->next = snakelist->next;
	snakelist->next = temp;
	temp->x = head_x;
	temp->y = head_y;
	GenerateTarget();
	return;
}

void Show()
{
	putimage(0, 0, Width, High, &img_bk, 0, 0);	// 显示背景	
	for (int i = 0; i < 30; ++i)
		putimage(0, 25 * i, 25, 25, &img_wall, 0, 0);
	for (int i = 1; i < 30; ++i)
		putimage(25 * i, 0, 25, 25, &img_wall, 0, 0);
	for (int i = 1; i < 30; ++i)
		putimage(725, 25 * i, 25, 25, &img_wall, 0, 0);
	for (int i = 1; i < 29; ++i)
		putimage(25 * i, 725, 25, 25, &img_wall, 0, 0);
	if (isGameOver == 0)
	{
		nodeptr_t templist = snakelist->next;
		putimage(targetx, targety, 25, 25, &img_target, 0, 0);	// 显示目标
		if (station == 1)
			putimage(templist->x, templist->y, 25, 25, &img_headup, 0, 0); // 显示蛇头
		if (station == 2)
			putimage(templist->x, templist->y, 25, 25, &img_headdown, 0, 0); // 显示蛇头
		if (station == 3)
			putimage(templist->x, templist->y, 25, 25, &img_headleft, 0, 0); // 显示蛇头
		if (station == 4)
			putimage(templist->x, templist->y, 25, 25, &img_headright, 0, 0); // 显示蛇头
		templist = templist->next;
		while (templist != nullptr)
		{
			putimage(templist->x, templist->y, 25, 25, &img_body, 0, 0); // 显示蛇身
			templist = templist->next;
		}
	}

	else
	{
		wchar_t str[50];
		swprintf(str, 100, L"Game Over");
		outtextxy(Width / 2, Width / 2, str);
	}
	
	wchar_t s[50];
	swprintf(s, 100, L"Score: %d", score);
	outtextxy(0, 0, s);
	FlushBatchDraw();
	Sleep(200);
}

void GenerateTarget()
{
	srand((unsigned)time(NULL));
	targetx = rand() % ((Width - 75) / 25) * 25 + 25;
	targety = rand() % ((Width - 75) / 25) * 25 + 25;
	nodeptr_t templist = snakelist;
	while (1)
	{
		while (templist->next != nullptr)
		{
			if (templist->next->x == targetx && templist->next->x == targety)
			{
				targetx = rand() % ((Width - 75) / 25) * 25 + 25;
				targety = rand() % ((Width - 75) / 25) * 25 + 25;
				break;
			}
			return;
		}
	}

}

//
bool EatDetect()
{
	nodeptr_t snakehead = snakelist->next;
	if (snakehead->x == targetx && snakehead->y == targety)
	{
		score = score + 1;
		return 1;
	}
		
	return 0;
}

//碰撞检测
bool TargetDetect()
{
	nodeptr_t temp = snakelist->next;
	int headx = temp->x;
	int heady = temp->y;
	if (headx == 0 || headx == Width - 25 || heady == 0 || heady == Width - 25)
		return 1;
	temp = temp->next;
	while (temp != nullptr)
	{
		if (temp->x == headx && temp->y == heady)
			return 1;
		temp = temp->next;
	}
	return 0;
}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值