C语言实现贪吃蛇游戏

重点:

蛇的移动是先更新蛇身和蛇头坐标,再重新画蛇实现,此过程在循环中进行

snake.h

#pragma once

#include <time.h>
#include <stdlib.h>
#include <stdio.h>
#include <conio.h>
#include <Windows.h>

#define WIDE 60
#define HIGH 20


//设计蛇身体和头
struct BODY {
	int X;
	int Y;
};			//一节蛇头或蛇身对应1个坐标

//设计蛇
struct SNAKE {
	struct BODY body[WIDE * HIGH];//蛇头+蛇身的上限是铺满整个界面,body[0][0]代表蛇头,其他代表蛇身
	int size;//蛇头+蛇身的节数
}snake;//顺便创建条全局蛇变量

//设计食物,一个食物对应1个坐标
struct FOOD {
	int X;
	int Y;
}food;//顺便创建一个全局食物变量

//int score = 0;//游戏得分
//
//int kx = 0;			//用户按下awsd任意键所得到的坐标值
//int ky = 0;
//
//int sleepTime = 300; //记录控制蛇移动速度的睡眠秒数
//
//int tailX = 0;		//蛇尾坐标
//int tailY = 0;

//初始化蛇
void initSnake();

//初始化食物
void initFood();

//画蛇和食物
void initUI();

//画墙
void initWall();

//开始游戏
void playGame();

//显示分数
void showScore();

 snake.c

#define _CRT_SECURE_NO_WARNINGS 1
#include "snake.h"

int score = 0;//游戏得分

int kx = 0;			//用户按下awsd任意键所得到的坐标值
int ky = 0;

int sleepTime = 300; //记录控制蛇移动速度的睡眠秒数

int tailX = 0;		//蛇尾坐标
int tailY = 0;

void initSnake()//初始化蛇
{
	//设置蛇长度
	snake.size = 2;

	//设置蛇头坐标
	snake.body[0].X = WIDE / 2;
	snake.body[0].Y = HIGH / 2;

	//设置蛇第一节身体的坐标
	snake.body[1].X = WIDE / 2 - 1;
	snake.body[1].Y = HIGH / 2;
}

void initFood()//初始化食物
{
	//设置食物坐标
	food.X = rand() % WIDE;//0~59
	food.Y = rand() % HIGH;//0~19
}

void initUI()//画蛇和食物
{
	COORD coord = { 0, 0 };
	//画蛇
	for (size_t i = 0; i < snake.size; i++)
	{
		coord.X = snake.body[i].X;
		coord.Y = snake.body[i].Y;

		SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), coord);//设置控制台光标起始位置
		if (i == 0)
		{
			putchar('@');//画蛇头
		}
		else
		{
			putchar('*');//画蛇身
		}
	}

	//去除蛇尾
	coord.X = tailX;
	coord.Y = tailY;
	SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), coord);//设置控制台光标起始位置
	putchar(' ');

	//画食物
	coord.X = food.X;
	coord.Y = food.Y;
	SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), coord);//设置控制台光标起始位置
	putchar('#');
}

void initWall()//画墙
{
	for (size_t i = 0; i <= HIGH; i++)
	{
		for (int j = 0; j <= WIDE; j++)
		{
			if (j == WIDE)
			{
				printf("|");
			}
			else if (i == HIGH)
			{
				printf("_");
			}
			else
			{
				printf(" ");
			}
		}
		printf("\n");
	}
}

void playGame()
{
	//设置蛇的默认移动方向
	char key = 'd';
	//判断蛇撞墙
	while (snake.body[0].X >= 0 && snake.body[0].X < WIDE
		&& snake.body[0].Y >= 0 && snake.body[0].Y < HIGH)
	{
		//刷新画蛇
		initUI();

		//接收用户的按键输入  awsd
		if (_kbhit())//不阻塞响应键盘输入,为真时说明用户按下按键
		{
			key = _getch();//不回显接收字符
		}

		switch (key)//根据用户按下不同按键得到不同坐标值
		{
		case 'a': kx = -1; ky = 0; break; 
		case 'w': kx = 0; ky = -1; break;
		case 's': kx = 0; ky = +1; break;
		case 'd': kx = +1; ky = 0; break;
		default: break;
		}

		//蛇头撞身体,蛇头坐标==任意一节蛇身坐标
		for (size_t i = 1; i < snake.size; i++)
		{
			if (snake.body[0].X == snake.body[i].X && snake.body[0].Y == snake.body[i].Y)
				return;//游戏结束
		}

		//蛇头撞食物
		if (snake.body[0].X == food.X && snake.body[0].Y == food.Y)
		{
			initFood();//刷新食物
			snake.size++;//身体增长
			score += 10;//加分
			sleepTime -= 100;//蛇移动速度加快
		}

		//存储蛇尾坐标
		tailX = snake.body[snake.size - 1].X;
		tailY = snake.body[snake.size - 1].Y;

		//蛇移动,前1节身体给后1节身体赋值
		for (int i = snake.size -1; i >0; i--)
		{
			snake.body[i].X = snake.body[i - 1].X;
			snake.body[i].Y = snake.body[i - 1].Y;
		}

		//根据用户按键修改蛇头坐标
		snake.body[0].X += kx;
		snake.body[0].Y += ky;

		Sleep(sleepTime);//控制蛇移动速度
	}
}

void showScore()//显示分数
{
	//移动控制台光标至墙外
	COORD coord;
	coord.X = 0;
	coord.Y = HIGH + 1;
	SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), coord);//设置控制台光标起始位置
	printf("Game Over\n");
	printf("此次成绩:%d\n", score);
}

test.c

#define _CRT_SECURE_NO_WARNINGS 1

#include "snake.h"

int main()
{
	//隐藏控制台光标,设置一次即可生效
	CONSOLE_CURSOR_INFO cci;
	cci.dwSize = sizeof(cci);
	cci.bVisible = FALSE;
	SetConsoleCursorInfo(GetStdHandle(STD_OUTPUT_HANDLE), &cci);

	srand((unsigned int)time(NULL));//设置随机数生成起点

	initSnake();//初始化蛇
	initFood();//初始化食物
	initWall();//画墙
	initUI();//画蛇和食物
	playGame();//开始游戏
	showScore();//显示分数
	return 0;
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值