基于ncurse实现的俄罗斯方块

1. 需求分析

  1. 方块的类型
  2. 方块的变形
  3. 方块的消除
  4. 方块的存储
  5. 方块的移动
  6. 接受用户的输入

2. 概要设计

2.1 方块类型与变形

一共有七种,变换的方式如下。变换后的任意形状方块实际上可以存在一个4x4的矩阵中。
我们再压一下位,就可以存在16位中。
在这里插入图片描述

2.2 方块的消除

只需要检查一整行全部都是方块即可。

2.3 方块的移动

详见tinytetris

使用一个简单的循环计时来实现(do_ticks())。

2.4 接受用户输入

直接使用ncurse中的getch即可获得键盘、鼠标等输入。

3. 实现

#include <stdlib.h>
#include <ncurses.h>
#include <time.h>
#include <string.h>#define MAP_ROWS 20
#define MAP_COLS 10
#define GAME_BEGIN_Y 4#define GRID_WIDTH 2
#define GRID_HEIGH 2#define WALL_WIDTH 1enum mov_dir {HOLD = 0,LEFT,RIGHT,DOWN
};
uint dir_to[4][2] = {{0,0},{-1,0},{1, 0},{0, 1}
};enum piece_block {I_BLOCK = 1,J_BLOCK,L_BLOCK,O_BLOCK,S_BLOCK,T_BLOCK,Z_BLOCK
};
uint8_t grid_map[MAP_ROWS][MAP_COLS];
char x;
char y;
uint8_t blk_idx;
uint8_t ticks = 0;uint8_t next_blk_idx;
int scores = 0;// 16bit
int block_magic[7][4] = {{ 240,17476, 3840, 8738},{ 113, 550, 1136, 802},{ 116, 1570, 368,547},{ 51, 51, 51, 51},{ 54, 1122, 864, 561},{ 114, 610, 624, 562},{ 99, 612, 1584, 306}  
};void gen_block( void )
{blk_idx = next_blk_idx;next_blk_idx = rand() % 28;
}
void gen_pos( void )
{x = rand() % 7;y = 0;
}void gen_new_block( )
{gen_block(); gen_pos();
}  uint8_t transform( void )
{uint8_t pos = blk_idx & 0x03;pos = (pos + 1) % 4;return (blk_idx & 0xfc ) | pos;
}
void draw_block_cell( int cx, int cy, uint8_t idx) {uint16_t magic = block_magic[idx >> 2][idx & 0x03];for (int i = 0; i < 16; ++i) {uint8_t x0 = i & 0x03;uint8_t y0 = i >> 2;int nx = cx + x0;int ny = cy + y0;if ( magic & (1 << i)) {attron(COLOR_PAIR( (idx >> 2) + 1));if (nx >= 0 && ny >= 0)mvaddch( ny, nx, '#');attroff(COLOR_PAIR( (idx >> 2) + 1));}}refresh();
}
void draw_grid_map(uint8_t x, uint8_t y)
{for ( int i = 0; i < MAP_ROWS; ++i) {for ( int j = 0; j < MAP_COLS; ++j) {if ( grid_map[i][j] ) {attron(COLOR_PAIR( grid_map[i][j] ));mvaddch(i + y , j + x  , '#');attroff(COLOR_PAIR( grid_map[i][j]) );}}} refresh();
}int check_hit( uint8_t idx, enum mov_dir dir)
{uint16_t magic = block_magic[ idx >> 2][ idx & 0x03];uint8_t nx = x + dir_to[dir][0];uint8_t ny = y + dir_to[dir][1];for ( int i = 0; i < 16; ++i) {uint8_t x0 = i & 0x03;uint8_t y0 = i >> 2;uint8_t cx = nx + x0;uint8_t cy = ny + y0;if ( (1 << i) & magic ) {if ( cx >= MAP_COLS || cx < 0 ) return 1;if ( cy >= MAP_ROWS + GAME_BEGIN_Y || cy < 0)return 1;if ( cy >= GAME_BEGIN_Y && grid_map[ cy - GAME_BEGIN_Y][ cx ]  )return 1;}}return 0;
}int check_remove ( void )
{for ( int i = MAP_ROWS  - 1; i > -1; --i) {int need_remove = 1;for ( int j = 0; j < MAP_COLS; ++j ) {if ( !grid_map[i][j]) {need_remove = 0;break;}}if ( need_remove )return 1;}return 0;}
int remove_line( int *line_cnt)
{int lowest_line = -1;for ( int i = MAP_ROWS - 1; i > -1; --i) {int need_rm = 1;for ( int j = 0; j < MAP_COLS; ++j) {if ( !grid_map[i][j]) {need_rm = 0;break;}}if ( need_rm ) {if ( -1 == lowest_line)lowest_line = i;++*line_cnt;for (int k = 0; k < MAP_COLS; ++k)grid_map[i][k] = 0;}}// 1 line: 10 score// 2 line: 20 + 5scores +=  10 * (*line_cnt) + 5 * (*line_cnt - 1 );  return lowest_line; 
}void grids_fall( int lowest_line, int line_ct )
{/*for (int i = lowest_line; i >= line_ct; --i) {for ( int j = 0; j < MAP_COLS; ++j)grid_map[i][j] = grid_map[i - line_ct][j];}
*/memmove(grid_map + line_ct, grid_map, sizeof(uint8_t) * (lowest_line + 1 - line_ct) * MAP_COLS);memset( grid_map, 0, sizeof(int)*MAP_COLS * line_ct );/* for ( int i = 0; i < MAP_COLS; ++i) {int mx = 23;while ( mx > 3 && grid_map[mx][i])--mx;int lowest_ept_grid = mx;while ( mx > 3 && !grid_map[mx][i])--mx;int lowest_grid = mx;int dis = lowest_ept_grid - lowest_grid;while ( lowest_grid > 3) {grid_map[ lowest_grid + dis][i] = grid_map[ lowest_grid][i];grid_map[ lowest_grid][i] = 0;--lowest_grid;}}
*/
}void draw_current_block( void )
{// x_p = MAP_COLS + 3 // y_p = 2/*uint16_t magic = block_magic[ blk_idx >> 2][ blk_idx & 0x03];for (int i = 0; i < 16; ++i ) {uint8_t x0 = i & 0x03;uint8_t y0 = i >> 2;if ( (1 << i) & magic ) {attron( COLOR_PAIR((blk_idx >> 2) + 1));mvaddch( 2 + y0, MAP_COLS + 4 + x0, '$');attroff( COLOR_PAIR( (blk_idx >> 2) + 1));}}*/mvprintw( 6, MAP_COLS + 4, "blk:%2d", blk_idx );mvprintw( 7, MAP_COLS + 4, "%2d,%2d", x, y);mvprintw(14, MAP_COLS + 4, "scores: %d", scores);mvprintw(17, MAP_COLS + 4, "w for transform");mvprintw(18, MAP_COLS + 4, "asd for dir");mvprintw(19, MAP_COLS + 4, "p for quik put");mvprintw(20, MAP_COLS + 4, "q for quit");draw_block_cell( MAP_COLS + 4, 2, blk_idx);draw_block_cell( MAP_COLS + 4, 10, next_blk_idx);
}void draw_status_bar( void )
{/*draw_block_cell( MAP_ROWS + 4, 2, blk_idx);mvprintw( 6, MAP_COLS + 4, "%2d,%2d", blk_idx >> 2, blk_idx & 0x03 );mvprintw( 7, MAP_COLS + 4, "%2d,%2d", x, y);draw_block_cell( MAP_ROWS + 4, 9, next_blk_idx);*/draw_current_block();
}
void do_remove( void )
{int rm_cnt = 0;if ( check_remove() ){int lowest_rm_line = remove_line( &rm_cnt );draw_frame();	grids_fall( lowest_rm_line, rm_cnt );draw_frame();}}
void clear_map_area( void )
{for ( int j = 0;j < MAP_ROWS + 1; ++j)mvhline(j, 0, ' ', MAP_COLS + 2);
}void draw_block ( void )
{draw_block_cell( x + 1, y - GAME_BEGIN_Y , blk_idx );refresh();
}void place_block( void )
{uint16_t magic = block_magic[ blk_idx >> 2 ][ blk_idx & 0x03];for ( int i = 0; i < 16; ++i ) {uint8_t x0 = i & 0x03;uint8_t y0 = i >> 2;if ( (1 << i) & magic ) {grid_map [ y+y0 - GAME_BEGIN_Y ] [ x+x0 ] = (blk_idx >> 2) + 1;}}}
void init_ncurse_color( void )
{start_color( );for (int i = 1; i < 8; ++i ) {init_pair(i, i, i);}
}void draw_grid( int x, int y, int color_pair_id )
{ }
void init_ncurse_settings( void )
{initscr();init_ncurse_color();noecho( );timeout(0);curs_set(0);resizeterm(44, 30);}
void init_rand_generator( void )
{srand( time(NULL) );next_blk_idx = rand() % 28; 
}int check_end( void )
{uint16_t magic = block_magic[ blk_idx >> 2][blk_idx & 0x03];for ( int i = 0; i < 16; ++i ) {uint8_t x0 = i & 0x03;uint8_t y0 = i >> 2;uint8_t nx = x + x0;uint8_t ny = y + y0;if ( (1<<i) & magic ) {if ( ny < GAME_BEGIN_Y)return 1;}}return 0;
}int do_tick( void )
{if ( ++ticks > 30) {ticks = 0;if ( check_hit(blk_idx, DOWN) ) {if (check_end( ))return 1;place_block();do_remove();gen_new_block(); draw_frame();return 0;}++y;}return 0;
}
int process_input( int ch )
{switch ( ch ){case 'a':case 'A':if ( !check_hit(blk_idx, LEFT) ) {--x;}break;case 'd':case 'D':if ( !check_hit(blk_idx, RIGHT) ) {++x;}break;case 's':case 'S':if ( !check_hit(blk_idx, DOWN ) ) {++y;break;}if ( check_end( ) ) {return 1;}place_block();do_remove();gen_new_block();break;case 'w':case 'W':if ( !check_hit(transform(), HOLD)) {blk_idx = transform();}break;case 'p':case 'P':while ( !check_hit(blk_idx, DOWN)) {++y;}if ( check_end() )return 1;place_block();do_remove();gen_new_block();break;case 'q':case 'Q':return 1;break;default:break;}return 0;
}
void draw_wall( void )
{// 0 col and MAP_COLS + 1 col// MAP_ROWS row is wallattron(COLOR_PAIR( 3 ));	mvvline( 0, 0, ' ', MAP_ROWS );mvvline( 0, MAP_COLS + 1, ' ', MAP_ROWS);mvhline( MAP_ROWS, 0, ' ',MAP_COLS + 2);attroff( COLOR_PAIR(3));/*for ( int i = 0; i < MAP_ROWS + 1; ++i) {for ( int j = 0; j < MAP_COLS + 2; ++j) {if ( i == 0 && (j == 0 || j == MAP_COLS + 1)) {attron( COLOR_PAIR(2));mvaddch(i, j, '#');attroff( COLOR_PAIR(2));}if ( i == MAP_ROWS || j == 0 || j == MAP_COLS + 1){attron( COLOR_PAIR(2) );mvaddch(i, j, '#');attroff( COLOR_PAIR(2));}}}
*/refresh();
}
void draw_frame( void )
{clear();draw_wall( );draw_grid_map( 1, 0);draw_block( );draw_status_bar(); 
}
void test_all_blk_show ( void )
{int cx = 0;int cy = 0;for ( int i = 0; i < 7; ++i,cy += 6) {cx = 0;for ( int j = 0; j < 4; ++j, cx += 6) {draw_block_cell( cx, cy, i * 4 + j);}}}int main( int argc, char *argv[])
{init_ncurse_settings( );init_rand_generator( );gen_new_block(); int ch;int is_end = 0;while ( !do_tick() ){usleep( 10000 );int ch = getch();if ( process_input( ch ) )break;draw_frame();	}endwin();return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/170336.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

基于SpringBoot+Redis的前后端分离外卖项目-苍穹外卖(八)

套餐模块功能开发 1. 新增套餐1.1 需求分析和设计1.1.1产品原型&#xff1a;1.1.2接口设计&#xff1a;1.1.3数据库设计&#xff1a; 1.2 代码开发1.2.1 DishController层1.2.2 DishService接口类1.2.3 DishServiceImpl接口实现类1.2.4 DishMapper层1.2.5 DishMapper.xml1.2.6 …

Spring Cache框架,实现了基于注解的缓存功能。

个人简介&#xff1a;Java领域新星创作者&#xff1b;阿里云技术博主、星级博主、专家博主&#xff1b;正在Java学习的路上摸爬滚打&#xff0c;记录学习的过程~ 个人主页&#xff1a;.29.的博客 学习社区&#xff1a;进去逛一逛~ Spring Cache框架 简介Spring Cache 环境准备S…

C# APS.NET CORE 6.0 WEB API IIS部署

1.创建 APS.NET CORE6.0 WEB API项目 默认选项即可 源代码&#xff1a; 项目文件展开&#xff1a; launchSettings.json {"$schema": "https://json.schemastore.org/launchsettings.json","iisSettings": {"windowsAuthentication"…

深入理解MySQL索引及事务

✏️✏️✏️今天给各位带来的是关于数据库索引以及事务方面的基础知识 清风的CSDN博客 &#x1f61b;&#x1f61b;&#x1f61b;希望我的文章能对你有所帮助&#xff0c;有不足的地方还请各位看官多多指教&#xff0c;大家一起学习交流&#xff01; 动动你们发财的小手&#…

微机原理_4

一、单项选择题&#xff08;本大题共 15 小题&#xff0c;每小题 3 分&#xff0c;共 45 分。在每小题给出的四个备选项中&#xff0c;选出一个正确的答案&#xff0c;请将选定的答案填涂在答题纸的相应位置上。) 1在产品研制的过程中,通常采用( )类型的存储芯片来存放待调试的…

河南省第五届“金盾信安杯”网络与数据安全大赛实操技能赛 部分wp(自己的一些思路和解析 )(主misc crypto )

芜湖 不评价 以下仅是自己的一些思路和解析 有什么问题或者建议随时都可以联系我 目录 题目一 来都来了 操作内容&#xff1a; flag值&#xff1a; 题目二 Honor 操作内容&#xff1a; flag值&#xff1a; 题目三 我看看谁还不会RSA 操作内容&#xff1a; flag值&a…

运维高级-day01

shell回顾 1、快速生成版权控制信息&#xff0c;具体的内容自己替换 [root scripts]# cat ~/.vimrc autocmd BufNewFile *.py,*.cc,*.sh,*.java exec ":call SetTitle()" func SetTitle() if expand("%:e") sh call setline(1,"#!/bin/bash")…

python:傅里叶分析,傅里叶变换 FFT

使用python进行傅里叶分析&#xff0c;傅里叶变换 FFT 的一些关键概念的引入&#xff1a; 1.1.离散傅里叶变换&#xff08;DFT&#xff09; 离散傅里叶变换(discrete Fourier transform) 傅里叶分析方法是信号分析的最基本方法&#xff0c;傅里叶变换是傅里叶分析的核心&…

上手 Promethus - 开源监控、报警工具包

名词解释 Promethus 是什么 开源的【系统监控和警报】工具包 专注于&#xff1a; 1&#xff09;可靠的实时监控 2&#xff09;收集时间序列数据 3&#xff09;提供强大的查询语言&#xff08;PromQL&#xff09;&#xff0c;用于分析这些数据 功能&#xff1a; 1&#xff0…

Java Web——XML

1. XML概述 XML是EXtensible Markup Language的缩写&#xff0c;翻译过来就是可扩展标记语言。XML是一种用于存储和传输数据的语言&#xff0c;它使用标签来标记数据&#xff0c;以便于计算机处理和我们人来阅读。 “可扩展”三个字表明XML可以根据需要进行扩展和定制。这意味…

ubuntu+Teslav100 环境配置

系统基本信息 nvidia-smi’ nvidia-smi 470.182.03 driver version:470.182.03 cuda version: 11.4 产看系统体系结构 uname -aUTC 2023 x86_64 x86_64 x86_64 GNU/Linux 下载miniconda https://mirrors.tuna.tsinghua.edu.cn/anaconda/miniconda/?CM&OA https://mi…

MyBatisPlus入门介绍

目录 一、MyBatisPlus介绍 润物无声 效率至上 丰富功能 二、Spring集成MyBatisPlus 三、SpringBoot集成MyBatisPlus 一、MyBatisPlus介绍 MyBatis-Plus&#xff08;简称 MP&#xff09;是一个MyBatis的增强工具&#xff0c;在MyBatis的基础上只做增强不做改变&#xff0c…

Kafka系列 - Kafka一篇入门

Kafka是一个分布式流式处理平台。很多分布式处理系统&#xff0c;例如Spark&#xff0c;Flink等都支持与Kafka集成。 Kafka使用场景 消息系统&#xff1a;Kafka实现了消息顺序性保证和回溯消费。存储系统&#xff1a;Kafka把消息持久化到磁盘&#xff0c;相比于其他基于内存的…

如何处理git多分支

本篇文章主要处理以下两种多分支问题 如何将自己在本地的修改上传到一个新的Git分支&#xff08;比如用于测试&#xff0c;不合并进main分支&#xff09;&#xff1f;如何在一个新的本地仓库拉取一个项目的非main分支&#xff0c;并处理他们关联关系&#xff1f; 1. 将自己在…

java基于springboot公益帮学网站 新闻发布系统的设计与实现vue

以Java为开发平台&#xff0c;综合利用Java Web开发技术、数据库技术等&#xff0c;开发出公益帮学网站。用户使用版块&#xff1a;可以选择注册并登录&#xff0c;可以浏览信息、可以网上互动、发布文章、内容推荐等。后台管理员管理版块&#xff1a;以管理员身份登录网站后台…

C# 读写FDX-B(ISO11784/85)动物标签源码

本示例使用的发卡器&#xff1a;EM4305 EM4469 ISO11784/85协议125K低频FXD-B动物标签读写发卡器-淘宝网 (taobao.com) using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using S…

rk3588配置uac功能,android13使能uac及adb的复合设备

最近&#xff0c;因新增需求需要在现有产品上增加UAC的功能&#xff0c;查阅并学习相关知识后&#xff0c;在rk3588 SOC硬件平台搭载android13系统平台上成功配置了uac及uac&adb的复合设备。基于开源共享精神希望给大家提供些参考。 1.技术可行性预研 &#xff08;1&#…

【一起来学kubernetes】7、k8s中的ingress详解

引言配置示例负载均衡的实现负载均衡策略实现模式实现方案Nginx类型Ingress实现Treafik类型Ingress实现HAProxy类型ingress实现Istio类型ingress实现APISIX类型ingress实现 更多 引言 Ingress是Kubernetes集群中的一种资源类型&#xff0c;用于实现用域名的方式访问Kubernetes…

自建私有化证书颁发机构(Certificate Authority,CA)实战之 《0x02 Nginx 配置 https双向认证》

自建CA实战之 《0x02 Nginx 配置 https双向认证》 上一章节我们已经实现了Nginx上配置https单向认证&#xff0c;主要场景为客户端验证服务端的身份&#xff0c;但是服务端不验证客户端的身份。 本章节我们将实现Nginx上配置https双向认证&#xff0c;主要场景为客户端验证服…

C++ 实现位图

引出 面试题&#xff1a;给出 40 亿个不重复的无符号整数&#xff0c;没有排过序。给定一个无符号整数&#xff0c;如何快速判断这个数是否在这 40 亿个无符号整数中。[ 腾讯面试题 ] 想法一&#xff1a;将 40 亿个数据存放到 set 里面&#xff0c;然后再查找指定的无符号整数。…