#include "stdafx.h"
//==============================================================================================
// team C<>DE_INSIDE.RND
// file name textris_demo.cpp
// completion level 2 ( basic, moderate, complete )
// author codesafer
// date 2017.06.28
/// since 2017.06.28
//------------------------------+---------------------------------------------------------------
#include "tex_framework.h"
constexpr int block_size = 4;
const TEX empty_tile{ C4::silver / C4::black, ' ' };
enum class KEY : int
{
space = 32,
left = 75,
right = 77,
up = 72,
down = 80,
};
//------------------------------+---------------------------------------------------------------
struct TBLOCK
{
using TYPE = unsigned short;
int index = 0;
const TYPE bits_set[ 8 ]
{
0xFFFF, 0xA808, 0x840A, 0x8888, 0xC808, 0xA088, 0x8848, 0xA880,
};
TYPE bits = bits_set[ 0 ];
const TYPE spin_geometry[ 16 ]
{
0x0001, 0x0002, 0x0004, 0x0010,
0x4000, 0x0008, 0x0080, 0x0020,
0x2000, 0x8000, 0x0800, 0x0040,
0x1000, 0x0400, 0x0200, 0x0100,
};
auto& operator=( const TBLOCK& other )
{
bits = other.bits;
index = other.index;
return *this;
}
auto& operator=( const int index )
{
bits = bits_set[ this->index = index ];
return *this;
}
TBLOCK() = default;
TBLOCK( const int index ) : index( index )
{
*this = index;
}
auto rotate_cw()
{
bits = ( bits << 4 ) & 0xFFF0 | ( bits >> 12 ) & 0x000F;
}
auto rotate_ccw()
{
bits = ( bits >> 4 ) & 0x0FFF | ( bits << 12 ) & 0xF000;
}
template< class T >
auto put( T& page, const int x, const int y, bool show = true )
{
const TEX block_tile { C4( index ) / C4( index | 8 ), ' ' };
const TEX tile = show ? block_tile : empty_tile;
for( int v = 0; v < block_size; ++v )
for( int u = 0; u < block_size; ++u )
if( bits & spin_geometry[ v * block_size + u ] )
page.put( ( x + u ) << 1, y + v, tile ),
page.put( ( ( x + u ) << 1 ) + 1, y + v, tile );
}
template< class T >
auto remove( T& page, const int x, const int y )
{
put( page, x, y, false );
}
};
//------------------------------+---------------------------------------------------------------
template< int x_size = 12 * 2, int y_size = 29 >
struct BOARD
{
PAGE< x_size, y_size > page;
auto initialize()
{
const TEX wall{ C4::silver / C4::gray, ' ' };
page.fill( empty_tile );
page.vert_line( 0, 0, y_size - 1, wall );
page.vert_line( 1, 0, y_size - 1, wall );
page.vert_line( x_size - 2, 0, y_size - 1, wall );
page.vert_line( x_size - 1, 0, y_size - 1, wall );
page.horz_line( 0, x_size, y_size - 1, wall );
}
auto is_blocked( const int x, const int y, const TBLOCK block ) const
{
for( int v = 0; v < block_size; ++v )
for( int u = 0; u < block_size; ++u )
if( page.cells[ y + v ][ ( x + u ) << 1 ] != empty_tile &&
block.bits & block.spin_geometry[ v * block_size + u ] )
return true;
return false;
}
CRE BOARD()
{
initialize();
}
};
//------------------------------+---------------------------------------------------------------
#include <random>
#include <time.h>
class TEXTRIS
{
SCREEN<> screen;
BOARD<> board;
PAGE< ( block_size + 2 ) * 2, block_size + 2 >
next_page;
TBLOCK next_block;
TBLOCK block;
int x, y;
int level;
int score;
int lines;
std::mt19937 rng;
std::uniform_int_distribution< int >
get_next;
auto title()
{
screen.top_page.fill( empty_tile );
const C4 color_set1[] { C4::white, C4::silver, C4::gray };
const C4 color_set2[] { C4::red, C4::white, C4::white, C4::white };
screen.waitfor_press( [ this, &color_set1, &color_set2 ]
{
static int i = 0;
screen.top_page.puts( 7, "TeXtris 1", color_set1, i++ / 100 );
screen.top_page.puts( 11, "Codesafer's C++ guide", color_set2,
sizeof color_set2 - i++ / 50 );
screen.top_page.puts( 15, "Press enter to start" );
screen.flush();
} );
}
enum class JUDGE : int
{
gameover,
blocked,
changed = 1,
movable,
};
auto draw_indicators()
{
screen.top_page.text_color = C4::lime / C4::black;
screen.top_page.put_number( 5, 2, "SCORE : ", ++score );
screen.top_page.put_number( 5, 4, "LEVEL : ", level );
screen.top_page.put_number( 5, 6, "LINES : ", lines );
}
auto draw_next_block()
{
next_page.fill( empty_tile );
next_page.frame_bold( 0, 0, next_page.xsize(), next_page.ysize(),
{ C4::silver / C4::navy, ' ' } );
TBLOCK( next_block ).put( next_page, 1, 1 );
screen.top_page.text_color = C4::lime / C4::navy;
screen.top_page.puts( 56, 0, " NEXT BLOCK " );
screen.top_page.draw( 56, 1, next_page );
}
auto change_block()
{
block = next_block;
next_block = get_next( rng );
x = board.page.center_x( block_size << 1 ) >> 1;
y = 0;
if( board.is_blocked( x, y, block ) )
return JUDGE::gameover;
draw_indicators();
draw_next_block();
return JUDGE::changed;
}
auto collapse_line( const int y )
{
for( int x = 1; x < 11; ++x )
board.page.cells[ y ][ x << 1 ] =
board.page.cells[ y - 1 ][ x << 1 ],
board.page.cells[ y ][ x << 1 | 1 ] =
board.page.cells[ y - 1 ][ x << 1 | 1 ];
}
auto clear_line( const int y )
{
for( int u = 1; u < 11; ++u )
board.page.cells[ y ][ u << 1 ] = empty_tile,
board.page.cells[ y ][ u << 1 | 1 ] = empty_tile;
lines++;
level = lines / 30 + 1;
}
auto remove_line()
{
const int v_end = min( y + block_size, board.page.ysize() - 1 );
for( int v = y, bonus = 0; v < v_end; ++v )
{
int count = 0;
for( int u = 1; u < 11; ++u )
count += board.page.cells[ v ][ u << 1 ] != empty_tile;
if( count == 10 )
{
for( int i = v; i > 0; --i )
collapse_line( i );
score += bonus += 10;
clear_line( 0 );
lines++;
}
}
}
auto move_down()
{
block.remove( board.page, x, y );
if( board.is_blocked( x, ++y, block ) )
{
block.put( board.page, x, y - 1 );
remove_line();
return change_block();
}
return JUDGE::movable;
}
public:
CRE TEXTRIS()
: rng( clock() )
, get_next( 1, 7 )
, level( 1 )
, score( 0 )
, lines( 0 )
{
next_block = get_next( rng );
}
auto process_key()
{
if( kbhit() )
{
KEY key = (KEY)getch();
if( (int)key & 0x80 ) key = (KEY)getch();
switch( key )
{
case KEY::left:
block.remove( board.page, x, y );
if( !board.is_blocked( x - 1, y, block ) )
x--;
break;
case KEY::right:
block.remove( board.page, x, y );
if( !board.is_blocked( x + 1, y, block ) )
x++;
break;
case KEY::up:
block.remove( board.page, x, y );
block.rotate_cw();
if( board.is_blocked( x, y, block ) )
block.rotate_ccw();
break;
case KEY::down:
move_down();
break;
case KEY::space:
while( move_down() == JUDGE::movable );
break;
}
}
}
auto run()
{
title();
screen.fadein( 500 );
change_block();
while( move_down() != JUDGE::gameover )
{
const int waiting = 30 - level;
for( int i = 0; i < waiting; ++i )
{
block.put( board.page, x, y );
screen.top_page.draw(
( screen.top_page.xsize() - board.page.xsize() ) >> 1,
-block_size, board.page );
screen.flush();
process_key();
Sleep( 1 );
}
}
screen.fadeout( 500 );
}
};
//------------------------------+---------------------------------------------------------------
int main()
{
TEXTRIS textris;
textris.run();
return 0;
}
//==============================================================================================
점심시간에 얼렁뚱땅 하는거라 리팩토링할 시간이 없다.
두칸 블럭으로 그리고 있어서 그려지는 좌표가 실제 좌표 x 의 2배인 점을 유의.
주석 적을 시간이 없으니 알아서들 보시게~
굳굳
오졌따리;
캬
336 라인... 도스시절이 살기 좋았던것 같아.
아랫쪽 lines++ 은 지워야할듯. : ) 위로 옮겼는데 왜 안지워졌지.
http://cafe.daum.net/codeinside/b8FO/179
c++ 공부하는데 엋멍 좋은 글이네요 감사합니다