7

私はASCIIベースのゲームの作成に取り組んでおり、Windowsを使用している場合は、MSDNのConsole.Write()を使用するように言われていますが、そうではありません。

したがって、私は、2つの画面バッファーを交互に使用できる関数または関数のグループをCで記述し、それらを画面に書き込むことを試みています。これは、manページのように、pico、vim、およびemacs。

バッファが機能していて、Cとputchar()を使用して各文字を画面に配置する0verkillと呼ばれるLinux用の古いASCIIゲームを見つけましたが、それを再作成しようとすると、テキストの流れが継続します。静的テキストのウィンドウサイズのパネルではありません。私は、cursesのような外部ライブラリを使用したくありません(移植性が低下するため)。可能な限り、ansi標準を維持したいと思います。

ありがとう!

4

4 に答える 4

5

curses のような外部ライブラリを使用したくありません (移植性が低下するため)。

何?curses や ncurses などのライブラリは、この種のものをより移植しやすくするように設計されています。

可能であれば、ANSI 標準に準拠したいと考えています。

...必要なものに対する ANSI 標準 (少なくとも C 用) はありません。この種の動作の実装はオペレーティング システムごとに異なるため、移植可能な方法で実行する場合は、ライブラリを使用する必要があります。正直なところ、 ncurses が移植されていないシステム用に開発する必要はありません。それなしでは使用できないすべてのプログラムを想像してみてください。

于 2009-10-09T04:40:20.283 に答える
4

あなたが探しているのは、画面をクリアするANSI 制御文字だと思います。ESC[2J状態が変化した後、コンソール画面を「更新」するためにそれを呼び出します。

残りの部分については、このページを参照してください。これらのコードを使用して、コンソールで色と書式設定 (間隔、配置、インデントなど) を定義できます。

于 2009-10-09T04:48:12.000 に答える
3

ANSI 標準 X3.64 と、DEC VT100 端末について説明している ISO/IEC 6429 があります。標準では、対応する端末エミュレーターが認識する色とカーソル位置の特定のエスケープ シーケンスについて説明しています。これは基本的にすべての X 端末ですが、Windows では必ずしもそうではありません (ユーザーがansi.sysをロードする必要がある可能性があります)。このような詳細を抽象化する ncurses を使用する必要がある理由を説明するのは、この最後の醜い矛盾です。

于 2009-10-09T04:51:22.803 に答える
3

アプリケーションから curses を抽象化する方法を示すヘッダーとソース ファイルの例。ほこりを集める; 15年以上前に書いた。買い手責任負担。

cursemu.h

/***************************************************************************
 *                                                                          
 *  DO NOT CHANGE ANYTHING BETWEEN THIS LINE AND THE NEXT LINE THAT HAS THE 
 *  WORDS "KLAATU BARRATA NIKTO" ON IT                                      
 *                                                                          
 ***************************************************************************/
#ifndef X__CURSEMU__H                                                        
#define X__CURSEMU__H                                                        

#include <stdio.h>

#ifdef  linux
#define _POSIX_VERSION
#endif                

#ifndef _POSIX_VERSION
#include <sgtty.h>    
#define  USE_OLD_TTY  
#include <sys/ioctl.h>
#undef  USE_OLD_TTY   

#ifndef  CBREAK
#define CBREAK RAW
#endif            

#if !defined(sun) && !defined(sequent) && !defined(hpux) && \
    !defined(_AIX) && !defined(aix)                          
#include <strings.h>                                         
#define strchr index                                         
#else                                                        
#include <string.h>                                          
#endif                                                       
#else                                                        
#include <string.h>                                          
#include <termios.h>                                         
#endif                                                       

#include <errno.h>
#include <sys/types.h>
#include <pwd.h>      
#include <sys/time.h> 
#include <sys/file.h> 
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>     
#include <signal.h>    

/* Keep looking ... */

int _tty_ch;

#ifdef  _POSIX_VERSION
struct termios _tty;  
tcflag_t _res_iflg,   
    _res_lflg;        

#define cbreak()(_tty.c_lflag&=~ICANON, \
  tcsetattr( _tty_ch, TCSANOW, &_tty ))  

#define noecho()(_tty.c_lflag &= ~(ECHO|ICRNL), \
  tcsetattr( _tty_ch, TCSADRAIN, &_tty ))        

#define savetty()((void) tcgetattr(_tty_ch, &_tty), \
  _res_iflg = _tty.c_iflag, _res_lflg = _tty.c_lflag )

#define resetty()(_tty.c_iflag = _res_iflg, _tty.c_lflag = _res_lflg,\
  (void) tcsetattr(_tty_ch, TCSADRAIN, &_tty))                        

#define erasechar()(_tty.c_cc[VERASE])
#else                                 
struct sgttyb _tty;                   
int _res_flg;                         

#define cbreak()(_tty.sg_flags|=CBREAK, ioctl(_tty_ch, TIOCSETP, &_tty))

#define noecho()(_tty.sg_flags &= ~(ECHO|CRMOD), \
  ioctl( _tty_ch, TIOCSETP, &_tty ))              

#define savetty()((void) ioctl(_tty_ch, TIOCGETP, &_tty), \
  _res_flg = _tty.sg_flags )                               

#define resetty()(_tty.sg_flags = _res_flg, \
  (void) ioctl(_tty_ch, TIOCSETP, &_tty))    
#define erasechar()(_tty.sg_erase)           
#endif                                       

/* KLAATU BARRATA NIKTO */

#define  TERMCAP_LENGTH 1024

struct CtrlSeq
{             
  char termcap[ TERMCAP_LENGTH ];

  int numRows, numCols;

  /*  These pointers are indexes into the termcap buffer, and represent the
   *  control sequences neccessary to send to the terminal window to perform
   *  their appropriately named feature.
   */
  char *highlight,
       *endMode,            /* End highlight mode, and other modes. */
       *clearScr,
       *clearEol,
       *scrollRegion,
       *moveCursor,
       *deleteRow,
       *insertRow,
       *saveCursor,         /* Save the current cursor position */
       *restoreCursor;      /* Restore the saved cursor position */

  int dumbTerm,             /* 1 if the terminal is a dumb terminal */
      flush;                /* 1 if the emulation should flush stdout */
};

struct CtrlSeq ctrlSeq;

#define DEFAULT_COLS    80
#define DEFAULT_ROWS    24

void ce_flush( int toSet );
void ce_puts( char *str );
void ce_gotoRowCol( int row, int col );

void ce_writeStrRowCol( char *theText, int row, int col );
void ce_writeStr( char *theText );
void ce_writeCharRowCol( char theChar, int row, int col );
void ce_writeChar( char theChar );

void ce_clearScreen( void );
void ce_clearEol( void );

void ce_highlight( int on );
void ce_scrollRegion( int row1, int row2 );
void ce_deleteRow( int row );
void ce_insertRow( int row );
void ce_saveCursor( void );
void ce_restoreCursor( void );

int ce_getRows( void );
int ce_getCols( void );

#endif

cursemu.c

#include "cursemu.h"

int putchar_x( int c )
{                     
  return( putchar( c ) );
}                        

/*  Returns 0 on success, -1 on error
 */                                  
int ce_startCurses( void )           
{                                    
  char *ptr,                         
       tempBuff[ 1024 ];             
  int  result = 0;                   

  if( (ptr = (char *)getenv( "TERM" )) != NULL )
    result = tgetent( tempBuff, ptr );          
  else                                          
    result = tgetent( tempBuff, "vt100" );      

  if( result < 1 )
  {               
    perror( "FATAL Error: No termcap entry found (even tried vt100)!\n" );
    return( -1 );                                                         
  }                                                                       

  ptr = ctrlSeq.termcap;

  if( (ctrlSeq.numCols = tgetnum( "co" )) == -1 )
    ctrlSeq.numCols = DEFAULT_COLS;              
  if( (ctrlSeq.numRows = tgetnum( "li" )) == -1 )
    ctrlSeq.numRows = DEFAULT_ROWS;              

  if( (ctrlSeq.moveCursor = (char *)tgetstr( "cm", &ptr )) == NULL )
    ctrlSeq.moveCursor = (char *)tgetstr( "cl", &ptr );             
  if( (ctrlSeq.highlight = (char *)tgetstr( "mr", &ptr )) == NULL ) 
    ctrlSeq.highlight = (char *)tgetstr( "md", &ptr );              

  ctrlSeq.endMode       = (char *)tgetstr( "me", &ptr );
  ctrlSeq.clearEol      = (char *)tgetstr( "ce", &ptr );
  ctrlSeq.clearScr      = (char *)tgetstr( "cl", &ptr );
  ctrlSeq.scrollRegion  = (char *)tgetstr( "cs", &ptr );
  ctrlSeq.deleteRow     = (char *)tgetstr( "dl", &ptr );
  ctrlSeq.insertRow     = (char *)tgetstr( "al", &ptr );
  ctrlSeq.saveCursor    = (char *)tgetstr( "sc", &ptr );
  ctrlSeq.restoreCursor = (char *)tgetstr( "rc", &ptr );

  ctrlSeq.dumbTerm = (ctrlSeq.moveCursor == NULL) ||
                     (ctrlSeq.scrollRegion == NULL) ||
                     (ctrlSeq.saveCursor == NULL) ||  
                     (ctrlSeq.restoreCursor == NULL) ||
                     (ctrlSeq.clearEol == NULL);       

  ctrlSeq.flush = 1;

  if( !ctrlSeq.dumbTerm )
  {                      
    if( (_tty_ch = open( "/dev/tty", O_RDWR, 0 ) ) == -1 )
      _tty_ch = 0;                                        

    savetty();
    cbreak(); 
    noecho(); 
    return( 0 );
  }             

  return( -1 );
}              

int ce_endCurses( void )
{                       
  ce_scrollRegion( -1, -1 );
  ce_gotoRowCol( ce_getRows() - 1, 0 );
  resetty();                           
}                                      

void ce_flush( int toSet )
{                         
  ctrlSeq.flush = toSet;  

  if( toSet == 1 )
    fflush( stdout );
}                    

void ce_puts( char *str )
{                        
  tputs( str, 0, putchar_x );

  if( ctrlSeq.flush )
    fflush( stdout );
}                    

void ce_gotoRowCol( int row, int col )
{                                     
  if( row > ctrlSeq.numRows )         
    row = ctrlSeq.numRows;            
  if( col > ctrlSeq.numCols )         
    col = ctrlSeq.numCols;            

  ce_puts( (char *)tgoto( ctrlSeq.moveCursor, col, row ) );
}                                                          

void ce_writeStrRowCol( char *theText, int row, int col )
{                                                        
  ce_flush( 0 );                                         
  ce_gotoRowCol( row, col );                             
  ce_writeStr( theText );                                
  ce_flush( 1 );                                         
}                                                        

void ce_writeStr( char *theText )
{                                
  ce_flush( 0 );                 
  printf( "%s", theText );       
  ce_flush( 1 );                 
}                                

void ce_writeCharRowCol( char theChar, int row, int col )
{                                                        
  ce_flush( 0 );                                         
  ce_gotoRowCol( row, col );                             
  ce_writeChar( theChar );                               
  ce_flush( 1 );                                         
}                                                        

void ce_writeChar( char theChar )
{                                
  ce_flush( 0 );                 
  printf( "%c", theChar );       
  ce_flush( 1 );                 
}                                

void ce_clearScreen( void )
{                          
  ce_puts( ctrlSeq.clearScr );
}

void ce_clearEol( void )
{
  ce_puts( ctrlSeq.clearEol );
}

void ce_highlight( int on )
{
  if( on == 0 )
    ce_puts( ctrlSeq.endMode );
  else
    ce_puts( ctrlSeq.highlight );
}

void ce_scrollRegion( int row1, int row2 )
{
  ce_puts( (char *)tgoto( ctrlSeq.scrollRegion, row1, row2 ) );
}

void ce_deleteRow( int row )
{
  ce_gotoRowCol( row, 0 );
  ce_puts( ctrlSeq.deleteRow );
}

void ce_insertRow( int row )
{
  ce_gotoRowCol( row, 0 );
  ce_puts( ctrlSeq.insertRow );
}

void ce_saveCursor( void )
{
  ce_puts( ctrlSeq.saveCursor );
}

void ce_restoreCursor( void )
{
  ce_puts( ctrlSeq.restoreCursor );
}

int ce_getRows( void )
{
  return( ctrlSeq.numRows );
}

int ce_getCols( void )
{
  return( ctrlSeq.numCols );
}

コンパイル中

必要:

gcc -o cursemu.o -lcurses -ltermcap
于 2009-10-09T05:16:39.500 に答える