我使用int n定义了一个struct Board,其值是一个小整数。在gtk信号“clicked”调用此方法之前,board-> n具有正确的值。 但是,在调用此函数时,第一个printf语句打印出的n值非常大32665。
draw_token (GtkButton *button, cairo_t *cr, Board *board){
printf("n: %d\n", board->n);
printf("button clicked\n");
//parse label of a button into the corresponding column number
guint col = (int)strtol(gtk_button_get_label(button), NULL, 0);
if (make_move(board, col) == false){
printf("draw cairo\n");
}
}
结构:
typedef struct board Board;
struct board{
int k;
int n;
char *moves;
int player;
};
回调所在的函数:
void gui_make_buttons(GtkWidget *box, Board *board){
guint n = board->n;
for (int i = 1 ; i <= n ; i++){
GtkWidget *button = gtk_button_new();
//make label for button
char label[3];
sprintf(label, "%d", i-1);
gtk_button_set_label((GtkButton*)button,label);
// gtk_widget_show(button);
gtk_container_add(GTK_CONTAINER(box), button);
g_signal_connect(button, "clicked",G_CALLBACK(gui_draw_token), board);
}
}
有人可以向我解释为什么只要点击按钮,n的值就会变为像36751这样的大值? 非常感谢你
使用main完成代码 gui.c:
#include <stdio.h>
#include <stdlib.h>
#include <gtk/gtk.h>
#include <stdbool.h>
#include "gui.h"
#include "board.h"
#include "connect.h"
gboolean draw_board (GtkWidget *widget, cairo_t *cr, gpointer board){
guint width, height;
width = gtk_widget_get_allocated_width (widget);
height = gtk_widget_get_allocated_height (widget);
guint row = height/((Board*)board)->n;
guint col = width/((Board*)board)->n;
printf("%d\n", row);
printf("%d\n", col);
// cairo_set_source_rgb (cr, 100, 100, 255);
// cairo_paint (cr);
cairo_set_source_rgb(cr, 0, 0, 255);
for (int i = 1; i < ((Board*)board)->n ; i++){
//draw horizontal grids;
cairo_move_to (cr, 0, row*i);
cairo_line_to (cr, width, row*i);
//draw vertical grids;
cairo_move_to (cr, col*i, 0);
cairo_line_to (cr, col*i, height);
}
// cairo_arc (cr, 100, 100, 50, 0, 2 * G_PI);
// cairo_move_to (cr, 30, 30);
// cairo_line_to (cr, 50, 50);
cairo_stroke (cr);
return false;
}
int main (int argc, char *argv[]){
//check for correct number of arguments.
if (!check_argument(argc, argv))
return EXIT_FAILURE;
int k = strtol(argv[1], NULL, 0);
int n = strtol(argv[2], NULL, 0);
play_game(k, n);
return EXIT_SUCCESS;
}
//show widgets and get gtk going
CGUI *gui_start_gtk(Board *board){
//assigns board to the gui struct at beginning of game
CGUI *gui = make_gui (board);
// gtk_widget_queue_draw (gui->drawing_area);
// gui_draw_init_board(gui);
gtk_widget_show_all (gui->window);
gtk_main ();
return gui;
}
/*
void gui_draw_init_board(GtkWidget *widget, cairo_t *cr, CGUI *gui){
printf("HI\n");
if (gui) {
guint k = gui->board->k;
guint n = gui->board->n;
printf("%d\n", k);
}
}
*/
void gui_make_buttons(GtkWidget *box, Board *board){
// guint n = board->n;
for (int i = 1 ; i <= (board->n) ; i++){
GtkWidget *button = gtk_button_new();
//make label for button
char label[3];
// sprintf(label, "%d", i-1);
sprintf(label, "%d", i-1);
gtk_button_set_label((GtkButton*)button,label);
// gtk_widget_show(button);
gtk_container_add(GTK_CONTAINER(box), button);
g_signal_connect(button, "clicked",G_CALLBACK(gui_draw_token), board);
}
}
void gui_draw_token (GtkButton *button, cairo_t *cr, gpointer board){
printf("button clicked\n");
printf("n: %d\n", ((Board*)board)->n);
//parse label of a button into the corresponding column number
guint col = (int)strtol(gtk_button_get_label(button), NULL, 0);
printf("%d\n", col);
printf("n: %d\n", ((Board*)board)->n);
if (make_move(board, col) == false){
printf("draw cairo\n");
}
}
CGUI *make_gui(Board *board){
CGUI *gui = (CGUI*) malloc(sizeof(CGUI));
//assign variables to gui object
gui->board = board;
GtkWidget *window;
GtkWidget *frame;
GtkWidget *drawing_area;
gtk_init(NULL, NULL);
//set up initial window
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
gtk_window_set_title(GTK_WINDOW(window), "Connect-N-K");
gtk_window_set_default_size (GTK_WINDOW(window), 600, 650);
gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER);
gtk_widget_show(window);
g_signal_connect_swapped(G_OBJECT(window), "destroy",
G_CALLBACK(gtk_main_quit), gui);
// g_signal_connect (window, "draw", G_CALLBACK (gui_draw_buttons), board);
//create boxes to fit buttons and drawing area
GtkWidget *box = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0);
GtkWidget *draw_box = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0);
GtkWidget *button_box = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0);
//make all buttons take up even amount of space
gtk_box_set_homogeneous((GtkBox*)button_box, true);
gtk_widget_set_size_request(button_box, 600, 50);
// gtk_box_pack_start (box, window, false, false, false);
gtk_container_add(GTK_CONTAINER(window), box);
gtk_container_add(GTK_CONTAINER(box), draw_box);
gtk_container_add(GTK_CONTAINER(box), button_box);
//set up initial frame
frame = gtk_frame_new (NULL);
gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_IN);
gtk_widget_set_size_request(frame, 600, 600);
gtk_container_add(GTK_CONTAINER(draw_box), frame);
//create and pack buttons.
gui_make_buttons(button_box, board);
//set up drawing area
drawing_area = gtk_drawing_area_new ();
gtk_widget_set_size_request(drawing_area, 600, 600);
gtk_container_add (GTK_CONTAINER (frame), drawing_area);
g_signal_connect (drawing_area, "draw", G_CALLBACK (draw_board), board);
printf("n: %d\n", board->n);
// printf("board in gui: %d\n", *board);
gui->window = window;
gui->frame = frame;
gui->drawing_area = drawing_area;
/*
//show widgets
connect.c:
/* connect.c */
#include <stdlib.h>
#include <stdio.h>
#include <stdbool.h>
#include <string.h>
#include "gui.h"
#include "board.h"
#include "connect.h"
#define BUFFER_SIZE 10
/*
static int check_argument(int argc, char *argv[]);
static void play_game(int k, int n);
*/
/*
int main(int argc, char *argv[]){
//check for correct number of arguments.
if (!check_argument(argc, argv))
return EXIT_FAILURE;
int k = strtol(argv[1], NULL, 0);
int n = strtol(argv[2], NULL, 0);
play_game(k, n);
return EXIT_SUCCESS;
}
*/
int check_argument(int argc, char *argv[]){
if(argc < 3 || argc >3){
fprintf(stderr, "Parameters entered incorrectly. Input two integers for k and n respectively.\n");
return false;
}
else
return true;
}
//go through all steps of the game
void play_game(int k, int n){
//check to see if k and n are appropriate
if(k>n){
fprintf(stderr, "k is greater than n, game will never be won.\n");
return;
}
Board *board = make_board(k, n);
// print_board(board);//print initial board
//initiate gui
// CGUI *gui = make_gui();//set first three vars
// gui_set_board(gui, board);//set the fourth var
// CGUI *gui = gui_start_gtk(board);
// connect_play_game_text(board);
connect_play_game_gui(board);
/* int player = 1; //let first player go first
char *s = (char*)malloc(BUFFER_SIZE);//allocate memory for int to read
int move_result;
do{
fgets(s, BUFFER_SIZE, stdin);
int cols = strtol(s, NULL, 0);
move_result = make_move(board,cols,player);
//switch players if legal move and no one wins
if(move_result == false)
player = 3-player;
//do nothing is move is illegal(move_result = -1, thus letting
//the same player choose again.
}
while(move_result != true);
//free up resources
free(s);
destroy_board(board);
*/
}
int connect_play_game_gui(Board *board){
printf("n in connect: %d\n", board->n);
CGUI *gui = gui_start_gtk(board);
// gui_set_board(gui, board);//set the fourth var
// int player = 1; //let first player go first
// char *s = (char*)malloc(BUFFER_SIZE);//allocate memory for int to read
// int move_result;
// fgets(s, BUFFER_SIZE, stdin);
// int cols = strtol(s, NULL, 0);
// move_result = make_move(board,cols,player);
//switch players if legal move and no one wins
// if(move_result == false){
// player = 3-player;
return true;
// }
//do nothing if move is illegal(move_result = -1, thus letting
//the same player choose again.
// while(move_result != true);
//free up resources
// free(s);
// destroy_board(board);
}
int connect_make_move_gui(int col, Board *board, int player){
return 1;
}
void connect_play_game_text(Board *board){
print_board(board);//print initial board
char *s = (char*)malloc(BUFFER_SIZE);//allocate memory for int to read
int move_result;
do{
fgets(s, BUFFER_SIZE, stdin);
int cols = strtol(s, NULL, 0);
move_result = make_move(board,cols);
}
while(move_result != true);
//free up resources
free(s);
destroy_board(board);
}
//initiate gui
//static void connect_init_gui
board.c:
#include <stdlib.h>
#include <stdio.h>
#include <stdbool.h>
#include <string.h>
#include "board.h"
#define DRAW 2
#define ILLEGAL_MOVE -1
static char set_player_char(int player);
static int check_draw(Board *board);
//make a new board
Board *make_board(int k, int n){
Board *board = (Board *) malloc(sizeof(Board));
board->moves = (char *)malloc(n*n);
(board->k) = k;
(board->n) = n;
board->player = 1;
//make an array of empty slots based of size n^2
for(int i = 0; i < n*n; i++){
board->moves[i] = '.';
}
return board;
}
//print board with updated moves, print last row first.
void print_board(Board *board){
int n = board->n;
//loop through each row
for(int i = n-1; i >= 0; i--){
//loop through each column
for(int j = 0; j<n; j++){
printf("%c", (board->moves)[i*n+j]);
printf(" ");//add space between columns
}
printf("\n"); //wrap around each row
}
printf("\n");
}
//set char for player
static char set_player_char(int player){
char player_char;
if (player == 1)
player_char = 'o';
else
player_char = '*';
return player_char;
}
//update board based on player's input, return the row move is made
int make_move(Board *board, int x){
printf("inmakemove n: %d\n", board->n);
// printf("board in make_move: %d\n", &board);
//if move is illegal, return
if (!check_legal_move(board, x))
return ILLEGAL_MOVE;
int n = board->n;
int row;
//loop through the rows of the given column to find an empty spot.
for (int i = 0; i < n; i++){
if ((board->moves)[i*n+x] == '.'){
(board->moves)[i*n+x] = set_player_char(board->player);
row = i;
break;
}
}
print_board(board);
//Check to see if a player has won the game.;
int stat = check_win(board, x, row);
if (stat == true){
fprintf(stdout, "Player %d won the game.\n", board->player);
return true;
}
//if all slots are filled, game is a draw.
if(stat == DRAW){
fprintf(stdout, "Game was a draw.\n");
return true;
}
//if no one won, game continues.
else{
board->player = 3-(board->player);
return false;
}
}
//check to see if move x is legal
int check_legal_move(Board *board, int x){
int n = board->n;
//see if column entered is legal.
if (x >= (board->n) || x<0){
fprintf(stderr, "Illegal move by player %d at column %d\
, number entered outside range of available columns.\n", board->player, x);
return false;
}
//see if column entered is already filled
if ((board->moves)[(n-1)*n+x] != '.'){
fprintf(stderr, "Illegal move by player %d at column %d\
, column is already filled.\n", board->player, x);
return false;
}
return true;
}
//check for winning move
int check_win(Board* board, int x, int row){
int n = board->n;
int k = board->k;
int current_move = row*n+x; //slot that the current move fills
char *moves = board->moves;
char player_char = set_player_char(board->player);
int score;
score = 1;
//Check to see how many continuous slots are filled with the current player'
//s token horizontally.
//going right
for (int i = 1; i<k && x+i<n; i++){
if(moves[current_move+i] == player_char)
score ++;
else
break;
}
//going left
for(int i = 1; i<k && x-i>=0; i++){
if(moves[current_move-i] == player_char)
score++;
else
break;
}
//if horizontally connect to k, the player wins.
if (score>=k)
return true;
//if not, check vertical.
score = 1;
//going up
for (int i = 1; i<k && row+i<n; i++){
if(moves[current_move+n*i] == player_char)
score ++;
else
break;
}
//going down
for(int i = 1; i<k && row-i>=0; i++){
if(moves[current_move-n*i] == player_char)
score ++;
else
break;
}
//if vertically connect to k, the player wins.
if (score>=k)
return true;
//if not, check rising to right diagnol. Reset score like previously.
score = 1;
//going right and up
for(int i = 1; i<k && row+i<n && x+i<n; i++){
if(moves[current_move+n*i+i] == player_char)
score ++;
else
break;
}
//going left and down
for(int i = 1; i<k && row-i>=0 && x-i>=0; i++){
if(moves[current_move-n*i-i] == player_char)
score ++;
else
break;
}
//if right diagonally connect to k, the player wins.
if (score>=k)
return true;
//if not, check left rising diagonal.
score = 1;
//check right and down
for(int i = 1; i<k && x+i<n && row-i>=0; i++){
if(moves[current_move-n*i+i] == player_char)
score ++;
else
break;
}
//check left and up
for(int i = 1; i<k && x-i>=0 && row+i<n; i++){
if(moves[current_move+n*i-i] == player_char)
score ++;
else
break;
}
//if left diagonally connect to k, the player wins.
if (score>=k)
return true;
if(check_draw(board))
return DRAW;
//if no k connect is made in any direction, game is not won.
return false;
}
//check to see if game has come to a draw
static int check_draw(Board *board){
int n = board->n;
//loop through the top row to see if there are any empty slots left
for (int i = 0; i<n; i++){
if((board->moves)[n*(n-1)+i] == '.')
return false;
}
//if no empty slots left, game was a draw.
return true;
}
//Free up resources.
void destroy_board(Board *board){
free(board->moves);
free(board);
}
对不起,这很长很麻烦,我还在处理代码和C新手。
答案 0 :(得分:1)
不是我知道gtk,而是一个快速谷歌,看起来,你在回调中得到的棋盘实际上并不是你传递的棋盘。您点击的活动的回调签名不正确
它应该看起来有点像void button_clicked(GtkWidget *widget, gpointer data)
答案 1 :(得分:1)
您需要将void gui_draw_token (GtkButton *button, cairo_t *cr, gpointer board)
更改为void gui_draw_token (GtkButton *button, gpointer board)
你不能只是编写回调签名并希望事情有效。对于签名,您需要查看适合信号的文档。例如,在本例中为GtkButton clicked signal文档。
如果您要删除所有不必要的代码并注释掉代码,这也有助于我们回答您的问题。
答案 2 :(得分:0)
char label[3]
已在圈外初始化,他正在更新label[0]
三次,从而导致label[1]
和label[2]
<的未定义输出/ p>
这就是我粗略看一下739782781行代码所得到的。对大家抱歉。
您没有告诉label
在sprintf
char label[3];
sprintf(label, "%d", i-1);
^ is wrong
应该是
char label[3];
sprintf(label[n-1], "%d", i-1);
我想。