#pragma once
#pragma warning(disable: 4996) // _CRT_SECURE_NO_WARNINGS
//==============================================================================================
// team C<>DE_INSIDE.RND
// file name tex_framework.h
// completion level 2 ( basic, moderate, complete )
// author codesafer
// date 2017.06.28
/// since 2016.10.17
//------------------------------+---------------------------------------------------------------
#include <cstddef> // std::size_t
#define CRE // constructor ( place holder )
using u8 = unsigned char;
using u16 = unsigned short;
using u32 = unsigned int;
using uu = std::size_t;
//------------------------------+---------------------------------------------------------------
// TEX color space
constexpr auto make_color16( u8 l, u8 r, u8 g, u8 b )
{
return u8( l << 3 | r << 2 | g << 1 | b );
}
enum class C4 : u8
{ // + R G B
black = make_color16( 0, 0, 0, 0 ),
navy = make_color16( 0, 0, 0, 1 ),
green = make_color16( 0, 0, 1, 0 ),
teal = make_color16( 0, 0, 1, 1 ),
maroon = make_color16( 0, 1, 0, 0 ),
purple = make_color16( 0, 1, 0, 1 ),
olive = make_color16( 0, 1, 1, 0 ),
silver = make_color16( 0, 1, 1, 1 ),
gray = make_color16( 1, 0, 0, 0 ),
blue = make_color16( 1, 0, 0, 1 ),
lime = make_color16( 1, 0, 1, 0 ),
aqua = make_color16( 1, 0, 1, 1 ),
red = make_color16( 1, 1, 0, 0 ),
fuchsia = make_color16( 1, 1, 0, 1 ),
yellow = make_color16( 1, 1, 1, 0 ),
white = make_color16( 1, 1, 1, 1 ),
};
constexpr auto operator/( C4 fore, C4 back )
{
return u8( static_cast< u8 >( back ) << 4 | static_cast< u8 >( fore ) );
};
constexpr auto get_fore( u8 color )
{
return static_cast< C4 >( color & 0xF );
}
constexpr auto get_back( u8 color )
{
return static_cast< C4 >( color >> 4 );
}
constexpr C4 c4_to_gray[]
{
C4::black, C4::gray, C4::gray, C4::gray, C4::gray, C4::gray, C4::gray, C4::silver,
C4::gray, C4::silver,C4::silver,C4::silver,C4::silver,C4::silver,C4::silver,C4::white,
};
constexpr u32 to_gray_level[]
{
0, 1, 1, 1, 1, 1, 1, 2, 1, 2, 2, 2, 2, 2, 2, 3,
};
constexpr C4 gray_level_to_c4[]
{
C4::black, C4::gray, C4::silver, C4::white,
};
constexpr C4 level_to_c4_clamp( u32 level )
{
return gray_level_to_c4[ U"001233"[ level + 1 ] ]; // 따옴표 안 숫자들 앞에 각각 back-slash 추가해주세요
}
auto& operator++( C4& c )
{
return c = level_to_c4_clamp( to_gray_level[ static_cast< u8 >( c ) ] + 1 );
};
auto& operator--( C4& c )
{
return c = level_to_c4_clamp( to_gray_level[ static_cast< u8 >( c ) ] - 1 );
};
//------------------------------+---------------------------------------------------------------
struct TEX
{
u8 color;
char letter;
CRE TEX() = default;
CRE TEX( const u8 color, const char c )
: color( color ), letter( c ) {}
CRE TEX( const int value )
: color( value & 0xFF ), letter( ( value & 0xFF00 ) >> 8 ) {}
auto operator==( const TEX other ) const
{
return color == other.color && letter == other.letter;
}
auto operator!=( const TEX other ) const
{
return !( *this == other );
}
};
//------------------------------+---------------------------------------------------------------
#include <array>
#include <algorithm> // std::min, std::max
template< int x_size = 80, int y_size = 25 >
class PAGE
{
static const int size = x_size * y_size;
using LINE = TEX( & )[ x_size ];
using MATRIX = TEX( & )[ y_size ][ x_size ];
public:
std::array< TEX, size > buffer;
MATRIX& cells = (MATRIX&)buffer;
u8 text_color = C4::silver / C4::black;
u8 number_color = C4::silver / C4::black;
u8 number_size = (u8)11;
auto xsize() const { return x_size; }
auto ysize() const { return y_size; }
enum class TEXT_ALIGN : int
{
left,
right,
};
///-------------------------+---------------------------------------------------------------
CRE PAGE() = default;
CRE PAGE( const PAGE& page )
{
buffer = page.buffer;
}
void fill( const TEX tex )
{
buffer.fill( tex );
}
void put( const int x, const int y, const TEX tex )
{
cells[ y ][ x ] = tex;
}
void put( const int x, const int y, const char c )
{
put( x, y, { text_color, c } );
}
auto center_x( int length )
{
return ( x_size - length ) >> 1;
}
auto center_x( const char* s )
{
return center_x( strlen( s ) );
}
auto puts( const int x, const int y, const char* str )
{
int i;
for( i = 0; str[ i ]; ++i )
put( x + i, y, str[ i ] );
return x + i;
}
auto puts( const int y, const char* str )
{
return puts( center_x( str ), y, str );
}
template< class T, uu SIZE >
auto puts( const int x, const int y, const char* str,
const T( &colors )[ SIZE ], const int offset = 0 )
{
int i;
for( i = 0; str[ i ]; ++i )
put( x + i, y,
{ static_cast< u8 >( colors[ ( i + offset ) % SIZE ] ), str[ i ] } );
return x + i;
}
template< class T, uu SIZE >
auto puts( const int y, const char* str,
const T( &colors )[ SIZE ], const int offset = 0 )
{
return puts( center_x( str ), y, str, colors, offset );
}
template< TEXT_ALIGN align >
auto to_string( const int n ) const
{
static char numstr[ 14 ];
int* c = (int*)numstr;
c[ 2 ] = c[ 1 ] = c[ 0 ] = 0x20202020;
bool neg = false;
u32 u = n;
if( n < 0 ) neg = true, u = -n;
char* p = numstr + ( sizeof numstr - 1 );
char* end = p - number_size;
do *--p = u % 10 + '0', u /= 10; while( u );
if( neg ) *--p = '-';
if( align == TEXT_ALIGN::left )
return p;
return end;
}
template< TEXT_ALIGN align = TEXT_ALIGN::right >
auto put_number( const int x, const int y,
const char* s, const int n )
{
return puts( puts( x, y, s ), y, to_string< align >( n ) );
}
void horz_line( const int left, const int right,
const int y, const TEX tex )
{
for( int x = left; x < right; ++x )
put( x, y, tex );
}
void vert_line( const int x, const int top,
const int bottom, const TEX tex )
{
for( int y = top; y < bottom; ++y )
put( x, y, tex );
}
void rectangle( const int left, const int top,
const int right, const int bottom, TEX tex )
{
const int y2 = bottom - 1;
horz_line( left, right, top, tex );
horz_line( left, right, y2, tex );
for( int y = top + 1; y < y2; ++y )
horz_line( left, right, y, tex );
}
void frame( const int left, const int top,
const int right, const int bottom, TEX tex )
{
const int y2 = bottom - 1;
horz_line( left, right, top, tex );
horz_line( left, right, y2, tex );
vert_line( left, top + 1, y2, tex );
vert_line( right - 1, top + 1, y2, tex );
}
void frame_bold( const int left, const int top,
const int right, const int bottom, TEX tex )
{
const int y2 = bottom - 1;
frame( left, top, right, bottom, tex );
vert_line( left + 1, top + 1, y2, tex );
vert_line( right - 2, top + 1, y2, tex );
}
template< int w, int h >
void draw( const int left, const int top, const PAGE< w, h >& page )
{
const int l = std::max( 0, -left );
const int t = std::max( 0, -top );
const int r = std::min( w, x_size - left );
const int b = std::min( h, y_size - top );
for( int y = t; y < b; ++y )
{
const int yt = y + top;
for( int x = l; x < r; ++x )
if( page.cells[ y ][ x ].letter )
put( x + left, yt, page.cells[ y ][ x ] );
}
}
void gray()
{
for( auto& tex : buffer )
tex.color = c4_to_gray[ static_cast< u8 >( get_fore( tex.color ) ) ] /
c4_to_gray[ static_cast< u8 >( get_back( tex.color ) ) ];
}
void lighten()
{
for( auto& tex : buffer )
{
auto fore = get_fore( tex.color );
auto back = get_back( tex.color );
tex.color = ++fore / ++back;
}
}
void darken()
{
for( auto& tex : buffer )
{
auto fore = get_fore( tex.color );
auto back = get_back( tex.color );
tex.color = --fore / --back;
}
}
};
//------------------------------+---------------------------------------------------------------
#include <conio.h> // _kbhit
#include <Windows.h>
template< int x_size = 80, int y_size = 25 >
class SCREEN
{
char buffer[ 8192 ];
HANDLE handle;
void go( const short x, const short y ) const
{
fflush( stdout );
SetConsoleCursorPosition( handle, { x, y } );
}
auto color( const u8 c ) const
{
fflush( stdout );
SetConsoleTextAttribute( handle, c );
return c;
}
void resize( short w, short h ) const
{
COORD coord { w, h };
SetConsoleScreenBufferSize( handle, coord );
SMALL_RECT rect = { 0,0, w - 1, h - 1 };
SetConsoleWindowInfo( handle, TRUE, &rect );
}
public:
PAGE< x_size, y_size > top_page;
///-------------------------+---------------------------------------------------------------
CRE SCREEN( bool full_screen = false )
: handle( GetStdHandle( STD_OUTPUT_HANDLE ) )
{
setvbuf( stdout, (char*)&buffer, _IOFBF, sizeof buffer );
if( full_screen )
SetConsoleDisplayMode( handle, CONSOLE_FULLSCREEN_MODE, NULL );
SetConsoleMode( handle, 0x0008 ); // DISABLE_NEWLINE_AUTO_RETURN
cursor( false );
}
auto xsize() const { return x_size; }
auto ysize() const { return y_size; }
void cursor( const bool show ) const
{
CONSOLE_CURSOR_INFO info = { 1, show };
SetConsoleCursorInfo( handle, &info );
}
void flush()
{
resize( x_size, y_size );
u8 old_color = color( top_page.buffer[ 0 ].color );
for( int y = 0; y < y_size; ++y )
{
go( 0, y );
TEX* scanline = top_page.cells[ y ];
for( int x = 0; x < x_size; ++x )
{
if( old_color != scanline[ x ].color )
old_color = color( scanline[ x ].color );
putchar( scanline[ x ].letter );
}
}
fflush( stdout );
}
template< class F >
void fade( const int delay, F operation )
{
top_page.gray();
flush();
for( int i = 0; i < 4; ++i )
{
::Sleep( delay );
operation();
flush();
}
}
void fadeout( const int delay = 1000 )
{
fade( delay, [ this ]{ top_page.lighten(); } );
}
void fadein( const int delay = 1000 )
{
fade( delay, [ this ]{ top_page.darken(); } );
}
template< class F = void(*)() >
auto waitfor_press( F f = []{} )
{
while( !_kbhit() ) f();
return getch();
}
};
//==============================================================================================
이게먼데요?
1. center_x 함수 두 개로 나눔.
2. waitfor_press 에 있던 getchar -> getch
3. text_number 함수명 put_number 로 변경.
@이힝 웅 강좌 소스코드.
봐도 몰것다
추천을 박습니다.
줄 맞추는 스타일 너무 좋아
CRE 이해가 안 됨 define 뒤에 아무것도 없는데 왜 타입이지
타입이 아니고 걍 줄맞춤?
ㅇㅇ CRE 는 space_holder 임. 자동정렬 되면서 앞으로 끌려가는걸 막기위한.
http://cafe.daum.net/codeinside/b8FO/180