1.需要实现的基本功能:
3.蛇撞墙死亡;
4.蛇撞自己死亡;
5.计算得分;
6.蛇加速,减速;
7.暂停游戏。
2.Win32 API:
2.1.介绍:
windows作为开发系统为程序员提供的一些函数接口,用以实现一些功能。
2.2.控制台程序:
2.2.1.mode—可控制黑框的大小:
mode con cols=100 lines=30
#include<stdlib.h>
int main()
{
system("mode con cols=50 lines=20");//这个函数就能执行系统命令
printf("hehen");
return 0;
}
2.2.2.title—可修改黑框的名字:
title 贪吃蛇
system("title 贪吃蛇");
2.2.3.pause—可使程序暂停:
system("pause");
2.2.4.cls—可清理屏幕内容:
system("cls");
2.3.控制台屏幕上的坐标—COORD:
COORD pos = { 3,5 };
2.4.获得句柄:GetStdHandle:
GetStdHandle是一个API函数。它用于从一个特定的标准设备(标准输入,标准输出,标准错误)中取得一个句柄(设备的控制权限),用来操作设备。
HANDLE handle = GetStdHandle(STD_OUTPUT_HANDLE);//获得标准输出的句柄
2.5.设置光标大小和可见性:
2.5.1.GetConsoleCursorInfo:
注:结构体:CONSOLE_CURSOR_INFO :
typedef struct _CONSOLE_CURSOR_INFO {
DWORD dwSize;
BOOL bVisible;
}CONSOLE_CURSOR_INFO,*PCONSOLE_CURSOR_INFO;
dwSize:此值介于1到100之间。光标外观发生变化,从完全填充到单元底部的水平线条。
bVisible:光标的可见性。
cursor_info.bVisible = false;
2.5.2.SetConsoleCursorInfo:
e.g:
int main()
{
HANDLE handle = GetStdHandle(STD_OUTPUT_HANDLE);//获得标准输出的句柄
CONSOLE_CURSOR_INFO cursor_info;
GetConsoleCursorInfo(handle,&cursor_info);
cursor_info.dwSize = 1;
SetConsoleCursorInfo(handle,&cursor_info);
return 0;
}
2.6.设置光标位置:SetConsoleCursorPosition:
用法:将坐标信息放在COORD类型的pos中,调用SetConsoleCursorPosition函数将光标位置设置到指定的位置。
void SetPos(int x, int y)
{
HANDLE handle = GetStdHandle(STD_OUTPUT_HANDLE);
COORD pos = { x,y };
SetConsoleCursorPosition(handle, pos);
}
2.7.获取按键情况:GetAsyncKeyState:
VK_LEFT—0x25 ; VK_UP—0x26 ; VK_RIGHT—0x27 ; VK_DOWN—0x28 ;
2.返回值:
short类型。最高位:1为按下,0为抬起;最低位:1为按下过,0为未按过。
#define PRESS_KET(vk)(GetAsyncKeyState(vk)&0x1?1:0)
3.贪吃蛇游戏设计与分析:
3.1.地图:
由于贪吃蛇墙体,蛇身等字块为宽字符,而c语言默认不包含宽字符,故需要在locale上进行修改。
3.1.1.locale是什么?
locale是c语言针对不同地区字符的区别,所提供的标准和当前地区的语言设置。
3.1.2.类项:
3.1.3.setlocale函数:
char* setlocale ( int category , const chat* locale )
3.1.4.打印宽字符:
#include<locale.h>
int main()
{
setlocale(LC_ALL, "");
wchar_t ch1 = L'几';//宽字符的类型
wchar_t ch2 = L'个';
printf("abn");
wprintf(L"%lcn", ch1);//打印宽字符
wprintf(L"%lcn", ch2);
wprintf(L"%lcn", ch1);
wprintf(L"%lcn", ch2);
return 0;
}
3.1.5.地图坐标:
3.2.数据结构的设计:
enum DIRECTION
{
UP = 1,
DOWN,
LEFT,
RIGHT
};
enum GAME_STATUS
{
OK,
END_NORMAL,
KILL_BY_WALL,
KILL_BY_SELF
};
//贪吃蛇的节点
typedef struct SnakeNode
{
int x;
int y;
struct SnakeNode* next;
}SnakeNode,*pSnakeNode;
//贪吃蛇的结构
typedef struct Snake
{
pSnakeNode _psnake;//指向贪吃蛇头节点的指针
pSnakeNode _pFood;//指向食物节点的指针
int _Score;//贪吃蛇积累的总分
int _FoodWeight;//一个食物的分数
int _SleepTime;//每走一步休息的时间,时间越短速度越快
enum DIRECTION _Dir;//描述蛇的方向
enum GAME_STATUS _Status;//游戏的状态:正常,退出,撞墙,撞到自己
}Snake,*pSnake;
4.具体实现:
头文件:snake.h
#pragma once
#include<locale.h>
#include<stdlib.h>
#include<windows.h>
#include<stdbool.h>
#include<stdio.h>
#include<time.h>
#define WALL L'□'
#define BODY L'●'
#define FOOD L'★'
#define POS_X 24
#define POS_Y 5
#define PRESS_KET(vk)(GetAsyncKeyState(vk)&0x1?1:0)
enum DIRECTION
{
UP = 1,
DOWN,
LEFT,
RIGHT
};
enum GAME_STATUS
{
OK,
END_NORMAL,
KILL_BY_WALL,
KILL_BY_SELF
};
//贪吃蛇的节点
typedef struct SnakeNode
{
int x;
int y;
struct SnakeNode* next;
}SnakeNode,*pSnakeNode;
//贪吃蛇的结构
typedef struct Snake
{
pSnakeNode _psnake;//指向贪吃蛇头节点的指针
pSnakeNode _pFood;//指向食物节点的指针
int _Score;//贪吃蛇积累的总分
int _FoodWeight;//一个食物的分数
int _SleepTime;//每走一步休息的时间,时间越短速度越快
enum DIRECTION _Dir;//描述蛇的方向
enum GAME_STATUS _Status;//游戏的状态:正常,退出,撞墙,撞到自己
}Snake,*pSnake;
//1.游戏开始 - 初始化游戏
void GameStart(pSnake ps);
void WelcomeToGame();//游戏开始的欢迎界面
void CreateMap();//打印地图
void InitSnake(pSnake ps);//初始化蛇
void CreateFood(pSnake ps);//创建食物
//2.游戏运行
void GameRun(pSnake ps);
void PrintHelpInfo();//打印辅助信息
void SnakeMove(pSnake ps);//蛇的移动
int NextIsFood(pSnake ps, pSnakeNode pNext);//判断下一个位置是否是食物
void KillByWall(pSnake ps);//蛇是否撞墙
void KillBySelf(pSnake ps);//蛇是否自杀
//3.游戏结束
void GameEnd(pSnake ps);
源文件:snake.c
#include"snake.h"
//1.游戏开始 - 初始化游戏
void SetPos(int x, int y)
{
HANDLE handle = GetStdHandle(STD_OUTPUT_HANDLE);
COORD pos = { x,y };
SetConsoleCursorPosition(handle, pos);
}
void WelcomeToGame()
{
//定位光标
SetPos(40, 15);
printf("欢迎来到贪吃蛇小游戏!");
SetPos(40, 25);
system("pause");
system("cls");
SetPos(25, 15);
printf("使用↑.↓.←.→控制蛇的移动,F3是加速,F4是减速");
SetPos(40, 25);
system("pause");
system("cls");
}
void CreateMap()
{
//上
SetPos(0, 0);
int i = 0;
for (i = 0; i <= 56; i += 2)
{
wprintf(L"%lc", WALL);
}
//下
SetPos(0, 26);
for (i = 0; i <= 56; i += 2)
{
wprintf(L"%lc", WALL);
}
//左
for (i = 1; i <= 25; i++)
{
SetPos(0, i);
wprintf(L"%lc", WALL);
}
//右
for (i = 1; i <= 25; i++)
{
SetPos(56, i);
wprintf(L"%lc", WALL);
}
}
void InitSnake(pSnake ps)
{
pSnakeNode cur = NULL;
int i = 0;
for (i = 0; i < 5; i++)
{
cur = (pSnakeNode)malloc(sizeof(SnakeNode));
if (cur == NULL)
{
perror("InitSnake()::malloc()");
return;
}
cur->x = POS_X + 2 * i;
cur->y = POS_Y;
cur->next = NULL;
//头插法
if (ps->_psnake == NULL)
{
ps->_psnake = cur;
}
else
{
cur->next = ps->_psnake;
ps->_psnake = cur;
}
}
//打印蛇身
cur = ps->_psnake;
while (cur)
{
SetPos(cur->x, cur->y);
wprintf(L"%lc", BODY);
cur = cur->next;
}
ps->_Status = OK;
ps->_Score = 0;
ps->_pFood = NULL;
ps->_SleepTime = 200;
ps->_FoodWeight = 10;
ps->_Dir = RIGHT;
}
void CreateFood(pSnake ps)
{
int x;
int y;
again:
do
{
x = rand() % 53 + 2;
y = rand() % 25 + 1;
} while (x % 2 != 0);
//坐标不能和蛇的身体冲突
pSnakeNode cur = ps->_psnake;
if (cur->x == x && cur->y == y)
{
goto again;
}
pSnakeNode pFood = (pSnakeNode)malloc(sizeof(SnakeNode));
if (pFood == NULL)
{
perror("CreateFood()::malloc()");
return;
}
pFood->x = x;
pFood->y = y;
ps->_pFood = pFood;
//打印食物
SetPos(x, y);
wprintf(L"%lc", FOOD);
}
void GameStart(pSnake ps)
{
//控制台窗口的设置
system("mode con cols=100 lines=30");
system("title 贪吃蛇");
//光标隐藏
HANDLE handle = GetStdHandle(STD_OUTPUT_HANDLE);//获得标准输出的句柄
CONSOLE_CURSOR_INFO cursor_info;
GetConsoleCursorInfo(handle, &cursor_info);
cursor_info.bVisible = false;
SetConsoleCursorInfo(handle, &cursor_info);
//打印欢迎界面
WelcomeToGame();
//创建地图
CreateMap();
//初始化贪吃蛇
InitSnake(ps);
//创建食物
CreateFood(ps);
}
//2.游戏运行
void PrintHelpInfo()//打印辅助信息
{
SetPos(64, 15);
printf("1.不能撞墙,不能咬自己。");
SetPos(64, 16);
printf("2.使用↑、↓、←、→控制蛇的移动。");
SetPos(64, 17);
printf("3.F3加速,F4减速。");
SetPos(64, 18);
printf("4.ESC退出,空格暂停。");
SetPos(64, 20);
printf("几个几个@版权");
}
int NextIsFood(pSnake ps, pSnakeNode pNext)//判断下一个位置是否是食物
{
if (ps->_pFood->x == pNext->x && ps->_pFood->y == pNext->y)
return 1;
else return 0;
}
void KillByWall(pSnake ps)//蛇是否撞墙
{
if (ps->_psnake->x == 0 || ps->_psnake->x == 56 || ps->_psnake->y == 0 || ps->_psnake->y == 26)
{
ps->_Status = KILL_BY_WALL;
}
}
void KillBySelf(pSnake ps)//蛇是否自杀
{
pSnakeNode cur = ps->_psnake->next;
while (cur)
{
if (ps->_psnake->x == cur->x && ps->_psnake->y == cur->y)
{
ps->_Status = KILL_BY_SELF;
}
cur = cur->next;
}
}
void SnakeMove(pSnake ps)//蛇的移动
{
pSnakeNode pNext = (pSnakeNode)malloc(sizeof(SnakeNode));
if (pNext == NULL)
{
perror("SnakeMove()::malloc()");
return;
}
pNext->next = NULL;
switch (ps->_Dir)
{
case UP:
pNext->x = ps->_psnake->x;
pNext->y = ps->_psnake->y - 1;
break;
case DOWN:
pNext->x = ps->_psnake->x;
pNext->y = ps->_psnake->y + 1;
break;
case LEFT:
pNext->x = ps->_psnake->x - 2;
pNext->y = ps->_psnake->y;
break;
case RIGHT:
pNext->x = ps->_psnake->x + 2;
pNext->y = ps->_psnake->y;
break;
}
//判断下一个位置是否是食物
if (NextIsFood(ps, pNext))//是
{
//头插
pNext->next = ps->_psnake;
ps->_psnake = pNext;
//打印蛇身
SetPos(ps->_psnake->x, ps->_psnake->y);
wprintf(L"%lc", BODY);
//处理食物
free(ps->_pFood);
ps->_Score += ps->_FoodWeight;
CreateFood(ps);
}
else//不是
{
//头插
pNext->next = ps->_psnake;
ps->_psnake = pNext;
//删除最后节点并打印蛇身
SetPos(ps->_psnake->x, ps->_psnake->y);
wprintf(L"%lc", BODY);
pSnakeNode cur = ps->_psnake;
while (cur->next->next)
{
cur = cur->next;
}
SetPos(cur->next->x, cur->next->y);
printf(" ");
free(cur->next);
cur->next = NULL;
}
//蛇是否撞墙
KillByWall(ps);
//蛇是否自杀
KillBySelf(ps);
}
void GameRun(pSnake ps)
{
PrintHelpInfo();
do
{
//打印按键得分
SetPos(64, 10);
printf("得分:%05d", ps->_Score);
SetPos(64, 11);
printf("每个食物的分数:%2d", ps->_FoodWeight);
//判断按键情况
if (PRESS_KET(VK_UP) && ps->_Dir != DOWN)
{
ps->_Dir = UP;
}
else if (PRESS_KET(VK_DOWN) && ps->_Dir != UP)
{
ps->_Dir = DOWN;
}
else if (PRESS_KET(VK_LEFT) && ps->_Dir != RIGHT)
{
ps->_Dir = LEFT;
}
else if (PRESS_KET(VK_RIGHT) && ps->_Dir != LEFT)
{
ps->_Dir = RIGHT;
}
else if (PRESS_KET(VK_ESCAPE))
{
ps->_Status = END_NORMAL;
}
else if (PRESS_KET(VK_SPACE))
{
while (1)
{
Sleep(100);
if (PRESS_KET(VK_SPACE))
{
break;
}
}
}
else if (PRESS_KET(VK_F3))//加速
{
if (ps->_SleepTime >= 80)
{
ps->_SleepTime -= 30;
ps->_FoodWeight += 2;
}
}
else if (PRESS_KET(VK_F4))//减速
{
if (ps->_SleepTime <= 320)
{
ps->_SleepTime += 30;
ps->_FoodWeight -= 2;
}
}
//蛇的移动
Sleep(ps->_SleepTime);
SnakeMove(ps);
} while (ps->_Status == OK);
}
//3.游戏结束
void GameEnd(pSnake ps)
{
SetPos(20, 12);
switch (ps->_Status)
{
case END_NORMAL:
printf("退出游戏n");
break;
case KILL_BY_SELF:
printf("撞自己了,游戏结束。n");
break;
case KILL_BY_WALL:
printf("撞墙了,游戏结束。n");
break;
}
SetPos(0, 27);
//释放蛇身节点
pSnakeNode cur = ps->_psnake;
while (cur)
{
pSnakeNode del = cur;
cur = cur->next;
free(del);
}
ps->_psnake = NULL;
}
main函数:main.c
#include"snake.h"
#include<stdio.h>
#include<locale.h>
int main()
{
//设置程序适应本地环境
setlocale(LC_ALL, "");
srand(time(NULL));
Snake snake = { 0 };
//1.游戏开始 - 初始化游戏
GameStart(&snake);
//2.游戏运行
GameRun(&snake);
//3.游戏结束
GameEnd(&snake);
return 0;
}
原文地址:https://blog.csdn.net/2301_78922485/article/details/134361907
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.7code.cn/show_24720.html
如若内容造成侵权/违法违规/事实不符,请联系代码007邮箱:suwngjj01@126.com进行投诉反馈,一经查实,立即删除!