انجمنهای فارسی اوبونتو
کمک و پشتیبانی => برنامهسازی => نویسنده: learner:~$ در 02 امرداد 1403، 04:32 بظ
-
درود
دارم <بازی پیتزا خور فضایی> که جادی با زبان پایتون نوشته رو با زبان سی پیاده سازی میکنم اما با ۳ تفاوت:
۱: از اشاره گر ها و ساختار ها برای درک بهتر و یاد گیری استفاده کنم حتی با اینکه لازم نداشته باشم.
۲: سعی کنم از این بازی رو با چندین کتابخانه دیگه پیاده سازی کنم.
۳:با کتابخانه ncurses بیشتر آشنا بشم .
-----
خب من قبلا این بازی رو تا حدی جلو بردم اما الان به چندتا مشکل اساسی برخوردم:
۱: زبان سی از اسکی پشتیبانی میکنه نه از utf-8 که این کار رو برای پیاده سازی سخت میکنه.
۲: هوش مصنوعی و دشمن های بازی
اینها مشکلات اسای بود که فکر میکردم با اون ها برخورد میکنم اما در کمال تعجب به یک و چند مشکل دیگه خوردم که ۲ روزه دارم روی اون مشکل ها وقت میزارم اما حل نشده:
۱: کشیدن جهان
۲: حرکت دادن بازیکن بدون نابودی جهان!
-------------------------------------
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <ncurses.h>
struct postion
{
int player_x;
int player_y;
}*player;
void draw_wall(int);
int main()
{
int playing = 1;
player = malloc(sizeof(*player));
initscr();
cbreak();
keypad(stdscr, 1);
curs_set(0);
noecho();
clear();
refresh();
player->player_x = COLS /2;
player->player_y = LINES /2;
clear();
mvprintw(player->player_y, player->player_x, "x");
refresh();
draw_wall(10);
refresh();
char ch;
while (playing)
{
ch = getchar();
switch (ch)
{
case 'w':
player->player_y -=1;
break;
case 's':
player->player_y +=1;
break;
case 'a':
player->player_x -=1;
break;
case 'd':
player->player_x +=1;
break;
case 'q':
playing = 0;
default:
continue;
}
mvprintw(player->player_y, player->player_x, "x");
refresh();
}
refresh();
endwin();
free(player);
return 0;
}
void draw_wall(int count)
{
const int spawn_x = COLS /2;
const int spawn_y = LINES /2;
srand(time(NULL));
initscr();
clear();
noecho();
cbreak();
curs_set(0);
int x, y;
for (int i = 0; i < count; i++)
{
x = rand()% (COLS - 1);
if(spawn_x == x)
continue;
y = rand()% (LINES -1);
if(spawn_y == y)
continue;
mvprintw(y, x, "><");
}
refresh();
endwin();
}
البته این نسخه نهایی نیست و باز هم نیاز به تغیرات داره با هر تغیر من کد جدید رو میفرستم.
کسانی هم که دوست دارند از این برنامه استفاده بکنند میتوانند با دستور:
gcc your_file_name -lncurses
بهره مند بشوند:)
-
دوستان من میتونم تابع کشیدن جهان و موانع رو داخل یک حلقه بندازم و داخل اون حلقه clear رو اضافه کنم که صفحه رو هربار پاک کنه ولی این خوب نیست:
۱: دنیای خوبی نمیشه
۲: جهان و موانع من هر ثانیه در حال حرکت هستند!
پس باید سعی کنم که یک جهان ثابت بکشم و بازیکن من در اون جهان درحال حرکت باشه ولی خب قبلا از این مشکلات نبود سری آخر که اینکار رو کردم اینطوری نمیشد.
-
برنامه رو پاک کردم وقصد دارم از اول بنویسم. تسلیم نخواهم شد 8)
-
خب نمیدونم خوشبختانه یا متاسفانه به نتایج جالبی دست یافتم
#include <stdio.h>
#include <ncurses.h>
#include <time.h>
#include <stdlib.h>
struct posions
{
int colmn;
int lines;
};
void spawn(int);
int main()
{
struct posions* player = NULL;
initscr();
int playing = TRUE;
player = malloc(sizeof(*player));
player->colmn = COLS /2;
player->lines = LINES /2;
clear();
cbreak();
noecho();
curs_set(0);
char ch;
while (playing)
{
spawn(20);
refresh();
ch = getchar();
switch (ch)
{
case 'w':
player->lines -= 1;
break;
case 's':
player->lines += 1;
break;
case 'a':
player->colmn -= 1;
break;
case 'd':
player->colmn += 1;
break;
case 'q':
playing = FALSE;
default:
continue;
}
clear();
mvprintw(player->lines, player->colmn, "*");
refresh();
}
getch();
free(player);
endwin();
return 0;
}
void spawn(int count)
{
int x, y;
const int spawn_x = COLS /2;
const int spawn_y = LINES /2;
for(int i = 0; i<count; i++)
{
x = rand() % (COLS -1);
if(x == spawn_x)
continue;
y = rand() % (LINES -1);
if(y == spawn_y)
continue;
mvprintw(y, x, ".");
}
refresh();
}
واقعا گیج شدم.
اما باز هم جای کار داره من نمیخوام جهانم این شکلی بشه.
-
موفق شدم!!!!
#include <stdio.h>
#include <ncurses.h>
#include <time.h>
#include <stdlib.h>
struct posions
{
int colmn;
int lines;
};
void spawn(int);
int main()
{
struct posions* player = NULL;
initscr();
int playing = TRUE;
player = malloc(sizeof(*player));
player->colmn = COLS /2;
player->lines = LINES /2;
clear();
cbreak();
noecho();
curs_set(0);
refresh();
char ch;
while (playing)
{
ch = getchar();
switch (ch)
{
case 'w':
player->lines -= 1;
break;
case 's':
player->lines += 1;
break;
case 'a':
player->colmn -= 1;
break;
case 'd':
player->colmn += 1;
break;
case 'q':
playing = FALSE;
default:
continue;
}
clear();
spawn(20);
mvprintw(player->lines, player->colmn, "*");
refresh();
}
getch();
free(player);
endwin();
return 0;
}
void spawn(int count)
{
srandom(COLS && LINES);
int x, y;
const int spawn_x = COLS /2;
const int spawn_y = LINES /2;
for(int i = 0; i<count; i++)
{
x = rand() % (COLS -1);
if(x == spawn_x)
continue;
y = rand() % (LINES -1);
if(y == spawn_y)
continue;
mvprintw(y, x, ".");
}
refresh();
}
اهداف بعدی:
۱: بر طرف کردن باگ تابع اسپاون.
۲: برطرف کردن باگ کلید q
۳: استفاده از رنگ
۴:تلاش برای ساخت دشمنان
۵: محدود کردن بازیکن به و خارج نشدن آن از صفحه
۶: پیدا کردن یک راه حل برای استفاده از کاراکتر های utf-8 یا unicode مثل پایتون
۷: تلاش برای رد نشدن بازیکن از موانع
-
باگ تابع اسپاون برطرف شد به خاطر الگوریتم بنده بود تغیر دیگری هم که دادم استفاده از goto به جای continue در تابع اسپاون هست:
#include <stdio.h>
#include <ncurses.h>
#include <time.h>
#include <stdlib.h>
struct posions
{
int colmn;
int lines;
};
void spawn(int);
void cheaker(struct posions*);
int main()
{
struct posions* player = NULL;
initscr();
int playing = TRUE;
player = malloc(sizeof(*player));
player->colmn = COLS /2;
player->lines = LINES /2;
clear();
cbreak();
noecho();
curs_set(0);
refresh();
char ch;
while (playing)
{
spawn(30);
ch = getchar();
switch (ch)
{
case 'w':
player->lines -= 1;
break;
case 's':
player->lines += 1;
break;
case 'a':
player->colmn -= 1;
break;
case 'd':
player->colmn += 1;
break;
case 'q':
playing = FALSE;
default:
continue;
}
clear();
mvprintw(player->lines, player->colmn, "*");
cheaker(player);
refresh();
}
getch();
free(player);
endwin();
return 0;
}
void spawn(int count)
{
srandom(COLS && LINES);
int x, y;
const int spawn_x = COLS /2;
const int spawn_y = LINES /2;
for(int i = 0; i<count; i++)
{
sp_x:
x = rand() % (COLS -1);
if(x == spawn_x)
goto sp_x;
sp_y:
y = rand() % (LINES -1);
if(y == spawn_y)
goto sp_y;
mvprintw(y, x, ".");
}
refresh();
}
void cheaker(struct posions* player)
{
if (player->colmn > COLS +1)
player->colmn -= 2;
}
هدف بعدی: برطرف کردن باگ کلید q
-
از اونجایی که نتونستم این باگ کلید q رو برطرف بکنم پس کاری کردم که بهتر به نظر بیاد پس به عنوان فیچر به برنامه اضافه میکنیم! ;D
#include <stdio.h>
#include <ncurses.h>
#include <time.h>
#include <stdlib.h>
struct posions
{
int colmn;
int lines;
};
void spawn(int);
int main()
{
struct posions* player = NULL;
initscr();
int playing = TRUE;
player = malloc(sizeof(*player));
player->colmn = COLS /2;
player->lines = LINES /2;
clear();
cbreak();
noecho();
curs_set(0);
refresh();
char ch;
while (playing)
{
spawn(30);
ch = getchar();
switch (ch)
{
case 'w':
player->lines -= 1;
break;
case 's':
player->lines += 1;
break;
case 'a':
player->colmn -= 1;
break;
case 'd':
player->colmn += 1;
break;
case 'q':
playing = FALSE;
break;
default:
continue;
}
clear();
mvprintw(player->lines, player->colmn, "*");
refresh();
}
getch();
free(player);
endwin();
return 0;
}
void spawn(int count)
{
srandom(COLS && LINES);
int x, y;
const int spawn_x = COLS /2;
const int spawn_y = LINES /2;
for(int i = 0; i<count; i++)
{
sp_x:
x = rand() % (COLS -1);
if(x == spawn_x)
goto sp_x;
sp_y:
y = rand() % (LINES -1);
if(y == spawn_y)
goto sp_y;
mvprintw(y, x, ".");
}
refresh();
}
تنها تغیری که کرده اینه که وقتی کلید q رو برای بار اول میزنید صفحه پاک میشه و با q دوم برنامه خاتمه پیدا میکنه.
هدف بعدی: استفاده از رنگ
-
خب حالا رنگ رو اضافه کردم نوشته بود قرمز میشه ولی قهوه ایی شد. خیلی بهتر از اون چیزی که فکرش رو میکردم شد(فقط موانع رو رنگی کردم ) اگر رنگ و ترکیبی مد نظذتون هست حتما بگید.
#include <stdio.h>
#include <ncurses.h>
#include <time.h>
#include <stdlib.h>
struct posions
{
int colmn;
int lines;
};
void spawn(int);
int main()
{
struct posions* player = NULL;
initscr();
int playing = TRUE;
player = malloc(sizeof(*player));
player->colmn = COLS /2;
player->lines = LINES /2;
clear();
cbreak();
noecho();
curs_set(0);
refresh();
char ch;
while (playing)
{
spawn(30);
ch = getchar();
switch (ch)
{
case 'w':
player->lines -= 1;
break;
case 's':
player->lines += 1;
break;
case 'a':
player->colmn -= 1;
break;
case 'd':
player->colmn += 1;
break;
case 'q':
playing = FALSE;
break;
default:
continue;
}
clear();
mvprintw(player->lines, player->colmn, "*");
refresh();
}
getch();
free(player);
endwin();
return 0;
}
void spawn(int count)
{
start_color();
init_pair(1, COLOR_RED, COLOR_BLACK);
attrset(A_BOLD | COLOR_PAIR(1));
srandom(COLS && LINES);
int x, y;
const int spawn_x = COLS /2;
const int spawn_y = LINES /2;
for(int i = 0; i<count; i++)
{
sp_x:
x = rand() % (COLS -1);
if(x == spawn_x)
goto sp_x;
sp_y:
y = rand() % (LINES -1);
if(y == spawn_y)
goto sp_y;
mvprintw(y, x, ".");
}
refresh();
attroff(A_BOLD | COLOR_PAIR(1));
}
هدف بعدی: اسپاون کردن دشمنان
-
خب دقیقا نمیدونم باید چطوری دشمن های بازی رو پیاده سازی کنم اما واسه اسپاون کردن این دشمن ها در ساده ترین حالت چندتا مشکل وجود داره:
۱: دشمن ها نباید توی محلی که موانع هستند اسپاون بشوند.
۲: دشمن ها نباید در موقعیت مرکزی یعنی جایی که بازیکن من هست قرار بگیر.
۳: دشمن ها نباید بین گوشه ها و صفحه میانی قرار بگیرند.
----
سخت ترین کار اینه که دشمن ها نباید روی موانع اسپاون بشوند. صبح یک تابع نوشتم بدون اینکه چیزی رو بفهمم اما همینطوری قرارش میدم:
void enemy_spawn(int count ,int* x , int* y)
{
int cols, lines;
srandom(COLS && LINES);
for(int i = 0; i < count;i++)
{
cols = rand() % (COLS -1);
if(cols == *x)
continue;
lines = rand() % (LINES -1);
if(lines == *y)
continue;
mvprintw(lines, cols, "&");
}
refresh();
}
void spawn(int count, int* colmn ,int* lines)
{
srandom(COLS && LINES);
int x, y;
const int spawn_x = COLS /2;
const int spawn_y = LINES /2;
for(int i = 0; i<count; i++)
{
x = rand() % (COLS -1);
if(x == spawn_x)
continue;
*colmn = x;
y = rand() % (LINES -1);
if(y == spawn_y)
continue;
*lines = y;
mvprintw(y, x, ".");
}
refresh();
}
منطق من این بود که بعد از هربار اجرای تابع اسپاون موقعیت جدیدی از موانع به ووجود میان. به خاطر همین سعی میکردم این تابع enemy-spawn و تابع اسپاون رو در یک حلقه بفرستم.
البته با استفاده از دو اشاره گر x, y منو دریافت میکرد. توضیح دادنش خیلی سخت تر از عملی کردنش هست.
اما منطق جدید بنده به این صورت هست:
که تمام موقعیت هایی که در نقطه x قرار دارند رو در یک آرایه ذخیره بکنه و برای y ها هم به همین صورت اما این منطق دارای یک مشکل اساسی هست اونم اینه که برنامه و منطق پیچیده میشه و همچنین کند تر میشه. اگر میتونستم از hashmap ها یا تاپل استفاده کنم عالی میشد. به نظرم میتونم از یک آرایه دو بعدی استفاده بکنم که کار راحت تر بشه اما پیاده سازی این کار رو بلد نیستم ولی ترس نداره.
-
خب دوستان بیاید از یک منطق ساده تر استفاده کنیم.
منطق خیلی راحتیه:
یک تابع مینویسم که ۵ تا دشمن رو اسپاون بکنه و اگر در اون موقعیت کاراکتری برابر نقطه یا استریک ( همون ستاره ) شد continue بکنه و دوباره انجامش بده. به نظر که خیلی قابل فهمه ولی امیدوارم جواب بده. دوستان مشکل استفاده از کاراکتر های یونیکد هم حل شد میتونم خیلی زیبا موانع رو ایجاد کنم
-
خب خیلی عجیبه این تابع کار نمیکنه!!! دیگه نمیدونم باید چیکار کنم و متاسفانه مشکل کاراکتر های یونیکد برگشته!
-
خب تونتسم دشمنان خودم رو اسپاون کنم ولی نه اونطوری که دوست داشتم:( :
#include <stdio.h>
#include <ncurses.h>
#include <time.h>
#include <stdlib.h>
struct posions
{
int colmn;
int lines;
};
void spawn(int);
void enemy_spawn(int);
int main()
{
struct posions* player = NULL;
initscr();
int playing = TRUE;
player = malloc(sizeof(*player));
player->colmn = COLS /2;
player->lines = LINES /2;
clear();
cbreak();
noecho();
curs_set(0);
refresh();
char ch;
while (playing)
{
spawn(30);
enemy_spawn(10);
ch = getchar();
switch (ch)
{
case 'w':
player->lines -= 1;
break;
case 's':
player->lines += 1;
break;
case 'a':
player->colmn -= 1;
break;
case 'd':
player->colmn += 1;
break;
case 'q':
playing = FALSE;
break;
default:
continue;
}
clear();
mvprintw(player->lines, player->colmn, "*");
refresh();
}
getch();
free(player);
endwin();
return 0;
}
void spawn(int count)
{
start_color();
init_pair(1, COLOR_BLUE, COLOR_BLACK);
attrset(A_BOLD | COLOR_PAIR(1) | A_CHARTEXT);
srandom(COLS && LINES);
int x, y;
const int spawn_x = COLS /2;
const int spawn_y = LINES /2;
for(int i = 0; i<count; i++)
{
sp_x:
x = rand() % (COLS -2);
if(x == spawn_x)
goto sp_x;
sp_y:
y = rand() % (LINES -2);
if(y == spawn_y)
goto sp_y;
mvprintw(y, x, ".");
}
refresh();
attroff(A_BOLD | COLOR_PAIR(1) | A_CHARTEXT);
}
void enemy_spawn(int count)
{
srandom(LINES && COLS);
start_color();
init_pair(2, COLOR_RED, COLOR_BLACK);
attrset(A_BOLD | COLOR_PAIR(2) | A_PROTECT);
int x, y;
const int spawn_x = COLS /2;
const int spawn_y = LINES /2;
char dot, asterik;
dot = '.';
asterik = '*';
for(int i = 0; i < count; i++)
{
spawn:
y = rand() % (LINES -2);
x = rand()% (COLS -2);
if((x || y) != dot || asterik || spawn_x || spawn_y)
{
mvprintw(y, x, "&");
} else {
goto spawn;
}
}
refresh();
attroff(A_BOLD | COLOR_PAIR(2) | A_PROTECT);
}
-
خب الان وقتشه یه تابع درست کنیم که ناظر بازی باشه و خیلی کارها باید انجام بده:
۱: محدود کردن بازیکن
۲:سرعت اسپاون غذا
۳:رد نشدن بازیکن از موانع
۴: شمردن امتیاز ( اینو میتونم یک تابع جدا بنویسم )
باز هم میتونم اضافه کنم ولی فعلا لازم نیست.
-----------------------------------------
قرار بود ۴ آپریل ۲۰۲۳ استاندارد زبان سی بیاد که مربوط به برنامه نویسی ماژولار بود. چرا خبری نیست!!!؟
-----------------------------------------
فعلا از محدود کردن بازیکن شروع میکنیم.
-
دوستان فعلا علاقه ایی به ادامه این بازی ندارم میخوام یک مقدار استراحت کنم و یک مقدار راست و پایتون کار کنم.
-
خب دوستان من برگشتم!
اصلا هرکاری میکنم نمیتونم با پایتو وفق پیدا کنم :oops: خیلی پیچیده هست.
خب فعلا میخوام یک تابع دیگه بنویسم کرسر طول و عرض صفحه منو پیمایش بکنه و موقعیت هایی که دشمنان و غذا هستند رو ذخیره بکنه و اگر موقعیت کرسر بنده با موقعیت غذا یکی شد به امتیاز های بنده ۳ تا اضافه بشه.
در کل میخوام یک تابع بنویسم که اگر موقعیت curser بنده با موقعیت غذا یکی بود به امتیاز های بنده یکی اضافه بشه و غذا پاک بشه و یک جای جدید اسپاون بشه.
البته این تابع تبدیل به دو زیر تابع میشه که یکی تابع cheak هست و دیگری food به نظر که سخت میاد. :P اما من تسلیم نمیشم.
-
نوشتمش!تروخدا بگید که من یک برنامه نویس رده افسانه ایی هستم 8)
خب حالا کاری که انجام دادم یکم ریسکی هست تو فرسته بعد میگم چرا.
#include <ncurses.h>
int main(){
initscr();
cbreak();
noecho();
curs_set(0);
int hight, width;
getmaxyx(stdscr, hight, width);
for (int i = 0; i < hight; i++) {
for (int j =0; j < width; j++) {
mvprintw(i, j, ".");
refresh();
}
refresh();
}
getch();
endwin();
return 0;
}
خب حالا باید یکم با این برنامه بازی کنیم:) و یه چیز خوب از این بدست بیاریم.
-
اگر دقت کرده باشید شما وقتی از تابع getmaxyx استفاده میکنید طول و عرض صفحه شما رو میده ولی ما نمیخوایم که کل طول و عرض صفحه استفاده کنیم میخوایم از طول منهای یک و عرض منهای یک استفاده کنیم پس باید از طول و عرض یکی کم کنیم. ولی ترجیح بنده منهای ۲ هست اینطوری خیلی تمیز تر در میاد. ( این فرسته ویرایش خواهد شد ! )
--------------------
خب حالا باید کم کم یک تابع بنویسیم که ناظر بازی باشه. میخواستم این تابع رو به چند تابع تقسیم کنم ولی به نظر همشون دارن یک کار میکنند و اون هم نظارت هست پس لازم به همچین کاری نیست.
-
خب حالا تابع غذا هم نوشتم اما هنوز کامل نشده چون نمیدونم چطور باید پیاده سازی بکنم:
void food_spawn(int delay)
{
const int spawn_point_x = COLS / 2;
const int spawn_point_y = LINES /2;
char asterik = '*';
char walls = '.';
char enemy = '&';
srandom(COLS && LINES);
start_color();
init_pair(3, COLOR_GREEN, COLOR_BLACK);
attrset(A_BOLD | COLOR_PAIR(3) |A_PROTECT);
int x, y;
for (int i = 0; i < 1; i++)
{
again:
x = rand() %(COLS - 2);
y = rand() %(LINES -2);
if ((x|| y) != walls || enemy || asterik || spawn_point_x || spawn_point_y)
{
mvprintw(y, x, "@");
} else {
goto again;
}
}
refresh();
attroff(A_BOLD | COLOR_PAIR(3) | A_PROTECT);
}
خب من دو چیز رو باید انجام بدم:
۱:وقتی مدت زمان اسپاون غذا تموم شد غذا پاک بشه!.
۲: وقتی موقعیت من با غذا یکی شد غذا پاک بشه و به امتیاز های من یکی اضافه بشه.
سوال اینجاست که چطور باید کاری کنم که اگر مثلا ۵ ثانیه از اسپاون غذا گذشت. غذا پاک بشه و در جای جدید اسپاون بشه. هرچند که تا کتابخانه time.h هست نیازی به نگرانی نیست.
-
خب بیاید یک کار دیگه انجام بدیم که یک مقدار منطق راحت تری داشته باشه هرچند که من نمیدونم اینکار جواب میده یا نه ولی:
چه میشه اگر موقعیت بازیکن با غذا یکی بشه؟ خب قاعدتا باید غذا پاک بشه ولی ما فقط یک تابع clear داریم که کل صفحه رو پاک میکنه! و من نمیتونم هر دقیقه صفحه رو پاک کنم. البته شاید بتونم همین الان یک ایده به ذهنم رسید.
ولی چه میشه اگر کاراکتر غذا رو با space عوض کنیم؟ البته نمیدونم میشه دوباره اونجا چیزی اسپاون بشه یا نه
-
خب حالا یک مقدار برنامه رو تونستم درک کنم ولی هنوز فرسنگ ها دور تر از انتظارات من هست.
الان اگر به روی غذا برید ( ! )با کاراکتر @@ مواجه میشید ولی من میخوام که غذا پاک بشه و در جای جدیدی اسپاون بشه.
-
اومدم یک حرکت جدید زدم. گفتم اگر موقعیت بازیکن من با غذا یکی بود برو در موقعیت غذا و کاراکتر '' قرار بده.
ولی باز هم نشد!
-
خب دوستان کلا برنامه رو از اول نوشتم و تابع غدا و ناظر رو حذف کردم الان فهمیدم که باید چیکار کنم و از همه مهتر یاد گرفتم و درک کردم:
#include <stdio.h>
#include <ncurses.h>
#include <stdlib.h>
#define LENGTH (elm_one, all) sizeof(all) / sizeof(elm_one)
struct posions
{
int colmn;
int lines;
}*player;
void spawn(int);
void enemy_spawn(int);
int main()
{
initscr();
int playing = TRUE;
player = malloc(sizeof(*player));
player->colmn = COLS /2;
player->lines = LINES /2;
clear();
cbreak();
noecho();
curs_set(0);
refresh();
char ch;
while (playing)
{
spawn(30);
enemy_spawn(10);
ch = getchar();
switch (ch)
{
case 'w':
player->lines -= 1;
break;
case 's':
player->lines += 1;
break;
case 'a':
player->colmn -= 1;
break;
case 'd':
player->colmn += 1;
break;
case 'q':
playing = FALSE;
break;
case 'p':
mvprintw(0, 0, "player_c: %d, player_l: %d\n", player->colmn, player->lines);
refresh();
break;
default:
continue;
}
clear();
mvprintw(player->lines, player->colmn, "*");
refresh();
}
getch();
free(player);
endwin();
return 0;
}
void spawn(int count)
{
start_color();
init_pair(1, COLOR_BLUE, COLOR_BLACK);
attrset(A_BOLD | COLOR_PAIR(1) | A_PROTECT);
srand(COLS && LINES);
const int spawn_x = COLS /2;
const int spawn_y = LINES /2;
for(int i = 0; i<count; i++)
{
sp_x:
int x = rand() % (COLS -1);
if(x == spawn_x)
goto sp_x;
sp_y:
int y = rand() % (LINES -1);
if(y == spawn_y)
goto sp_y;
mvprintw(y, x, ".");
}
refresh();
attroff(A_BOLD | COLOR_PAIR(1) | A_CHARTEXT);
}
void enemy_spawn(int count)
{
const int spawn_x = COLS /2;
const int spawn_y = LINES/2;
start_color();
init_pair(2, COLOR_RED, COLOR_BLACK);
attrset(COLOR_PAIR(2) | A_BOLD | A_PROTECT);
srand(COLS & LINES);
for(int i = 0; i < count;i++)
{
int x = rand() % (COLS -1);
int y = rand() % (LINES -1);
if(move(y, x) != '.')
{
mvprintw(y, x, "&");
}
}
refresh();
attroff(COLOR_PAIR(2) | A_BOLD| A_PROTECT);
}
اینطوری خیلی منطقی تره.
من گفتم اگر میخوای بری دشمن رو رسم کنی برو تو موقعیت x,y (با استفاده از تابع move ) و چک بکن که برابر موانع نباشه. البته امیدوارم درست باشه.
-
خب
از صبح تا الان دارم روی دو تا چیز کار میکنم :
۱: رد نشدن بازیکن از موانع
۲: رد نشدن بازیکن از صفحه
بیشتر درگیر دومی بودم هرکاری کردم نشد. به خاطر همین میخوام یک حرکت جدید رو امتحان کنم. ساخت پنجره! البته این اولین ایده من بودم و ایده دوم من اینه که یک ترمینال بسازم؟یا اندازه صفحه ترمنیال فعلی رو به تعداد ستون و سطر منهای یک تغیر بدم ولی این یک مقدار پیچیده هست و اصلا معلوم نیست که کار کنه یا نه. پس فعلا یک پنجره درست میکنم.
اگر هم کنجکاو شدید که چطور میخوای یک پنجره با ابعاد تعداد ستون و سطر های خودت درست باید بگم اینطوری:
#include <ncurses.h>
int main()
{
initscr();
clear();
WINDOW* win = newwin(LINES-1, COLS-1, 10, 10);
box(win, 0, 0);
wrefresh(win);
wgetch(win);
delwin(win);
endwin();
return 0;
}
-
خب دوستان واقعا خسته شدم. نیازه به استراحت دارم. برای همین میخوام این پیاده سازی رو یک مقدار به تعویق بندازم و یک مقدار چیز های جدید یاد بگیرم.
میخوام این مدت گیت رو به صورت جدی یاد بگیرم و برنامه نویسی سطح پیشرفته رو یاد بگیرم و اون ها رو توی سی پیاده سازی کنم و درک خودم رو بالاتر ببرم.
منظورم از برنامه نویسی سطح پیشرفته مفاهیم پیشرفته برنامه نویسی هست مثل لیست های پیوندی هش مپ ها و الگوریتم های جستجو و ...
-
#include <stdlib.h>
#include <ncurses.h>
#include <stdio.h>
#define spawn_x COLS/2
#define spawn_y LINES/2
void spawn(int);
void food(int, int);
int in_range(int, int, int);
void __clear_postion__(int x, int y);
int random_range(int min, int max, int seed);
int main()
{
initscr();
cbreak();
noecho();
curs_set(FALSE);
clear();
unsigned short score;
int player_l, player_c;
int maxl, maxc;
maxl = LINES -1;
maxc = COLS -1;
player_c = spawn_x;
player_l = spawn_y;
int playing = TRUE;
char ch;
char character;
chtype walls;
refresh();
while (playing)
{
spawn(200);
food(player_l, player_c);
ch = getchar();
switch (ch)
{
case 'w' :
walls = mvinch(player_l-1, player_c);
character = walls & A_CHARTEXT;
if(character != '.')
{
player_l-=1;
}
break;
case 's':
walls = mvinch(player_l+1, player_c);
character = walls & A_CHARTEXT;
if(character != '.')
{
player_l +=1;
}
break;
case 'a':
walls = mvinch(player_l, player_c-1) ;
character = walls & A_CHARTEXT;
if(character != '.')
{
player_c -=1;
}
break;
case 'd':
walls = mvinch(player_l, player_c+1);
character = walls & A_CHARTEXT;
if(character != '.')
{
player_c +=1;
}
break;
case 'q':
playing = FALSE;
break;
default:
continue;
}
clear();
player_c = in_range(player_c, 0, maxc);
player_l = in_range(player_l, 0, maxl);
mvaddch(player_l, player_c, '*');
refresh();
}
getch();
refresh();
endwin();
return 0;
}
void spawn(int count)
{
start_color();
init_pair(1, COLOR_CYAN, COLOR_BLACK);
attrset(COLOR_PAIR(1) | A_BOLD | A_PROTECT);
int x,y;
srand(COLS);
for(int i =0; i < count; i++)
{
sp_x:
x = rand() % COLS + 1;
sp_y:
y = rand() % LINES + 1;
if(x == spawn_x)
goto sp_x;
if(y == spawn_y)
goto sp_y;
mvaddch(y,x, '.');
}
refresh();
attroff(COLOR_PAIR(1) | A_BOLD | A_PROTECT);
}
int in_range(int a, int min, int max)
{
if(a > max)
{
return max;
}
if(a < min)
{
return min;
}
return a;
}
void food(int playerl, int playerc)
{
start_color();
init_pair(2, COLOR_YELLOW, COLOR_BLACK);
attrset(A_BOLD | COLOR_PAIR(2) | A_PROTECT);
int food_c, food_l;
chtype walls;
char character;
//spawn a food
for(int i =0; i <1; i++)
{
spawn_food_x:
food_c = rand() % (COLS+1);
if(food_c == spawn_x)
{
goto spawn_food_x;
}
spawn_food_y:
food_l = rand() % (LINES+1);
if(food_l == spawn_y)
{
goto spawn_food_y;
}
walls = mvinch(food_l, food_c);
character = walls & A_CHARTEXT;
if(character != '.')
{
mvaddch(food_l, food_c, '^');
} else {
continue;
}
refresh();
int old_food_l = food_l;
int old_food_c = food_c;
}
attroff(A_BOLD | A_PROTECT | COLOR_PAIR(2));
}
void __clear_postion__(int x, int y)
{
mvaddch(x, y, ' ');
refresh();
}
int random_range(int min, int max, int seed)
{
if( min > max)
{
fprintf(stderr, "Erro beccuase min is bigger than your max: %d > %d", min, max);
}
if(seed ==0)
{
return rand() % (max + min -1) + min;
}
srand(seed);
return rand() % (max + min -1) + min;
}
-
لعنت به این پایتون با این سینتکس و قابلیت های کوفتیش! خب من الان چیکار کنم که غذای من دوباره ظاهر نشه؟!
#include <stdlib.h>
#include <ncurses.h>
#include <stdio.h>
#include <sys/cdefs.h>
#define spawn_x COLS/2
#define spawn_y LINES/2
void spawn(int);
void food(int, int, int*, int*);
int in_range(int, int, int);
void __clear_postion__(int x, int y);
int random_range(int min, int max, int seed);
void door_knob(void);
void check(int, int, int, int);
int main()
{
initscr();
cbreak();
noecho();
curs_set(FALSE);
clear();
unsigned short score;
int player_l, player_c;
int maxl, maxc;
maxl = LINES -1;
maxc = COLS -1;
player_c = spawn_x;
player_l = spawn_y;
int playing = TRUE;
int food_l, food_c;
char ch;
char character;
chtype walls;
int i;
int j;
refresh();
while (playing)
{
spawn(100);
food(player_l, player_c, &food_l, &food_c);
if(food_c == player_c && food_l == player_l)
{
mvdelch(food_l, food_c);
food(player_l, player_c, &food_l, &food_c);
}
ch = getch();
switch (ch)
{
case 'w' :
walls = mvinch(player_l-1, player_c);
character = walls & A_CHARTEXT;
if(character != '.') {player_l-=1;}
break;
case 's':
walls = mvinch(player_l+1, player_c);
character = walls & A_CHARTEXT;
if(character != '.') {player_l +=1;}
break;
case 'a':
walls = mvinch(player_l, player_c-1) ;
character = walls & A_CHARTEXT;
if(character != '.') {player_c -=1;}
break;
case 'd':
walls = mvinch(player_l, player_c+1);
character = walls & A_CHARTEXT;
if(character != '.') {player_c +=1;}
break;
case 'q':
playing = FALSE;
break;
default:
continue;
}
clear();
player_c = in_range(player_c, 0, maxc);
player_l = in_range(player_l, 0, maxl);
mvaddch(player_l, player_c, '*');
refresh();
}
getch();
refresh();
endwin();
return 0;
}
void spawn(int count)
{
start_color();
init_pair(1, COLOR_CYAN, COLOR_BLACK);
attrset(COLOR_PAIR(1) | A_BOLD | A_PROTECT);
int x,y;
srand(COLS);
for(int i =0; i < count; i++)
{
sp_x:
x = rand() % COLS + 1;
sp_y:
y = rand() % LINES + 1;
if(x == spawn_x)
goto sp_x;
if(y == spawn_y)
goto sp_y;
mvaddch(y,x, '.');
}
refresh();
attroff(COLOR_PAIR(1) | A_BOLD | A_PROTECT);
}
int in_range(int a, int min, int max)
{
if(a > max) {return max;}
if(a < min) {return min;}
return a;
}
void food(int playerl, int playerc, int *line, int *col)
{
start_color();
init_pair(2, COLOR_YELLOW, COLOR_BLACK);
attrset(A_BOLD | COLOR_PAIR(2) | A_PROTECT);
int food_c, food_l;
chtype walls;
char character;
//spawn a food
for(int i =0; i <1; i++)
{
spawn_food_x:
food_c = rand() % (COLS+1);
if(food_c == spawn_x)
{
goto spawn_food_x;
}
spawn_food_y:
food_l = rand() % (LINES+1);
if(food_l == spawn_y)
{
goto spawn_food_y;
}
walls = mvinch(food_l, food_c);
character = walls & A_CHARTEXT;
if(character != '.')
{
mvaddch(food_l, food_c, '^');
} else {
goto spawn_food_x;
}
refresh();
*line = food_l;
*col = food_c;
}
attroff(A_BOLD | A_PROTECT | COLOR_PAIR(2));
}
void __clear_postion__(int x, int y)
{
mvaddch(x, y, ' ');
refresh();
}
int random_range(int min, int max, int seed)
{
if( min > max)
{
fprintf(stderr, "Erro beccuase min is bigger than your max: %d > %d", min, max);
}
if(seed ==0)
{
return rand() % (max + min -1) + min;
}
srand(seed);
return rand() % (max + min -1) + min;
}
حتی هوش مصنوعی هم گند زد به کدم! اصلا هیچی حالیش نیست.
-
#include <raylib.h>
typedef struct
{
float x,y;
int speed_x, speed_y;
int radius;
}BALL;
typedef struct
{
float x,y;
float width, higth;
int speed;
}Paddle,CpuPaddle;
BALL ball;
Paddle player;
CpuPaddle Cpu;
void draw();
void draw_Paddle();
void Cpu_draw();
void Update();
void Update_paddle();
void Cpu_update(int ball_y);
int main()
{
//screen initiliaze
int screen_l = 500;
int screen_c = 1300;
InitWindow(screen_c, screen_l, "PONG");
SetTargetFPS(60);
//ball
ball.radius = 10;
ball.x = (float)screen_c/ 2;
ball.y = (float)screen_l/2;
ball.speed_x = 7, ball.speed_y = 7;
//player paddle
player.width = 25;
player.higth = 120;
player.x = screen_c - player.width -10;
player.y = (float)screen_l/2 - player.higth/2;
player.speed = 6;
//Cpu
Cpu.higth = 120;
Cpu.width = 25;
Cpu.x = 10;
Cpu.y =(float) screen_l/2- Cpu.higth/2;
Cpu.speed = 6;
//vars and vectors
Vector2 Vec;
Rectangle Cpu_Rect;
while (!WindowShouldClose())
{
BeginDrawing();
//updating
Update();
Update_paddle();
Cpu_update(ball.y);
//checking for collisions
Vector2 Vec = {ball.x, ball.y};
Rectangle Rect = {player.x, player.y, player.higth, player.width};
Rectangle Cpu_Rect = {Cpu.x, Cpu.y, Cpu.higth, Cpu.width};
if(CheckCollisionCircleRec(Vec, ball.radius, Rect))
{
ball.speed_x *= -1;
}
if(CheckCollisionCircleRec(Vec, ball.radius, Cpu_Rect))
{
ball.speed_x *= -1;
}
//drawing
ClearBackground(BLACK);
DrawLine(screen_c/2, 0, screen_c/2, screen_l, WHITE);
draw();
Cpu_draw();
draw_Paddle();
EndDrawing();
}
CloseWindow();
return 0;
}
void draw()
{
DrawCircle(ball.x, ball.y, ball.radius, WHITE);
}
void Update()
{
ball.x +=(float) ball.speed_x;
ball.y +=(float) ball.speed_y;
if(ball.y + ball.radius >= GetScreenHeight() ||
ball.y - ball.radius <= 0)
{
ball.speed_y *= -1;
}
if(ball.x + ball.radius >= GetScreenWidth() ||
ball.x - ball.radius <= 0)
{
ball.speed_x *= -1;
}
if(player.y <= 0)
{
player.y = 0;
}
if(player.y + player.higth >= GetScreenHeight())
{
player.y = GetScreenHeight() - player.higth;
}
if(Cpu.y <= 0)
{
Cpu.y = 0;
}
if(Cpu.y + Cpu.higth >= GetScreenHeight())
{
Cpu.y = GetScreenHeight() - Cpu.higth;
}
}
void draw_Paddle()
{
DrawRectangle(player.x, player.y, player.width, player.higth, WHITE);
}
void Update_paddle()
{
if(IsKeyDown(KEY_UP))
{
player.y = player.y - player.speed;
}
if(IsKeyDown(KEY_DOWN))
{
player.y = player.y + player.speed;
}
}
void Cpu_draw()
{
DrawRectangle(Cpu.x, Cpu.y, Cpu.width, Cpu.higth, WHITE);
}
void Cpu_update(int ball_y)
{
if(Cpu.y + Cpu.higth/2 >ball_y)
{
Cpu.y = Cpu.y - Cpu.speed;
}
if(Cpu.y + Cpu.higth <=ball_y)
{
Cpu.y = Cpu.y + Cpu.speed;
}
}
درود دارم بازی pong رو مینویسم. الان به چندتا باگ عجیب خورم:
۱: وقتی توپ به حریف میخوره معلوم نیست که برگرده یا نه.
۲: وقتی توپ به من میخوره اصلا بر نمیگرده و باید به دیوار بخوره تا برگرده .
برای اجرا:
gcc main.c -lraylib
-
درود
میخوام یک پروژه جذاب رو شروع کنم:
morse coder && decoder
همیشه دلم میخواست مورس کد رو یاد بگیرم و ازش استفاده بکنم البته مورس کد انگلیسی نه پارسی!
به هرحال به نظرم پروژه جذابیه و شاید بتونم به سوکت نویسی و شبکه هم ربطش بدم کی میدونه؟!
خب هنوز فکر نکردم که باید جیکار کنم ولی اینا رو میدونم:
۱: باید متن انگلیسی رو در یک فایل تکست بریزم
۲:باید یک برنامه بنویسم که :
۱:کد های انگلیسی رو تبدیل به مورس کد بکنه( از یک فایل دریافت بکنه و بخونه).
۲:کد مورس رو درون فایل بنویسه.
۳:اگر داخل فایل مورس کد بود تبدیل به متن انگلیسی بکنه.
---------------
خب برای منی که ی برنامه نویس تازه کارم مشکله ولی میخوام برنامه خودم رو به صورت در هم بنویسم یعنی هرجایی که تونستم بنویسم و هرجایی که نتونستم رو بزارم آخر.
از طرفی خیلی دوست داشتم این برنامه رو با پایتون بنویسم چون اینجور چیز ها خوراک پایتون هست. ولی بعد از ۱ ساعت تلاش کلا بیخیال شدم.
به احتمال زیاد از زبان سی پلاس پلاس استفاده بکنم به دو دلیل :
۱: شی گرایی توی سی پلاس پلاس و راست خیلی راحت تر و قابل فهم تر هست.
۲: مجبورم به دلایلی س پ پ رو یاد بگیرم.
البته نگران نباشید!!! به هیچ عنوان نیازی به سینتکس مسخره زبان س پ پ نداریم چون از cstd ها استفاده خواهیم کرد!
-
این برنامه هنوز تکمیل نشده. سوییچ های i, h کار میکندد. به احتمال زیاد به سوییچ های بیشتری نیاز پیدا بکنم چون میخوام این برنامه رو راهی AUR بکنم. هنوز خیلی کار داره ولی خب فعلا خوبه:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <getopt.h>
typedef struct
{
char letter;
char* code;
}Morse_EN;
typedef struct
{
int number;
char* code;
}Morse_NUM;
Morse_EN morse_table []=
{
{'A', ".-"},
{'B', "-..."},
{'C', "-.-"},
{'D', "-.."},
{'E', "."},
{'F', "..-"},
{'G', "--."},
{'H', "...."},
{'I', ".."},
{'J', ".---"},
{'K', "-.-"},
{'L', ".-.."},
{'M', "--"},
{'N', "-."},
{'O', "---"},
{'P', ".--."},
{'Q', "--.-"},
{'R', ".-."},
{'S', "..."},
{'T', "-"},
{'U', "..-"},
{'V', "...-"},
{'W', ".--"},
{'X', "-..-"},
{'Y', "-.--"},
{'Z', "--.."},
};
Morse_NUM morse_numbers[] =
{
{1, ".----"},
{2, "..---"},
{3, "...--"},
{4, "....-"},
{5, "....."},
{6, "-...."},
{7, "--..."},
{8, "---.."},
{9, "----."},
{0, "-----"},
};
void Usage(FILE* stream, int exit_code, const char* prog_name);
void Collision_args(int next_option, const char* prog_name, const char* file_name);
void encode(const char* file_name);
unsigned long int file_size(const char* file_name);
const char* prog_name;
int main(int argc, char* argv[])
{
// entry point
prog_name = argv[0];
int next_option;
//define short options:
const char* const short_option = "ihd:e:";
//define long options:
const struct option long_options[] =
{
{"info", no_argument, NULL, 'i'},
{"help", no_argument, NULL, 'h'},
{"decode", required_argument, NULL, 'd'},
{"encode", required_argument, NULL, 'e'},
{NULL, no_argument, NULL, 0}
};
do {
next_option = getopt_long(argc, argv, short_option, long_options, NULL);
Collision_args(next_option, argv[0], optarg);
}while (next_option != -1);
return EXIT_SUCCESS;
}
void Usage(FILE* stream, int exit_code, const char* prog_name)
{
fprintf(stream, "usage: <%s> --options.\n", prog_name);
fprintf(stream,
"-i --info give a information and rules for Morse code: -i or --info\n"
"-h --help print this message: -h or --help.\n"
"-d --decode decode The Morse code file: -d or --deocde.\n"
"-e --encode encode The Text file: -e --encode.\n");
}
void Collision_args(int next_option, const char* prog_name, const char* file_name)
{
switch (next_option)
{
case 'i':
fprintf(stdout,
"1: The length of a dot is one unit.\n"
"2: a dash is tree units.\n"
"3: The space between parts of The same letter is one unit\n"
"4: The space between letters is three units.\n"
"5: The space between words is seven units.\n\n\n"
);
fprintf(stdout, "-------------------------------------------\n\n");
fprintf(stdout,
"A: .-\n"
"B: -...\n"
"C: -.-.\n"
"D: -..\n"
"E: .\n"
"F: ..-.\n"
"G: --.\n"
"H: ....\n"
"I: ..\n"
"J: .---\n"
"K: -.-\n"
"L: .-..\n"
"M: --\n"
"N: -.\n"
"O: ---\n"
"P: .--.\n"
"Q: --.-\n"
"R: .-.\n"
"S: ...\n"
"T: -\n"
"U: ..-\n"
"V: ...-\n"
"W: .--\n"
"X: -..-\n"
"Y: -.--\n"
"Z: --..\n\n\n"
);
fprintf(stdout, "Numbers: \n\n");
fprintf(stdout,
"1: .----\n"
"2: ..---\n"
"3: ...--\n"
"4: ....-\n"
"5: .....\n"
"6: -....\n"
"7: --...\n"
"8: ---..\n"
"9: ----.\n"
"0: -----\n"
);
break;
case -1:
//Usage(stdout, EXIT_FAILURE, prog_name);
break;
case '?':
Usage(stderr, EXIT_FAILURE, "morse");
break;
case 'h':
Usage(stdout, 0, prog_name);
break;
case 'd':
break;
case 'e':
encode(file_name);
break;
default:
Usage(stdout, EXIT_SUCCESS, prog_name);
abort();
}
}
void encode(const char* file_name)
{
char* date;
FILE* fptr = NULL;
fptr = fopen(file_name, "r");
if(!fptr)
{
perror("failed");
exit(EXIT_FAILURE);
}
fseek(fptr, 0, SEEK_SET);
char ch = fgetc(fptr);
if(ch != EOF)
printf("the char is %c", ch);
fclose(fptr);
}
unsigned long int file_size(const char* file_name)
{
FILE* fptr = fopen(file_name, "rb");
if(!fptr)
{
perror("failed");
exit(EXIT_FAILURE);
}
fseek(fptr, 0L, SEEK_END);
unsigned long int size = ftell(fptr);
return size;
}
-
خب برنامه رو پاک کردم چون خیلی بد نوشته بودم بزارید اول تیکه های کوچیک رو بنویسیم بعد بریم سراغ لقمه های بزرگتر