前言:如何检测你是否已经基本入门编程了?来做个2048吧,熟悉语法,会将问题具象为代码来解决,好处大大滴有啊🤩,下面贴上博主自己用C实现的2048,之前虽然写过一次,但全忘干净了😶,所以这次的代码看起来会比较臃肿(大脑已经干了,现在干啥啥不会),大家参考后可以自行优化修改,也欢迎讨论😘
main函数:
#include "map.h"
#include "move_and_add.h"
#include "score.h"
int main(){
int map[4][4]={0};
char input_key;
int if_init=0;
int score=0;
int end_flay=0;
printf("Using w,a,s,d to control map moving!\n");
while(1){
end_flay=game_End(map,&score);
if(end_flay){//判断游戏是否结束
printf("GAME OVER!\nYour score is %d\n",score);
}
generate_Map(map,if_init);
print_Map(map);
scanf("%c",&input_key);
getchar();//使用scanf后记得过滤回车键
switch(input_key){
case 'w':
move_Up(map);//先做移动
add(map,'U');//全部移动完毕都再合并
move_Up(map);//合并后棋盘中可能会有空缺,再移动一次
break;
case 's':
move_Down(map);
add(map,'D');
move_Down(map);
break;
case 'a':
move_Left(map);
add(map,'L');
move_Left(map);
break;
case 'd':
move_Right(map);
add(map,'R');
move_Right(map);
break;
default:
printf("Wrong input!\n");
break;
}
if_init++;
}
return 0;
}
移动和相加函数:
//比较容易遇到的问题:每次相加只能执行一次
#include "move_and_add.h"
void add(int (*m)[4],char direction){//实现等项相加
int bool_num=0;
switch(direction){
case 'U':
for(int i=0;i<4;i++){//从上往下遍历,有空缺再用一次move来弥补
for(int j=0;j<3;j++){
if(bool_num==1){
break;
}
if(m[j][i]==m[j+1][i]){
m[j][i]+=m[j][i];
m[j+1][i]=0;
bool_num=1;
}
}
bool_num=0;
}
break;
case 'D':
for(int i=0;i<4;i++){
for(int j=4;j>0;j--){
if(bool_num==1){
break;
}
if(m[j][i]==m[j-1][i]){
m[j][i]+=m[j][i];
m[j-1][i]=0;
bool_num=1;
}
}
bool_num=0;
}
break;
case 'L':
for(int i=0;i<4;i++){
for(int j=0;j<3;j++){
if(bool_num==1){
break;
}
if(m[i][j]==m[i][j+1]){
m[i][j]+=m[i][j];
m[i][j+1]=0;
bool_num=1;
}
}
bool_num=0;
}
case 'R':
for(int i=0;i<4;i++){
for(int j=3;j>0;j--){
if(bool_num==1){
break;
}
if(m[i][j]==m[i][j-1]){
m[i][j]+=m[i][j];
m[i][j-1]=0;
bool_num=1;
}
}
bool_num=0;
}
}
}
void move_Up(int (*m)[4]){//向上操作,下面的三个函数同理
for(int i=0;i<4;i++){
for(int j=1;j<4;j++){//从上至下依次遍历,直到出现非0数字,再进行反向遍历将其移动至顶端,下同
if(m[j][i]!=0){
for(int k=j;k>0;k--){//若两个不同数字相邻,则改变下标,进行三次循环
if(m[k-1][i]==0){
m[k-1][i]=m[k][i];
m[k][i]=0;
}
}
}
}
}
}
void move_Down(int (*m)[4]){
for(int i=0;i<4;i++){
for(int j=3;j>=0;j--){
if(m[j][i]!=0){
for(int k=j;k<3;k++){
if(m[k+1][i]==0){
m[k+1][i]=m[k][i];
m[k][i]=0;
}
}
}
}
}
}
void move_Left(int (*m)[4]){
for(int i=0;i<4;i++){
for(int j=1;j<4;j++){
if(m[i][j]!=0){
for(int k=j;k>0;k--){
if(m[i][k-1]==0){
m[i][k-1]=m[i][k];
m[i][k]=0;
}
}
}
}
}
}
void move_Right(int (*m)[4]){
for(int i=0;i<4;i++){
for(int j=3;j>=0;j--){
if(m[i][j]!=0){
for(int k=j;k<3;k++){
if(m[i][k+1]==0){
m[i][k+1]=m[i][k];
m[i][k]=0;
}
}
}
}
}
}
棋盘操作函数:
#include "map.h"
void generate_Map(int (*m)[4],int if_start){
srand(time(NULL));
int quit=0;//每次只生成2个随即数
int rand_num=0;
int rand_line=0;
int rand_columu=0;
for(int i=0;i<16;i++){
if(if_start==0){
if(quit>=2){//当产生两个随机数后退出
break;
}
}
else{
if(quit>=1){
break;
}
}
rand_num=(int)((double)rand()/RAND_MAX*2);//随机生成0或1判断填入的数是2还是4
rand_line=(int)((double)rand()/RAND_MAX*4);//随机生成0~3代表要填入数字的行,下面的列同理
rand_columu=(int)((double)rand()/RAND_MAX*4);
if(m[rand_line][rand_columu]==0){//判断此位置原先存放的数是否为0
if(rand_num==0){
m[rand_line][rand_columu]=2;
}
else{
m[rand_line][rand_columu]=4;
}
quit++;
}
}
}
void print_Map(int (*m)[4]){
for(int i=0;i<4;i++){
for(int j=0;j<4;j++){
printf("%d\t",m[i][j]);//打印每一行的数据
}
printf("\n\n\n");//行间换行
}
}
计分并判断是否结束的函数:
#include "score.h"
int game_End(int (*m)[4],int* score){
int bool_num=1;
*score=0;
for(int i=0;i<4;i++){
for(int j=0;j<4;j++){
if(m[i][j]==0){
bool_num=0;
}
if(*score<m[i][j]){
*score=m[i][j];
}
}
}
return bool_num;
}