供参考 Lobstermania老虎机模拟器

jpm9511

成员
已加入
2020年7月15日
留言内容
5
编程经验
Beginner
如果你're interested, I've just set up a github repository for my 1st project. You can find this console app by clicking here: Lobstermania模拟器.

用例范例
  1. 作为了解视频老虎机概率,支出和算法的学习工具。
  2. 作为开发游戏图形版本的基本引擎。
  3. 通过更改符号,支出和游戏规则,作为开发其他老虎机游戏的基础。
享受!
 

跳伞者

工作人员
已加入
2019年4月6日
留言内容
2,612
地点
弗吉尼亚州切萨皮克
编程经验
10+
如果您的目标之一是真正学习C#,则应遵循C#/ .NET Framework的命名约定。

 

跳伞者

工作人员
已加入
2019年4月6日
留言内容
2,612
地点
弗吉尼亚州切萨皮克
编程经验
10+
抱歉,上面的链接错误...这是更通用的.NET Framework指南,上面的C#约定涉及某些C#特定的东西。

 

跳伞者

工作人员
已加入
2019年4月6日
留言内容
2,612
地点
弗吉尼亚州切萨皮克
编程经验
10+
你为什么"stringly-typed"?您不应该强力输入并使用枚举吗?
C#:
SYMBOLS123 = { "WS", "LM", "BU", "BO", "LH", "TU", "CL", "SG", "SF", "LO", "LT" };

// All 11 game symbols, Corresponds to: 
{ "Wild", "Lobstermania", "Buoy", "Boat", "Lighthouse", "Tuna", "Clam", "Seagull", "Starfish", "Bonus", "Scatter" }
 

跳伞者

工作人员
已加入
2019年4月6日
留言内容
2,612
地点
弗吉尼亚州切萨皮克
编程经验
10+
Yikes! Those goto's are making my eyes twitch... Must go start refactoring code...
 

跳伞者

工作人员
已加入
2019年4月6日
留言内容
2,612
地点
弗吉尼亚州切萨皮克
编程经验
10+
Goto[icode]'s are bad. I've refactored the code to not use [icode]goto's. Also using exceptions for flow control is the same as using exceptions as goto's. I've changed the code to use TryParse() instead.

重新编写以下代码:

from LM962.cs:
switch (sym)
{
:
    case "WS": // Wild
    :

    // Leading 3 wilds
    if ((line[1] == "WS") && (line[2] == "WS") && (line[3] == "LM") && (line[4] == "WS") && (line[4] != "LM"))
    {
        sym = "LM";
        count = 4;
        goto Done;
    }
    if ((line[1] == "WS") && (line[2] == "WS") && (line[3] != "LM") && (line[3] != "WS") && (line[4] != line[3]))
    {
        sym = "WS";
        count = 3;
    }

Done:
    break; // case "WS"
:
}
作为
No more goto.:
switch (sym)
{
:
    case "WS": // Wild
    :

    // Leading 3 wilds
    if ((line[1] == "WS") && (line[2] == "WS") && (line[3] == "LM") && (line[4] == "WS") && (line[4] != "LM"))
    {
        sym = "LM";
        count = 4;
        break;
    }
    if ((line[1] == "WS") && (line[2] == "WS") && (line[3] != "LM") && (line[3] != "WS") && (line[4] != line[3]))
    {
        sym = "WS";
        count = 3;
    }

    break; // case "WS"
:
}



Program.cs:
public static void Main()
{
    mainMenu:
    Console.Clear();
    Console.WriteLine("PRESS:\n");
    Console.WriteLine("\t1 for Bulk Game Spins\n\t2 for Individual Games\n\t3 to quit\n");
    Console.Write("Your choice: ");
    string res = Console.ReadLine();
    int num;
    try
    {
        num = Convert.ToInt32(res);
    }
    catch (Exception)
    {
        Console.WriteLine("\n***ERROR: Please enter number 1, 2, or 3 !!!");
        Thread.Sleep(2000); // sleep for 2 seconds
        goto mainMenu;
    }
    switch(num)
    {
        case 1:
            long numSpins;
            int paylines; // number of paylines to play

            labelNumSpins:
            Console.Write("\nEnter the number of spins:  ");
            try
            {
                numSpins = Convert.ToInt64(Console.ReadLine()); // convert to a long
                if (numSpins <= 0)
                    throw new ArgumentOutOfRangeException();
            }
            catch (Exception)
            {
                Console.WriteLine("\n***ERROR: Please enter a positive number greater than 0 !!!");
                goto labelNumSpins;
            }

            labelActivePaylines:
            Console.Write("Enter the number of active paylines (1 through 15):  ");

            try
            {
                paylines = Convert.ToInt32(Console.ReadLine()); // convert to an int

                if (paylines < 1 || paylines > 15)
                    throw new ArgumentOutOfRangeException();
            }
            catch (Exception)
            {
                Console.WriteLine("\n***ERROR: Please enter a positive number between 1 and 15 !!!");
                goto labelActivePaylines;
            }

            Console.Clear();
            BulkGameSpins(numSpins,paylines);
            Console.WriteLine("Press any key to continue to Main Menu ...");
            Console.ReadKey();
            goto mainMenu;
        case 2:
            Console.Clear();
            IndividualGames();
            goto mainMenu;
        case 3:
            Environment.Exit(0); // planned exit
            break;
        default:
            goto mainMenu;
    }

} // End method Main

private static void BulkGameSpins(long numSpins, int numPayLines)
{
    LM962 game = new LM962()
    {
        activePaylines = numPayLines
        };

    DateTime start_t = DateTime.Now;

    Console.WriteLine("Progress Bar ({0:N0} spins)\n",numSpins);
    Console.WriteLine("0%       100%");
    Console.WriteLine("|--------|");


    if (numSpins <= 10)
    {
        Console.WriteLine("**********"); // 10 markers
        for (long i = 1; i <= numSpins; i++)
            game.Spin();
    }
    else
    {
        int marks = 1; // Number of printed marks
        long markerEvery = (long)Math.Ceiling((double)numSpins / (double)10); // print progression marker at every 1/10th of total spins.

        for (long i = 1; i <= numSpins; i++)
        {
            game.Spin();
            if ((i % markerEvery == 0))
            {
                Console.Write("*");
                marks++;
            }
        }

        for (int i = marks; i <= 10; i++)
            Console.Write("*");
    }

    Console.WriteLine();
    game.stats.DisplaySessionStats(numPayLines);

    DateTime end_t = DateTime.Now;
    TimeSpan runtime = end_t - start_t;
    Console.WriteLine("\nRun completed in {0:t}\n", runtime);

} // End method BulkGameSpins

private static void IndividualGames()
{
    LM962 game = new LM962
    {
        printGameboard = true,
        printPaylines = true
        };

    for (; ;) // ever
    {
        Console.Clear(); // clear the console screen
        Console.WriteLine("\nPlaying {0} active paylines.\n", game.activePaylines);

        game.Spin();
        game.stats.DisplayGameStats ();
        game.stats.ResetGameStats();

        Console.WriteLine("Press the P key to change the number of pay lines");
        Console.WriteLine("Press the Escape key to return to the Main Menu");
        Console.WriteLine("\nPress any other key to continue playing.");
        ConsoleKeyInfo cki = Console.ReadKey(true);

        if (cki.KeyChar == 'p')
        {
            getPayLines:
            Console.Write("\nEnter the new number of active paylines (1 through 15):  ");
            int paylines;
            try
            {
                paylines = Convert.ToInt32(Console.ReadLine()); // convert to an int

                if (paylines < 1 || paylines > 15)
                    throw new ArgumentOutOfRangeException();
            }
            catch (Exception)
            {
                Console.WriteLine("\n***ERROR: Please enter a positive number between 1 and 15 !!!");
                goto getPayLines;
            }

            game.activePaylines = paylines;

        } // end if cki.KeyChar == 'p'

        if (cki.Key == ConsoleKey.Escape) // quit when you hit the escape key
            break;
    }  // end for ever

} // End method IndividualGames
作为
No more goto's。不再将异常用于流控制。:
private static int GetIntValue(string prompt, int min, int max, Action onError = null)
{
    while (true)
    {
        Console.Write(prompt);
        string input = Console.ReadLine();
        if (int.TryParse(input, out int value) && min <= value && value <= max)
            return value;
        onError?.Invoke();
    }
}

private static long GetLongValue(string prompt, long min, long max, Action onError = null)
{
    while (true)
    {
        Console.Write(prompt);
        string input = Console.ReadLine();
        if (long.TryParse(input, out long value) && min <= value && value <= max)
            return value;
        onError?.Invoke();
    }
}

private static void RunBulkGameSpins()
{
    var numSpins = GetLongValue("Enter the number of spins: ",
                                min: 1, max: long.MaxValue,
                                () => Console.Error.WriteLine("***ERROR: Please enter a positive number greater than 0 !!!"));

    var paylines = GetIntValue("Enter the number of active paylines (1 through 15): ",
                               min: 1, max: 15,
                               () => Console.Error.WriteLine("***ERROR: Please enter a positive number between 1 and 15 !!!"));

    Console.Clear();
    BulkGameSpins(numSpins, paylines);
    Console.WriteLine("Press any key to continue to Main Menu ...");
    Console.ReadKey();
}

private static string BuildMenuString()
{
    var sb = new StringBuilder();
    sb.AppendLine("PRESS:");
    sb.AppendLine();
    sb.AppendLine("\t1 for Bulk Game Spins");
    sb.AppendLine("\t2 for Individual Games");
    sb.AppendLine("\t3 to quit");
    sb.AppendLine();
    sb.Append("Your choice: ");
    return sb.ToString();
}

public static void Main()
{
    var menu = BuildMenuString();
    int num;
    do
    {
        Console.Clear();

        num = GetIntValue(prompt: menu,
                          min: 1, max: 3,
                          onError: () =>
                          {
                              Console.WriteLine("***ERROR: Please enter number 1, 2, or 3 !!!");
                              Thread.Sleep(2000);
                              Console.Clear();
                          });
        switch (num)
        {
            case 1:
                RunBulkGameSpins();
                break;

            case 2:
                IndividualGames();
                break;
        }
    } while (num != 3);
}

private static void BulkGameSpins(long numSpins, int numPayLines)
{
    LM962 game = new LM962()
    {
        activePaylines = numPayLines
        };

    DateTime start_t = DateTime.Now;

    Console.WriteLine("Progress Bar ({0:N0} spins)\n",numSpins);
    Console.WriteLine("0%       100%");
    Console.WriteLine("|--------|");


    if (numSpins <= 10)
    {
        Console.WriteLine("**********"); // 10 markers
        for (long i = 1; i <= numSpins; i++)
            game.Spin();
    }
    else
    {
        int marks = 1; // Number of printed marks
        long markerEvery = (long)Math.Ceiling((double)numSpins / (double)10); // print progression marker at every 1/10th of total spins.

        for (long i = 1; i <= numSpins; i++)
        {
            game.Spin();
            if ((i % markerEvery == 0))
            {
                Console.Write("*");
                marks++;
            }
        }

        for (int i = marks; i <= 10; i++)
            Console.Write("*");
    }

    Console.WriteLine();
    game.stats.DisplaySessionStats(numPayLines);

    DateTime end_t = DateTime.Now;
    TimeSpan runtime = end_t - start_t;
    Console.WriteLine("\nRun completed in {0:t}\n", runtime);

} // End method BulkGameSpins

private static void IndividualGames()
{
    LM962 game = new LM962
    {
        printGameboard = true,
        printPaylines = true
        };

    while (true)
    {
        Console.Clear();
        Console.WriteLine("\nPlaying {0} active paylines.\n", game.activePaylines);

        game.Spin();
        game.stats.DisplayGameStats ();
        game.stats.ResetGameStats();

        Console.WriteLine("Press the P key to change the number of pay lines");
        Console.WriteLine("Press the Escape key to return to the Main Menu");
        Console.WriteLine("\nPress any other key to continue playing.");
        ConsoleKeyInfo cki = Console.ReadKey(true);

        if (cki.KeyChar == 'p' || cki.KeyChar == 'P')
        {
            game.activePaylines = GetIntValue("\nEnter the new number of active paylines (1 through 15): ",
                                              1, 15,
                                              () => Console.WriteLine("\n***ERROR: Please enter a positive number between 1 and 15 !!!"));
        }

        if (cki.Key == ConsoleKey.Escape)
            break;
    }
}

我已经提交了 拉取要求.
 

跳伞者

工作人员
已加入
2019年4月6日
留言内容
2,612
地点
弗吉尼亚州切萨皮克
编程经验
10+
Why are you "stringly-typed"?您不应该强力输入并使用枚举吗?
C#:
SYMBOLS123 = { "WS", "LM", "BU", "BO", "LH", "TU", "CL", "SG", "SF", "LO", "LT" };

// All 11 game symbols, Corresponds to:
{ "Wild", "Lobstermania", "Buoy", "Boat", "Lighthouse", "Tuna", "Clam", "Seagull", "Starfish", "Bonus", "Scatter" }
顺便说一句,从字符串转换为枚举使我的速度提高了100%。可能是因为可以直接比较int,而不必取消引用字符串才能进行比较。
 

jpm9511

成员
已加入
2020年7月15日
留言内容
5
编程经验
Beginner
如果您的目标之一是真正学习C#,则应遵循C#/ .NET Framework的命名约定。


感谢您抽出宝贵的时间查看我的代码并提供反馈。我很感激。我将学习命名约定并将其应用于本项目以及将来的所有命名约定。感谢您的链接!
 

jpm9511

成员
已加入
2020年7月15日
留言内容
5
编程经验
Beginner
顺便说一句,从字符串转换为枚举使我的速度提高了100%。可能是因为可以直接比较int,而不必取消引用字符串才能进行比较。
好点!我在master分支上的第一个提交基于char数据类型。我改用弦乐使人们更容易理解。第一个版本的运行速度也显着提高(比字符串版本快约100%)。我知道当前使用字符串的版本会花费大部分时间来进行字符串==比较,而不是对其进行性能分析。我什至从未想到使用枚举而不是char。这将满足我对易于理解的代码和速度的需求。
 

跳伞者

工作人员
已加入
2019年4月6日
留言内容
2,612
地点
弗吉尼亚州切萨皮克
编程经验
10+
我没有看到类名称LM962看起来像是在声称的96.2%的投资回报率。承认我只进行了10,000,000次旋转和1,000,000次旋转,而不是全部259,440,000次旋转,但是我希望收益至少始终在90%的高位,而不是80%的中低位。

我没有仔细研究卷轴的组成和分布。我只对看起来与PAR表一致的卷轴长度进行了抽查。
 

jpm9511

成员
已加入
2020年7月15日
留言内容
5
编程经验
Beginner
我没有看到类名称LM962看起来像是在声称的96.2%的投资回报率。承认我只进行了10,000,000次旋转和1,000,000次旋转,而不是全部259,440,000次旋转,但是我希望收益至少始终在90%的高位,而不是80%的中低位。

我没有仔细研究卷轴的组成和分布。我只对看起来与PAR表一致的卷轴长度进行了抽查。

听起来好像您没有将支付线的数量设置为1。您必须使用1条支付线,否则使用的每条额外支付线的投资回报率%都会连续下降。此外,规格表还显示1行的投资回报率%(以及点击率等其他统计信息)。您可以通过更改程序来绝对验证理论上的投资回报%,以便驱动该功能:
GetLinePayout(payLines); //将包括任何奖金赢<<- (LM962:115)
可以在支付线上遍历符号的所有可能组合(11x11x11x10x10)-前3个转盘中的每个转盘有11个符号,其余2个转盘中的每个都只有10个符号。您需要调用GetScatterWin()来获得任何零散胜利(这些胜利是在游戏板级别上而不是线路级别上。顺便说一句,我已经在命中率和投资回报率等方面进行了确定性验证,等等。我的第一次承诺。

由于此模拟器是不确定性的(从支付线上的卷轴上随机选择每个插槽),因此您在1条支付线上进行的运行次数越多,得出的收益将更接近理论上96.2%的票面收益。

程式编号:9
// IMPORTANT NUMBERS
// -----------------
//每个JACKPOT的理论旋转数8,107,500
//所有插槽组合的数量(47x46x48x50x50-每个卷轴1个插槽)= 259,440,000
// 一行上所有可能的符号组合数(11x11x11x10x10)= 133,100



我包括了10M次旋转的屏幕截图,支付线= 1,2次不同的时间,支付线= 15,2次不同的时间。

1595043205787.png



1595043736307.png



1595043933090.png


1595044621472.png
 
最佳 底部