当前位置:网站首页>Snake game, C language
Snake game, C language
2022-08-09 07:32:00 【hash crazy】
效果演示Snach.c
文件
#include <stdlib.h>
#include <stdlib.h>
#include <stdio.h>
#include <conio.h>
#include <time.h>
#include "consfun.h"
#include "config.h"
#define NR(x) (sizeof(x)/sizeof(x[0]+0)) /*计算数组长度*/
#define TITLE "**贪吃蛇游戏**"
#define AUTHOR "作者:张某某"
#define DATE "日期:2020年06月10日"
#define WIDTH 54 /*地图宽度*/
#define HEIGHT WIDTH/2 /*地图高度*/
#define SHead "◆" /*蛇头*/
#define SBody "■" /*蛇身体*/
/*定义一条蛇,蛇头方向RIGHT,生命值1,长度0,分数0*/
Snake S;
/*定义食物*/
Point Food;
/*菜单项*/
const char *menu[] = {
"*开始游戏*","*游戏难度*","*退出游戏*"};
/*游戏难度*/
const char *rank[] = {
"初级","中级","高级"};
/*Game difficulty marker*/
int lev = 0;
/*Print characters to the specified position*/
int Print(int x, int y,const char str[],short color){
gotoxy(x,y); /*设置光标位置*/
textcolor(color); /*设置前景颜色*/
printf("%s",str);
return 0;
}
/*显示菜单*/
int showMenu(){
int i = 0,size = NR(menu),ret = 0, ind = 0;
consinit(70, 30);
Print((WIDTH-strlen(TITLE))/2,0,TITLE,2); /*打印标题*/
Print(WIDTH+1,0,"游戏难度:",2); /*Print the game difficulty*/
Print(WIDTH+11,0,rank[lev],2);
Print((WIDTH-strlen(AUTHOR))/2,HEIGHT-4,AUTHOR,2); /*Print the author*/
Print((WIDTH-strlen(DATE))/2,HEIGHT-3,DATE,2); /*打印日期*/
Print(WIDTH,HEIGHT + 1,"按Esc键退出游戏",2);
while(1){
/*Controls menu selections*/
for(i = 0;i < size;i++) /*Cycle through the print menu items*/
Print( (WIDTH-strlen(menu[i]))/2, (HEIGHT-size)/2+i,menu[i], i == ind ? 5 : 2 );
while((ret = _getch()) != ESC && ret != UP && ret != DOWN && ret != ENTER);/*控制用户输入*/
ret == UP && ind > 0 ? ind -= 1 : ret == DOWN && ind < size - 1 ? ind += 1 : 0;/*Controls the change of the selected index*/
if(ret == ENTER){
/*Determine which option was pressed【回车】*/
switch(ind){
case 0:{
/*开始游戏*/
/*显示地图*/
showMap();
if (!SnakeMove(&S)){
/*返回值为0It is a reminder that the game is over!*/
Print(WIDTH/2-5,HEIGHT/2,"Game Over!",12);
while((ret = _getch()) != ESC);/*控制用户输入*/
}
break ;
}
case 1:{
/*游戏难度*/
/*Cyclically changing difficulty levels*/
lev = (lev + 1) % NR(rank);
/*Printing difficulty level*/
Print(WIDTH+11,0,rank[lev],2);
break ;
}
case 2: exit(0); /*退出游戏*/
}
}else if(ret == ESC) exit(0); /*按ESC键退出游戏*/
}
return 0;
}
/*创建地图*/
void showMap(){
char str[20] = {
0};
int i,j;
clrscr();
Print(WIDTH+1,0, "游戏难度:",2);
Print(WIDTH+1,2, "游戏时间:",2);
Print(WIDTH+1,4, "snake health:",2);
Print(WIDTH+1,6, "当前得分:",2);
Print(WIDTH,HEIGHT+1,"按Esc键返回菜单",2);
Print(WIDTH+11,0,rank[lev],2);
Print(WIDTH+11,2,"0",2);/*游戏时间*/
Print(WIDTH+11,4,"1",2);/*snake health*/
Print(WIDTH+11,6,"0",2);/*当前得分*/
for(i=0;i<WIDTH;++i)/*Print map boundaries*/
for(j=0;j<HEIGHT;++j)
if(i==0||j==0||i==WIDTH-1||j==HEIGHT-1)
Print(i,j,"#",2);
InitSnake(&S,2);/*初始化蛇*/
randFood(&S);/*随机生成食物*/
}
/*初始化蛇*/
void InitSnake(Snake *ps,const int len){
Node *p;
int i = 0;
ps->hp = 1;/*初始生命值*/
ps->len = 0;/*Snake length is cleared*/
ps->score = 0;/*当前得分*/
ps->sym = RIGHT;/*蛇头方向*/
ps->head = NULL;
for(;i < len; i++){
if((p = (Node*)malloc(sizeof(Node))) == NULL){
/*Determine whether the memory allocation was successful*/
Print(0,0,"分配内存失败,按任意键退出程序!",2);
system("pause>nul");
exit(0);
}
/*New node coordinates*/
p->pos.x = ((WIDTH + len * 2) / 2 - (len - i) * 2) | 1; /* xCoordinates must be odd */
p->pos.y = HEIGHT / 2;
/*采用头插法*/
p->next = ps->head;
ps->head = p;
/*蛇长加1*/
ps->len++;
/*Print the node to the screen*/
Print(p->pos.x,p->pos.y,SBody,2);
}
Print(ps->head->pos.x,ps->head->pos.y,SHead,2);
}
/*随机生成食物*/
void randFood(const Snake *s){
int x, y, k = 1;
Node *p = s->head;/*Create a node pointing to the snake head*/
while(p != NULL && k){
/*Randomly generate coordinates within the bounds of the map*/
x = (rand() % (WIDTH - 3) + 1) | 1;/* xCoordinates must be odd */
y = rand() % (HEIGHT - 2) + 1;
while(p != NULL && k)/*Determine whether the random coordinates overlap with the snake body*/
p->pos.x == x && p->pos.y == y ? k = 0 : (int)(p = p->next);
k = !k;
}
Food.x = x; Food.y = y;
/*Print food to the screen*/
Print(x,y,SBody,9);
}
/*控制蛇的移动*/
int SnakeMove(Snake *s){
int vec = 0,i = 0,j;
char key,str[10];
DWORD old;
long time;
while(j = 1){
if(_kbhit()){
key = _getch();
/*Press the direction of the snake head to shield the specified direction key*/
if(s->sym == UP && key == DOWN) continue;
else if(s->sym == DOWN && key == UP) continue;
else if(s->sym == LEFT && key == RIGHT) continue;
else if(s->sym == RIGHT && key == LEFT) continue;
switch(key){
/*If the arrow keys are pressed,Change the direction of the snake head*/
case UP : s->sym = UP ; break;
case DOWN : s->sym = DOWN ; break;
case LEFT : s->sym = LEFT ; break;
case RIGHT: s->sym = RIGHT; break;
case ESC : return 1;
default : continue;
}
vec = 1;
/*Life after snake collision-1*/
if(!ChangeSnackXY(s)){
s->hp -= 1;
_itoa_s((int)s->hp,str,sizeof(str)-1,10);
Print(WIDTH+11,4,str,2);/*snake health*/
Print(0,HEIGHT,"撞到障碍物,生命值-1!",12);
}
}
if(vec != 0){
vec = (lev == 0 ? 300 : (lev == 1 ? 150 : 30));
time = GetTickCount() - old;/*Calculate start game time*/
_itoa_s((int)(time / 1000),str,sizeof(str)-1,10);
Print(WIDTH+11,2,str,2);/*Print game time*/
if((time / vec) % 2){
/*控制移动速度*/
/*Life after snake collision-1*/
if(i-- == 0 && !(ChangeSnackXY(s))){
/*用i保证ChangeSnackXY(s)Only run once during the valid time*/
s->hp -= 1;
_itoa_s((int)s->hp,str,sizeof(str)-1,10);
Print(WIDTH+11,4,str,2);/*snake health*/
Print(0,HEIGHT,"撞到障碍物,生命值-1!",12);
}
}else
i = 0;
}else{
old = GetTickCount();
}
if((int)s->hp <= 0) return 0;/*Health is less than or equal to0时,函数返回0*/
}
return 1;
}
/*Update snake position*/
int ChangeSnackXY(Snake *s){
int x = s->head->pos.x, y = s->head->pos.y;
Node *p = s->head->next;
int vx = 0, vy = 0;
switch(s->sym){
case UP : vy = -1; break;
case DOWN : vy = 1; break;
case LEFT : vx = -2; break;
case RIGHT: vx = 2; break;
}
vx += x; vy += y;
if(vx < 1 || vx >= WIDTH - 2 || vy == 0 || vy >= HEIGHT - 1) return 0;/*The snake head hits the border and returns0*/
while(p != NULL){
/*The head of the snake meets the body of the snake and returns0*/
if(p->pos.x == vx && p->pos.y == vy)
return 0;
else
p = p->next;
}
if(vx == Food.x && vy == Food.y){
/*Eat food snakes grow1*/
SAdd(s);
return 1;
}
p = s->head->next;/*Repoint to the next node of the snake head*/
s->head->pos.x = vx;/*修改蛇头坐标*/
s->head->pos.y = vy;
Print(x,y,SBody,2);/*The old snake head was changed to the body*/
Print(vx,vy,SHead,2);/*Reposition the snake head*/
while(p != NULL){
/*Loop to update the coordinates of each node of the snake*/
vx = p->pos.x;
vy = p->pos.y;
p->pos.x = x;
p->pos.y = y;
x = vx; y = vy;
p = p->next;
}
Print(x,y," ",2);/*Erase old snake tail position characters*/
Sleep(30);/*休眠30毫秒*/
return 1;
}
/*Snakes grow longer after eating food1*/
void SAdd(Snake *s){
char str[20] = {
0};
Node *p;
if((p = (Node*)malloc(sizeof(Node))) == NULL){
/*Determine whether the memory allocation was successful*/
Print(0,0,"分配内存失败,按任意键退出程序!",2);
system("pause>nul");
exit(0);
}
Print(s->head->pos.x,s->head->pos.y,SBody,2);/*Change the coordinates of the old snake head to the body character*/
p->pos.x = Food.x;/*Use food as a new snake head*/
p->pos.y = Food.y;
p->next = s->head;
s->head = p;
s->len++;
s->score++;
s->hp += 0.1f;
_itoa_s((int)s->hp,str,sizeof(str)-1,10);
Print(WIDTH+11,4,str,2);/*Update snake health*/
_itoa_s(s->score,str,sizeof(str)-1,10);
Print(WIDTH+11,6,str,2);/*更新当前得分*/
Print(p->pos.x,p->pos.y,SHead,2);/*更新蛇头位置*/
Print(0,HEIGHT,"吃到食物,蛇长+1! ",12);
randFood(s);/*随机生成食物*/
}
int main(){
SetConsoleTitleA("贪吃蛇游戏");
/*定义随机数种子*/
srand((unsigned)time(NULL));
showMenu();
return 0;
}
consfun.h
——WINDOWSCommand window programming common functions(网上找的,非原创)
#include <windows.h>
#include <wincon.h>
void consinit(short x,short y);
void gotoxy(int,int);
void clrscr(void);
void textcolor(short newcolor);
void textbackground(short newcolor);
void textattr(short newattr);
/* 功能:Initialize the command window,Sets the number of rows and columns of the window 参数:y-行数,x-列数 */
void consinit(short x, short y)
{
COORD scr={
x,y};
CONSOLE_SCREEN_BUFFER_INFO info;
SMALL_RECT rect={
0,0,x-1,y-1};
HANDLE stdOut = GetStdHandle(STD_OUTPUT_HANDLE);
GetConsoleScreenBufferInfo(stdOut,&info); //Get command window information
//If the original screen buffer is small, you must first set the new buffer size,Resize the window again
if(info.dwSize.X*info.dwSize.Y<x*y)
{
SetConsoleScreenBufferSize(stdOut,scr);
SetConsoleWindowInfo(stdOut,TRUE,&rect);//An error occurs when the buffer is smaller than needed
}
else
{
SetConsoleWindowInfo(stdOut,TRUE,&rect);
SetConsoleScreenBufferSize(stdOut,scr); //Setting a value smaller than what is required for the window area will give an error
}
gotoxy(0,0);
}
/* 设置光标位置:Make subsequent output from the screenx行y列输出 参数:x-行(从0开始) y-列(从0开始) */
void gotoxy(int x, int y)
{
COORD Position;
CONSOLE_CURSOR_INFO cci;
Position.X=x; Position.Y=y;
SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE),Position);
GetConsoleCursorInfo(GetStdHandle(STD_OUTPUT_HANDLE), &cci); /*获取光标信息*/
cci.dwSize = 1; cci.bVisible = 0; /*Set cursor size and visibility parameters*/
SetConsoleCursorInfo(GetStdHandle(STD_OUTPUT_HANDLE), &cci); /*设置(应用)光标信息*/
}
/* 清屏:Clear the screen with the current background color,and position the cursor in the upper left corner(0,0) 参数:无 */
void clrscr(void)
{
COORD scr={
0,0};
DWORD num;
HANDLE stdOut = GetStdHandle(STD_OUTPUT_HANDLE);
CONSOLE_SCREEN_BUFFER_INFO info;
GetConsoleScreenBufferInfo(stdOut,&info);
num=info.dwMaximumWindowSize.X*info.dwMaximumWindowSize.Y;
FillConsoleOutputAttribute(stdOut,(WORD)info.wAttributes,num,scr,&num);
FillConsoleOutputCharacter(stdOut,' ',num,scr,&num);
gotoxy(0,0);
}
/* 设置字体颜色:Changes future output font foreground color to given value 参数:newcolor-The new color value The color value range is :0x00 ~ 0x0f */
void textcolor(short newcolor)
{
HANDLE stdOut = GetStdHandle(STD_OUTPUT_HANDLE);
CONSOLE_SCREEN_BUFFER_INFO info;
GetConsoleScreenBufferInfo(stdOut,&info);
SetConsoleTextAttribute(stdOut, (WORD)(newcolor|info.wAttributes & 0xF0));
}
/* 设置背景颜色:Changes the background color of subsequent outputs to the given value 参数:newcolor-The new color value The color value range is :0x00 ~ 0x0f */
void textbackground( short newcolor)
{
HANDLE stdOut = GetStdHandle(STD_OUTPUT_HANDLE);
CONSOLE_SCREEN_BUFFER_INFO info;
GetConsoleScreenBufferInfo(stdOut,&info);
SetConsoleTextAttribute(stdOut,(WORD)((newcolor<<4)|(info.wAttributes&0x0F)));
}
/* 设置文本属性:Set both foreground and background colors 参数:newattr-新的属性值 The color value range is :0x00 ~ 0xff,低4Bit is the foreground color,高4Bit is the background color */
void textattr(short newattr)
{
HANDLE stdOut = GetStdHandle(STD_OUTPUT_HANDLE);
SetConsoleTextAttribute(stdOut,newattr);
}
config.h
——Contains the snake data structure、Constants and related function declarations
/*Define the entity type tag*/
enum {
EMPTY , /*空*/
FOOD , /*食物*/
SNACK , /*蛇*/
};
/*定义Keyboard的键值数据 */
enum {
UP = 72 ,
DOWN = 80 ,
LEFT = 75 ,
RIGHT = 77 ,
ENTER = 13 ,
ESC = 27 ,
};
/*Defines the coordinate structure type*/
typedef struct {
short x,y;
}Point;
/*Define the node structure type*/
typedef struct node{
Point pos;
struct node *next;
}Node;
/*Define the snake structure type*/
typedef struct snake{
Node *head;
short sym; /*蛇头方向*/
float hp; /*生命值*/
short len; /*长度*/
int score;/*分数*/
}Snake; /*Point to a snake*/
/*Print characters to the specified position*/
int Print(int,int,const char[],short);
/*显示菜单*/
int showMenu();
/*创建地图*/
void showMap();
/*初始化蛇,并打印到屏幕*/
void InitSnake(Snake*,const int);
/*随机生成食物,并打印到屏幕*/
void randFood(const Snake *);
/*控制蛇的移动*/
int SnakeMove(Snake *);
/*Update snake position*/
int ChangeSnackXY(Snake *);
/*Snakes grow longer after eating food1*/
void SAdd(Snake *);
边栏推荐
猜你喜欢
Variable used in lambda expression should be final or effectively final报错解决方案
错误:为 repo ‘oracle_linux_repo‘ 下载元数据失败 : Cannot download repomd.xml: Cannot download repodata/repomd.
【报错】Root Cause com.mysql.jdbc.exceptions.jdbc4.CommunicationsException: Communications link failure
虚拟机网卡报错:Bringing up interface eth0: Error: No suitable device found: no device found for connection
金九银十即将到来,求职套路多,面试指南我来分享~
Inception V3 Eye Closure Detection
【Oracle 11g】Redhat 6.5 安装 Oracle11g
力扣 636. 函数的独占时间
买口罩(0-1背包)
搭载开源鸿蒙系统的嵌入式XM-RK3568工业互联方案
随机推荐
SAP ALV 数据导出被截断的bug
排序第一节——插入排序(直接插入排序+希尔排序)(视频讲解26分钟)
Oracle 限制时将空值排除
Sklearn data preprocessing
CoCube传感器MPU6050笔记
web自动化测试有哪些工具和框架?
Codeforces Round #359 (Div. 2) C. Robbers' watch Violent Enumeration
【模板】树链剖分 P3384
虚拟机网卡报错:Bringing up interface eth0: Error: No suitable device found: no device found for connection
训练好的深度学习模型,多种部署方式
工信部等四部门推动绿色智能家居产品下乡
【sqlite3】sqlite3.OperationalError: table addresses has 7 columns but 6 values were supplied
基于布朗运动的文本生成方法-LANGUAGE MODELING VIA STOCHASTIC PROCESSES
常见的分布式事务解决方案
ImportError: cannot import name ‘imresize‘
字节也开始缩招了...
差分约束-图论
Lottie系列三 :原理分析
XILINX K7 FPGA+RK3399 PCIE驱动调试
P1505 [National Training Team] Tourism Tree Chain Breakdown