C语言控制台版2048小游戏
效果不好,见谅,没事就写了一个!!!
/** *@authorRouth *@main.c *@date2014,4,26 */ #include<stdio.h> #include<stdlib.h> #include<conio.h> #include<windows.h> //consolewidth #defineCONSOLE_WIDTH80 #defineBOX_WIDTH10 intBOX[4][4]={ {0,0,0,0}, {0,0,0,0}, {0,0,0,0}, {0,0,0,0}}; //theconsoleoutputhandle HANDLEc_handle; voidsetCursorPosition(shortx,shorty){ staticCOORDc; c.X=x; c.Y=y; SetConsoleCursorPosition(c_handle,c); } voiddrawTheGameBox(){ printf("%15s■■■■■■■■■■■■■■■■■■■■■\n",""); printf("%15s■%8s■%8s■%8s■%8s■\n","","","","",""); printf("%15s■%8s■%8s■%8s■%8s■\n","","","","",""); printf("%15s■%8s■%8s■%8s■%8s■\n","","","","",""); printf("%15s■%8s■%8s■%8s■%8s■\n","","","","",""); printf("%15s■■■■■■■■■■■■■■■■■■■■■\n",""); printf("%15s■%8s■%8s■%8s■%8s■\n","","","","",""); printf("%15s■%8s■%8s■%8s■%8s■\n","","","","",""); printf("%15s■%8s■%8s■%8s■%8s■\n","","","","",""); printf("%15s■%8s■%8s■%8s■%8s■\n","","","","",""); printf("%15s■■■■■■■■■■■■■■■■■■■■■\n",""); printf("%15s■%8s■%8s■%8s■%8s■\n","","","","",""); printf("%15s■%8s■%8s■%8s■%8s■\n","","","","",""); printf("%15s■%8s■%8s■%8s■%8s■\n","","","","",""); printf("%15s■%8s■%8s■%8s■%8s■\n","","","","",""); printf("%15s■■■■■■■■■■■■■■■■■■■■■\n",""); printf("%15s■%8s■%8s■%8s■%8s■\n","","","","",""); printf("%15s■%8s■%8s■%8s■%8s■\n","","","","",""); printf("%15s■%8s■%8s■%8s■%8s■\n","","","","",""); printf("%15s■%8s■%8s■%8s■%8s■\n","","","","",""); printf("%15s■■■■■■■■■■■■■■■■■■■■■\n",""); } /** *getarandomposition:R *thex:0xff&(R>>4) *they:0x0f&R */ intrandom(){ inti=0,j=0,_index=0,rrr=0; intrand_arr[16]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; srand((unsigned)time(NULL)); //rand() for(i=0;i<4;i++){ for(j=0;j<4;j++){ if(BOX[i][j]==0){ rand_arr[_index++]=(0xff&i<<4)|(0xf&j); } } } if(_index==0){ return-1; } returnrand_arr[rand()%_index]; } /**thecleanarray.**/ int*alogs(intitem[]){ inti=0,j=0; inttep[4]={0,0,0,0},tmp[4]={0,0,0,0}; for(i=0;i<4;i++){ if(item[i]!=0){ tep[j++]=item[i]; } } for(i=0;i<3;i++){ if(tep[0]==0)break; if(tep[i]==tep[i+1]){ tep[i]*=2; tep[i+1]=0; } } j=0; for(i=0;i<4;i++){ if(tep[i]!=0){ tmp[j++]=tep[i]; } } return(int*)(&tmp); } /**BOXcanmove.*/ intvalidate(intitem[]){ inti=0; for(i=0;i<3;i++){ if(item[i]!=0&&item[i]==item[i+1])return1; if(item[i]==0&&item[i+1]!=0)return1; } return0; } intkeydownControlx(intkey){ inti=0,j=0; int*p; inttp[4]={0,0,0,0}; switch(key){ case72://up j=0; for(i=0;i<4;i++){ tp[0]=BOX[0][i]; tp[1]=BOX[1][i]; tp[2]=BOX[2][i]; tp[3]=BOX[3][i]; p=alogs(tp); if(!validate(tp))j++; BOX[0][i]=p[0]; BOX[1][i]=p[1]; BOX[2][i]=p[2]; BOX[3][i]=p[3]; } returnj!=4; case80://down j=0; for(i=0;i<4;i++){ tp[0]=BOX[3][i]; tp[1]=BOX[2][i]; tp[2]=BOX[1][i]; tp[3]=BOX[0][i]; p=alogs(tp); if(!validate(tp))j++; BOX[3][i]=p[0]; BOX[2][i]=p[1]; BOX[1][i]=p[2]; BOX[0][i]=p[3]; } returnj!=4; case75://left j=0; for(i=0;i<4;i++){ tp[0]=BOX[i][0]; tp[1]=BOX[i][1]; tp[2]=BOX[i][2]; tp[3]=BOX[i][3]; p=alogs(tp); if(!validate(tp))j++; BOX[i][0]=p[0]; BOX[i][1]=p[1]; BOX[i][2]=p[2]; BOX[i][3]=p[3]; } returnj!=4; case77://right j=0; for(i=0;i<4;i++){ tp[0]=BOX[i][3]; tp[1]=BOX[i][2]; tp[2]=BOX[i][1]; tp[3]=BOX[i][0]; p=alogs(tp); if(!validate(tp))j++; BOX[i][3]=p[0]; BOX[i][2]=p[1]; BOX[i][1]=p[2]; BOX[i][0]=p[3]; } returnj!=4; default:return0; } return0; } intmain(){ inti=0,j=0,r=0; /**setthecursor,visibleorinvisible.*/ CONSOLE_CURSOR_INFOcci={1,0}; /**gettheconsoleoutputhandle.*/ c_handle=GetStdHandle(STD_OUTPUT_HANDLE); //hidethecursor. SetConsoleCursorInfo(c_handle,&cci); // SetConsoleTextAttribute(c_handle,0x3); //system("color30"); drawTheGameBox(); r=random(); if(rand()%2==0){ BOX[0xff&(r>>4)][0xf&r]=2; }else{ BOX[0xff&(r>>4)][0xf&r]=4; } for(i=0;i<4;i++){ for(j=0;j<4;j++){ if(BOX[i][j]==0)continue; setCursorPosition(17+j*8+2+(j*2),i*4+(i+2)); //SetConsoleTextAttribute(c_handle,BOX[i][j]); printf("%d",BOX[i][j]); } } //begin while(1){ Sleep(100); //keydown. while(_kbhit()) { //thekeydownfun. if(!keydownControlx(_getch()))continue; //cleartheconsoleandredraw. system("cls"); SetConsoleTextAttribute(c_handle,0x3); drawTheGameBox(); for(i=0;i<4;i++){ for(j=0;j<4;j++){ if(BOX[i][j]==0)continue; setCursorPosition(17+j*8+2+(j*2),i*4+(i+2)); //SetConsoleTextAttribute(c_handle,BOX[i][j]); printf("%d",BOX[i][j]); } } r=random(); if(r==-1){//gameover //SetConsoleTextAttribute(c_handle,0xff0000); setCursorPosition(27,10); printf("GAMEORVER!!!!!!!"); } if(rand()%2==0){ BOX[0xff&(r>>4)][0xf&r]=2; }else{ BOX[0xff&(r>>4)][0xf&r]=4; } Sleep(100); setCursorPosition(17+(0xf&r)*8+2+((0xf&r)*2),(0xff&(r>>4))*4+((0xff&(r>>4))+2)); //SetConsoleTextAttribute(c_handle,BOX[0xff&(r>>4)][0xf&r]); printf("%d",BOX[0xff&(r>>4)][0xf&r]); } } return0; }
附上另外一个小伙伴的代码
/* *Copyright(C)JudgeYoung *E-mail:yjjtc@126.com *Version:1.0 */ #include<stdio.h> #include<time.h>/*包含设定随机数种子所需要的time()函数*/ #include<conio.h>/*包含Windows平台上完成输入字符不带回显和回车确认的getch()函数*/ #include<windows.h>/*包含Windows平台上完成设定输出光标位置达到清屏功能的函数*/ voidstart_game();/*开始游戏*/ voidreset_game();/*重置游戏*/ /*往左右上下四个方向移动*/ voidmove_left(); voidmove_right(); voidmove_up(); voidmove_down(); voidrefresh_show();/*刷新界面显示*/ voidadd_rand_num();/*生成随机数,本程序中仅生成2或4,概率之比设为2:1*/ voidcheck_game_over();/*检测是否输掉游戏,设定游戏结束标志*/ intget_null_count();/*获取游戏面板上空位置数量*/ intboard[4][4];/*游戏数字面板,抽象为二维数组*/ intscore;/*游戏的分*/ intbest;/*游戏最高分*/ intif_need_add_num;/*是否需要生成随机数标志,1表示需要,0表示不需要*/ intif_game_over;/*是否游戏结束标志,1表示游戏结束,0表示正常*/ /*main函数函数定义*/ intmain() { start_game(); } /*开始游戏函数定义*/ voidstart_game() { reset_game(); charcmd; while(1) { cmd=getch();/*接收标准输入流字符命令*/ if(if_game_over)/*判断是否需已经输掉游戏*/ { if(cmd=='y'||cmd=='Y')/*重玩游戏*/ { reset_game(); continue; } elseif(cmd=='n'||cmd=='N')/*退出*/ { return; } else { continue; } } if_need_add_num=0;/*先设定不默认需要生成随机数,需要时再设定为1*/ switch(cmd)/*命令解析,w,s,a,d字符代表上下左右命令*/ { case'a': case'A': case75: move_left(); break; case's': case'S': case80: move_down(); break; case'w': case'W': case72: move_up(); break; case'd': case'D': case77: move_right(); break; } score>best?best=score:1;/*打破得分纪录*/ if(if_need_add_num)/*默认为需要生成随机数时也同时需要刷新显示,反之亦然*/ { add_rand_num(); refresh_show(); } } } /*重置游戏函数定义*/ voidreset_game() { score=0; if_need_add_num=1; if_game_over=0; /*了解到游戏初始化时出现的两个数一定会有个2,所以先随机生成一个2,其他均为0*/ intn=rand()%16; for(inti=0;i<4;i++) { for(intj=0;j<4;j++) { board[i][j]=(n--==0?2:0); } } /*前面已经生成了一个2,这里再生成一个随机的2或者4,且设定生成2的概率是4的两倍*/ add_rand_num(); /*在这里刷新界面并显示的时候,界面上已经默认出现了两个数字,其他的都为空(值为0)*/ system("cls"); refresh_show(); } /*生成随机数函数定义*/ voidadd_rand_num() { srand(time(0)); intn=rand()%get_null_count();/*确定在何处空位置生成随机数*/ for(inti=0;i<4;i++) { for(intj=0;j<4;j++) { if(board[i][j]==0&&n--==0)/*定位待生成的位置*/ { board[i][j]=(rand()%3?2:4);/*确定生成何值,设定生成2的概率是4的概率的两倍*/ return; } } } } /*获取空位置数量函数定义*/ intget_null_count() { intn=0; for(inti=0;i<4;i++) { for(intj=0;j<4;j++) { board[i][j]==0?n++:1; } } returnn; } /*检查游戏是否结束函数定义*/ voidcheck_game_over() { for(inti=0;i<4;i++) { for(intj=0;j<3;j++) { /*横向和纵向比较挨着的两个元素是否相等,若有相等则游戏不结束*/ if(board[i][j]==board[i][j+1]||board[j][i]==board[j+1][i]) { if_game_over=0; return; } } } if_game_over=1; } /* *如下四个函数,实现上下左右移动时数字面板的变化算法 *左和右移动的本质一样,区别仅仅是列项的遍历方向相反 *上和下移动的本质一样,区别仅仅是行项的遍历方向相反 *左和上移动的本质也一样,区别仅仅是遍历时行和列互换 */ /*左移函数定义*/ voidmove_left() { /*变量i用来遍历行项的下标,并且在移动时所有行相互独立,互不影响*/ for(inti=0;i<4;i++) { /*变量j为列下标,变量k为待比较(合并)项的下标,循环进入时k<j*/ for(intj=1,k=0;j<4;j++) { if(board[i][j]>0)/*找出k后面第一个不为空的项,下标为j,之后分三种情况*/ { if(board[i][k]==board[i][j])/*情况1:k项和j项相等,此时合并方块并计分*/ { score+=board[i][k++]<<=1; board[i][j]=0; if_need_add_num=1;/*需要生成随机数和刷新界面*/ } elseif(board[i][k]==0)/*情况2:k项为空,则把j项赋值给k项,相当于j方块移动到k方块*/ { board[i][k]=board[i][j]; board[i][j]=0; if_need_add_num=1; } else/*情况3:k项不为空,且和j项不相等,此时把j项赋值给k+1项,相当于移动到k+1的位置*/ { board[i][++k]=board[i][j]; if(j!=k)/*判断j项和k项是否原先就挨在一起,若不是则把j项赋值为空(值为0)*/ { board[i][j]=0; if_need_add_num=1; } } } } } } /*右移函数定义*/ voidmove_right() { /*仿照左移操作,区别仅仅是j和k都反向遍历*/ for(inti=0;i<4;i++) { for(intj=2,k=3;j>=0;j--) { if(board[i][j]>0) { if(board[i][k]==board[i][j]) { score+=board[i][k--]<<=1; board[i][j]=0; if_need_add_num=1; } elseif(board[i][k]==0) { board[i][k]=board[i][j]; board[i][j]=0; if_need_add_num=1; } else { board[i][--k]=board[i][j]; if(j!=k) { board[i][j]=0; if_need_add_num=1; } } } } } } /*上移函数定义*/ voidmove_up() { /*仿照左移操作,区别仅仅是行列互换后遍历*/ for(inti=0;i<4;i++) { for(intj=1,k=0;j<4;j++) { if(board[j][i]>0) { if(board[k][i]==board[j][i]) { score+=board[k++][i]<<=1; board[j][i]=0; if_need_add_num=1; } elseif(board[k][i]==0) { board[k][i]=board[j][i]; board[j][i]=0; if_need_add_num=1; } else { board[++k][i]=board[j][i]; if(j!=k) { board[j][i]=0; if_need_add_num=1; } } } } } } /*下移函数定义*/ voidmove_down() { /*仿照左移操作,区别仅仅是行列互换后遍历,且j和k都反向遍历*/ for(inti=0;i<4;i++) { for(intj=2,k=3;j>=0;j--) { if(board[j][i]>0) { if(board[k][i]==board[j][i]) { score+=board[k--][i]<<=1; board[j][i]=0; if_need_add_num=1; } elseif(board[k][i]==0) { board[k][i]=board[j][i]; board[j][i]=0; if_need_add_num=1; } else { board[--k][i]=board[j][i]; if(j!=k) { board[j][i]=0; if_need_add_num=1; } } } } } } /*刷新界面函数定义*/ voidrefresh_show() { /*重设光标输出位置方式清屏可以减少闪烁,system("cls")为备用清屏命令,均为Windows平台相关*/ COORDpos={0,0}; SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE),pos); printf("\n\n\n\n"); printf("GAME:2048SCORE:%06dBEST:%06d\n",score,best); printf("--------------------------------------------------\n\n"); /*绘制表格和数字*/ printf("┌──┬──┬──┬──┐\n"); for(inti=0;i<4;i++) { printf("│"); for(intj=0;j<4;j++) { if(board[i][j]!=0) { if(board[i][j]<10) { printf("%d│",board[i][j]); } elseif(board[i][j]<100) { printf("%d│",board[i][j]); } elseif(board[i][j]<1000) { printf("%d│",board[i][j]); } elseif(board[i][j]<10000) { printf("%4d│",board[i][j]); } else { intn=board[i][j]; for(intk=1;k<20;k++) { n>>=1; if(n==1) { printf("2^%02d│",k);/*超过四位的数字用2的幂形式表示,如2^13形式*/ break; } } } } elseprintf("│"); } if(i<3) { printf("\n├──┼──┼──┼──┤\n"); } else { printf("\n└──┴──┴──┴──┘\n"); } } printf("\n"); printf("--------------------------------------------------\n"); printf("W↑A←→D↓S"); if(get_null_count()==0) { check_game_over(); if(if_game_over)/*判断是否输掉游戏*/ { printf("\rGAMEOVER!TRYTHEGAMEAGAIN?[Y/N]"); } } }
以上所述就是本文的全部内容了,希望大家能够喜欢。