리눅스 기반 테트리스 급질문입니다. 부디 답변 부탁드립니다.

demetrio의 이미지

안녕하세요,

제가 우분투 상에서 테트리스 코드를 짜봤습니다.

기본적인 기능들은 잘 동작하는데 일정 시간이 지나면 블록이 내려가는 기능이 동작을 안하네요.

강제로 내려보내면 잘 내려가는데 혼자선 절대 안내려가요.

일단 증상을 말씀드리면 아무 버튼이나 막 누르고 있으면 한칸씩 내려가는게 보입니다. 그러나 가만히 놔두면 화면상 블록은 내려가질 않네요. 그렇게 잠시 두다가 뭔가 누르면 순간이동하듯이 저 밑에 내려가 있는걸로 봐선 한칸씩 내려가는 기능이 돌아가고 있긴

한건데 이게 출력으로 나타나질 않습니다. 이문제 해결하려고 시간에 맞춰 내려가는 부분만 따로 스레드로 빼서 돌렸는데 역시 안되네요. 코드 첨부합니다. 제발 아시는 분 답변 부탁드려요. 너무 답답합니다.

#include<stdio.h>
#include<stdlib.h>
#include<time.h>
#include<curses.h>
#include<sys/timeb.h>
#include<term.h>
#include<unistd.h>
#include<termios.h>
#include<pthread.h>
 
#define LEFT 68
#define RIGHT 67
#define UP 65
#define DOWN 66
#define BH 20
#define BW 10
#define TRUE 1
#define FALSE 0
#define EMPTY 0
#define BRICK 1
#define WALL 2
 
void DrawScreen();
void DrawBoard();
int ProcessKey();
void PrintBrick(int check);
int GetAround(int x, int y, int b, int r);
int MoveDown();
void TestFull();
int kbhit();
void *t_function(void *data);
 
static struct termios initial_settings, new_settings;
static int peek_character = -1;
struct timeb utm;
struct Point {
    int x, y;
};
struct Point Shape[7][4][4] = {
    {{{0,0},{1,0},{0,1},{1,1}}, {{0,0},{1,0},{0,1},{1,1}}, {{0,0},{1,0},{0,1},{1,1}}, {{0,0},{1,0},{0,1},{1,1}}},
    {{{0,0},{-1,0},{1,0},{2,0}}, {{0,0},{0,-1},{0,1},{0,2}}, {{0,0},{-1,0},{1,0},{2,0}}, {{0,0},{0,-1},{0,1},{0,2}}},
    {{{0,0},{-1,0},{0,-1},{1,-1}}, {{0,0},{-1,0},{-1,-1},{0,1}}, {{0,0},{-1,0},{0,-1},{1,-1}}, {{0,0},{-1,0},{-1,-1},{0,1}}},
    {{{0,0},{0,-1},{-1,-1},{1,0}}, {{0,0},{0,1},{1,0},{1,-1}}, {{0,0},{0,-1},{-1,-1},{1,0}}, {{0,0},{0,1},{1,0},{1,-1}}},
    {{{0,0},{-1,0},{-1,-1},{1,0}}, {{0,0},{0,-1},{1,-1},{0,1}}, {{0,0},{-1,0},{1,0},{1,1}}, {{0,0},{0,-1},{0,1},{-1,1}}},
    {{{0,0},{-1,0},{1,0},{1,-1}}, {{0,0},{0,-1},{0,1},{1,1}}, {{0,0},{1,0},{-1,0},{-1,1}}, {{0,0},{0,1},{0,-1},{-1,-1}}},
    {{{0,0},{-1,0},{1,0},{0,1}}, {{0,0},{-1,0},{0,-1},{0,1}}, {{0,0},{-1,0},{0,-1},{1,0}}, {{0,0},{0,-1},{1,0},{0,1}}}
};
 
char *arTile[] = {". ", "[]", "||"};
int board[BW+2][BH+2];
int nx, ny;
int brick, rot, up, am, tm, gameover;
 
int main()
{
    initscr();
    tcgetattr(fileno(stdin), &initial_settings);
    new_settings = initial_settings;
    new_settings.c_lflag &= ~ICANON;
    pthread_t p_thread[1];
 
    int i, j, thr_id, status;
    int a = 1;
 
    system("clear");
 
    for(i=0; i<BW+2; i++)
    {
        for(j=0; j<BH+2; j++)
        {
            if(i==0 || j==0 || i==BW+1 || j==BH+1)
            {
                board[i][j] = WALL;
            }
            else
            {
                board[i][j] = EMPTY;
            }
        }
    }
    DrawScreen();
 
    thr_id = pthread_create(&p_thread[0], NULL, t_function, (void *)&a);
 
    if(thr_id != 0)
    {
        perror("thread creation failed");
        exit(EXIT_FAILURE);
    }
 
    while(1)
    {
        srand(time(NULL));
        brick = rand()%7;
        nx = BW/2;
        ny = 2;
        rot = 0;
 
        PrintBrick(TRUE);
        if(GetAround(nx, ny, brick, rot) != EMPTY) break;
 
        while(1)
        {
            if(ProcessKey() == TRUE)
            {
                PrintBrick(TRUE);
                break;
                PrintBrick(TRUE);
            }
            if(gameover == 2)
            {
                break;
            }
        }
        if(gameover == 2)
        {
            break;
        }
    }
    pthread_join(p_thread[0], (void **)&status);
    exit(EXIT_SUCCESS);
 
    system("clear");
    endwin();
}
 
void DrawScreen()
{
    int x, y;
 
    for(x=0; x<BW+2; x++)
    {
        for(y=0; y<BH+2; y++)
        {
            move(5 + y, 15 + x*2);
            printw(arTile[board[x][y]]);
        }
    }
}
 
void DrawBoard()
{
    int x, y;
 
    for(x=1; x<BW+1; x++)
    {
        for(y=1; y<BH+1; y++)
        {
            move(5 + y, 15 + x*2);
            printw(arTile[board[x][y]]);
        }
    }
}
 
int ProcessKey()
{
    int getkey;
 
    if(kbhit())
    {
        PrintBrick(TRUE);
        getkey = getch();
        PrintBrick(TRUE);
        switch(getkey)
        {
            case -1:
                break;
            case 27:
                PrintBrick(TRUE);
                getkey = getch();
                PrintBrick(TRUE);
 
                if(getkey == -1)
                {
                    gameover = 2;
                    break;
                }
                else if(getkey == 91)
                {
                    PrintBrick(TRUE);
                    getkey = getch();
                    PrintBrick(TRUE);
 
                    if(getkey == LEFT)
                    {
                        if(GetAround(nx-1, ny, brick, rot) == EMPTY)
                        {
                            PrintBrick(FALSE);
                            nx--;
                            PrintBrick(TRUE);
                            DrawScreen();
                            DrawBoard();
                        }
                    }
                    if(getkey == RIGHT)
                    {
                        if(GetAround(nx+1, ny, brick, rot) == EMPTY)
                        {
                            PrintBrick(FALSE);
                            nx++;
                            PrintBrick(TRUE);
                            DrawScreen();
                            DrawBoard();
                        }
                    }
                    if(getkey == UP)
                    {
                        if(GetAround(nx+1, ny, brick, rot) == EMPTY)
                        {
                            PrintBrick(FALSE);
                            rot++;
                            rot = rot%4;
                            if(GetAround(nx, ny, brick, rot) == EMPTY)
                            {
                                PrintBrick(TRUE);
                                DrawScreen();
                                DrawBoard();
                            }
                        }
                    }
                    if(getkey == DOWN)
                    {
                        if(MoveDown())
                        {
                            PrintBrick(TRUE);
                            return TRUE;
                        }
                    }
                }
                break;
            case 'q':
                gameover = 2;
                break;
        }
        fflush(stdin);
    }
    return FALSE;
}
 
int GetAround(int x, int y, int b, int r)
{
    int i;
    int a = 0;
 
    for(i=0; i<4; i++)
    {
        if(a > board[x+Shape[b][r][i].x][y+Shape[b][r][i].y])
        {
            a = a;
        }
        else
        {
            a = board[x+Shape[b][r][i].x][y+Shape[b][r][i].y];
        }
    }
    return a;
}
 
void PrintBrick(int check)
{
    int i;
 
    for(i=0; i<4; i++)
    {
        move(5 + ny + Shape[brick][rot][i].y, 15 + 2*(nx + Shape[brick][rot][i].x));
        if(check == 0)
        {
            printw(arTile[EMPTY]);
        }
        else if(check == 1)
        {
            printw(arTile[BRICK]);
        }
    }
}
 
int MoveDown()
{
    if(GetAround(nx, ny+1, brick, rot) != EMPTY)
    {
        TestFull();
        return TRUE;
    }
    PrintBrick(FALSE);
    ny++;
    PrintBrick(TRUE);
    DrawScreen();
    DrawBoard();
    return FALSE;
}
 
void TestFull()
{
    int x, y, i, ty;
 
    for(i=0; i<4; i++)
    {
        board[nx + Shape[brick][rot][i].x][ny+Shape[brick][rot][i].y] = BRICK;
    }
 
    for(y=1; y<BH + 1; y++)
    {
        for(x=1; x<BW + 1; x++)
        {
            if(board[x][y] != BRICK) break;
        }
        if(x == BW+1)
        {
            for(ty=y; ty>1; ty--)
            {
                for(x=1; x<BW+1; x++)
                {
                    board[x][ty] = board[x][ty-1];
                }
            }
            DrawBoard();
        }
    }
}
 
int kbhit()
{
    char ch;
    int nread;
 
    if(peek_character != -1) return TRUE;
 
    new_settings.c_cc[VMIN] = 0;
    tcsetattr(0, TCSANOW, &new_settings);
    nread = read(0, &ch, 1);
    new_settings.c_cc[VMIN] = 1;
    tcsetattr(0, TCSANOW, &new_settings);
 
    if(nread == TRUE || nread != UP)
    {
        peek_character = ch;
        return TRUE;
    }
    return FALSE;
}
 
void *t_function(void *data)
{
    ftime(&utm);
    tm = utm.millitm + utm.time*1000;
    am = tm;
 
    while(1)
    {
        ftime(&utm);
        tm = utm.millitm + utm.time*1000;
 
        if(tm >= am + 500)
        {
            MoveDown();
            am = tm;
        }
    }
}

댓글 달기

Filtered HTML

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

BBCode

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param>
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

Textile

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • You can use Textile markup to format text.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Markdown

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • Quick Tips:
    • Two or more spaces at a line's end = Line break
    • Double returns = Paragraph
    • *Single asterisks* or _single underscores_ = Emphasis
    • **Double** or __double__ = Strong
    • This is [a link](http://the.link.example.com "The optional title text")
    For complete details on the Markdown syntax, see the Markdown documentation and Markdown Extra documentation for tables, footnotes, and more.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Plain text

  • HTML 태그를 사용할 수 없습니다.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 줄과 단락은 자동으로 분리됩니다.
댓글 첨부 파일
이 댓글에 이미지나 파일을 업로드 합니다.
파일 크기는 8 MB보다 작아야 합니다.
허용할 파일 형식: txt pdf doc xls gif jpg jpeg mp3 png rar zip.
CAPTCHA
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.