用覆盖写的贪吃蛇,比system("cls")更快,对眼睛更友好

用覆盖写的贪吃蛇,比system(“cls”)更快,对眼睛更友好

#include<bits/stdc++.h>
#include<windows.h>
#include<conio.h>
using namespace std;

//用覆盖写的贪吃蛇,比system("cls")更快,对眼睛更友好 
//实现方法就是将光标移动到需要覆盖的位置,再输出

//用来存坐标
struct axis{
    int x,y;
};

//自己做的非小数数字转换成字符串
string string_num(long long num){
    string str;
    bool pd=true,fu=num<0;
    num=abs(num);
    while(num||pd){
        str=char(num%10+'0')+str;
        num/=10;
        pd=false;
    }
    if(fu)return '-'+str;
    return str;
}

//让光标移动到控制台指定位置(从0,0开始) 
void setCursorPosition(int x, int y){
    COORD coord;
    coord.X=x;
    coord.Y=y;
    SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE),coord);
}

//让输出变色(修复了实际颜色比理想颜色亮(比如是黑色不是纯黑) ) 
void color_print(int color,int color2){
    SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),color+color2*16);
}

//隐藏、显示光标
void hidden(bool pd){
    CONSOLE_CURSOR_INFO cci;
    GetConsoleCursorInfo(GetStdHandle(STD_OUTPUT_HANDLE),&cci);
    cci.bVisible=pd;//赋1为显示,赋0为隐藏
    SetConsoleCursorInfo(GetStdHandle(STD_OUTPUT_HANDLE),&cci);
}

//修复了随机数产生了比max(a,b)大的数,而且修复了每个数产生的比例不等的情况
long long random(long long a,long long b){
    return rand()*1.0/(RAND_MAX+1)*(max(a,b)-min(a,b)+1)+min(a,b);
}

const int length=25,width=25;//地图长宽 
const string str="██";//字符串皮肤 
const int lenstr=2;//不能接str.size()(str.length() 也是一样的),因为有些直接赋值的字符串用size()获取的长度有问题,比如:██size()是4,实际要正确渲染的长度是2,而cin读入的就没有这个问题(我也不知道为什么) 
//中字是字数*2,大部分字符都是字数*2,字母和数字等是字数 
int mapnum[length][width]={1,2,3};
int sx=2,sy=0;

int main(){//(width+2+Status_bar+1)*lenstr    length+2
    string cangshu1="mode con:cols="+string(((width+2)*lenstr<15)?"15":string_num((width+2)*lenstr))+" lines="+string_num(length+2);//设置控制台长和宽
    char cangshu2[cangshu1.size()+1];//因为system只能接受char数组,不支持string,所以要转换 
    for(int i=0;i<cangshu1.size();i++)cangshu2[i]=cangshu1[i];
    cangshu2[cangshu1.size()]='\0';//必须加,不然会无效指令
    system(cangshu2);//有些系统可能设置不了 
    
    srand(time(0)+GetTickCount());//GetTickCount()从系统开机时间到现在的毫秒,可以大量避免同一秒内运行随机结果相同的情况(加time(0)是为了避免用GetTickCount()时系统重启重新计时导致随机结果受影响才加的 
    hidden(false);
    char lttk='d';
    int slen=3,foodmaplen=0,frandomi;
    axis foodmap[length*width];
    //添加可以生成食物的位置和打印地图和在一起写了 
    for(int i=-1;i<=length;i++){
        for(int j=-1;j<=width;j++){
    		setCursorPosition((j+1)*lenstr,i+1);
            if(i>=0&&i<length&&j>=0&&j<width){
	            if(mapnum[i][j]==0){
		            foodmap[foodmaplen].x=j;
		            foodmap[foodmaplen].y=i;
		            foodmaplen++;
		            color_print(0,0);
		        }
		        else{
		            if(sy==i&&sx==j)color_print(4,0);
		            else color_print(12,0);
		        }
			}
            else if(i==-1||i==length||j==-1||j==width)color_print(9,0);
            else color_print(0,0);
			cout<<str;
        }
        if(i!=length)cout<<endl;//不能接'\n',因为'\n'占一个字符,对限制长度的控制台需多留一个位置输出'\n' 
    }
    if(foodmaplen==0)return 0;
	random_shuffle(foodmap,foodmap+foodmaplen);//随机打乱数组(好像支持结构体) 
    frandomi=random(0,foodmaplen-1);//随机抽取一个坐标(和上一个随机打乱数组连在一起,感觉是不是有点多此一举?但我也不知道为什们,一开始只用了随机抽取一个坐标的写法,总是随机到同一位置,不是随机种子的问题,而再次抽取坐标时就没有这种情况) 
    mapnum[foodmap[frandomi].y][foodmap[frandomi].x]=-1;
    setCursorPosition((foodmap[frandomi].x+1)*lenstr,foodmap[frandomi].y+1);
    color_print(10,0);
    cout<<str;
    while(1){
        double t=(slen-3)*1.0/10;//3是初始蛇身长度,10是达到最大速度的长度 
        t=(t>1)?1:t;
        t=(t<0)?0:t;//限制,让t在0~1之间 
        Sleep(200-100*t);//200是最慢的等待时间,100是减少的最大等待时间 
        hidden(false);
        //检测按下的按键(支持wasd和方向键,我写的是把方向键归wasd判断了) 
        if(kbhit()){//检查控制台是否按下某一个按键
            char chartlttk;//实际用来判断的按下的按键 
            int inttlttk=getch();//存按下的按键的ASCLL码 
            if(!inttlttk||inttlttk==224)inttlttk=getch();//方向键第一次被侦测会返回0或224,所以要再次侦测(我测试了很多遍,都没返回0,可我找到资料写的是会返回0或224,我也不知道为什么) 
            switch(inttlttk){//72是↑,80是↓,75是←,77是→
                case 72:chartlttk='w';break;
                case 80:chartlttk='s';break;
                case 75:chartlttk='a';break;
                case 77:chartlttk='d';break;
                default:
                    chartlttk=inttlttk+(inttlttk>='A'&&inttlttk<='Z')*' ';//Shift+按键会返回大写,所以加了个判断 
                    break;
            }
            if((chartlttk=='a'||chartlttk=='d')&&(lttk=='w'||lttk=='s')||(chartlttk=='w'||chartlttk=='s')&&(lttk=='a'||lttk=='d'))lttk=chartlttk;//左转和右转才会改方向 
        }
        int tsx=sx,tsy=sy;//存蛇头原位置 
        sx+=(lttk=='d')-(lttk=='a');
        sy+=(lttk=='s')-(lttk=='w');//移动 
        if(sx<0||sx>=width||sy<0||sy>=length||mapnum[sy][sx]>1)break;//判断是否撞墙或碰到蛇身(我写的是碰到蛇尾不会结束,不喜欢的可以换成mapnum[sy][sx]>0) 
        setCursorPosition((tsx+1)*lenstr,tsy+1);//覆盖蛇头原位置 
        color_print(12,0);
        cout<<str;
        setCursorPosition((sx+1)*lenstr,sy+1);//覆盖蛇头现在位置 
        color_print(4,0);
        cout<<str;
        if(mapnum[sy][sx]==-1){//碰到食物 
            int shu=1;//增加的长度 
            foodmaplen=0;
            slen+=shu;
            for(int i=0;i<length;i++){//添加可以生成食物位置和增加蛇身每个的长度和在一起写了 
                for(int j=0;j<width;j++){
                    if(shu-1>0&&mapnum[i][j]>0)mapnum[i][j]+=shu-1;//对shu为1可能有点多此一举,主要是支持拓展 
                    else if(mapnum[i][j]==0&&(i!=sy||j!=sx)){
                        foodmap[foodmaplen].x=j;
                        foodmap[foodmaplen].y=i;
                        foodmaplen++;
                    }
                }
            }
            if(foodmaplen==0)break;//没有可以用来生成食物的位置了,胜利
            random_shuffle(foodmap,foodmap+foodmaplen);
            frandomi=random(0,foodmaplen-1);
            mapnum[foodmap[frandomi].y][foodmap[frandomi].x]=-1; 
            setCursorPosition((foodmap[frandomi].x+1)*lenstr,foodmap[frandomi].y+1);
            color_print(10,0);
            cout<<str;
        }
        else{
            for(int i=0;i<length;i++){
                for(int j=0;j<width;j++){
                    if(mapnum[i][j]==1&&(i!=sy||j!=sx)){//覆盖蛇尾(当前位置的值是1的就是蛇尾) 
                        setCursorPosition((j+1)*lenstr,(i+1));
                        color_print(0,0);
                        cout<<str;
                    }
                    if(mapnum[i][j]>0)mapnum[i][j]--;//将每一个蛇身的值减一 
                }
            }
        }
        mapnum[sy][sx]=slen;
    }
    setCursorPosition(0,1+length);
    color_print(7,0);
    return 0;
}
1 个赞

改版

//出生作者,写这么多行代码,改起来烦死了,懒得删
//原作者是XXS,需要护眼,所以才关了清屏,别被他的注释骗了
//还有个原因,是作者电脑不好,清屏的话会卡死
//本版本版权归BYD出生所有,不喜勿喷;(BYD什么意思懂的都懂好吧beyound) 


#include<bits/stdc++.h>
#include<windows.h>
#include<conio.h>
using namespace std;

struct axis{
    int x,y;
};

string string_num(long long num){
    string str;
    bool pd=true,fu=num<0;
    num=abs(num);
    while(num||pd){
        str=char(num%10+'0')+str;
        num/=10;
        pd=false;
    }
    if(fu)return '-'+str;
    return str;
}

void setCursorPosition(int x, int y){
    COORD coord;
    coord.X=x;
    coord.Y=y;
    SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE),coord);
}

//让输出变色(修复了实际颜色比理想颜色亮(比如是黑色不是纯黑) ) 
void color_print(int color,int color2){
    SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),color+color2*16);
}

//隐藏光标
void hidden(bool pd){
    CONSOLE_CURSOR_INFO cci;
    GetConsoleCursorInfo(GetStdHandle(STD_OUTPUT_HANDLE),&cci);
    cci.bVisible=pd;//赋1为显示,赋0为隐藏
    SetConsoleCursorInfo(GetStdHandle(STD_OUTPUT_HANDLE),&cci);
}

//修复了随机数产生了比max(a,b)大的数,而且修复了每个数产生的比例不等的情况
long long random(long long a,long long b){
    return rand()*1.0/(RAND_MAX+1)*(max(a,b)-min(a,b)+1)+min(a,b);
}

const int length=25,width=25,Status_bar=10,xxlen=3;
//██
//|_|
// 
//■
//●
//◇
//◆
//卐 
const string str="卐";
const string Statusstr[3]={"游戏作者","作者脑汁里的水长,高","作者纯出生"} ;
const int lenstr=2;//不能接str.size()(str.length() 也是一样的),因为有些直接赋值的字符串用size()获取的长度有问题,比如:██size()是4,实际要正确渲染的长度是2,而cin读入的就没有这个问题
int mapnum[length][width]={1,2,3};
int sx=2,sy=0;

int main(){//(width+2+Status_bar+1)*lenstr    length+2
    string cangshu1="mode con:cols="+string(((width+2+Status_bar+1)*lenstr<15)?"15":string_num((width+2+Status_bar+1)*lenstr))+" lines="+string_num(length+2);
    char cangshu2[cangshu1.size()+1];
    for(int i=0;i<cangshu1.size();i++)cangshu2[i]=cangshu1[i];
    cangshu2[cangshu1.size()]='\0';
    system(cangshu2);

    srand(time(0)+GetTickCount());
    hidden(false);
    char lttk='d';
    int slen=3,foodmaplen=0,frandomi;
    axis foodmap[length*width];
    for(int i=-1;i<=length;i++){
        for(int j=-1;j<=width+Status_bar+1;j++){
    		setCursorPosition((j+1)*lenstr,i+1);
            if(i>=0&&i<length&&j>=0&&j<width){
	            if(mapnum[i][j]==0){
		            foodmap[foodmaplen].x=j;
		            foodmap[foodmaplen].y=i;
		            foodmaplen++;
		            color_print(0,0);
		        }
		        else{
		            if(sy==i&&sx==j)color_print(4,0);
		            else color_print(12,0);
		        }
			}
            else if(i==-1||i==length||j==-1||j==width||j==width+Status_bar+1)color_print(9,0);
            else color_print(0,0);
			cout<<str;
        }
        if(i!=length)cout<<endl;//不能接'\n',因为'\n'占一个字符,对有限制长度的控制台需多留一个位置输出'\n' 
    }
    if(foodmaplen==0)return 0;
    random_shuffle(foodmap,foodmap+foodmaplen);
    frandomi=random(0,foodmaplen-1);
    mapnum[foodmap[frandomi].y][foodmap[frandomi].x]=-1;
    setCursorPosition((foodmap[frandomi].x+1)*lenstr,foodmap[frandomi].y+1);
    color_print(10,0);
    cout<<str;
    for(int i=0;i<xxlen;i++){
	    setCursorPosition((width+2)*lenstr+(Status_bar*lenstr-Statusstr[i].size())/2,1+1+i*4);
	    color_print(7,0);
	    cout<<Statusstr[i];
	    string tstr;
	    if(i==0)tstr="BYD出生";
	    else if(i==1)tstr="长:"+string_num(length)+" 宽:"+string_num(width);
	    else if(i==2)tstr=string_num(slen);
	    setCursorPosition((width+2)*lenstr+(Status_bar*lenstr-tstr.size())/2,1+1+2+i*4);//((xxlen*4-1+1+1+1)+(length+1-1))/2
	    cout<<tstr;
	}
	setCursorPosition((width+2)*lenstr+(Status_bar*lenstr-16)/2,((xxlen*4-1+1+1+1)+(length+1-1))/2);
	cout<<"点击直接die";
	clock_t shijian=clock();
    while(1){
        //int t=(slen-3)*1.0/(length*width-3);
        double t=(slen-3)*1.0/(10);
        t=(t>1)?1:t;//200-100*t
        t=(t<0)?0:t;
        if(true){
        	clock_t start=clock();
        	while(clock()-start<200-100*t){
				setCursorPosition((width+2)*lenstr+(Status_bar*lenstr-16)/2,((xxlen*4-1+1+1+1)+(length+1-1))/2);
        		if((clock()-shijian)/500%2==0)color_print(7,0);
        		else color_print(0,0);
				cout<<"点击直接die";
			}
		}
        //t=1-(t<0)?0:t;
        //Sleep(100+100*t);
        hidden(false);
        if(kbhit()){
            char chartlttk;
            int inttlttk=getch();
            if(!inttlttk||inttlttk==224)inttlttk=getch();
            switch(inttlttk){
                case 72:chartlttk='w';break;
                case 80:chartlttk='s';break;
                case 75:chartlttk='a';break;
                case 77:chartlttk='d';break;
                default:
                    chartlttk=inttlttk+(inttlttk>='A'&&inttlttk<='Z')*' ';
                    break;
            }
            if((chartlttk=='a'||chartlttk=='d')&&(lttk=='w'||lttk=='s')||(chartlttk=='w'||chartlttk=='s')&&(lttk=='a'||lttk=='d'))lttk=chartlttk;
        }
        int tsx=sx,tsy=sy;
        sx+=(lttk=='d')-(lttk=='a');
        sy+=(lttk=='s')-(lttk=='w');
        if(sx<0||sx>=width||sy<0||sy>=length||mapnum[sy][sx]>1)break;
        setCursorPosition((tsx+1)*lenstr,tsy+1);
        color_print(12,0);
        cout<<str;
        setCursorPosition((sx+1)*lenstr,sy+1);
        color_print(4,0);
        cout<<str;
        if(mapnum[sy][sx]==-1){
            int shu=1;
            foodmaplen=0;
            slen+=shu;
            for(int i=0;i<length;i++){
                for(int j=0;j<width;j++){
                    if(shu-1>0&&mapnum[i][j]>0)mapnum[i][j]+=shu-1;
                    else if(mapnum[i][j]==0&&(i!=sy||j!=sx)){
                        foodmap[foodmaplen].x=j;
                        foodmap[foodmaplen].y=i;
                        foodmaplen++;
                    }
                }
            }
            if(foodmaplen==0)break;//胜利
            random_shuffle(foodmap,foodmap+foodmaplen);
            frandomi=random(0,foodmaplen-1);
            mapnum[foodmap[frandomi].y][foodmap[frandomi].x]=-1;
            setCursorPosition((foodmap[frandomi].x+1)*lenstr,foodmap[frandomi].y+1);
            color_print(10,0);
            cout<<str;
        }
        else{
            for(int i=0;i<length;i++){
                for(int j=0;j<width;j++){
                    if(mapnum[i][j]==1&&(i!=sy||j!=sx)){
                        setCursorPosition((j+1)*lenstr,(i+1));
                        color_print(0,0);
                        cout<<str;
                    }
                    if(mapnum[i][j]>0)mapnum[i][j]--;
                }
            }
        }
        mapnum[sy][sx]=slen;
        setCursorPosition(0,0);
    }
    setCursorPosition(0,1+length);
    color_print(7,0);
    return 0;
}

好好好
泄露新版内容

666

那你用system(“cls”)吧,一闪一闪的