C++ 写贪吃蛇 简易的贪吃蛇源码【加入新模式:人机对战】 简单易懂 画面精美

C++ 贪吃蛇



我们先思考贪吃蛇如何运作:
无非就四种情况

  1. 画蛇
  2. 直行
  3. 转弯
  4. 吃到食物

有些人可能写出来的程序是一闪一闪的,很难看。因为多次清屏的缘故,画蛇其实不用每次清屏画蛇。
其实完全可以将蛇尾给清除,比如几个空格盖住就可以了,蛇头在画一个就是了。

直行和转弯,只要标记一个蛇头的方向就可以了。
定义一个flg数组:

const int flg[4][2]={{1,0},{0,2},{0,-2},{-1,0}};//下右左上 

然后每次判断键盘WASD或上下左右是否被按下,如果按下,就要判断是否有效,比如说返回,显然不行。

如果吃到食物,长度+1,就可以了,也就不用清蛇尾了。

下载链接在文章末尾。

all.h

all.h函数库

最初版(1.0.0)

其实也就这么简单,下面附上我的代码:

#include "all.h"//手写函数库 到上面链接copy
using namespace std;
const int flg[4][2]={{1,0},{0,2},{0,-2},{-1,0}};//下右左上 
int n=28,m=76,tim;
struct xcw{int x,y;}tan[1000005];//1头 tot尾 
int tot,f,score,food,ground=0;
bool vis[1005][1005];
int main();
void retr(){
	HWND hWnd=GetForegroundWindow();
	ShowWindow(hWnd,SW_HIDE);//隐藏窗口 
	exit(0);
}
bool check(int x,int y){//是否撞到东西 
	if(x<1||x>n||y<2||y>m) return 0;
	bool t=1;
	for(int i=1;i<=tot;i++)
	if(x==tan[i].x&&y==tan[i].y){t=0;break;}
	return t;
}
void fnd(int x,int y){
	if(check(x,y)) return;
	setcolor(7+ground);cls();
	printf("Lose\n");//游戏结束 
	printf("分数:%d\n",score);
	printf("E键退出,R键重来\n");
	char ch=getch();
	while(ch!='E'&&ch!='e'&&ch!='R'&&ch!='r') ch=getch();
	if(ch=='E'||ch=='e') retr();
	else{main();exit(0);}
}
void rand_food(){//随机产生食物,不能重复 
	setcolor(12+ground);
	int x=brand()%(n+1),y=(brand()%m/2)*2;
	while(!check(x,y)) x=brand()%(n+1),y=(brand()%m/2)*2;
	GOTO(x,y);printf("▇");
	if(!vis[x][y]) food++;vis[x][y]=1;
	x=brand()%(n+1),y=(brand()%m/2)*2;
	while(!check(x,y)) x=brand()%(n+1),y=(brand()%m/2)*2;
	GOTO(x,y);printf("▇");
	if(!vis[x][y]) food++;vis[x][y]=1;
	setcolor(10+ground);
}
void draw(){//画地图 
	setcolor(14+ground);
	for(int i=0;i<=n+1;i++) GOTO(i,m+2),printf("▇"),GOTO(i,0),printf("▇");
	for(int i=1;i<=m/2+1;i++) GOTO(n+1,i*2),printf("▇"),GOTO(0,i*2),printf("▇");
	setcolor(10+ground);
}
int main(){
	system("mode con cols=80 lines=31");//设置窗口大小 
	cls();//清屏 
	printf("设置速度(豪秒/格)(建议100):");
	cin>>tim;bsrand();MEM(vis,0);food=0;MEM(tan,0);score=0;
	setcolor(10+ground);//设置颜色 
	cls();
	draw();
	f=1;tan[1]=(xcw){1,6};tan[2]=(xcw){1,4};tan[tot=3]=(xcw){1,2};//初始化蛇 
	for(int i=1;i<=tot;i++) GOTO(tan[i].x,tan[i].y),printf("▇");//画蛇 
	while(1){
		while(!kbhit()){//判断是否有键按下
			Sleep(tim);//延时
			if(food==0) rand_food();
			int x=tan[1].x,y=tan[1].y;
			x+=flg[f][0],y+=flg[f][1];
			for(int i=tot;i;i--) tan[i+1]=tan[i];//移动蛇
			GOTO(tan[tot+1].x,tan[tot+1].y);
			printf("  ");//清除蛇尾 
			if(vis[x][y]) vis[x][y]=0,score++,food--,++tot,GOTO(tan[tot].x,tan[tot].y),printf("▇");//吃到食物长度加一
			fnd(x,y);
			tan[1]=(xcw){x,y};
			GOTO(tan[1].x,tan[1].y);
			printf("▇");//画蛇头 
		}
		char ch=getch();
		bool t=0;
		if(ch=='E'||ch=='e') retr();
		if(ch==-32) ch=getch(),t=1;
		if((ch==75&&t||ch=='A'||ch=='a')&&f^1) f=2;//改变方向 
		if((ch==77&&t||ch=='D'||ch=='d')&&f^2) f=1;
		if((ch==80&&t||ch=='S'||ch=='s')&&f^3) f=0;
		if((ch==72&&t||ch=='W'||ch=='w')&&f^0) f=3;
	}
	return 0;
}

以上是最基础的写法。

最新版(1.2.0)

增加了多人对抗,多人合作模式,特别的,加入了人机模式,我用13行写出来的,竟然我都打不过。
人机其实想法很简单:找最近的食物,本来想在加强,但是我连这样都打不过,还谈什么加强,我好弱啊。
但是人机也有Bug,他会把自己绕死,虽然概率很小。

#include "all.h"//手写函数库 到上面链接copy
using namespace std;
const int flg[4][2]={{1,0},{0,2},{0,-2},{-1,0}};//下右左上 
int n=28,m=76,tim;
struct xcw{int x,y;}tan[5][1000005],foodd[2];//1头 tot尾 
int tot[5],f[5],score,food,ground=0,ms,ans_len=1e9;
bool vis[1005][1005];
void retr();
void result();
bool check();
void fnd();
void rand_food();
void draw();
int choose();
void stop();
int mods();
int ads();
int get_food();
int other();
void machine();
int change();
int main();
void retr(){
	HWND hWnd=GetForegroundWindow();
	ShowWindow(hWnd,SW_HIDE);
	exit(0);
}
void Ending(){
	printf("E键退出,R键重来\n");
	char ch=getch();
	while(ch!='E'&&ch!='e'&&ch!='R'&&ch!='r') ch=getch();
	if(ch=='E'||ch=='e') retr();
	else{main();exit(0);}
}
void result(int t){
	setcolor(7+ground);cls();
	if(ms==2){
		if(t==0) printf("Win!!!");else
		printf("Lose...\n");
		printf("机器人:%d\n你:%d\n",tot[2],tot[0]);
	}else
	if(ms==3) if(t==1) printf("White Lose\n");else printf("White win\n");else
	if(ms==5) if(t==1) printf("Player 2 win\n");else printf("Player 1 win\n");
	Ending();
}
bool check(int x,int y){
	if(x<1||x>n||y<2||y>m) return 0;
	bool t=1;
	if(ms!=3)
	for(int i=1;i<=tot[0];i++)
	if(x==tan[0][i].x&&y==tan[0][i].y){t=0;break;}
	
	if(ms==1||ms==4||ms==5)
	for(int i=1;i<=tot[1];i++)
	if(x==tan[1][i].x&&y==tan[1][i].y){t=0;break;}
	
	if(ms==2||ms==3)
	for(int i=1;i<=tot[2];i++)
	if(x==tan[2][i].x&&y==tan[2][i].y){t=0;break;}
	
	if(ms==3)
	for(int i=1;i<=tot[3];i++)
	if(x==tan[3][i].x&&y==tan[3][i].y){t=0;break;}
	return t;
}
void fnd(int t,int x,int y){
	if(check(x,y)) return;
	setcolor(7+ground);cls();
	if(ms==3) if(t==3) printf("White lose\n");else printf("White win\n");else
	if(ms==4||ms==5) if(t==1) printf("Player 1 win\n");else printf("Player 2 win\n");
	else{
		if(t==2) printf("Win!!!\n");else printf("Lose...\n");
		printf("分数:%d\n",score);score=0;
	}
	Ending();
}
void rand_food(){
	if(!vis[foodd[0].x][foodd[0].y]){
		setcolor(12+ground);
		int x=brand()%(n+1),y=(brand()%m/2)*2;
		while(!check(x,y)) x=brand()%(n+1),y=(brand()%m/2)*2;
		GOTO(x,y);printf("▇");
		if(!vis[x][y]) food++;vis[x][y]=1;foodd[0]=(xcw){x,y};
	}
	if(!vis[foodd[1].x][foodd[1].y]){
		setcolor(12+ground);
		int x=brand()%(n+1),y=(brand()%m/2)*2;
		while(!check(x,y)) x=brand()%(n+1),y=(brand()%m/2)*2;
		GOTO(x,y);printf("▇");
		food++;vis[x][y]=1;foodd[1]=(xcw){x,y};
	}
}
void draw(){
	setcolor(14+ground);
	for(int i=0;i<=n+1;i++) GOTO(i,m+2),printf("▇"),GOTO(i,0),printf("▇");
	for(int i=1;i<=m/2+1;i++) GOTO(n+1,i*2),printf("▇"),GOTO(0,i*2),printf("▇");
}
int choose(){
	printf("0.退出\n");
	printf("1.单人模式\n");
	printf("2.双人模式\n");
	printf("3.人机对抗(谁先吃20个)\n");
	printf("4.机机对抗(谁先吃20个)\n");
	printf("5.对抗模式\n");
	printf("6.对抗模式(谁先吃20个)\n");
	printf("快捷键:\n");
	printf("P:暂停\n");
	printf("E:退出\n");
	char ch=getch();
	while(ch<'0'||ch>'6') ch=getch();
	if(ch=='0') retr();else
	if(ch=='1') ms=0;else
	if(ch=='2') ms=1;else
	if(ch=='3') ms=2;else
	if(ch=='4') ms=3;else
	if(ch=='5') ms=4;else
	if(ch=='6') ms=5;
}
void stop(){
	char ch=getch();
	while(ch!='P'&&ch!='p') ch=getch();
}
int mods(){
	setcolor(10+ground);
	if(ms!=3){
		tan[0][1]=(xcw){1,6};tan[0][2]=(xcw){1,4};tan[0][tot[0]=3]=(xcw){1,2};f[0]=1;
		for(int i=1;i<=tot[0];i++) GOTO(tan[0][i].x,tan[0][i].y),printf("▇");
	}
	if(ms==1||ms==4||ms==5){
		setcolor(7+ground);
		tan[1][1]=(xcw){n,m-6};tan[1][2]=(xcw){n,m-4};tan[1][tot[1]=3]=(xcw){n,m-2};f[1]=2;
		for(int i=1;i<=tot[1];i++) GOTO(tan[1][i].x,tan[1][i].y),printf("▇");
	}
	if(ms==2||ms==3){
		setcolor(15+ground);
		tan[2][1]=(xcw){n,m-6};tan[2][2]=(xcw){n,m-4};tan[2][tot[2]=3]=(xcw){n,m-2};f[2]=2;
		for(int i=1;i<=tot[2];i++) GOTO(tan[2][i].x,tan[2][i].y),printf("▇");
	}
	if(ms==3){
		setcolor(13+ground);
		tan[3][1]=(xcw){1,6};tan[3][2]=(xcw){1,4};tan[3][tot[3]=3]=(xcw){1,2};f[3]=1;
		for(int i=1;i<=tot[3];i++) GOTO(tan[3][i].x,tan[3][i].y),printf("▇");
	}
}
int ads(int x){return x<0?-x:x;}
int get_food(int x,int y,xcw z){return ads(x-z.x)+ads(y-z.y);}
int other(int x){
	if(x==0) return 3;else
	if(x==1) return 2;else
	if(x==2) return 1;else
	return 0;
}
void machine(int t,int x,int y){//机器判断 
	bool tt=0;int foodid,minn=1e9,newf=f[t];
	if(get_food(x,y,foodd[0])<=get_food(x,y,foodd[1])&&vis[foodd[0].x][foodd[0].y]||!vis[foodd[1].x][foodd[1].y]) foodid=0;else foodid=1;
	for(int i=0;i<4;i++)
	if(f[t]^other(i)){
		if(check(x+flg[i][0],y+flg[i][1])){
			int now=get_food(x+flg[i][0],y+flg[i][1],foodd[foodid]);
			if(now<minn) newf=i,tt=1,minn=now;
			if(!tt) newf=i;
		}
	}
	f[t]=newf;
}
int change(int t){
	if(t==0) setcolor(10+ground);else
	if(t==1) setcolor(7+ground);else
	if(t==2) setcolor(15+ground);else
	if(t==3) setcolor(13+ground);
	int x=tan[t][1].x,y=tan[t][1].y;
	if(t==2||t==3) machine(t,x,y);
	x+=flg[f[t]][0],y+=flg[f[t]][1];
	for(int i=tot[t];i;i--) tan[t][i+1]=tan[t][i];
	GOTO(tan[t][tot[t]+1].x,tan[t][tot[t]+1].y);
	printf("  ");
	if(vis[x][y]){
		vis[x][y]=0,score+=(t==0||t==1),food--;
		if(++tot[t]>=23&&(ms==3||ms==5)) result(t);
		GOTO(tan[t][tot[t]].x,tan[t][tot[t]].y),printf("▇");
	}
	fnd(t,x,y);
	tan[t][1]=(xcw){x,y};
	GOTO(tan[t][1].x,tan[t][1].y);
	printf("▇");
}
int main(){
	bsrand();score=0;
	system("title ");
	system("mode con cols=80 lines=31");
	choose();cls();
	printf("设置速度(毫秒/格)(建议100):");
	cin>>tim;
	MEM(vis,0);food=0;MEM(tan,0);
	cls();draw();mods();
	while(1){
		while(!kbhit()){
			Sleep(tim);
			rand_food();
			if(ms!=3) change(0);
			rand_food();
			if(ms==1||ms==4||ms==5) change(1);else
			if(ms==2) change(2);else
			if(ms==3) change(2),change(3);
		}
		char ch=getch();
		bool t=0;
		if(ch=='E'||ch=='e') retr();else
		if(ch=='P'||ch=='p') stop();else
		if(ms==0||ms==2){
			if(ch==-32) ch=getch(),t=1;
			if((ch==75&&t||ch=='A'||ch=='a')&&f[0]^1) f[0]=2;else
			if((ch==77&&t||ch=='D'||ch=='d')&&f[0]^2) f[0]=1;else
			if((ch==80&&t||ch=='S'||ch=='s')&&f[0]^3) f[0]=0;else
			if((ch==72&&t||ch=='W'||ch=='w')&&f[0]^0) f[0]=3;
		}else
		if(ms==1||ms==4||ms==5){
			if((ch=='W'||ch=='w')&&f[0]^0) f[0]=3;else
			if((ch=='A'||ch=='a')&&f[0]^1) f[0]=2;else
			if((ch=='D'||ch=='d')&&f[0]^2) f[0]=1;else
			if((ch=='S'||ch=='s')&&f[0]^3) f[0]=0;
			
			if(ch==-32) ch=getch(),t=1;
			if(ch==72&&t&&f[1]^0) f[1]=3;else
			if(ch==75&&t&&f[1]^1) f[1]=2;else
			if(ch==77&&t&&f[1]^2) f[1]=1;else
			if(ch==80&&t&&f[1]^3) f[1]=0;
		}
	}
	return 0;
}

exe文件下载

1.0.0
1.2.0

喜欢就加个关注吧!
  • 22
    点赞
  • 88
    收藏
    觉得还不错? 一键收藏
  • 21
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 21
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值