PDA

View Full Version : سوال: مشکل در انجام بازی پازل



sjhosseini
چهارشنبه 06 خرداد 1388, 10:43 صبح
سلام
من یه بازی پازل به زبان سی دارم که با استفاده از صف ها انجام میشه.
می خوام این بازی رو به سی شارپ تبدیل کنم در تبدیل اون هم دچار مشکل شدم . فکر میکنم تبدیل اشاره گرها رو بدرستی انجام ندادم.
این کد سی بازی پازل

#include <graphics.h>
#include <time.h>
#include <stdlib.h>
#include <conio.h>
#include <values.h>
#include <alloc.h>
#include <dos.h>

/* Define maximum depth of the tree */
#define MAXDEPTH 12

int count=0;
int Kg=0;

enum DIR {LEFT, RIGHT, UP, DOWN}; /* Enumerate directions */
struct queue
{
char m[3][3]; /* stores the 3 X 3 matrix; used char to save space */
int parent; /* index no. of the node's parent in the queue */
char level; /* level of the node in the tree */
char r8, c8; /* row, column no. of the blank tile */
enum DIR action; /* stores what direction was taken to reach
current state. Used for avoiding 'undoing' and
for displaying */
};

/* Global Varibles */

struct queue *q; /* stores the states of the BFS tree */
int front, rear; /* point to the front and rear of the queue */
int path[MAXDEPTH]; /* stores the path from the root to the leaf
that was selected by the heuristic */
enum DIR valid[5]; /* valid[1] thru valid[4] store the directions
the blank tile can take from the current state.
Moves that cause 'undoing' are invalid.
valid[0] stores the number of such valid moves */

/* Function Declarations */

void init(void);
void get_valid_moves(void);
void jumble(void);
void move(enum DIR dir);
void move_rear(enum DIR dir);
int iswin(void);
int heuristic(int n);
void getpath(int i, int *k);
void init_display(void);
void display(int n, unsigned int no_moves);

/* Main Function */

int main(void)
{
int gd = VGA, gm = VGAHI;
int hval, hmin, leaf_level;
int i, j, k, next_node, next_node2, next_node3;
unsigned int no_moves=0, no_moves2=0;
enum DIR d;

init(); /* initializations */
randomize(); /* initialize the random no. generator */
jumble(); /* randomize the matrix */

initgraph(&gd, &gm, "");
if(graphresult() != grOk)
{
cprintf("Error: Graphics could not be initialised\r\n");
free(q);
return 1;
}
init_display(); /* display the initial position */
getch();

q[0].action = -1;

while(1)
{
/* construct the BFS tree upto MAXDEPTH levels */
for(rear=1, front=0; q[front].level < MAXDEPTH-1; front++)
{
get_valid_moves(); /* stores valid moves in array 'valid[]'
valid[0] contains number of valid moves */
for(j=1; j<=valid[0]; j++) /* for each valid child, do */
{
move_rear(valid[j]); /* Add the next valid state to
the rear of the queue */
q[rear].parent = front; /* Note its parent's index in the q */
/* child's level is one more than parent's */
q[rear].level = q[front].level + 1;
if(iswin()) /* if game is won, then */
{
k = 0;
getpath(rear, &k); /* get path from root to leaf (goal state) */
for(i=0; i<k; i++) /* Display the moves one by one */
display(path[i], ++no_moves);

free(q); /* clean up */
getch();
closegraph();
return 0;
}
rear++;
}
}
/* finished expanding tree to MAXDEPTH levels */

leaf_level = q[rear-1].level;
/* for all leaves apply the heuristic to find the successor */
for(hmin=MAXINT, i=rear-1; ; i--)
{
if(q[i].level != leaf_level) /* check if it is leaf */
break;
hval = heuristic(i); /* apply heuristic and get its value */
if(hval < hmin)
{
hmin = hval; /* find the minimum hueristic value */
next_node3 = next_node2; /* find the 3rd best node */
next_node2 = next_node; /* find the 2nd best node */
next_node = i; /* find the best node's index in q */
}
}

/* If game not over in 150 moves, maybe caught in loop.
Try to come out of loops by selecting 2nd best or 3rd best node */
if(no_moves2 > 150)
{
no_moves2 = 0;
next_node = random(2) ? next_node2 : next_node3;
}
k = 0;
getpath(next_node, &k);

no_moves2 += k;
for(i=0; i<k; i++)
{
display(path[i], ++no_moves);
// printf("%d ",path[i]);
}

/* make the selected leaf node as the next root node */
q[0] = q[next_node];
q[0].parent = -1;
q[0].level = 0;
} /* end of while(1) */
}

void init(void)
{
int i, j;

/* Allocate memory for the queue */
q = (struct queue *) malloc(sizeof(struct queue) * 2048);
if(q == NULL)
{
closegraph();
cprintf("\r\nError: Not enough memory\r\n");
exit(1);
}

/* initialize the matrix to the correct order */
for(i=0; i<3; i++)
for(j=0; j<3; j++)
q[0].m[i][j] = i * 3 + j;

front = 0;
rear = 1;
q[0].action = -1;
q[0].r8 = q[0].c8 = 2; /* Note the position of the blank tile */
q[0].parent = -1;
q[0].level = 0;
}

void jumble(void)
{
int i, j;

j = 150 + random(50);
for(i=0; i<j; i++)
{
get_valid_moves();
move(valid[random(valid[0]) + 1]);
}
}

void get_valid_moves(void)
{
valid[0] = 0;


/*The 'if' conditions are for avoiding undoing */
switch(q[front].r8)
{
case 1: if(q[front].action != DOWN) valid[++valid[0]] = UP;
case 0: if(q[front].action != UP) valid[++valid[0]] = DOWN; break;
case 2: if(q[front].action != DOWN) valid[++valid[0]] = UP;
}
switch(q[front].c8)
{
case 1: if(q[front].action != RIGHT) valid[++valid[0]] = LEFT;
case 0: if(q[front].action != LEFT) valid[++valid[0]] = RIGHT; break;
case 2: if(q[front].action != RIGHT) valid[++valid[0]] = LEFT;
}
}

void move(enum DIR dir)
{
int r, c;

switch(dir)
{
case UP : r = -1; c = 0; break;
case LEFT : r = 0; c = -1; break;
case DOWN : r = 1; c = 0; break;
case RIGHT: r = 0; c = 1; break;
}

q[front].action = dir;
/* fill the blank tile */
q[front].m[q[front].r8][q[front].c8] = q[front].m[q[front].r8+r][q[front].c8 + c];
/* assign new blank tile and its position */
q[front].r8+=r;
q[front].c8+=c;
q[front].m[q[front].r8][q[front].c8] = 8;
}

int iswin(void)
{
int i, j;

for(i=0; i<3; i++)
for(j=0; j<3; j++)
if(q[rear].m[i][j] != i * 3 + j)
return 0;
return 1;
}

void move_rear(enum DIR dir)
{
int i, j, r, c;

for(i=0; i<3; i++)
for(j=0; j<3; j++)
q[rear].m[i][j] = q[front].m[i][j];

switch(dir)
{
case UP : r = -1; c = 0; break;
case LEFT : r = 0; c = -1; break;
case DOWN : r = 1; c = 0; break;
case RIGHT: r = 0; c = 1; break;
}

q[rear].action = dir;
/* fill the blank tile */
q[rear].m[q[front].r8][q[front].c8] = q[rear].m[q[front].r8+r][q[front].c8 + c];
/* assign new blank tile and its position */
q[rear].m[q[rear].r8 = q[front].r8 + r][q[rear].c8 = q[front].c8 + c] = 8;
}
/////....................................
int heuristic(int n)
{
/* This heuristic returns the sum of (the difference between the
row positions of the number in current postion and in goal position
+ the similar difference in the column positions) for all 9 tiles.
So the heuristic value for goal state is zero.
Hence minimize the heuristic value.
*/
int i, j, diff;

for(diff=i=0; i<3; i++)
for(j=0; j<3; j++)
diff += abs(q[n].m[i][j] / 3 - i) + abs((q[n].m[i][j] % 3) - j);
return diff;
}

void getpath(int i, int *k)
{
if(q[i].parent != 0)
getpath(q[i].parent, k);
path[*k] = i;
(*k)++;
// printf("i=%d,p=%d,k=%d ",i,path[*k],*k);
}

void init_display(void)
{
int i, j, i50, j50;
char num[2];

setlinestyle(SOLID_LINE, 0, THICK_WIDTH);
setcolor(LIGHTCYAN);
rectangle(243, 163, 396, 316);
settextstyle(7, HORIZ_DIR, 5);
settextjustify(CENTER_TEXT, CENTER_TEXT);
setfillstyle(SOLID_FILL, BLUE);
for(i=0; i<3; i++)
for(j=0; j<3; j++)
{
i50 = i * 50;
j50 = j * 50;
if(q[0].m[i][j] != 8)
{
itoa(q[0].m[i][j] + 1, num, 10);
setcolor(3);
rectangle(246 + j50, 166 + i50, 293 + j50, 213 + i50);
bar(248 + j50, 168 + i50, 291 + j50, 212 + i50);
}
else
{
num[0] = ' ';
num[1] = '\0';
}
setcolor(WHITE);
outtextxy(270 + j50, 186 + i50, num);
}
settextjustify(LEFT_TEXT, TOP_TEXT);
settextstyle(6, HORIZ_DIR, 1);
setfillstyle(EMPTY_FILL, BLACK);
setcolor(YELLOW);
outtextxy(235, 350, "Number of moves: 0");
}

void display(int n, unsigned int no_moves)
{
char image[1406];
char no_moves_c[33];
int i50, j50, dx, dy, k;

sprintf(no_moves_c, "%4u", no_moves);
bar(370, 350, 410, 380);
outtextxy(370, 350, no_moves_c);

j50 = q[n].r8 * 50;
i50 = q[n].c8 * 50;
getimage(245 + i50, 165 + j50, 294 + i50, 214 + j50, image);

dx = dy = 0;
switch(q[n].action)
{
case LEFT: dx = 10; break;
case RIGHT: dx = -10; break;
case UP: dy = 10; break;
case DOWN: dy = -10; break;
}

for(k=0; k<5;)
{
putimage(245 + i50 + k*dx, 165 + j50 + k*dy, image, XOR_PUT);
k++;
putimage(245 + i50 + k*dx, 165 + j50 + k*dy, image, COPY_PUT);
delay(25);
}
delay(45);
}



البته برای اجرای بازی هم حتما باید فایل رو با پسوند سی ذخیره کنید.

بازی رو که به سی شارپ تبدیل کردم هم بصورت ضمیمه گذاشتم. البته تا یه جاهای تونستم درست کنم واسه همین بازی هم تا یه جاهای اجرا میشه.
توی کد سی از تابع بازگشتی استفاده شده که پارامتر اشاره گر داره . تابع getpath
بعدش هم اینکه ابتدای برنامه از نوع ساختار صف یه اشاره گر تعریف کرده و فضای رو هم به این اشاره گر داده با این خط کد:

q = (struct queue *) malloc(sizeof(struct queue) * 2048);
خب اولا که من نتونستم معادل چنین خطی رو توی سی شارپ پیدا کنم. تمامی پست های مربوط به اشاره گرها رو هم توی سایت برنامه نویس یا سایت های دیگه مطالعه کردم اما اکثرا توصیه به این شده که از اشاره گر ها استفاده نشه.
خب من به جای اینکه از اشاره گر برای ساختار استفاده کنم از یک آرایه با طول زیاد برای اینکار استفاده کنم. که همین عمل رو توی کد سی پیاده کردم ولی کد سی اجرای غلط میداد. یعنی برنامه طوری نوشته شده که حتما باید اشاره گری از ساختار وجود داشته باشه.

لطفا اگه کسی میتونه منو توی انجام بازی کمک کنه خواهش میکنم دریغ نکنه

sjhosseini
چهارشنبه 06 خرداد 1388, 18:21 عصر
کسی نیست جواب سوال ما رو بدونه؟
خواهش میکنم اگه کسی میدونه دریغ نکنه؟؟؟؟؟؟؟؟

SMRAH1
پنج شنبه 07 خرداد 1388, 15:11 عصر
سلام

بسته به پیاده سازی کمی متفاوت است (این که در پیاده سازی C# برای queue ،ساختار در نظر بگیریم یا کلاس).با این حال یک نمونه تبدیل شده این کد به فرم تحت C# رو انجام دادم.
به نظر این گونه پروژه ها،برای دوستانی که با محیط گرافیکی TC آشنا هستند و می خواهند به #C یا VC مهاجرت کنند،گزینه های مناسبی برای تبدیل به پروژه #C هستند.

سعی کردم ساختار کلی برنامه رو حفظ کنم ولی به فراخور تفاوت های ذاتی #C با ++C ،تغییراتی در برنامه داده ام.

موفق باشید

msh1992
پنج شنبه 09 خرداد 1392, 12:16 عصر
سلام
کسی میتونه بگه مشکل graphics.h در ++visual c چیه من هر کاری کردم باز هم error میده چی کار کنم معادل داره