轻松玩Linux,从写个2048玩玩开始,不多说,有注解有代码,就差你了,快上车!
1.简介:Linux上的2048;写个2048代码还能玩到2048,那你就是写得了代码,玩得了2048的2048程序员了。
2.准备:电脑有Linux系统就可以了,gcc,编辑器任意;
3.原理:主要是对一个4*4的数组的操作处理,还需要用到字符的输出显示,键盘输入的获取;
4.展示一下:
5.动手:
a.显示内容:
a1.打开屏幕,关闭屏幕
void open_screen(void)
{
initscr(); //初始化字符屏幕
cbreak(); //Ctrl + c
noecho(); //不用回显
keypad(stdscr, TRUE); //使用功能键
}
void close_screen(void)
{
endwin(); //关闭字符窗口
}
a2.初始化一个放数组的窗口:
WINDOW *w_2048=NULL;
void init_window()
{
w_2048 = newwin(4, 24, w_2048_y0, w_2048_x0);
}
a3.在刚刚的窗口内显示内容:
void init_window_h(void)
{
w_2048 = newwin(2, 24, 4, 40);
//指定位置显示字符
wmove(w_2048, 0,5 );
waddstr(w_2048,"hello 2048!");
wmove(w_2048, 1,3 );
waddstr(w_2048,"designed by lin");
wrefresh(w_2048);
}
b.获取键盘输入:
#define LEFT 1
#define RIGHT 2
#define UP 3
#define DOWN 4
#define QUIT 10
int get_user_input()
{
keypad(w_2048,true);//打开功能键(方向键等)
int ch=wgetch(w_2048);
keypad(w_2048,false);//功取消能键
if(ch=='Q'||ch=='q')
return QUIT;
if(ch=='W'||ch=='w'||ch==KEY_UP)
return UP;
if(ch=='S'||ch=='s'||ch==KEY_DOWN)
return DOWN;
if(ch=='A'||ch=='a'||ch==KEY_LEFT)
return LEFT;
if(ch=='D'||ch=='d'||ch==KEY_RIGHT)
return RIGHT;
}
c.数组处理:
随机数随机填充:
#define N 4
int matrix_2048[N][N]={
0,0,0,0,
0,0,0,0,
0,0,0,0,
0,0,0,0
};
void fill_a_number(void)
{
srandom(time(NULL));//设置随机数种子
//long int random();
int k=random();
k=k%4;
int p=random();
p=p%4;
for(int i=0;i<4;i++) //获取是否还有0
for(int j=0;j<4;j++)
if(matrix_2048[i][j]==0)
num++;
if(num==0)
return;
while(matrix_2048[k][p]!=0)
{
k=random();
k=k%4;
p=random();
p=p%4;
}
int m=random();
m=m%5;
while(m==0||m==1||m==3)
{
m=random();
m=m%5;
}
matrix_2048[k][p]=m;
}
void draw_matrix(void)
{
fill_a_number(); //随机在0的位置填充一个数
for(int i=0;i<4;i++)
{
for(int j=0;j<4;j++)
{
wmove(w_2048, i,j*6 );
char buf[6];
sprintf(buf,"%d",matrix_2048[i][j]);
waddstr(w_2048,buf);
}
}
wrefresh(w_2048);
}
方法一:思想比较简单,就是每次都先去0,再合成,再去0;
void left_zero()//左移去0
{
int m,n;
for(m=0;m<4;m++) //移动0
{
int a[4]={0,0,0,0},k=0;
for(n=0;n<4;n++)
{
if(matrix_2048[m][n]!=0)
{
a[k]=matrix_2048[m][n];
k++;
}
}
for(n=0;n<4;n++)
{
matrix_2048[m][n]=a[n];
}
}
}
int m=0,n=0;
if(Ku==LEFT)
{
for(m=0;m<4;m++)//计算
for(n=0;n<4;n++)
{
left_zero();
if(n+1<4&&matrix_2048[m][n+1]==matrix_2048[m][n])
{
matrix_2048[m][n]+=matrix_2048[m][n+1];
matrix_2048[m][n+1]=0;
sadd+=matrix_2048[m][n];
}
}
}
while(1)
{
//获取键盘操作,对相应方向的数值比较运算,计算出分数
int mv=get_user_input();
if(mv==QUIT)//操作退出
break;
int chan=change_matrix(mv);//更改矩阵,改变=0,不改变=1,用来判断是否有效滑动
int cheak=0;//判断邻近是否有相同字符
for(int i=0;i<3;i++)
for(int j=0;j<3;j++)
{
if(matrix_2048[i][j]==matrix_2048[i][j+1]||matrix_2048[i][j]==matrix_2048[i+1][j])
cheak++;
}
for(int i=0;i<3;i++)
if(matrix_2048[3][i]==matrix_2048[3][i+1])
cheak++;
for(int i=0;i<3;i++)
if(matrix_2048[i][3]==matrix_2048[i+1][3])
cheak++;
for(int i=0;i<4;i++)//判断有没有0
for(int j=0;j<4;j++)
{
if(matrix_2048[i][j]==0)
cheak++;
}
if(cheak==0) //判断结束,没有0字符,没有邻近相同字符
break;
if(chan==1) //判断滑动是否有效
continue;
init_window();
init_window_s();//分数窗口
//显示数字矩阵
draw_matrix();
}
方法二:快捷:
//向左滑动 矩阵matrix_2048
void move_left()
{
int i;
int x;
int m;
int k;
for (i = 0; i < N; i++)
{
//matrix_2048[i]第i行
m = 0;
x = 0;
for (k = 0; k < N; k++)
{
if (matrix_2048[i][k] != 0)
{
if (x == 0)
{
x = matrix_2048[i][k];
matrix_2048[i][k] = 0;
}
else
{
if (matrix_2048[i][k] == x)
{
//合并,再移动
x = x + matrix_2048[i][k];
matrix_2048[i][k] = 0;
matrix_2048[i][m++] = x;
x = 0;
}
else
{
//相邻但不相等
//先移动x,然后把matrix[i][k]->x
matrix_2048[i][m++] = x;
x = matrix_2048[i][k];
matrix_2048[i][k] = 0;
}
}
}
}
matrix_2048[i][m++] = x;
}
}
if (mv == LEFT)
{
move_left();
}
d.判断结束:
条件满足:1.字符的右、下没有相同字符 2.没有0字符,同时满足即调转结束;
e.积分数:每次有合成即对分数增加
6.主代码:
#include <curses.h> //随机数random
#include<time.h>
#include<stdlib.h>
#include"input.h"
//指向标题窗口
WINDOW *w_2048_h=NULL;
//指向数字窗口
WINDOW *w_2048=NULL;
//指向得分窗口
WINDOW *w_score = NULL;
//结束窗口
WINDOW *w_2048_over=NULL;
//窗口w_2048,左上顶点的坐标,在第几行,第几列
int w_2048_y0 = 4;
int w_2048_x0 = 40;
#define N 4
int matrix_2048[N][N]={
0,0,0,0,
0,0,0,0,
0,0,0,0,
0,0,0,0
};
//标题窗口
void init_window_h(void)
{
w_2048_h = newwin(2, 24, 1, 39);
//显示字符
wmove(w_2048_h, 0,5 ); //
waddstr(w_2048_h,"hello 2048!");
wmove(w_2048_h, 1,3 ); //
waddstr(w_2048_h,"designed by lin");
wrefresh(w_2048_h);
}
//分数窗口
int sco=0,sadd=0;
void init_window_s(void)
{
sco+=sadd;
w_score = newwin(2, 24, 5, 20);
//显示字符
wmove(w_score, 0,5 ); //
waddstr(w_score,"score ");
wmove(w_score, 1,5 ); //
char buf[6]="";
sprintf(buf,"%d",sco);
waddstr(w_score,buf);
wrefresh(w_score);
sadd=0;
}
int num=0;
void init_window()
{
w_2048 = newwin(4, 24, w_2048_y0, w_2048_x0);
}
void fill_a_number(void)
{
srandom(time(NULL));//设置随机数种子
//long int random();
int k=random();
k=k%4;
int p=random();
p=p%4;
for(int i=0;i<4;i++) //获取是否还有0
for(int j=0;j<4;j++)
if(matrix_2048[i][j]==0)
num++;
if(num==0)
return;
while(matrix_2048[k][p]!=0)
{
k=random();
k=k%4;
p=random();
p=p%4;
}
int m=random();
m=m%5;
while(m==0||m==1||m==3)
{
m=random();
m=m%5;
}
matrix_2048[k][p]=m;
}
void draw_matrix(void)
{
fill_a_number(); //随机在0的位置填充一个数
for(int i=0;i<4;i++)
{
for(int j=0;j<4;j++)
{
wmove(w_2048, i,j*6 );
char buf[6];
sprintf(buf,"%d",matrix_2048[i][j]);
waddstr(w_2048,buf);
}
}
wrefresh(w_2048);
}
void left_zero()//左移去0
{
int m,n;
for(m=0;m<4;m++) //移动0
{
int a[4]={0,0,0,0},k=0;
for(n=0;n<4;n++)
{
if(matrix_2048[m][n]!=0)
{
a[k]=matrix_2048[m][n];
k++;
}
}
for(n=0;n<4;n++)
{
matrix_2048[m][n]=a[n];
}
}
}
void right_zero()//右移去0
{
int m,n;
for(m=0;m<4;m++)
{
int a[4]={0,0,0,0},k=3;
for(n=3;n>=0;n--)
{
if(matrix_2048[m][n]!=0)
{
a[k]=matrix_2048[m][n];
k--;
}
}
for(n=0;n<4;n++)
{
matrix_2048[m][n]=a[n];
}
}
}
void up_zero()//上移去0
{
int m,n;
for(n=0;n<4;n++)
{
int a[4]={0,0,0,0},k=0;
for(m=0;m<4;m++)
{
if(matrix_2048[m][n]!=0)
{
a[k]=matrix_2048[m][n];
k++;
}
}
for(m=0;m<4;m++)
{
matrix_2048[m][n]=a[m];
}
}
}
void down_zero()//下移去0
{
int m,n;
for(n=0;n<4;n++)
{
int a[4]={0,0,0,0},k=3;
for(m=3;m>=0;m--)
{
if(matrix_2048[m][n]!=0)
{
a[k]=matrix_2048[m][n];
k--;
}
}
for(m=3;m>=0;m--)
{
matrix_2048[m][n]=a[m];
}
}
}
int change_matrix(int Ku)
{
int matrix[N][N]={
0,0,0,0,
0,0,0,0,
0,0,0,0,
0,0,0,0
};
for(int m=0;m<4;m++)//保存
for(int n=0;n<4;n++)
{
matrix[m][n]=matrix_2048[m][n];
}
int m=0,n=0;
if(Ku==LEFT)
{
for(m=0;m<4;m++)//计算
for(n=0;n<4;n++)
{
left_zero();
if(n+1<4&&matrix_2048[m][n+1]==matrix_2048[m][n])
{
matrix_2048[m][n]+=matrix_2048[m][n+1];
matrix_2048[m][n+1]=0;
sadd+=matrix_2048[m][n];
}
}
}
if(Ku==RIGHT)
{
for(m=0;m<4;m++)
for(n=3;n>=0;n--)
{
right_zero();
if(n-1>=0&&matrix_2048[m][n-1]==matrix_2048[m][n])
{
matrix_2048[m][n]+=matrix_2048[m][n-1];
matrix_2048[m][n-1]=0;
sadd+=matrix_2048[m][n];
}
}
}
if(Ku==UP)
{
for(n=0;n<4;n++)
for(m=0;m<4;m++)
{
up_zero();
if(m+1<4&&matrix_2048[m+1][n]==matrix_2048[m][n])
{
matrix_2048[m][n]+=matrix_2048[m+1][n];
matrix_2048[m+1][n]=0;
sadd+=matrix_2048[m][n];
}
}
}
if(Ku==DOWN)
{
for(n=0;n<4;n++)
for(m=3;m>=0;m--)
{
down_zero();
if(m-1>=0&&matrix_2048[m-1][n]==matrix_2048[m][n])
{
matrix_2048[m][n]+=matrix_2048[m-1][n];
matrix_2048[m-1][n]=0;
sadd+=matrix_2048[m][n];
}
}
}
//判断数组是否改变
for(m=0;m<4;m++)
for(n=0;n<4;n++)
{
if(matrix[m][n]!=matrix_2048[m][n])
return 0;
}
return 1;
}
void game_over()
{
w_2048_over = newwin(2, 24, 1, 10);
//显示结束字符
wmove(w_2048_over, 0,5 ); //
waddstr(w_2048_over,"game over !");
wrefresh(w_2048_over);
}
//2048游戏的主循环
void game_2048(void)
{
//初始化一个数字矩阵窗口
init_window();
init_window_h();//标题窗口
init_window_s();//分数窗口
//显示数字矩阵
draw_matrix();
while(1)
{
//获取键盘操作,对相应方向的数值比较运算,计算出分数
int mv=get_user_input();
if(mv==QUIT)//操作退出
break;
int chan=change_matrix(mv);//更改矩阵,改变=0,不改变=1,用来判断是否有效滑动
int cheak=0;//判断邻近是否有相同字符
for(int i=0;i<3;i++)
for(int j=0;j<3;j++)
{
if(matrix_2048[i][j]==matrix_2048[i][j+1]||matrix_2048[i][j]==matrix_2048[i+1][j])
cheak++;
}
for(int i=0;i<3;i++)
if(matrix_2048[3][i]==matrix_2048[3][i+1])
cheak++;
for(int i=0;i<3;i++)
if(matrix_2048[i][3]==matrix_2048[i+1][3])
cheak++;
for(int i=0;i<4;i++)//判断有没有0
for(int j=0;j<4;j++)
{
if(matrix_2048[i][j]==0)
cheak++;
}
if(cheak==0) //判断结束,没有0字符,没有邻近相同字符
break;
if(chan==1) //判断滑动是否有效
continue;
init_window();
init_window_s();//分数窗口
//显示数字矩阵
draw_matrix();
}
while(1)
game_over();
}
附:全部代码打包