2048

2048小游戏是用Linux C语言写的,运行在Ubuntu系统上,其中Ubuntu链接Ncuses库。首先,我们简单了解一下Ncurses。 Ncurses库是由原CURSES库发展而来的,这个库提供了C/C++对屏幕以及光标、鼠标访问的特性。使得C/C++简易写屏成为可能。

1.1常用函数的介绍

如果要调用NCURSES库中的函数,你必须在代码中加载ncurses.h文件,就是在C或C++程序中添加#include <nursses.h>这一行。
例如: Hello World程序
#include<nurses.h>
int main()
{
initscr(); //初始化,进入curses模式 ,用来清除屏幕("stdscr"窗口)上所有的字符,使屏幕变为空白,等待下一步处理
printw(“Hello World”); //在虚拟屏幕上打印Hello World 输出到”stdscr"的虚拟坐标(0,0)上
refresh(); //将虚拟屏幕上的内容写到显示器上,并刷新 (将缓冲区的内容输出到 屏幕上)printw+refresh()可以不断在虚拟屏幕上写入数据,而调用refresh()函数时让一切看起来似乎时一次完成的。因为refresh()函数至核查窗口和数据中变动的部分。
getch(); //等待用户输入
endwin(); //退出NCURSES模式 释放了curses子系统和相关数据结构的内存,才回到普通字符行模式,否则,结束后终端可能运转得不正常 如果你的程序不能正常地显示东西了,看看initscr()函数和endwin()函数是不是在不该被调用的地方调用了
}

1.2 游戏代码

1.2.1 input.h

#ifdef   __INPUT_H
#define  __INPUT_H#define UP 1
#define DOWN 2
#define LEFT 3
#define RIGHT 4#define FIRST 10
#define NEXT  11
#define THEN 12
#define LAST 13#define QUIT 100
#define UNKNOW 250int get_user_input(void);#endif

1.2.2 input.c

#include <curses.h>
#include "input.h"extern WINDOW *w_2048;  //声明一个外部变量,表示这个变量是其他文件(2048.c)中定义的
int get_user_input(void)
{keypad(w_2048,TRUE);int ch=wgetch(w_2048);keypad(w_2048,FALSE);if(ch=='q'||ch=='Q'){return QUIT;}else if(ch=='a'||ch==KEY_LEFT){return LEFT;}else if(ch=='d'||ch==KEY_RIGHT){return RIGHT;}else if(ch=='s'||ch==KEY_DOWN){return DOWN;}else if(ch=='w'||ch==KEY_UP){return UP;}else if(ch=='1'){return FIRST;}else if(ch=='2'){return NEXT;}else if(ch=='3'){return THEN;}else if(ch=='4'){return LAST;}else{return UNKNOW;}}

相关函数解释:
1.keypad()函数
这个函数允许使用功能键:F1,F2,方向键等。使用keypad(stdscr,TURE)就是显示设备 (stdscr)上使用这些功能。keypad(stdscr,FALSE);就是显示设备(stdscr)关闭这些功能。
2.wgetch()函数
wgetch(*WINDOWS)
这个函数从指定的窗口接收字符

1.2.3 screen.h代码

#define __SCREEN_H
#define __SCREEN_H//打开字符屏幕
void open_screen(void);//关闭字符屏幕
void close_screen(void);

1.2.4 screen.c代码

#include <curses.h>
//打开字符屏幕
void open_screen(void)
{initscr();cbreak();noecho();keypad(stdscr,TRUE);}//关闭字符屏幕
void close_screen(void)
{endwin();
}

相关代码解释:
1. initscr()函数
初始化,进入curses模式 ,用来清除屏幕("stdscr"窗口)上所有的字符,使屏幕变为空白,等待下一步处理
2. cbreak()函数
通常情况下,用户输入的字符将被终端程序送入终端的缓冲区。但当用户有输入换行符时,终端程序将会终端,同时输出当前的缓冲区内容并启用新行的输出缓冲。后面的2048.c代码中, game_is_over()函数 直接改成printf(“game over”) ;程序结束后,会在终端输出game over。但是改成printf(“game over\n”),会显示在屏幕上。但是大多数需要用户输入单个字符并能显示在屏幕上。
cbreak()用来禁用行缓冲,这个函数所初始化的模式可以用来给程序传送控制字符,比如:挂起,中断或退出。这些控制字符被认为是终端驱动程序中的控制字符,因而将这些这符传给终端程序。
3.noecho()函数
这个函数控制用户输入的键盘回显。 noecho()函数可以不让控制字符出现在屏幕上。

1.2.5 main.c代码

#include <stdio.h>
#include <time.h>
#include <stdlib.h>
#include "screen.h"
#include "time.h"int main()
{   //设置随机数zhongzsrandom(time(NULL));   //创建(初始化)我们的字符窗口屏幕open_screen();//进入2048的主循环game_2048();  //关闭字符屏幕close_screnen();return 0;
}

1.2.6 2048.h代码

#ifndef __2048_H__
#define __2048_H__void game_2048(void);#endif

1.2.7 2048.c 代码

#include <curses.h>
#include <stdlib.h>
#include <string.h>
#include "input.h"
#include <unistd.h>//提示窗口相关参数
WINDOW *wel=NULL;
int wel_lines=2;      //提示窗口的行数
int wel_columns=40;   //提示窗口的列数
int wel_y0=0;         //提示窗口左上顶点的y坐标
int wel_x0=20;        //提示窗口右上顶点的x坐标//游戏数字窗口
WINDOW *w_2048=NULL;
int w_2048_lines=4;
int w_2048_coluwns=24;
int w_2048_y0=3;
int w_2048_x0=20;//得分窗口
WINDOW *w_score=NULL;
int w_score_lines=2;
int w_score_coluwns=24;
int w_score_y0=10;
int w_score_x0=20;//结束窗口
WINDOW *w_over=NULL;
int w_over_lines=4;
int w_over_coluwns=24;
int w_over_y0=14;
int w_over_x0=20;#define ITEM_NUM 4int matrix_2048[ITEM_NUM][ITEM_NUM]=
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
};//删除行
void Del(int num)
{int i; for(i=0;i<ITEM_NUM;i++){if(matrix_2048[num][i]!=0)matrix_2048[num][i]=0;}
}//获取0的个数
int get_zero_num()
{int i,j;int n=0;//计数for(i=0;i<ITEM_NUM;i++){for(j=0;j<ITEM_NUM;j++){if(matrix_2048[i][j]==0)n++;}}return n;
}//在空白位置上随机填充一个数字
void fill_a_number(void)
{int zero_num=get_zero_num();if(zero_num==0){return;}int pos=random()%zero_num+1;  //范围是【1~zero_num】int n=0;//第几个0int i,j; for(i=0;i<ITEM_NUM;i++){for(j=0;j<ITEM_NJM;j++){if(matrix_2048[i][j]==0){n++;if(n==pos){//要填充的位置找到了int a[4]={2,2,4,8};int index=random()%4;matrix_2048[i][j]=a[index];return ;}}}}
}//初始化游戏界面需要用到的窗口
void init_windows()
{start_color();init_pair(1,COLOR_RED,COLOR_BLACK);    //1.创建一个提示(欢迎)字符wel=newwin(wel_lines,wel_columns,wel_y0,wel_x0);wmove(wel,0,0);wattron(wel,COLOR_PAIR(1));waddstr(wel,"welcome to game2048");wmove(wel,1,3);waddstr(wel,"Author:liyingzhi");        wrefresh(wel);//2.创建一个游戏数字字符窗口    w_2048=newwin(w_2048_lines,w_2048_coluwns,w_2048_y0,w_2048_x0);//3.显示最高得分w_score=newwin(w_score_lines,w_score_coluwns,w_score_y0,w_score_x0);//4.结束窗口w_over=newwin(w_over_lines,w_over_coluwns,w_over_y0,w_over_x0);
}
void del_windows()
{delwin(wel);     //删除欢迎框delwin(w_2048);  //删除字符框delwin(w_score); //删除得分框
}//在非0位置随机删除一个数字
void delete_number(int del)
{int zero_num=get_zero_num();int i,j;if(zero_num==0){return;}for(i=0;i<ITEM_NUM;i++){for(j=0;j<ITEM_NUM;j++){if (del==j){matrix_2048[i][j]=0;}   }}
}//根据矩阵matrix_2048[][]的内容,在游戏中显示
void show_matrix(void)
{int i,j;int max=matrix_2048[0][0];//最高得分for(i=0;i<ITEM_NUM;i++){for(j=0;j<ITEM_NUM;j++){//移动光标wmovewmove(w_2048, i, j*6);//添加要显示的字符串  int转换成charchar buf[6];if(matrix_2048[i][j]==0){sprintf(buf,"%5d",'_');}else{sprintf(buf,"%5d",matrix_2048[i][j]);}waddstr(w_2048,buf);if(matrix_2048[i][j]>max){max=matrix_2048[i][j];}}
}  //刷新窗口wrefresh(w_2048);//显示得分wmove(w_score,0,6);char buf1[24];sprintf(buf1,"score:%5d",max);waddstr(w_score,buf1);//刷新窗口 wrefreshwrefresh(w_score);}void  move_rightr(void)
{ int  i;for(i=0;i<ITEM_NUM;i++){int x=0;//辅助存储非0值进行比较int m=ITEM_NUM-1;//指向这一行最后面(要被覆盖)的位置int k=0;//哨兵,从右往左,找下一个非0元素a[i][k],和x进行比较for(k=ITEM_NUM-1;k>=0;k--){if(matrix_2048[i][k]!=0){if(x==0){x=matrix_2048[i][k];matrix_2048[i][k]=0;}else{//找到两个非0值,进行比较if(matrix_2048[i][k]==x){//需要合并,后移x=x+matrix_2048[i][k];  //合并的值matrix_2048[i][k]=0;   //前移后的数字为0matrix_2048[i][m--]=x;  //合并的值后移x=0;}else{matrix_2048[i][m--]=x;x=matrix_2048[i][k];matrix_2048[i][k]=0;}}}}matrix_2048[i][m--]=x;
}void move_up(void)
{    int i;  for(i=0;i<ITEM_NUM;i++){int x=0;//辅助存储非0值进行比较int m=0;//指向这一行最前面(要被覆盖)的位置int k=0;//哨兵,从上往下,找下一个非0元素 a[i][k],和x进行比较  for(k=0;k<ITEM_NUM;k++){if(matrix_2048[k][i]!=0){if(x==0){x=matrix_2048[k][i];matrix_2048[k][i]=0;      }else{//找到两个非0值,进行比较if(matrix_2048[k][i]==x){  //需要合并,前移x=x+matrix_2048[k][i];  //合并的值matrix_2048[k][i]=0;  //前移后的数字为0matrix_2048[m++][i]=x;  //合并的值前移x=0;//x已经合并前移了,x要重新清0}else{matrix_2048[m++][i]=x;x=matrix_2048[k][i];matrix_2048[k][i]=0;   }       }}}matrix_2048[m++][i]=x;}void move_dowm(void)
{  int i;  for(i=0;i<ITEM_NUM;i++){int x=0;//辅助存储非0值进行比较int m=ITEM_NUM-1;//指向这一行最前面(要被覆盖)的位置int k=0;//哨兵,从下往上,找下一个非0元素 a[i][k],和x进行比较  for(k=ITEM_NUM-1;k>=0;k--){if(matrix_2048[k][i]!=0){if(x==0){x=matrix_2048[k][i];matrix_2048[k][i]=0;      }else{//找到两个非0值,进行比较if(matrix_2048[k][i]==x){  //需要合并,前移x=x+matrix_2048[k][i];  //合并的值matrix_2048[k][i]=0;  //前移后的数字为0matrix_2048[m--][i]=x;  //合并的值前移x=0;//x已经合并前移了,x要重新清0}else{matrix_2048[m--][i]=x;x=matrix_2048[k][i];matrix_2048[k][i]=0;}}}}matrix_2048[m--][i]=x;}
}void move_left(void)
{int i;    for(i=0;i<ITEM_NUM;i++){int x=0;//辅助存储非0值进行比较int m=0;//指向这一行最前面(要被覆盖)的位置int k=0;//哨兵,从左至右,找下一个非0元素 a[i][k],和x进行比较for(k=0;k<ITEM_NUM;k++){if(matrix_2048[i][k]!=0){if(x==0){x=matrix_2048[i][k];matrix_2048[i][k]=0;}else{//找到两个非0值,进行比较if(matrix_2048[i][k]==x){  //需要合并,前移x=x+matrix_2048[i][k];   //合并的值matrix_2048[i][k]=0;     //前移后的数字为0matrix_2048[i][m++]=x;   //合并的值前移x=0;//x已经合并前移了,x要重新清0}else{matrix_2048[i][m++]=x;x=matrix_2048[i][k];matrix_2048[i][k]=0;}}}}matrix_2048[i][m++]=x;}}
//完整代码在网址中

函数分析
1、删除函数Del: 参数num是个整型数字,num等于1时,删除第一行;num等于2时,删除第二行。
每一行会有ITEM_NUM个数字,所以用一个for循环,把一行的数字删了
2、get_zero_num()函数:遍历整个二维数组,返回0的个数
3、fill_a_number()函数:首先用get_zero_num()判断是否有空位,random()%zero_num的范围是0~zero_num-1 pos=random()%zero_num+1的范围是1到zero_num pos就可以随机取其中空白的一个位置 int a[4]数组存放要填充的数字
4、init_windows():初始化窗口
newwin()函数的作用是分配内存给窗口相关的数据结构,返回一个指向窗口的结构指针,失败返回NULL。
delwin()函数可以删除一个窗口,并且释放存储窗口数据结构的内存和信息。
第一个参数:窗口的行数 第二个参数:窗口的列数 第三个参数:窗口左上顶点的行坐标
第四个参数:窗口左上顶点的列坐标 成功返回OK,失败返回ERR
mvwin()函数:第一个参数:要移动的窗口的指针 第二个参数:要移动位置左上顶点的行坐标 第三个参数:要移动位置左上顶点的列坐标 成功返回OK,失败返回ERR
5.show_matrix()
max存放最高分数,sprintf()函数把格式化数据写入字符串 第一个参数为要写入的字符串,第二个为格式化字符串,第三 个为变量。sprintf()最常见的应 用之一莫过于把整数打印到字符串中,如:sprintf(s, “%d”, 123); //把整数123打印成一个字符串保存在s中 sprintf(s, “%8x”, 4567); //小写16进制,宽度占8个位置,右对齐 sprintf()会根据参数format 字符串来转换并格式化数据,然后将结果。复制到参数str 所指的字符串数组,直到出现字符串结束(’\0’)为止。
waddstr(w_2048,buf);在w_2048这个窗口输出字符buf
6.move_left()
二维数组行遍历,按下左移键或W,整行往左移,填补空位置(0)。如果相邻位置值相同,要合并并且前移(使用后置++)
x用来存储比较的第一个非0值 m指向这一行最前面(要被覆盖)的位置 k为哨兵,从左至右找下一个非0值
if(x==0) x保存第一个非0值,如果一行只有一个非0值或者是第奇数个0,就执行 matrix_2048[i][m++]。但是m++是后置++, 是赋值后++。如果不止一个0,那么两个值比较,如果相等,x保存合并值,前移后的matrix_2048[i][k]变为0。合并的值前移。如果不相同,首先移动第一个x,利用循环外的matrix_2048[i][m++]移动第二个x
7.move_right()
二维数组行遍历。与move_left不同的是,从右往左遍历,整体往右移,所以第一个遍历的非0数,放到最右边(下标最大值)所以m- -
8.move_up()
二维数组列遍历。所以i和k要交换位置,从上往下遍历,第一个遍历的非0数,放在最上面(下标最小),所以m++
9.move_dowm()
二位数组列遍历。与move_dowm()不同的是,从下往上遍历,第一个遍历的非0数,放在最下面(下标最大),所以m- -
10.change_matrix
判断按下方向键,是否二维数组是否有改变,把matrix_2048备份到matrix_2048_bak,如果有改变,返回1,没有改变,返回0

完整代码地址
链接:https://pan.baidu.com/s/1BvlnS57pMeShkYlHf-YvzA
提取码:s4lb

Linux C语言编写2048小游戏相关推荐

  1. C语言编写2048小游戏

    该博文为原创文章,未经博主同意不得转载,如同意转载请注明博文出处 本文章博客地址:https://cplusplus.blog.csdn.net/article/details/104992424 2 ...

  2. c语言2048代码linux,C语言实现2048小游戏(示例代码)

    2048 一.设计思路 1.游戏规则 想要制作游戏,首先需要了解游戏的规则,下面就来介绍2048的游戏规则 2048游戏共有16个格子,初始时初始数字由2或者4构成. 手指向一个方向滑动,所有格子会向 ...

  3. linux 剪刀石头布c语言,利用C语言编写“剪刀石头布”小游戏

    前言 大家好~ 我是一名C语言初学者,学了C语言基础后,我制作了一个小游戏:剪刀石头布. 希望大家能对我的思路和代码提出小Tips(eg.更简便的方法与程序) 我也会虚心接受大家的建议~ 一.游戏原理 ...

  4. C语言实现2048小游戏

    C语言实现2048小游戏-粤嵌GE6818嵌入式系统实训 部分功能演示视频. 实现的全部功能: 1.字模显示封面组员名字 2.完成2048游戏在板子上的运行 3.成功或者失败需要有标志也可以计分 4. ...

  5. C语言实现2048小游戏---粤嵌GE6818嵌入式系统实训

    C语言实现2048小游戏---粤嵌GE6818嵌入式系统实训 实现的全部功能: 功能演示: 版本介绍 简易版--大佬选这个 完整版--想保研.想得高分.想要装逼的同学选这个 至尊版--零基础的.想要装 ...

  6. c语言编写数据存储的游戏,c语言经典小程序和c语言编写的小游戏带注释(自动保存的).doc...

    c语言经典小程序和c语言编写的小游戏带注释(自动保存的) 1.写一个定时?关机的小程?序,可以立即关?闭计算机,也可以一段?时间后关闭?计算机. #inclu?de #inclu?de #inclu? ...

  7. java编写2048小游戏

    java版2048小游戏 java编写2048小游戏 java编写2048小游戏 // An highlighted block /*** */ package games;/*** @author ...

  8. java 2048游戏_JAVA2048游戏 本课程设计是基于java语言的2048小游戏设计 联合开发网 - pudn.com...

    JAVA2048游戏 所属分类:游戏 开发工具:Java 文件大小:789KB 下载次数:4 上传日期:2020-11-23 10:57:11 上 传 者:滴滴滴大萌 说明:  本课程设计是基于jav ...

  9. 用C语言编写一个小游戏

    这是一个比较通用的方法来编写一个小游戏用 C 语言: 首先,确定游戏的目标和规则.这可能包括游戏的玩法.胜负条件.游戏元素和游戏流程等. 其次,确定游戏的用户界面.这可能包括游戏的菜单.按钮.文本框. ...

最新文章

  1. xshell远程登录ubuntu设置流程
  2. oral_quiz-#求链表中的倒数第K个结点#
  3. JMeter进阶系列01--JMeter二次开发
  4. 在Service中通过WindowManger添加View的方式来把UI界面显示出来
  5. eclipse java 编译jar_Eclipse对Java项目打Jar包
  6. 我的 FPGA 学习历程(11)—— 实验:按键消抖
  7. PW Live 直播 | 清华大学博士生岂凡超:义原知识库的应用和扩充
  8. android aar项目_介绍如何调试Xamarin.Android的binding项目
  9. XHTML教会我的一些东西-1
  10. django后台多页面分页逻辑python代码
  11. python Scrapy爬取天气预报,零基础的你也可以快速上手
  12. 公有链、私有链、联盟链、许可链,这些区块链又分别代表着什么意思?
  13. Android 违规使用 Java,谷歌或面临 88 亿美元赔款
  14. 部署Webpart的方法
  15. docker安装redis提示没有日记写入权限_Docker 从入门到掉坑
  16. 基于51单片机交通灯程序设计与仿真
  17. Gerber文件的输出
  18. ICT技术认证都有哪些?他们的区别是什么?
  19. Win10电脑如何清理系统垃圾
  20. C语言 由拼音字串获取拼音数量

热门文章

  1. 联想c245如何使用html,[转载]联想C245一体机电脑改XP成功,REALTEK ALC269声卡正常驱动...
  2. 加强膝关节周围肌肉力量的九个简单动作练法
  3. 数据结构LRUCache(Least Recently Used – 最近最少使用缓存)
  4. 南通seo:竞争对手的SEO分析策略
  5. 蓝桥ROS机器人课程总结2022
  6. 百度地图 api php thinkhp,TP5调用百度地图接口进行开发
  7. 【BZOJ】T3041 水叮当的舞步
  8. 2022年西式面点师(初级)考试题模拟考试题库及答案
  9. 网站优化,这十个工具你可以看看
  10. Jquery查找元素的方法汇总