public static (int a, int b) GenerateSiblingIntegerPair(int min, int max, double maxPercent, bool allowEqual = true)
{
if (min >= max)
throw new ArgumentException("min must be less than max");
if (maxPercent <= 0)
throw new ArgumentException("maxPercent must be > 0");
// 1. สุ่มค่าแรก (a)
int a = GenerateRandomNumber(min, max + 1);
// 2. คำนวณช่วงของ b โดยอิงจาก a และ maxPercent
double delta = a * maxPercent;
int bMin = (int)Math.Max(min, Math.Ceiling(a - delta));
int bMax = (int)Math.Min(max, Math.Floor(a + delta));
// 3. Fallback กรณีช่วงแคบเกินไป (เช่น a มีค่าน้อยมาก)
if (bMin > bMax)
{
bMin = Math.Max(min, a - 1);
bMax = Math.Min(max, a + 1);
}
// 4. สุ่มค่า b
int b = GenerateRandomNumber(bMin, bMax + 1);
// 5. ถ้าไม่ยอมให้ a == b และช่วงกว้างพอ ให้สุ่มใหม่จนกว่าจะไม่ซ้ำ
if (!allowEqual && a == b && bMin < bMax)
{
while (a == b)
{
b = GenerateRandomNumber(bMin, bMax + 1);
}
}
return (a, b);
}
จากโค้ดเหมือนมันยังได้ค่าไม่โดนใจนักครับ
โดยโค้ดใช้งานประมาณนี้
[Spoil] คลิกเพื่อดูข้อความที่ซ่อนไว้ private double GetSmartPercent(int a, int b)
{
int max = Math.Max(Math.Abs(a), Math.Abs(b));
if (max < 100)
return 20; // เลขเล็ก อนุโลม
if (max < 1000)
return 10; // เลขกลาง เริ่มเข้ม
return 5; // เลขใหญ่ ต้องใกล้จริง
}
// ----------------------------------------------------------
// ฟังก์ชันสร้างไฟล์ PDF (ใช้ iText แทน System.Drawing.Printing)
// ----------------------------------------------------------
private void CreateFilePDF(string filename = "")
{
if (string.IsNullOrEmpty(filename))
CreateFilePDFBase();
else
CreateFilePDFBase(filename);
minValue = numberSelect1.Minimum;
maxValue = numberSelect1.Maximum;
bool isDecimalMode = IsDecimalRange(minValue, maxValue);
string format = isDecimalMode ? "0.###" : "0";
for (int p = 1; p <= iPageAll; p++)
{
PDFAddNewPage();
xRow = 150;//
yRow = PageSize.A4.GetTop() - 150;
float c01W = 100, c02W = 50, cH = 25;
int totalProblems = 12;
for (int i = 0; i < totalProblems; i++)
{
double a, b;
if (isDecimalMode)
{
(a, b) = RandomNumber.GenerateSiblingDecimalPair(minValue, maxValue);
}
else
{
int _min = (int)Math.Ceiling(minValue);
int _max = (int)Math.Floor(maxValue);
double pFM = GetSmartPercent(_min, _max);
var pair = RandomNumber.GenerateSiblingIntegerPair(_min,_max, pFM);
a = pair.a;
b = pair.b;
}
pdfpage.DrawStringPDF(a.ToString(format), FontManager.baseFontComicSansMS, 20, new iText.Kernel.Geom.Rectangle(xRow, yRow, c01W, cH), TextAlignment.RIGHT);
pdfpage.DrawTextFieldPDF(new iText.Kernel.Geom.Rectangle(xRow + c01W + 10, yRow - 5, c02W, cH),
justification: TextAlignment.CENTER, borderWidth: 1.2f);
pdfpage.DrawStringPDF(b.ToString(format), FontManager.baseFontComicSansMS, 20, new iText.Kernel.Geom.Rectangle(xRow + c01W + c02W + 20, yRow, c01W, cH), TextAlignment.LEFT);
yRow -= 40;
}
}
EndCreateFilePDFBase();
}
ถ้าอยากให้ตัวเลขใกล้เคียงกันมากกว่านี้ ต้องแก้ที่จุดไหน ครับ
รบกวนโปรแกรมเมอร์ หรือ ท่านที่เข้าใจเรื่องการสุ่มตัวเลข ช่วยแนะนำ หน่อยครับ
{
if (min >= max)
throw new ArgumentException("min must be less than max");
if (maxPercent <= 0)
throw new ArgumentException("maxPercent must be > 0");
// 1. สุ่มค่าแรก (a)
int a = GenerateRandomNumber(min, max + 1);
// 2. คำนวณช่วงของ b โดยอิงจาก a และ maxPercent
double delta = a * maxPercent;
int bMin = (int)Math.Max(min, Math.Ceiling(a - delta));
int bMax = (int)Math.Min(max, Math.Floor(a + delta));
// 3. Fallback กรณีช่วงแคบเกินไป (เช่น a มีค่าน้อยมาก)
if (bMin > bMax)
{
bMin = Math.Max(min, a - 1);
bMax = Math.Min(max, a + 1);
}
// 4. สุ่มค่า b
int b = GenerateRandomNumber(bMin, bMax + 1);
// 5. ถ้าไม่ยอมให้ a == b และช่วงกว้างพอ ให้สุ่มใหม่จนกว่าจะไม่ซ้ำ
if (!allowEqual && a == b && bMin < bMax)
{
while (a == b)
{
b = GenerateRandomNumber(bMin, bMax + 1);
}
}
return (a, b);
}
จากโค้ดเหมือนมันยังได้ค่าไม่โดนใจนักครับ
โดยโค้ดใช้งานประมาณนี้
[Spoil] คลิกเพื่อดูข้อความที่ซ่อนไว้
ถ้าอยากให้ตัวเลขใกล้เคียงกันมากกว่านี้ ต้องแก้ที่จุดไหน ครับ