贪吃蛇小游戏可以按照自己的想法改代码,理解好游戏的核心就行。
这些代码只要学会C语言的函数和数组就可以自己写,很简单的,主要看start_game()这个函数就行。
#include<stdio.h>
#include<stdlib.h>
#include<Windows.h>
#include<conio.h> // 控制台输入输出库头文件
#include<windows.h>
#include<time.h>
#define High 24 /*坐标原点在左上方,在此游戏画面尺寸以向下为x的正半轴,向右为Y的正半轴 */
#define Width 100
void time_c();
void start_game();
char zhanghao[15]="11111111111"; //私人账号
char mima[15]="111111"; //私人密码
/* ------------------游戏代码--------------------- */
//全局变量
int moveDirection=4; //小蛇移动方向 ,上下左右分别用1,2,3,4表示
int food_x,food_y; //食物的坐标
int boom_x, boom_y; //炸弹的坐标
int canvas[High][Width]={0}; //二维数组存储画布中对应元素
int score=0; //初始得分为0分
//该函数是用于控制 控制台的光标的移动
void gotoxy(int x,int y)
{
HANDLE handle=GetStdHandle(STD_OUTPUT_HANDLE); //调用
COORD pos; //定义一个坐标
pos.X=x;
pos.Y=y;
SetConsoleCursorPosition(handle,pos);
}
//该函数是为了蛇的正常运动以及保证食物和炸弹的持续出现
void moveSankeByDirection()
{
int i,j;
for(i=1;i<High-1;i++)
{
for(j=1;j<Width-1;j++)
{
if(canvas[i][j]>0)
canvas[i][j]++;
}
}
int oldTail_i,oldTail_j,oldHead_i,oldHead_j;
int m=0;
for(i=1;i<High-1;i++)
{
for(j=1;j<Width-1;j++)
{
if(canvas[i][j]>0)
{
if(m<canvas[i][j]) //数一直在变,最大的数是蛇尾,所以找最大的数
{
m=canvas[i][j];
oldTail_i=i;
oldTail_j=j;
}
if(canvas[i][j]==2) //旧蛇头的位置
{
oldHead_i=i;
oldHead_j=j;
}
}
}
}
int newHead_i,newHead_j;
if(moveDirection==1) //向上移动
{
newHead_i=oldHead_i-1;
newHead_j=oldHead_j;
}
if(moveDirection==2) //向下移动
{
newHead_i=oldHead_i+1;
newHead_j=oldHead_j;
}
if(moveDirection==3) //向左移动
{
newHead_i=oldHead_i;
newHead_j=oldHead_j-1;
}
if(moveDirection==4) //向右移动
{
newHead_i=oldHead_i;
newHead_j=oldHead_j+1;
}
//如果吃到食物
if(canvas[newHead_i][newHead_j]==-2)
{
canvas[food_x][food_y]=0;
//产生一个新的食物
food_x=rand()%(High-5)+2;
food_y=rand()%(Width-5)+2;
canvas[food_x][food_y]=-2;
score+=10;
//原来的旧蛇尾不用减,长度增加1
}
else//否则,为了保持长度不变,原来的旧蛇尾减掉
{
canvas[oldTail_i][oldTail_j]=0;
}
//如果吃到炸弹减20分,随机产生新的炸弹
if(canvas[newHead_i][newHead_j]==-3)
{
canvas[boom_x][boom_y]=0;
boom_x=rand()%(High-5)+2;
boom_y=rand()%(Width-5)+2;
canvas[boom_x][boom_y]=-3;
score-=20;
}
//如果小蛇和自身相撞或者撞墙或者得分小于0 ,游戏失败,
if(canvas[newHead_i][newHead_j]>0||canvas[newHead_i][newHead_j]==-1 ||score<0)
{
system("color 0c");
printf("游戏失败!\n");
printf("游戏重新开始!\n");
start_game();
}
else
{
canvas[newHead_i][newHead_j]=1; //为新的蛇头赋值
}
}
//初始化时的函数
void startup()
{
int i,j;
//初始化边框
for(i=0;i<High;i++)
{
canvas[i][0]=-1;
canvas[i][Width-1]=-1;
}
for(j=0;j<Width;j++)
{
canvas[0][j]=-1;
canvas[High-1][j]=-1;
}
//初始化蛇头
canvas[High/2][Width/2]=1;
//初始化蛇身,画布元素分别为2,3,4,5
for(i=1;i<=4;i++)
canvas[High/2][Width/2-i]=i+1;
//初始小蛇向右移动
moveDirection=4;
food_x=rand()%(High-5)+2; //随机产生食物
food_y=rand()%(Width-5)+2;
canvas[food_x][food_y]=-2;
boom_x=rand()%(High-5)+2; //随机产生炸弹
boom_y=rand()%(Width-5)+2;
canvas[boom_x][boom_y]=-3;
}
//一个根据咱们定义的画布上的数据而分别为用户呈现不同视觉效果的函数
void show()
{
gotoxy(0,0);
int i,j;
for(i=0;i<High;i++)
{
for(j=0;j<Width;j++)
{
if (canvas[i][j] == -1)
printf("#"); //输出城墙
else if (canvas[i][j] == -2)
printf("$"); //输出食物
else if (canvas[i][j] == 0)
printf(" "); //输出空格
else if (canvas[i][j] > 1)
printf("*"); //输出蛇身
else if (canvas[i][j] == 1)
printf("@"); //输出蛇头
else if (canvas[i][j] == -3)
printf("Q"); //输出炸弹
}
printf("\n");
}
}
//与用户无关的更新的函数
void updateWithoutInput()
{
moveSankeByDirection();//为什么不直接调用moveSankeByDirection函数,主要是与updateWithInput函数形成对比,让代码更有可读性
}
//与用户有关的更新的函数 ,判断用户的输入
void updateWithInput()
{
char input;
if(kbhit()) //kbhit是conio库中的函数,判断是否有输入
{
input=getch(); //根据用户不同的输入来移动,不必输入回车
if(input=='w')
{
moveDirection=1; //位置上移
moveSankeByDirection();
}
if(input=='s')
{
moveDirection=2; //位置下移
moveSankeByDirection();
}
if(input=='a')
{
moveDirection=3; //位置左移
moveSankeByDirection();
}
if(input=='d')
{
moveDirection=4; //位置右移
moveSankeByDirection();
}
if (input == '\033')
exit(0); //按下esc可以退出
if (input == 32)
system("pause"); //按下空格键可以暂停
}
}
void game_rule()
{
printf("|游戏规则:1.通过awsd来进行上下左右控制贪吃蛇移动 |\n");
printf("| 2.按空格键可以暂停游戏,按esc键可以退出游戏 |\n");
printf("| 3.贪吃蛇吃到炸弹Q则分数减20,吃到食物$则分数加10 |\n");
printf("| 4.如果往蛇自己的现态反方向运动,或撞到墙,或分数小于0.则游戏失败 |\n");
printf("| 提示:开始游戏之前把输入法换成英文 |\n");
printf("得分:%d\n", score);
}
void start_game() //游戏运行总调用
{
time_c(); //倒计时5秒
system("cls"); //清屏
system("color 0A"); //系统的文字颜色—绿色
startup(); //数据初始化
while(1) //游戏循环执行
{
show(); //显示画面
updateWithoutInput();
updateWithInput();
game_rule();
}
}
/*开挂代码*/
void movekaigua()
{
int food_x2, food_y2;
int i,j;
for(i=1;i<High-1;i++)
{
for(j=1;j<Width-1;j++)
{
if(canvas[i][j]>0)
canvas[i][j]++;
}
}
int oldTail_i,oldTail_j,oldHead_i,oldHead_j;
int m=0;
for(i=1;i<High-1;i++)
{
for(j=1;j<Width-1;j++)
{
if(canvas[i][j]>0)
{
if(m<canvas[i][j]) //数一直在变,最大的数是蛇尾,所以找最大的数
{
m=canvas[i][j];
oldTail_i=i;
oldTail_j=j;
}
if(canvas[i][j]==2) //旧蛇头的位置
{
oldHead_i=i;
oldHead_j=j;
}
}
}
}
int newHead_i,newHead_j;
if(moveDirection==1) //向上移动
{
newHead_i=oldHead_i-1;
newHead_j=oldHead_j;
}
if(moveDirection==2) //向下移动
{
newHead_i=oldHead_i+1;
newHead_j=oldHead_j;
}
if(moveDirection==3) //向左移动
{
newHead_i=oldHead_i;
newHead_j=oldHead_j-1;
}
if(moveDirection==4) //向右移动
{
newHead_i=oldHead_i;
newHead_j=oldHead_j+1;
}
//如果吃到食物
if(canvas[newHead_i][newHead_j]==-2)
{
canvas[food_x][food_y]=0;
food_x=rand()%(High-5)+2;
food_y=rand()%(Width-5)+2;
canvas[food_x][food_y]=-2;
food_x2=rand()%(High-5)+2;
food_y2=rand()%(Width-5)+2;
canvas[food_x2][food_y2]=-2;
score+=100;
}
else//否则,为了保持长度不变,原来的旧蛇尾减掉
{
canvas[oldTail_i][oldTail_j]=0;
}
if(canvas[newHead_i][newHead_j]==-3)
{
canvas[boom_x][boom_y]=0;
boom_x=rand()%(High-5)+2;
boom_y=rand()%(Width-5)+2;
canvas[boom_x][boom_y]=-3;
printf("开挂模式,吃到炸弹+20%%暴击\n");
score+=20;
}
//如果小蛇和自身相撞或者撞墙或者得分小于0 ,游戏失败,
if(canvas[newHead_i][newHead_j]>0)
{
system("color 0c");
printf("游戏失败!请您继续充值\n");
Sleep(2000); //Windows API函数为了不占过多cpu资源,让程序休眠
system("pause"); //C语言标准库中的函数,让程序实现冻结屏幕,便于观察程序的执行结果
exit(0); //c语言标准库中的函数,用于终止程序
}
else
{
canvas[newHead_i][newHead_j]=1; //为新的蛇头赋值
}
}
void kaigua()
{
startup(); //数据初始化
while(1) //游戏循环执行
{
show(); //显示画面
movekaigua();
updateWithInput();
printf("得分:%d\n",score);
}
}
/* -------------------------登录代码--------------------- */
void time_c() //倒计时
{
int cnt = 5;
while(--cnt >= 0)
{
Sleep(1000);
printf("倒计时:%-4d\r", cnt);
}
}
void entering()
{
char user[15],pass[15];
again:
printf("请输入私人账号:\n");
scanf("%s",user);
printf("请输入密码:\n");
scanf("%s",pass);
if (strcmp(user,zhanghao)==0 && strcmp(pass,mima)==0)
{
printf("开始游戏\n");
start_game();
}
else
{
printf("账号或密码错误,请重新输入...\n");
goto again;
}
}
void registers()
{
char new_user[15],new_pass[15],new_pass2[15],phone[15];
int verg, input_verg;
again6:
printf("请输入新的账号(手机号):\n");
scanf("%s",new_user);
printf("请输入新的密码:\n");
scanf("%s",new_pass);
printf("请再次输入确认新的密码:\n");
scanf("%s",new_pass2);
if (strcmp(new_pass,new_pass2)!=0)
{
printf("第一次和第二次输入的密码不同!请重新注册\n");
goto again6;
}
printf("正在验证中...\n");
printf("请输入你的手机号码:\n");
scanf("%s",phone);
if (strcmp(phone,new_user)!=0)
{
printf("账号与手机号不同!请重新注册\n");
goto again6;
}
printf("正在给%s发送验证码...\n",phone);
Sleep(4000);
srand((unsigned)time(NULL));
verg=11111+rand()%89999;
printf("验证码为:%d\n",verg);
printf("请输入收到的验证码:\n");
scanf("%d",&input_verg);
if(verg==input_verg)
{
printf("注册账号成功!\n");
printf("准备开始游戏!\n");
start_game();
}
else
{
printf("验证码错误!请重新注册\n");
goto again6;
}
}
void invin()
{
int m,money;
printf("对不起,你的余额不足,无法买挂\n");
printf("请您及时充值\n");
heihei:
printf("请您选择支付方式:1.微信支付 2.支付宝 3.银行卡\n");
scanf("%d",&m);
if(m==1||m==2)
{
printf("请您输入充值金额:\n");
scanf("%d",&money);
if(money<666)
{
printf("您的充值金额为%d元,小于666元,无法买挂!\n",money);
printf("请您继续充值! \n");
goto heihei;
}
else
{
printf("尊敬的VIP用户,您的挂已到账,祝您游戏愉快! \n");
time_c();
/*修改游戏参数*/
system("color 5E");
kaigua();
}
}
else
{
printf("发生错误404:\n");
}
}
void over()
{
int n;
printf("你确定要退出吗?\n");
printf(" 0.退出 1.继续游戏 \n");
scanf("%d",&n);
if(n==0)
exit(0);
else
printf("出现bug \n");
}
void begin()
{
int num;
printf("---------------------------------------------\n");
printf("|*******************************************|\n");
printf("|* 欢迎登录贪吃蛇 *|\n");
printf("|* *|\n");
printf("|* 1.登录账号 *|\n");
printf("|* 2.注册账号 *|\n");
printf("|* 3.开挂模式 *|\n");
printf("|* 0.退出 *|\n");
printf("|* *|\n");
printf("|*******************************************| \n");
printf("---------------------------------------------\n");
printf("请输入你的选择:\n");
scanf("%d",&num);
switch(num)
{
case 1:
entering();
break;
case 2:
registers();
break;
case 3:
invin();
break;
case 0:
over();
break;
default:
printf("输入错误!\n");
break;
}
}
int main()
{
begin();//登录界面
return 0;
}
游戏核心的理解:
小蛇移动:
刚开始小蛇默认向右
第一步用12345数字记录小蛇的位置(1表示蛇头用‘@’输出,其他大于0的数用‘*’输出,表示蛇尾),然后使所有的小蛇位置数字加一。
第二步使小蛇的最大值位置处变为0,就相当于那个位置的蛇尾消失了。
第三步使最小正值(2)的上/下/右位置(根据按键判断方向)的元素变为1(新蛇头)。
小蛇吃到食物后变长:
上面的第二步是使最大值变为0,我们可以试想一下 如果这个过程吃到食物,最大值就不变为0了,那么这不就相当于小蛇变长了吗?这时,我们只需要加一个if else判断是否吃到食物即可。
通过这个步骤可以使小蛇移动一个格子,我们把函数放到无限循环while(1)中,就可以使小蛇无限移动了。如果蛇头(1)遇到墙壁(-1),或者遇到炸弹(-3)或者遇到自己(2、3、4) 就可以退出代码了。
这个游戏本质上是数据的改变,我们把数据转换成我们看到的蛇头(@ ,1),蛇身(*,正数),墙壁(#,-1),食物($,-2),炸弹(Q,-3) 而已