Linux C语言编写2048小游戏
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小游戏相关推荐
- C语言编写2048小游戏
该博文为原创文章,未经博主同意不得转载,如同意转载请注明博文出处 本文章博客地址:https://cplusplus.blog.csdn.net/article/details/104992424 2 ...
- c语言2048代码linux,C语言实现2048小游戏(示例代码)
2048 一.设计思路 1.游戏规则 想要制作游戏,首先需要了解游戏的规则,下面就来介绍2048的游戏规则 2048游戏共有16个格子,初始时初始数字由2或者4构成. 手指向一个方向滑动,所有格子会向 ...
- linux 剪刀石头布c语言,利用C语言编写“剪刀石头布”小游戏
前言 大家好~ 我是一名C语言初学者,学了C语言基础后,我制作了一个小游戏:剪刀石头布. 希望大家能对我的思路和代码提出小Tips(eg.更简便的方法与程序) 我也会虚心接受大家的建议~ 一.游戏原理 ...
- C语言实现2048小游戏
C语言实现2048小游戏-粤嵌GE6818嵌入式系统实训 部分功能演示视频. 实现的全部功能: 1.字模显示封面组员名字 2.完成2048游戏在板子上的运行 3.成功或者失败需要有标志也可以计分 4. ...
- C语言实现2048小游戏---粤嵌GE6818嵌入式系统实训
C语言实现2048小游戏---粤嵌GE6818嵌入式系统实训 实现的全部功能: 功能演示: 版本介绍 简易版--大佬选这个 完整版--想保研.想得高分.想要装逼的同学选这个 至尊版--零基础的.想要装 ...
- c语言编写数据存储的游戏,c语言经典小程序和c语言编写的小游戏带注释(自动保存的).doc...
c语言经典小程序和c语言编写的小游戏带注释(自动保存的) 1.写一个定时?关机的小程?序,可以立即关?闭计算机,也可以一段?时间后关闭?计算机. #inclu?de #inclu?de #inclu? ...
- java编写2048小游戏
java版2048小游戏 java编写2048小游戏 java编写2048小游戏 // An highlighted block /*** */ package games;/*** @author ...
- java 2048游戏_JAVA2048游戏 本课程设计是基于java语言的2048小游戏设计 联合开发网 - pudn.com...
JAVA2048游戏 所属分类:游戏 开发工具:Java 文件大小:789KB 下载次数:4 上传日期:2020-11-23 10:57:11 上 传 者:滴滴滴大萌 说明: 本课程设计是基于jav ...
- 用C语言编写一个小游戏
这是一个比较通用的方法来编写一个小游戏用 C 语言: 首先,确定游戏的目标和规则.这可能包括游戏的玩法.胜负条件.游戏元素和游戏流程等. 其次,确定游戏的用户界面.这可能包括游戏的菜单.按钮.文本框. ...
最新文章
- xshell远程登录ubuntu设置流程
- oral_quiz-#求链表中的倒数第K个结点#
- JMeter进阶系列01--JMeter二次开发
- 在Service中通过WindowManger添加View的方式来把UI界面显示出来
- eclipse java 编译jar_Eclipse对Java项目打Jar包
- 我的 FPGA 学习历程(11)—— 实验:按键消抖
- PW Live 直播 | 清华大学博士生岂凡超:义原知识库的应用和扩充
- android aar项目_介绍如何调试Xamarin.Android的binding项目
- XHTML教会我的一些东西-1
- django后台多页面分页逻辑python代码
- python Scrapy爬取天气预报,零基础的你也可以快速上手
- 公有链、私有链、联盟链、许可链,这些区块链又分别代表着什么意思?
- Android 违规使用 Java,谷歌或面临 88 亿美元赔款
- 部署Webpart的方法
- docker安装redis提示没有日记写入权限_Docker 从入门到掉坑
- 基于51单片机交通灯程序设计与仿真
- Gerber文件的输出
- ICT技术认证都有哪些?他们的区别是什么?
- Win10电脑如何清理系统垃圾
- C语言 由拼音字串获取拼音数量
热门文章
- 联想c245如何使用html,[转载]联想C245一体机电脑改XP成功,REALTEK ALC269声卡正常驱动...
- 加强膝关节周围肌肉力量的九个简单动作练法
- 数据结构LRUCache(Least Recently Used – 最近最少使用缓存)
- 南通seo:竞争对手的SEO分析策略
- 蓝桥ROS机器人课程总结2022
- 百度地图 api php thinkhp,TP5调用百度地图接口进行开发
- 【BZOJ】T3041 水叮当的舞步
- 2022年西式面点师(初级)考试题模拟考试题库及答案
- 网站优化,这十个工具你可以看看
- Jquery查找元素的方法汇总