2015-11-29 27 views
0

我正在制作一个Tic-Tac-Toe游戏作为学校项目。我在3行中设置了9个按钮,因此每当用户点击其中一个按钮时,其标签将以纯文本形式变为X或O.GTK2 +自动调整按钮标签的字体大小

enter image description here

我想知道是否有可能为大小的X/O取决于窗口的大小来改变。我的另一个想法是使用X/O图像而不是纯文本(至少因为我认为如果我使用大图像,它会自动缩小);我并不想这样做,尽管因为检查玩家赢得比赛的功能比较了标签的文字。

这是负责创建和添加按钮的代码:

GtkWidget *button; 
button = gtk_button_new_with_label(""); 
gtk_box_pack_start(GTK_BOX(theBox),button,FALSE,TRUE,0); 
g_signal_connect(GTK_OBJECT(button),"clicked",GTK_SIGNAL_FUNC(ButtonClicked),EntryBox); 
gtk_widget_show(button); 

这是我ButtonClicked功能:

void ButtonClicked(GtkButton *button, gpointer data) 
{ 
    if (strcmp(gtk_button_get_label(button), "") == 0) 
    if (count % 2 != 0) 
     gtk_button_set_label(button, "X"); 
} 

而且,当我在这里,我还有一个问题:我将窗口边框设置为0,但仍然可以看到非常少量的边框,有什么方法可以摆脱它?

+0

的标签文本不要拿作为一般规则,这就是为什么你可以添加prpoperties或用户数据指针。那么用* cairo *直接在和'“expose-event”中绘制它呢? –

回答

0

你可以试试这个,我用"expose-event"绘制XO并且如果用户没有点击这些事,也imlpemented一个简单的函数来检查得主空单元格。单元格值是通过将数据传递给事件处理程序来设置的。

"button-release-event"允许在单击单元格时,你做什么,然后你就可以在下一回合更改为其它播放器和设置XO到单击的单元格,这取决于球员必须转弯时,它是clicke。

入住这

#include <gtk/gtk.h> 

#include <stdlib.h> 
#include <math.h> 

enum Player 
{ 
    FirstPlayer, 
    SecondPlayer 
}; 

enum TicTacValue 
{ 
    None, 
    Empty, 
    Unset, 
    X, 
    O 
}; 

struct GameData 
{ 
    enum TicTacValue value; 
    enum Player *player; 
    struct GameData *data; 
    gint row; 
    gint column; 
}; 

enum TicTacValue 
evaluate(enum TicTacValue previous, enum TicTacValue next) 
{ 
    if (previous == Unset) 
     return next; 
    if (previous != next) 
     return None; 
    return next; 
} 

void 
check_winner(struct GameData *data) 
{ 
    enum TicTacValue rows[3] = {Unset, Unset, Unset}; 
    enum TicTacValue diagonals[2] = {Unset, Unset}; 
    enum TicTacValue columns[3] = {Unset, Unset, Unset}; 
    enum TicTacValue winner; 

    for (size_t i = 0 ; i < 9 ; ++i) 
    { 
     columns[i % 3] = evaluate(columns[i % 3], data[i].value); 
     rows[i/3] = evaluate(rows[i/3], data[i].value); 
     switch (i) 
     { 
      case 4: 
       diagonals[0] = evaluate(diagonals[0], data[i].value); 
       diagonals[1] = evaluate(diagonals[1], data[i].value); 
       break; 
      case 0: 
      case 8: 
       diagonals[0] = evaluate(diagonals[0], data[i].value); 
       break; 
      case 2: 
      case 6: 
       diagonals[1] = evaluate(diagonals[1], data[i].value); 
       break; 
     } 
    } 

    winner = diagonals[0] | diagonals[1]; 
    winner = winner | columns[0] | columns[1] | columns[2]; 
    winner = winner | rows[0] | rows[1] | rows[2]; 
    if (winner < Unset) 
     return; 
    fprintf(stderr, "Player %d WINS (-)\n", winner - Unset); 
} 

gboolean 
on_click(GtkWidget *widget, GdkEventButton *event, gpointer data) 
{ 
    struct GameData *game_data; 
    game_data = (struct GameData *) data; 
    if (game_data->value != Empty) 
     return FALSE; 
    if (*(game_data->player) == FirstPlayer) 
    { 
     game_data->value = X; 
     *(game_data->player) = SecondPlayer; 
    } 
    else 
    { 
     game_data->value = O; 
     *(game_data->player) = FirstPlayer; 
    } 
    gtk_widget_queue_draw(widget); 
    check_winner(game_data->data); 
    return FALSE; 
} 

void 
draw_delmiter_line(cairo_t *cairo, gint x1, gint y1, gint x2, gint y2) 
{ 
    cairo_save(cairo); 
    cairo_set_source_rgb(cairo, 0.65, 0.65, 0.65); 
    cairo_set_antialias(cairo, CAIRO_ANTIALIAS_NONE); 
    cairo_set_line_width(cairo, 1); 
    cairo_move_to(cairo, x1, y1); 
    cairo_line_to(cairo, x2, y2); 
    cairo_stroke(cairo); 
    cairo_restore(cairo); 
} 

void 
draw_x(cairo_t *cairo, gint width, gint height) 
{ 
    gint size; 

    size = width/3.5; 

    cairo_save(cairo); 
    cairo_set_source_rgb(cairo, 0.25, 0.4, 1.0); 
    cairo_set_line_width(cairo, 2.5); 
    cairo_translate(cairo, width/2, height/2); 
    cairo_move_to(cairo, -size, -size); 
    cairo_line_to(cairo, +size, +size); 
    cairo_move_to(cairo, +size, -size); 
    cairo_line_to(cairo, -size, +size); 
    cairo_stroke(cairo); 
    cairo_restore(cairo); 
} 

void 
draw_o(cairo_t *cairo, gint width, gint height) 
{ 
    cairo_save(cairo); 
    cairo_set_source_rgb(cairo, 1.0, 0.25, 0.25); 
    cairo_set_line_width(cairo, 2.5); 
    cairo_arc(cairo, width/2, height/2, width/3, 0, 2.0 * M_PI); 
    cairo_stroke(cairo); 
    cairo_restore(cairo); 
} 

gboolean 
on_expose(GtkWidget *widget, GdkEventExpose *event, gpointer data) 
{ 
    GdkWindow *window; 
    cairo_t *cairo; 
    const struct GameData *game_data; 
    gint width; 
    gint height; 

    window = gtk_widget_get_window(widget); 
    cairo = gdk_cairo_create(window); 
    game_data = (const struct GameData *) data; 

    gdk_window_get_size(window, &width, &height); 

    if (game_data->row != 2) 
     draw_delmiter_line(cairo, 0, height, width, height); 
    if (game_data->column != 3) 
     draw_delmiter_line(cairo, width, 0, width, height); 

    if (game_data->value == X) 
     draw_x(cairo, width, height); 
    else if (game_data->value == O) 
     draw_o(cairo, width, height); 
    cairo_destroy(cairo); 
    return FALSE; 
} 

int 
main(int argc, char **argv) 
{ 
    GtkWidget *window; 
    GtkWidget *horizontal[3]; 
    GtkWidget *vertical; 
    struct GameData data[9]; 
    enum Player current_player; 
    gtk_init(&argc, &argv); 

    window = gtk_window_new(GTK_WINDOW_TOPLEVEL); 
    vertical = gtk_vbox_new(TRUE, 0); 
    for (size_t i = 0 ; i < 3 ; ++i) 
    { 
     horizontal[i] = gtk_hbox_new(TRUE, 0); 
     gtk_box_pack_start(GTK_BOX(vertical), horizontal[i], TRUE, TRUE, 0); 
    } 

    current_player = FirstPlayer; 
    for (size_t i = 0 ; i < 9 ; ++i) 
    { 
     GtkWidget *cell; 

     cell = gtk_drawing_area_new(); 
     data[i].value = Empty; 
     data[i].player = &current_player; 
     data[i].data = data; 
     data[i].row = i/3; 
     data[i].column = i % 3; 

     g_signal_connect(G_OBJECT(cell), "expose-event", G_CALLBACK(on_expose), &data[i]); 
     g_signal_connect(G_OBJECT(cell), "button-release-event", G_CALLBACK(on_click), &data[i]); 

     gtk_widget_add_events(cell, GDK_BUTTON_RELEASE_MASK | GDK_BUTTON_PRESS_MASK); 
     gtk_box_pack_start(GTK_BOX(horizontal[data[i].row]), cell, TRUE, TRUE, 0); 
    } 
    g_signal_connect(G_OBJECT(window), "destroy", G_CALLBACK(gtk_main_quit), NULL); 

    gtk_container_add(GTK_CONTAINER(window), vertical); 
    gtk_widget_set_size_request(window, 300, 300); 
    gtk_window_set_resizable(GTK_WINDOW(window), FALSE); 
    gtk_widget_show_all(window); 
    gtk_main(); 

    return 0; 
}