[C#]תוצאה שונה בין ריצה רגילה לריצה שורה שורה - תכנות - HWzone פורומים
עבור לתוכן
  • צור חשבון

[C#]תוצאה שונה בין ריצה רגילה לריצה שורה שורה


TheReaper

Recommended Posts

המטרה של הקוד היא לצייר בעקרון "עץ" עם התפצלויות רנדומליות

יש נקודה התחלתית שגדלה כל פעם וכל פעם שהיא גדלה היא מקבל +1 אנרגיה

כל פעם התוכנית בודקת אם יש יותר מ10 אנרגיה

אם כן אז יש סיכוי של 10% שהצמח יתפצל

ברגע שהצמח מתפצל נוצרים 2 חדשים שהולכים ל2 צדדים ולכל אחד מהם יש 0 אנרגיה

הבעיה-

אני מריץ את הקוד עם הגבלה של 200 עדכונים

אם אני שם עצירה בנקודה מסויימת (למשל זו שאחראית על הפיצול) אז בסוף אני נשאר עם משהו כמו 120 פיצולים שזה הגיוני

אבל אם אני מריץ את זה רגיל לפעמים אני מגיע למצבים של 10K+ פיצולים

זה העדכון

      if (Numberofupdates < 200)
{
// TODO: Add your update logic here
for (int i = SplitsList.Count-1; i >=0; i--)
{
if (SplitsList[i].Energy > 10)
if (RandomSplitChance())
SplitPlant(SplitsList[i]);
}
for (int i = SplitsList.Count - 1; i >= 0; i--)
{
Growplant(SplitsList[i]);
}
Numberofupdates++;
}
else
{
oktodraw = true;

}

השורה אחרונה זה כדי שיהיה אפשר לעצור בELSE

זה הגדילה

    void Growplant(Split S)
{
GameBoard[(int)S.Location.X + (int)S.Location.Y * ScreenWidth] = Color.Black;
S.Location.Y++;
S.Energy++;
switch(S.Direction)
{
case 1:
S.Location.X--;
break;
case 2:
S.Location.X++;
break;

}
}

זה הפיצול

    void SplitPlant(Split Splitted)
{
SplitsList.Add(new Split(new Vector2(Splitted.Location.X-1,Splitted.Location.Y),0,1));
SplitsList.Add(new Split(new Vector2(Splitted.Location.X+1,Splitted.Location.Y),0,2));
SplitsList.Remove(Splitted);
}

זה הרנדום

    bool RandomSplitChance()
{
Random Rnd = new Random();
if (Rnd.Next(10) == 0)
return true;
else
return false;
}

הגדרות משתנים בMAIN

    Color[] GameBoard;
int ScreenHeight;
int ScreenWidth;
List<Split> SplitsList=new List<Split>();
Texture2D GameBoardTexture;
int Numberofupdates = 0;
bool oktodraw = false;

הגדרות של קלאס Split

    public Vector2 Location = new Vector2();
public int Energy;
public int Direction;
public Split(Vector2 _Location, int _Energy,int _Direction)
{
this.Location = _Location;
this.Energy = _Energy;
Direction = _Direction;
}

קישור לתוכן
שתף באתרים אחרים

א) איזו שפה? C#?

ב) לא שמת פה את כל הקוד ואת ההגדרות.

ג) רואים שאתה משתמש באיזשהו random number generator, אז זה לא אמור להפתיע שאתה מקבל תוצאות שונות בריצות שונות. תנסה להכריח אותו לייצר תמיד אותם מספרים, ע"י קביעת seed ראשוני שהוא קבוע.

ד) יתכן שזה שאתה עוצר את הריצה עם breakpoint משנה את התזמון בצורה זו או אחרת, אולי יש איפשהו race condition?

קישור לתוכן
שתף באתרים אחרים

א) איזו שפה? C#?

ב) לא שמת פה את כל הקוד ואת ההגדרות.

ג) רואים שאתה משתמש באיזשהו random number generator, אז זה לא אמור להפתיע שאתה מקבל תוצאות שונות בריצות שונות. תנסה להכריח אותו לייצר תמיד אותם מספרים, ע"י קביעת seed ראשוני שהוא קבוע.

ד) יתכן שזה שאתה עוצר את הריצה עם breakpoint משנה את התזמון בצורה זו או אחרת, אולי יש איפשהו race condition?

1.כן עם שימוש בXNA (אני אערוך את הכותרת)

2.אני לא חושב שזה ממש משנה... רובם זה או משתנים רגילים בסיסיים (LIST,INT) או קלאסים שאני הגדרתי שהם גם בסיסיים לחלוטין

3.הבעיה היא שהם אפילו לא קרובים סטטיסטית (10K לעומת 100) ומה זה להגדיר SEED ראשוני קבוע?

4.מה זה race condition?

קישור לתוכן
שתף באתרים אחרים

לגבי race condition, יש הסבר כאן.

התוכנה שלך בנוייה בצורה כזו שכל שינוי קטן בסדרת המספרים יכול לגרור אותה לנתיב שונה בקוד. כלומר לא חייב להיות איזשהו קשר, יתכן שפשוט יש באג בקוד שנחשף בסדרת קלט מסויימת אשר מתקבלת מ-rand.

לגבי הגדרת seed: רוב ה-pseudo random number generators בעצם מחזיקים מספר (או סט מספרים) שמהווה את המצב של הגנרטור. על מנת לייצר מספרים אקראיים, מפעילים נוסחה מתמטית מסויימת על המצב. המסקנה היא שבהנתן מצב ראשוני מסויים, אזי סדרת המספרים "האקראית" שתיווצר ממנו תהיה בעצם תמיד זהה. מצב ראשוני זה נקרא seed.

הרבה פעמים מאתחילם את המצב הראשוני לפי הזמן הנוכחי, וכך בכל ריצה מקבלים סדרה שונה של מספרים (שהרי כל ריצה קורית בזמן אחר). אם רוצים, לדוגמא למטרת בדיקות ודיבוג (שזה המצב שלך) לדאוג שתמיד תתקבל אותה סדרת מספרים "אקראית", אפשר לאתחל את ה-seed בתחילת התוכנית למשהו קבוע, לדוגמא 4321.


עריכה: אני חושב שמצאתי חלק מהבעיה שלך! אני לא מכיר C# מאוד טוב, אז יש פה ניחוש מושכל.

אתה מייצר גנרטור חדש בכל פעם שאתה קורה ל-RandomSplitChance ע"י השורה: Random Rnd = new Random();

זה לא הדרך הנכונה להשתמש ב-random number generator.

אני מניח שכל פעם שנוצר Random חדש ה-seed שלו מאותחל לפי הזמן הנוכחי. בזמן שאתה עוצר את התוכנה זמן זה כמובן משתנה באופן שונה מאשר מה שקורה כשהתוכנה רצה ללא הפסקות.

מה שנכון לעשות (כנראה, אני לא מכיר C#) זה לאתחל Random פעם אחת בתחילת התוכנית ואז להשתמש באותו האובייקט כל פעם. כלומר תעביר את השורה Random Rnd = new Random(); אל מחוץ לפונקציה.

קישור לתוכן
שתף באתרים אחרים

1.קראתי על RACE CONDITION אבל זה לא ממש רלוונטי כי יש רק תראד אחד (אחר"כ נדבר על ריבוי ליבות קודם גורמים לזה לעבוד)

2.יש לי בעיה עם הליסט והלולאה שרצה עליה כיוון שאני לא בדיוק יודע איך זה מתפקד

על פניו נראה שההתפצלויות החדשות נוצרות בסוף והלולאה עוברת עליהן רק בסייקל הבא

3.הSEED הזה... איך אני את זה בתוכנית? זה ביחד עם הרנדום הקיים של C# או שאני צריך לעשות משהו מתמטי בעצמי?

קישור לתוכן
שתף באתרים אחרים

כנראה שאתה יכול לתת פרמטר בזמן יצירת הRandom, או אולי יש איזה מתודה. אתה בטח לא אמור לעזות שום דבר מתמטי. רק לספק מספר.

אל תשכח להוציא את new Random() מתוך הפונקציה, על מנת שיקרה רק פעם אחת בתחילת התוכנית!

קישור לתוכן
שתף באתרים אחרים

אוקי הוצאתי את הרנדום החוצה והרצתי רגיל ועם עצירות

הגעתי לתוצאות זהות של 700~ אבל אני עדיין מחפש את התוצאות של ה10K~ כדי לדעת שזה באמת עובד כמו שצריך

תודה על העזרה

קישור לתוכן
שתף באתרים אחרים

ארכיון

דיון זה הועבר לארכיון ולא ניתן להוסיף בו תגובות חדשות.

×
  • צור חדש...