2048最核心的应该是合并的部分,一开始不知道怎么4行往一个方向合并,就想着那就先把一行的合并搞定.只要实现一个一维数组往同一个方向合并,之后慢慢扩展就可以了.
- 实现一行合并的代码
#include <stdio.h>
int main(){
int a[4]={2,0,2,0};
int i;
int n=3;
while(n--){
for(i=0;i<3;i++){ //删除中间的0,创造合并条件
if(a[i]==0){
a[i]=a[i+1];
a[i+1]=0;
}
}
}
n=3;
for(i=0;i<3;i++){ //同时合并,合并之后,可能会产生0
if(a[i]==a[i+1]){ //比如一开始是{2,2,2,2},合并后是{4,0,4,0}
a[i]+=a[i+1];
a[i+1]=0;
}
}
while(n--){ //删除中间的0
for(i=0;i<3;i++){
if(a[i]==0){
a[i]=a[i+1];
a[i+1]=0;
}
}
}
n=3;
for(i=0;i<4;i++){
printf("%d",a[i]);
}
return 0;
}
- 完整代码
一.主函数
main.c
#include <stdio.h>
#include "draw.h"
#include "control.h"
#include "game.h"
int main(void){
int box[4][4]={0};
int step=0;
int score=0;
int dir;
int result;
int state=0;
srand(time(NULL));
rand_init(box); //在界面上随机生成2个数字,2或4
while(1){
draw_from(box,step,score); //刷新界面
if(state==1){
printf("YOU WIN!\n");
break;
}
dir = user_command(); //等待按键输入
if (dir == 4){ //回车结束游戏
break;
}
else if(dir==5){ //其他按键,返回刷新界面
continue;
}
else{ //上下左右
result=merge(box,dir);
state=check(box); //检查输赢状态
if(result==-1){ //无效移动
if(state==-1){
printf("GAME OVER!\n");
break;
}
else{
continue;
}
}
else{ //有效移动,计算得分和步数
score+=result;
step++;
randnumber(box,result); //生成随机数2或4
}
}
}
return 0;
}
二.界面绘制
draw.c
#include <stdio.h>
void draw_from(int box[4][4],int step,int score);
void draw_from(int box[4][4],int step,int score){
int i,j;
int x=0,y=0;
printf("\033[2J");
printf("steps: %d\n",step);
printf("scores: %d\n",score);
for(i=0;i<=16;i++){
for(j=0;j<=32;j++){
if(i%4==0){
if(j%8==0){
printf("\033[42;33m+\033[0m");
}
else{
printf("\033[42;33m-\033[0m");
}
}
else if(i%2==1){
if(j%8==0){
printf("\033[42;33m|\033[0m");
}
else{
printf(" ");
}
}
else if(i%2==0){
if(j%8==0){
printf("\033[42;33m|\033[0m"); //可以改颜色
}
else if(j%8==3){
if(box[x][y]==0){
y++;
printf(" \t");
}
else{
printf(" \033[0;33m%d\t\033[0m",box[x][y++]);
}
if(y==4){
x++;
y=0;
}
}
else;
}
else;
}
printf("\n\033[?25l");
}
}
头文件
draw.h
#ifndef _DRAW_H
#define _DRAW_H
extern void draw_from(int box[4][4],int step,int score);
#endif
三.键盘操作控制
control.c
#include <stdio.h>
#include <termios.h>
#include <unistd.h>
#include <assert.h>
#include <string.h>
int user_command(void);
char my_getch();
int user_command(){
char ch = my_getch();
if (ch == 27)
{
ch = my_getch();
if (ch == 91)
{
ch = my_getch();
switch(ch){
case 65: return 0;break;
case 66: return 1;break;
case 67: return 2;break;
case 68: return 3;break;
}
}
}
else if(ch == '\n')
{
return 4;
}
else{
return 5;
}
}
char my_getch()
{
int c=0; int res=0;
struct termios org_opts, new_opts;
res=tcgetattr(STDIN_FILENO, &org_opts);
assert(res==0);
memcpy(&new_opts, &org_opts, sizeof(new_opts));
new_opts.c_lflag &= ~(ICANON | ECHO | ECHOE | ECHOK | ECHONL | ECHOPRT | ECHOKE | ICRNL);
tcsetattr(STDIN_FILENO, TCSANOW, &new_opts);
c=getchar();//
res=tcsetattr(STDIN_FILENO, TCSANOW, &org_opts);
assert(res==0);
return c;
}
头文件
control.h
#ifndef _DRAW_H
#define _DRAW_H
extern int user_command(void);
extern char my_getch();
#endif
四.游戏过程
game.c
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
void rand_init(int (*box)[4]);
int merge(int (*box)[4], int dir);
int up(int (*box)[4],int dir,int (*temp)[4]);
int down(int (*box)[4],int dir,int (*temp)[4]);
int left(int (*box)[4],int dir,int (*temp)[4]);
int right(int (*box)[4],int dir,int (*temp)[4]);
void randnumber(int (*box)[4],int result);
int check(int (*box)[4]);
void copy_box(int (*box)[4],int (*temp)[4]);
int compare_box(int (*box)[4],int (*temp)[4]);
void rand_init(int (*box)[4]){
randnumber(box,0);
randnumber(box,0);
return ;
}
int merge(int (*box)[4], int dir){
int temp[4][4];
int score;
copy_box(box,temp);
switch(dir){
case 0: //上
score=up(box,dir,temp);
return score;
break;
case 1: //下
score=down(box,dir,temp);
return score;
break;
case 2: //右
score=right(box,dir,temp);
return score;
break;
case 3: //左
score=left(box,dir,temp);
return score;
break;
}
}
int up(int (*box)[4],int dir,int (*temp)[4]){
int i,j;
int n;
int t;
int score=0;
for(j=0;j<4;j++){
n=3;
while(n--){
for(i=0;i<3;i++){
if(box[i][j]==0){
box[i][j]=box[i+1][j];
box[i+1][j]=0;
}
}
}
for(i=0;i<3;i++){
if(box[i][j]==box[i+1][j]){
box[i][j]+=box[i+1][j];
score+=box[i][j];
box[i+1][j]=0;
}
}
n=3;
while(n--){
for(i=0;i<3;i++){
if(box[i][j]==0){
box[i][j]=box[i+1][j];
box[i+1][j]=0;
}
}
}
}
t=compare_box(box,temp);
if(t==-1){
return -1;
}
else{
return score;
}
}
int down(int (*box)[4],int dir,int (*temp)[4]){
int i,j;
int n;
int t;
int score=0;
for(j=0;j<4;j++){
n=3;
while(n--){
for(i=3;i>0;i--){
if(box[i][j]==0){
box[i][j]=box[i-1][j];
box[i-1][j]=0;
}
}
}
for(i=3;i>0;i--){
if(box[i][j]==box[i-1][j]){
box[i][j]+=box[i-1][j];
score+=box[i][j];
box[i-1][j]=0;
}
}
n=3;
while(n--){
for(i=3;i>0;i--){
if(box[i][j]==0){
box[i][j]=box[i-1][j];
box[i-1][j]=0;
}
}
}
}
t=compare_box(box,temp);
if(t==-1){
return -1;
}
else{
return score;
}
}
int left(int (*box)[4],int dir,int (*temp)[4]){
int i,j;
int n;
int t;
int score=0;
for(i=0;i<4;i++){
n=3;
while(n--){
for(j=0;j<3;j++){ //删除0 ,创造合并条件
if(box[i][j]==0){
box[i][j]=box[i][j+1];
box[i][j+1]=0;
}
}
}
for(j=0;j<3;j++){ //合并 ,合并必会产生0
if(box[i][j]==box[i][j+1]){
box[i][j]+=box[i][j+1];
score+=box[i][j]; //和并分数
box[i][j+1]=0;
}
}
n=3;
while(n--){ //删除0
for(j=0;j<3;j++){
if(box[i][j]==0){
box[i][j]=box[i][j+1];
box[i][j+1]=0;
}
}
}
}
t=compare_box(box,temp);
if(t==-1){
return -1;
}
else{
return score;
}
}
int right(int (*box)[4],int dir,int (*temp)[4]){
int i,j;
int n;
int t;
int score=0;
for(i=0;i<4;i++){
n=3;
while(n--){
for(j=3;j>0;j--){
if(box[i][j]==0){
box[i][j]=box[i][j-1];
box[i][j-1]=0;
}
}
}
for(j=3;j>0;j--){
if(box[i][j]==box[i][j-1]){
box[i][j]+=box[i][j-1];
score+=box[i][j];
box[i][j-1]=0;
}
}
n=3;
while(n--){
for(j=3;j>0;j--){
if(box[i][j]==0){
box[i][j]=box[i][j-1];
box[i][j-1]=0;
}
}
}
}
t=compare_box(box,temp);
if(t==-1){
return -1;
}
else{
return score;
}
}
void randnumber(int (*box)[4],int result){
int x;
int y;
int whitch;
if(result>=0){ //有效移动,产生随机数
do{ //随机找到空的格子
x=rand()%4;
y=rand()%4;
}while(box[x][y]!=0);
whitch=rand()%10;
if(whitch<9){ //90%概率生成2
box[x][y]=2;
}
else{
box[x][y]=4; //10%概率生成4
}
}
return ;
}
int check(int (*box)[4]){
int i,j;
for(i=0;i<4;i++){ //检查是否出现2048
for(j=0;j<4;j++){
if(box[i][j]==2048){
return 1;
}
}
}
for(i=0;i<4;i++){ //横向检查
for(j=0;j<3;j++){
if(box[i][j]==box[i][j+1] || box[i][j]==0 || box[i][j+1]==0){
return 0;
}
}
}
for(j=0;j<4;j++){ //纵向检查
for(i=0;i<3;i++){
if(box[i][j]==box[i+1][j]){
return 0;
}
}
}
return -1;
}
void copy_box(int (*box)[4],int (*temp)[4]){
int i,j;
for(i=0;i<4;i++){
for(j=0;j<4;j++){
temp[i][j]=box[i][j];
}
}
}
int compare_box(int (*box)[4],int (*temp)[4]){
int i,j;
for(i=0;i<4;i++){
for(j=0;j<4;j++){
if(temp[i][j]!=box[i][j]){
return 1; //不一样,有效移动
}
}
}
return -1;
}
头文件
game.h
#ifndef _DRAW_H
#define _DRAW_H
extern void rand_init(int (*box)[4]);
extern int merge(int (*box)[4], int dir);
extern int up(int (*box)[4],int dir,int (*temp)[4]);
extern int down(int (*box)[4],int dir,int (*temp)[4]);
extern int left(int (*box)[4],int dir,int (*temp)[4]);
extern int right(int (*box)[4],int dir,int (*temp)[4]);
extern void randnumber(int (*box)[4],int result);
extern int check(int (*box)[4]);
extern void copy_box(int (*box)[4],int (*temp)[4]);
extern int compare_box(int (*box)[4],int (*temp)[4]);
#endif
五.游戏截图
界面简陋了一点😁
游戏结束:
合成2048: