#include <stdio.h>
#include <Windows.h>
#include <stdlib.h>
#include <time.h>
#include <conio.h>
#define row 32 //游戏区行数
#define col 72 //游戏区列数
#define nothing 0
#define wall 1
#define food 2
#define head 3
#define BODY 4
#define up 72
#define down 80
#define left 75
#define right 77
#define space 32
#define esc 27
//蛇头
struct Snake
{
int len,x,y;
}snake;
//蛇身
struct Body
{
int x,y;
}body[row*col];
int zhuangtai[row][col]; //标记游戏区各个位置的状态
//隐藏光标
void hidecursor();
//光标跳转
void cursorjump(int x, int y);
//初始化界面
void injm();
//颜色设置
void color(int c);
//从文件读取最高分
void rg();
//更新最高分到文件
void wg();
//初始化蛇
void insnake();
//随机生成食物
void randfood();
//判断得分与结束
void jgfun(int x, int y);
//打印蛇与覆盖蛇
void pfsnake(int flag);
//移动蛇
void movesnake(int x, int y);
//执行按键
void run(int x, int y);
//游戏主体逻辑函数
void game();
//
void in();
void exp();
void mod();
void mmod();
void scmod();
void mrun(int x, int y);
void mjgfun(int x, int y);
void minjm();
int maxlife, life; //全局变量
int main()
{
while(1)
{
in();
int n;scanf("%d",&n);
switch (n) {
case 2:
scmod();
break;
case 3:
exp();
break;
case 1:
mmod();
default:
system("cls");
cursorjump(2 * (col / 3), row / 2 );
printf("请重新选择");
Sleep(1000);
system("cls");
main();
}
}
return 0;
}
void exp(){
system("cls");
cursorjump(2 * (col / 3), row / 2 - 15);
printf("贪吃蛇生存版游戏说明");
cursorjump(2 * (col / 3)-20, row / 2 - 12);
printf("1.不能撞墙,不能吃到自己,生命值不能为0,否则死亡");
cursorjump(2 * (col / 3)-20, row / 2 - 10);
printf("2.用↑.↓.←.→分别控制蛇的移动");
cursorjump(2 * (col / 3)-20, row / 2 - 8);
printf("3.你的初始生命值为8");
cursorjump(2 * (col / 3)-20, row / 2 - 6);
printf("4.每改变一次方向你的生命值将会减少2");
cursorjump(2 * (col / 3)-20, row / 2 - 4);
printf("5.害怕你死的太快,每吃到一次食物你的生命值将会增加16");
cursorjump(2 * (col / 3)-20, row / 2 - 2);
printf("6.space 暂停,按↑.↓.←.→开始");
cursorjump(2 * (col / 3)-20, row / 2 );
printf("5.r/R重新开始游戏或返回菜单");
cursorjump(2 * (col / 3)-20, row / 2 +2);
printf("7.esc 退出游戏");
cursorjump(2 * (col / 3)-20, row / 2 +4);
printf("tips:长按↑.↓.←.→加速");
_getch();
system("cls");
}
void scmod()
{
maxlife = 0, life = 9;//初始生命值为8 每改变一次方向将会消耗2生命值
system("title 贪吃蛇生存版");
system("mode con cols=144 lines=33"); //设置cmd窗口的大小
hidecursor();
rg();
injm();
insnake();
srand((unsigned int)time(NULL)); //设置随机数生成起点
randfood();
pfsnake(1);
game();
}
void mmod()
{
maxlife = 0, life = 0;//初始生命值为8 每改变一次方向将会消耗2生命值
system("title 贪吃蛇");
system("mode con cols=144 lines=33"); //设置cmd窗口的大小
hidecursor();
rg();
minjm();
insnake();
srand((unsigned int)time(NULL)); //设置随机数生成起点
randfood();
pfsnake(1);
mod();
}
void in()
{
color(6);
cursorjump(2 * (col / 3)+5, row / 2 - 15);
printf(" \n");
printf(" __________ ___ \n");
printf(" / \\ / \\ \\ |____ __\\__ \n");
printf(" / ________ \\ / ___ \\ _/ __ | | / \n");
printf(" | | |__| _/_ |_| / [|] |/ \n");
printf(" | | | | | / _|_ \\__/ \n");
printf(" \\ \\_______ / \\ |___/ ____ \n");
printf(" \\ \\ ____ ____ ____ __ | | ___ ______ \n");
printf(" \\_______ \\ | |/ \\ / \\_/ / | | / / / \\ \n");
printf(" \\ \\ | ___ \\ / ____ / | |/ / / ____ \\ \n");
printf(" __ | | | / \\ \\ | | | / | / | /____\\ | \n");
printf(" \\ \\_______| | | | | | | |__| | | \\ | ________/ \n");
printf(" \\ / | | | | \\ \\ | |\\ \\ \\ \\____ \n");
printf(" \\__________/ |__| |__| \\___/\\__\\ |__| \\__\\ \\______/ \n");
cursorjump(2 * (col / 3), row / 2 +3);
printf("1.正常模式");
cursorjump(2 * (col / 3), row / 2 +5);
printf("2.生存模式");
cursorjump(2 * (col / 3), row / 2 +7);
printf("3.游戏说明");
cursorjump(2 * (col / 3), row / 2 +9);
printf("请选择(1/2/3):");
}
//隐藏光标
void hidecursor()
{
CONSOLE_CURSOR_INFO curInfo; //定义光标信息的结构体变量
curInfo.dwSize = 1; //如果没赋值的话,光标隐藏无效
curInfo.bVisible = FALSE;
HANDLE handle = GetStdHandle(STD_OUTPUT_HANDLE); //获取控制台句柄
SetConsoleCursorInfo(handle, &curInfo); //设置光标信息
}
//光标跳转
void cursorjump(int x, int y)
{
COORD pos; //定义光标位置的结构体变量 typedef unsigned long DWORD;//DWORD 表示 32bit 无符号整数,
pos.X = x; pos.Y = y;
HANDLE handle = GetStdHandle(STD_OUTPUT_HANDLE); //获取控制台句柄
SetConsoleCursorPosition(handle, pos); //设置光标位置
}
//初始化界面
void injm()
{
color(6);
for (int i = 0; i < row; i++)
{
for (int j = 0; j < col; j++)
{
if (j == 0 || j == col - 1)
{
zhuangtai[i][j] = wall;
cursorjump(2 * j, i);
printf("■");
}
else if (i == 0 || i == row - 1)
{
zhuangtai[i][j] = wall;
printf("■");
}
else
{
zhuangtai[i][j] = nothing;
}
}
}
color(6);
cursorjump(0, row);
printf("当前生命值:%d", life);
cursorjump(col, row);
printf("历史最高存活生命值:%d", maxlife);
}
//颜色设置
void color(int c)
{
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), c); //颜色设置
//注:SetConsoleTextAttribute是一个API(应用程序编程接口)
}
//从文件读取最高分
void rg()
{
FILE* pf = fopen("贪吃蛇最高得分记录.txt", "r");
if (pf == NULL)
{
pf = fopen("贪吃蛇最高得分记录.txt", "w");
fwrite(&maxlife, sizeof(int), 1, pf);
}
fseek(pf, 0, SEEK_SET);
fread(&maxlife, sizeof(int), 1, pf);
fclose(pf); pf = NULL;
}
//更新最高分到文件
void wg()
{
FILE* pf = fopen("贪吃蛇最高得分记录.txt", "w");
if (pf == NULL)
{
printf("保存最高得分记录失败\n");exit(0);
}
fwrite(&life, sizeof(int), 1, pf);
fclose(pf); pf = NULL;
}
//初始化蛇
void insnake()
{
snake.len = 2;
snake.x = col / 2;
snake.y = row / 2;
//蛇身
body[0].x = col / 2 - 1;
body[0].y = row / 2;
body[1].x = col / 2 - 2;
body[1].y = row / 2;
//将蛇头和蛇身位置进行标记
zhuangtai[snake.y][snake.x] = head;
zhuangtai[body[0].y][body[0].x] = BODY;
zhuangtai[body[1].y][body[1].x] = BODY;
}
//随机生成食物
void randfood()
{
int i, j;
do
{
i = rand() % row;
j = rand() % col;
} while (zhuangtai[i][j] != nothing); //确保生成食物的位置为空,若不为空则重新生成
zhuangtai[i][j] = food; //将食物位置进行标记
color(12);
cursorjump(2 * j, i); //光标跳转到生成的随机位置处
printf("●"); //打印食物
}
//判断得分与结束
void jgfun(int x, int y)
{
if (zhuangtai[snake.y + y][snake.x + x] == food)
{
snake.len++;
life += 16;
color(6);
cursorjump(0, row);
printf("当前生命值:%d", life);
randfood();
}
else if (zhuangtai[snake.y + y][snake.x + x] == wall || zhuangtai[snake.y + y][snake.x + x] == BODY||life==0)
{
Sleep(1000); //留给玩家反应时间
system("cls"); //清空屏幕
color(6);
cursorjump(2 * (col / 3), row / 2 - 3);
if (life > maxlife)
{
printf("您已死亡,恭喜你打破最高记录,最高记录更新为%d", life);wg();
}
else if (life == maxlife)
{
printf("您已死亡,与最高记录持平,加油再创佳绩");
}
else
{
printf("您已死亡,请继续加油,当前与最高记录相差%d", maxlife - life);
}
cursorjump(2 * (col / 3), row / 2);
printf("YOU DIE !");
while (1) //询问玩家是否再来一局
{
char ch;
cursorjump(2 * (col / 3), row / 2 + 3);
printf("是否复活?\n");
cursorjump(2 * (col / 3), row / 2 + 4);
printf("Y or N :\n");
cursorjump(2 * (col / 3)+8, row / 2 + 4);
scanf("%c", &ch);
if (ch == 'y' || ch == 'Y')
{
system("cls");
main();
}
else if (ch == 'n' || ch == 'N')
{
cursorjump(2 * (col / 3), row / 2 + 6);
exit(0);
}
else
{
cursorjump(2 * (col / 3), row / 2 + 6);
printf("选择错误,请再次选择");
}
}
}
}
//打印蛇与覆盖蛇
void pfsnake(int flag)
{
if (flag == 1) //打印蛇
{
color(7);
cursorjump(2 * snake.x, snake.y);
printf("●");
for (int i = 0; i < snake.len; i++)
{
color(12);
cursorjump(2 * body[i].x, body[i].y);
printf("●");
}
}
else
{
if (body[snake.len - 1].x != 0)
{
cursorjump(2 * body[snake.len - 1].x, body[snake.len - 1].y);
printf(" ");
}
}
}
//移动蛇
void movesnake(int x, int y)
{
pfsnake(0); //先覆盖当前所显示的蛇
zhuangtai[body[snake.len - 1].y][body[snake.len - 1].x] = nothing; //蛇移动后蛇尾重新标记为空
zhuangtai[snake.y][snake.x] = BODY; //蛇移动后蛇头的位置变为蛇身
//蛇移动后各个蛇身位置坐标需要更新
for (int i = snake.len - 1; i > 0; i--)
{
body[i].x = body[i - 1].x;
body[i].y = body[i - 1].y;
}
body[0].x = snake.x;
body[0].y = snake.y;
//蛇头
snake.x = snake.x + x;
snake.y = snake.y + y;
pfsnake(1);
}
//执行按键
void run(int x, int y)
{
int t = 0;
while (1)
{
if (t == 0) t = 3000; //t越小越快
while (--t)
{
if (kbhit() != 0) {break;}//若键盘被敲击,则退出循环
}
if (t == 0)
{
jgfun(x, y); movesnake(x, y); //移动蛇
}
else return; //返回Game函数读取键值
}
}
//游戏主体逻辑函数
void game()
{
int n = right; //开始游戏时,默认向后移动
int tp = 0; //记录蛇的移动方向 当前键值
goto first;
while (1)
{
n = getch(); //读取键值
switch (n)
{
case up:
case down:
if (tp != left&&tp != right)
{
n = tp;
}
break;
case left:
case right:
if (tp != up&&tp != down)
{
n = tp;
}
case space:
case esc:
case 'r':
case 'R':
break;
default:
n = tp;
break;
}
first: //第一次进入循环先向默认方向前进
switch (n)
{
case up: //倒着的直角坐标系
life--;
color(6);
cursorjump(0, row);
printf("当前生命值:%d", life);run(0, -1); tp = up;break;
case down:
life--;
color(6);
cursorjump(0, row);
printf("当前生命值:%d", life);run(0, 1); tp = down;break;
case left:
life --;
color(6);
cursorjump(0, row);
printf("当前生命值:%d", life);run(-1, 0); tp = left;break;
case right:
life --;
color(6);
cursorjump(0, row);
printf("当前生命值:%d", life);run(1, 0); tp = right;break;
case space:
system("pause>nul"); break;
case esc:
system("cls"); //清空屏幕
color(7);
cursorjump(col - 8, row / 2);
printf(" 游戏结束 ");
cursorjump(col - 8, row / 2 + 2);
exit(0);
case 'r':
case 'R': //重新开始
system("cls"); //清空屏幕
main();
}
}
}
void mod()
{
int n = right; //开始游戏时,默认向后移动
int tp = 0; //记录蛇的移动方向 当前键值
goto first;
while (1)
{
n = getch(); //读取键值
switch (n)
{
case up:
case down:
if (tp != left&&tp != right)
{
n = tp;
}
break;
case left:
case right:
if (tp != up&&tp != down)
{
n = tp;
}
case space:
case esc:
case 'r':
case 'R':
break;
default:
n = tp;
break;
}
first: //第一次进入循环先向默认方向前进
switch (n)
{
case up: //倒着的直角坐标系
mrun(0, -1); tp = up;break;
case down:
mrun(0, 1); tp = down;break;
case left:
mrun(-1, 0); tp = left;break;
case right:
mrun(1, 0); tp = right;break;
case space:
system("pause>nul"); break;
case esc:
system("cls"); //清空屏幕
color(7);
cursorjump(col - 8, row / 2);
printf(" 游戏结束 ");
cursorjump(col - 8, row / 2 + 2);
exit(0);
case 'r':
case 'R': //重新开始
system("cls"); //清空屏幕
main();
}
}
}
//执行按键
void mrun(int x, int y)
{
int t = 0;
while (1)
{
if (t == 0)
t = 3000; //t越小越快
while (--t)
{
if (kbhit() != 0) break;//若键盘被敲击,则退出循环
}
if (t == 0)
{
mjgfun(x, y); movesnake(x, y); //移动蛇
}
else break; //返回Game函数读取键值
}
}
void mjgfun(int x, int y)
{
if (zhuangtai[snake.y + y][snake.x + x] == food)
{
snake.len++;
life += 5;
color(6);
cursorjump(0, row);
printf("当前得分:%d", life);
randfood();
}
else if (zhuangtai[snake.y + y][snake.x + x] == wall || zhuangtai[snake.y + y][snake.x + x] == BODY)
{
Sleep(1000); //留给玩家反应时间
system("cls"); //清空屏幕
color(6);
cursorjump(2 * (col / 3), row / 2 - 3);
if (life > maxlife)
{
printf("恭喜你打破最高记录,最高记录更新为%d", life);wg();
}
else if (life == maxlife)
{
printf("与最高记录持平,加油再创佳绩");
}
else
{
printf("请继续加油,当前与最高记录相差%d", maxlife - life);
}
cursorjump(2 * (col / 3), row / 2);
printf("GAME OVER");
while (1) //询问玩家是否再来一局
{
char ch;
cursorjump(2 * (col / 3), row / 2 + 3);
printf("再来一局?\n");
cursorjump(2 * (col / 3), row / 2 + 4);
printf("Y or N :\n");
cursorjump(2 * (col / 3)+8, row / 2 + 4);
scanf("%c", &ch);
if (ch == 'y' || ch == 'Y')
{
system("cls");
main();
}
else if (ch == 'n' || ch == 'N')
{
cursorjump(2 * (col / 3), row / 2 + 6);
exit(0);
}
else
{
cursorjump(2 * (col / 3), row / 2 + 6);
printf("选择错误,请再次选择");
}
}
}
}
void minjm()
{
color(6);
for (int i = 0; i < row; i++)
{
for (int j = 0; j < col; j++)
{
if (j == 0 || j == col - 1)
{
zhuangtai[i][j] = wall;
cursorjump(2 * j, i);
printf("■");
}
else if (i == 0 || i == row - 1)
{
zhuangtai[i][j] = wall;
printf("■");
}
else
{
zhuangtai[i][j] = nothing;
}
}
}
color(6);
cursorjump(0, row);
printf("当前得分:%d", life);
cursorjump(col, row);
printf("历史最高得分:%d", maxlife);
}
贪吃蛇大作战 内涵生存模式
最新推荐文章于 2024-07-06 15:15:17 发布