我正在做一个Tic-Tac-Toe游戏作为学校项目。我在3行中设置了9个按钮,因此每当用户点击其中一个按钮时,其标签就会以纯文本形式更改为X或O.
我想知道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 :(得分:0)
您可以试试这个,我使用"expose-event"
绘制X
和O
以及一个空单元格,以防用户尚未点击它并且还使用了简单的功能来检查胜利者。通过将数据传递给事件处理程序来设置单元格值。
"button-release-event"
允许您在单击某个单元格时执行某些操作,然后您可以将下一轮转到另一个玩家,并将X
或O
设置为所单击的单元格,具体取决于当它被陈词滥调时哪个玩家转过来。
检查
#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 = ¤t_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;
}