简体   繁体   English

随机生成器代码?

[英]Random Generator Code?

I'm trying to get this code to produce an array comprising unique random musical notes. 我正在尝试获取此代码以生成包含唯一随机音符的数组。 It will, based on parameters given make a note and assign an accidental sign to it, with a possibility of either displaying as its flat or sharp counterpart. 它会根据给定的参数做一个注释并为它分配一个偶然的符号,并可能显示为平坦或清晰的对应符号。 For example, if the random generator said the note "A" will be flat, there's a chance it will show up as either A♭ or G♯. 例如,如果随机生成器说音符“ A”将是平坦的,则很有可能会显示为A♯或G♯。

Now, I haven't handled the half-step notes (eg C♭ is turned into B♯, etc.), but that's mainly because the first part isn't working. 现在,我还没有处理半音符(例如,C♭变成B♯等),但这主要是因为第一部分无法正常工作。 The problem I have now is the code I'm using doesn't seem to work consistently. 我现在遇到的问题是我使用的代码似乎无法始终如一地工作。 It will correctly translate the notes at some times and mess them up on others. 它将在某些时候正确翻译笔记,并在其他时候将它们弄乱。 There's no systematic pattern of error, either, at least, not from I've tried to decipher. 至少也没有系统的错误模式,这不是我尝试破译的。

I'm using XNA for this to display the notes on the screen, but the real problem is with the data. 我正在为此使用XNA在屏幕上显示注释,但真正的问题在于数据。 I'm using a Note class I made. 我正在使用自己制作的Note类。

Here's the code I'm using: 这是我正在使用的代码:

First the Note class: 首先是Note类:

 public class Note
    {
        public enum Notes
        {
            A = 0,
            B = 1,
            C = 2,
            D = 3,
            E = 4,
            F = 5,
            G = 6
        }
        public Notes noteLetter { get; private set; }
        public Notes translatedLetter { get; private set; }
        public bool isFlat { get; private set; }
        public bool showSharp { get; private set; }

        private const int NOTE_COUNT = 7;

        /// <summary>
        /// Creates a Note
        /// </summary>
        /// <param name="note">The basic note</param>
        /// <param name="flat">Is the note flat?</param>
        /// <param name="sharp">Will be shown as it's sharp counterpart?</param>
        public Note(Notes note, bool flat, bool sharp)
        {
            noteLetter = note;
            isFlat = flat;
            showSharp = sharp;

            if (isFlat && showSharp)
            {
                int hashCode = (int)noteLetter;
                translatedLetter = (Notes)((hashCode + NOTE_COUNT - 1) % NOTE_COUNT);
            }
            else
            {
                translatedLetter = noteLetter;
                showSharp = isFlat;
            }

        }
    }

Then the Game1.cs file: 然后是Game1.cs文件:

 public class Game1 : Microsoft.Xna.Framework.Game
    {
        GraphicsDeviceManager graphics;
        SpriteBatch spriteBatch;

        KeyboardState KeyBState, prevKeybState;

        Texture2D sprite;

        Rectangle noteSource;
        Rectangle accSource;

        const int ACCIDENTAL_START_X = 840;

        const int BORDER_OFFSET = 12;

        Vector2 notePosition;

        SpriteFont font;

        /// <summary>
        /// The array of notes, row/column format
        /// </summary>
        Note[,] box;

        const int ROW_SIZE = 3, COLUMN_SIZE = 4;

        public Game1()
        {
            graphics = new GraphicsDeviceManager(this);
            Content.RootDirectory = "Content";

            box = new Note[ROW_SIZE, COLUMN_SIZE];
            noteSource = new Rectangle(0, 0, 120, 120);
            accSource = new Rectangle(ACCIDENTAL_START_X, 0, 50, 50);

            notePosition = Vector2.Zero;
        }


        protected override void Initialize()
        {
            // TODO: Add your initialization logic here
            MakeTable();

            base.Initialize();
        }


        protected override void LoadContent()
        {
            // Create a new SpriteBatch, which can be used to draw textures.
            spriteBatch = new SpriteBatch(GraphicsDevice);
            sprite = Content.Load<Texture2D>("Note Pieces2");
            font = Content.Load<SpriteFont>("font");
            // TODO: use this.Content to load your game content here
        }


        protected override void UnloadContent()
        {
            // TODO: Unload any non ContentManager content here
        }


        protected override void Update(GameTime gameTime)
        {
            // Allows the game to exit
            KeyBState = Keyboard.GetState();

            if (KeyBState.IsKeyDown(Keys.Escape))
                this.Exit();

            if (KeyBState.IsKeyDown(Keys.Space) && prevKeybState.IsKeyUp(Keys.Space))
                MakeTable();

            // TODO: Add your update logic here
            prevKeybState = KeyBState;
            base.Update(gameTime);
        }


        protected override void Draw(GameTime gameTime)
        {
            GraphicsDevice.Clear(Color.CornflowerBlue);

            // TODO: Add your drawing code here
            spriteBatch.Begin();
            for (int r = 0; r < ROW_SIZE; r++)
            {
                for (int c = 0; c < COLUMN_SIZE; c++)
                {
                    Note temp = box[r, c];
                    notePosition.Y = r * noteSource.Width + (r * BORDER_OFFSET);
                    notePosition.X = c * noteSource.Height + (c * BORDER_OFFSET);
                    noteSource.X = temp.translatedLetter.GetHashCode() * noteSource.Width;

                    spriteBatch.Draw(sprite, notePosition, noteSource, Color.White);

                    notePosition.X += noteSource.Width / 2;
                    notePosition.Y += 7;

                    spriteBatch.DrawString(font,
                        temp.noteLetter.ToString() +
                        (temp.isFlat ? "b " : "  ") +
                        temp.translatedLetter +
                        (temp.showSharp ? "#" : ""), notePosition, Color.Black);

                    notePosition.X -= noteSource.Width / 2;
                    notePosition.Y -= 7;

                    if (temp.isFlat)
                    {
                        notePosition.X += 63;
                        notePosition.Y += 63;

                        accSource.X = ACCIDENTAL_START_X;
                        accSource.Y = 0;
                        if (temp.showSharp)
                        {
                            accSource.X += (temp.translatedLetter.GetHashCode() % 2) * (accSource.Width * 2);
                            accSource.Y += ((int)(temp.translatedLetter.GetHashCode() / 2)) * accSource.Height;
                            spriteBatch.Draw(sprite, notePosition, accSource, Color.White);
                        }
                        /*
                    else
                    {
                        accSource.X += (temp.translatedLetter.GetHashCode() % 2) * (accSource.Width * 2) + accSource.Width;
                        accSource.Y += ((int)(temp.translatedLetter.GetHashCode() / 2)) * accSource.Height;
                        spriteBatch.Draw(sprite, notePosition, accSource, Color.White);
                    }
                    */
                    }

                }
            }
            spriteBatch.End();
            base.Draw(gameTime);
        }

        /// <summary>
        /// Makes a new random table of notes
        /// </summary>
        private void MakeTable()
        {
            //make everything null
            for (int r = 0; r < ROW_SIZE; r++)
            {
                for (int c = 0; c < COLUMN_SIZE; c++)
                {
                    box[r, c] = null;
                }
            }

            //then start
            Random rand = new Random();
            for (int i = 0; i < 12; i++)
            {
                bool isUnique;
                bool noteEntered;

                do
                {
                    Note newNote = new Note((Note.Notes)rand.Next(0, 7),
                                rand.Next(0, 2) == 0 ? true : false,
                                rand.Next(0, 2) == 0 ? true : false);

                    isUnique = true;
                    noteEntered = false;
                    //Check to see if there exists a note like this
                    for (int r = 0; r < ROW_SIZE; r++)
                    {
                        for (int c = 0; c < COLUMN_SIZE; c++)
                        {
                            Note temp = box[r, c];
                            if (noteEntered || !isUnique)
                                continue;
                            else if (temp != null &&
                                temp.noteLetter == newNote.noteLetter &&
                                temp.isFlat == newNote.isFlat)
                            {
                                isUnique = false;
                            }
                            else if (temp == null)
                            {
                                box[r, c] = newNote;
                                noteEntered = true;
                            }

                        }
                    }
                } while (!isUnique);
            }
        }
    }

The main code running everything is the MakeTable() method, but I put in everything just in case there's a problem somewhere else. 运行所有内容的主要代码是MakeTable()方法,但是我放置了所有内容,以防万一其他地方有问题。 To the best of my knowledge, other than graphics libraries, I'm not using any libraries related to the XNA Framework that would cause this to go wrong. 据我所知,除图形库外,我没有使用任何与XNA Framework相关的库,这会导致此错误。 I'm using a rebuild of XNA made by CodePlex. 我正在使用CodePlex进行的XNA重建。 I know they're still working on some things, but this shouldn't be an issue. 我知道他们仍在做某些事情,但这不应该成为问题。 Can someone help me with this? 有人可以帮我弄这个吗?

I figured it out now. 我现在想通了。 I took Lee Daniel Crocker's advice, and fixed up my program. 我接受了李·丹尼尔·克罗克(Lee Daniel Crocker)的建议,并确定了我的程序。 I made a 12-value enum, and I edited the MakeTable() method so that it pulls each note from a distinct set and feeds them randomly into another array. 我做了一个12值的枚举,并编辑了MakeTable()方法,以便它从不同的集合中提取每个音符,并将它们随机地馈送到另一个数组中。 Additionally, I fixed up my picture so that I can draw it easier. 另外,我固定了我的图片,以便可以更轻松地绘制它。 In hindsight, even I don't know why I did what I originally did. 事后看来,即使也不知道为什么我做我原来的工作。

By the way, I moved MakeTable() to the Note class to make it easier to write MakeTable() . 顺便说一句,我将MakeTable()移至Note类,以使其更易于编写MakeTable()

Here's my code: 这是我的代码:

First, Note : 首先, Note

    /// <summary>
    /// A musical note
    /// </summary>
    public class Note
    {
        public enum Notes
        {
            Ab = 10,
            A = 0,
            Bb = 11,
            B = 1,
            C = 2,
            Db = 13,
            D = 3,
            Eb = 14,
            E = 4,
            F = 5,
            Gb = 16,
            G = 6
        }
        /// <summary>
        /// This holds the notes with accidentals
        /// </summary>
        public Notes noteLetter { get; private set; }
        /// <summary>
        /// this holds the note without any accidentals
        /// </summary>
        public Notes naturalLetter { get; private set; }
        /// <summary>
        /// Holds the value of the note if showsharp is true
        /// </summary>
        public Notes translatedLetter { get; private set; }
        /// <summary>
        /// Denotes whether or not the note will represented
        /// as its sharp counterpart, its prerequisite being
        /// that it was flat in the first place
        /// </summary>
        public bool showSharp { get; private set; }

        /// <summary>
        /// Creates a Note
        /// </summary>
        /// <param name="note">The basic note</param>
        /// <param name="sharp">Will be shown as it's sharp counterpart?</param>
        public Note(Notes note, bool sharp)
        {
            noteLetter = note;
            switch(noteLetter)
            {
                case Notes.Ab:
                    naturalLetter = Notes.A;
                    translatedLetter = Notes.G;
                    break;
                case Notes.Bb:
                    naturalLetter = Notes.B;
                    translatedLetter = Notes.A;
                    break;
                case Notes.Db:
                    naturalLetter = Notes.D;
                    translatedLetter = Notes.C;
                    break;
                case Notes.Eb:
                    naturalLetter = Notes.E;
                    translatedLetter = Notes.D;
                    break;
                case Notes.Gb:
                    naturalLetter = Notes.G;
                    translatedLetter = Notes.F;
                    break;
                default:
                    naturalLetter = noteLetter;
                    break;
            }
            showSharp = sharp;

            if (showSharp)
            {
                switch (noteLetter)
                {
                    case Notes.A:
                    case Notes.B:
                    case Notes.C:
                    case Notes.D:
                    case Notes.E:
                    case Notes.F:
                    case Notes.G:
                        showSharp = false;
                        break;
                }
            }

        }

        /// <summary>
        /// Will make a random table of Note objects
        /// </summary>
        /// <param name="table">the array in which to place the Note objects</param>
        public static void MakeTable(out Note[,] table)
        {
            Note[,] temp = new Note[3, 4];

            Random rand = new Random();

            temp[0, 0] = new Note(Notes.Ab, (rand.Next(0, 2) == 0 ? true : false));
            temp[0, 1] = new Note(Notes.A, (rand.Next(0, 2) == 0 ? true : false));
            temp[0, 2] = new Note(Notes.Bb, (rand.Next(0, 2) == 0 ? true : false));
            temp[0, 3] = new Note(Notes.B, (rand.Next(0, 2) == 0 ? true : false));
            temp[1, 0] = new Note(Notes.C, (rand.Next(0, 2) == 0 ? true : false));
            temp[1, 1] = new Note(Notes.Db, (rand.Next(0, 2) == 0 ? true : false));
            temp[1, 2] = new Note(Notes.D, (rand.Next(0, 2) == 0 ? true : false));
            temp[1, 3] = new Note(Notes.Eb, (rand.Next(0, 2) == 0 ? true : false));
            temp[2, 0] = new Note(Notes.E, (rand.Next(0, 2) == 0 ? true : false));
            temp[2, 1] = new Note(Notes.F, (rand.Next(0, 2) == 0 ? true : false));
            temp[2, 2] = new Note(Notes.Gb, (rand.Next(0, 2) == 0 ? true : false));
            temp[2, 3] = new Note(Notes.G, (rand.Next(0, 2) == 0 ? true : false));

            table = new Note[3, 4];

            for (int i = 0; i < 12; i++)
            {
                int row;
                int col;

                row = rand.Next(0, 3);
                col = rand.Next(0, 4);

                while (table[row, col] != null)
                {
                    //Randomly choose if either the row or column will be incremented
                    bool useRow = (rand.Next(0, 2) == 0 ? true : false);

                    //then increment one of them
                    if (useRow)
                    {
                        row = (row + 1) % 3;
                    }
                    else
                    {
                        col = (col + 1) % 4;
                    }
                }

                //Place notes in the empty registers
                if (table[row, col] == null)
                {
                    table[row, col] = temp[(int)(i / 4), i % 4];
                }
            }
        }
    }

And Game1 : Game1

/// <summary>
/// This is the main type for your game
/// </summary>
public class Game1 : Microsoft.Xna.Framework.Game
{
    GraphicsDeviceManager graphics;
    SpriteBatch spriteBatch;

    KeyboardState KeyBState, prevKeybState;

    Texture2D sprite;

    Rectangle noteSource;
    Rectangle accSource;

    const int ACCIDENTAL_START_X = 840;

    const int BORDER_OFFSET = 12;

    Vector2 notePosition;

    SpriteFont font;

    /// <summary>
    /// The array of notes, row/column format
    /// </summary>
    Note[,] box;

    const int ROW_SIZE = 3, COLUMN_SIZE = 4;

    public Game1()
    {
        graphics = new GraphicsDeviceManager(this);
        Content.RootDirectory = "Content";

        box = new Note[ROW_SIZE, COLUMN_SIZE];
        noteSource = new Rectangle(0, 0, 120, 120);
        accSource = new Rectangle(ACCIDENTAL_START_X, 0, 50, 50);

        notePosition = Vector2.Zero;
    }

    /// <summary>
    /// Allows the game to perform any initialization it needs to before starting to run.
    /// This is where it can query for any required services and load any non-graphic
    /// related content.  Calling base.Initialize will enumerate through any components
    /// and initialize them as well.
    /// </summary>
    protected override void Initialize()
    {
        // TODO: Add your initialization logic here
        Note.MakeTable(out box);

        base.Initialize();
    }

    /// <summary>
    /// LoadContent will be called once per game and is the place to load
    /// all of your content.
    /// </summary>
    protected override void LoadContent()
    {
        // Create a new SpriteBatch, which can be used to draw textures.
        spriteBatch = new SpriteBatch(GraphicsDevice);
        sprite = Content.Load<Texture2D>("Note Pieces2");
        font = Content.Load<SpriteFont>("font");
        // TODO: use this.Content to load your game content here
    }

    /// <summary>
    /// UnloadContent will be called once per game and is the place to unload
    /// all content.
    /// </summary>
    protected override void UnloadContent()
    {
        // TODO: Unload any non ContentManager content here
    }

    /// <summary>
    /// Allows the game to run logic such as updating the world,
    /// checking for collisions, gathering input, and playing audio.
    /// </summary>
    /// <param name="gameTime">Provides a snapshot of timing values.</param>
    protected override void Update(GameTime gameTime)
    {
        // Allows the game to exit
        KeyBState = Keyboard.GetState();

        if (KeyBState.IsKeyDown(Keys.Escape))
            this.Exit();

        if (KeyBState.IsKeyDown(Keys.Space) && prevKeybState.IsKeyUp(Keys.Space))
            Note.MakeTable(out box);

        // TODO: Add your update logic here
        prevKeybState = KeyBState;
        base.Update(gameTime);
    }

    /// <summary>
    /// This is called when the game should draw itself.
    /// </summary>
    /// <param name="gameTime">Provides a snapshot of timing values.</param>
    protected override void Draw(GameTime gameTime)
    {
        GraphicsDevice.Clear(Color.CornflowerBlue);

        // TODO: Add your drawing code here
        spriteBatch.Begin();
        for (int r = 0; r < ROW_SIZE; r++)
        {
            for (int c = 0; c < COLUMN_SIZE; c++)
            {
                Note temp = box[r, c];
                notePosition.Y = r * noteSource.Width + ((r + 1) * BORDER_OFFSET);
                notePosition.X = c * noteSource.Height + ((c + 1) * BORDER_OFFSET);
                noteSource.X = (temp.showSharp ? (int)temp.translatedLetter : (int)temp.naturalLetter) * noteSource.Width;

                spriteBatch.Draw(sprite, notePosition, noteSource, Color.White);

                notePosition.X += noteSource.Width / 2;
                notePosition.Y += 7;

                spriteBatch.DrawString(font,
                    temp.noteLetter.ToString() + " " +
                    (temp.showSharp ? "#" : ""), notePosition, Color.Black);

                notePosition.X -= noteSource.Width / 2;
                notePosition.Y -= 7;

                switch (temp.noteLetter)
                {
                    case Note.Notes.Ab:
                    case Note.Notes.Bb:
                    case Note.Notes.Db:
                    case Note.Notes.Eb:
                    case Note.Notes.Gb:
                        notePosition.X += 63;
                        notePosition.Y += 63;

                        int accOffset = 0;
                        if (temp.showSharp)
                        {
                            accSource.X = (int)temp.translatedLetter * noteSource.Width;
                        }
                        else
                        {
                            accSource.X = (int)temp.naturalLetter * noteSource.Width;
                            accOffset = accSource.Width;
                        }

                        accSource.X += accOffset;
                        accSource.Y = noteSource.Height;
                        spriteBatch.Draw(sprite, notePosition, accSource, Color.White);
                        break;
                }

            }
        }
        spriteBatch.End();
        base.Draw(gameTime);
      }
    }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM