【问题标题】:How to generate new back colour if two object's back colour match?如果两个对象的背景颜色匹配,如何生成新的背景颜色?
【发布时间】:2019-05-11 17:11:20
【问题描述】:

我有一个相当简单的 WCF 程序,用户可以在其中单击两个按钮:
ChangeBackGroundColourChangeButtonColour

WCF 服务从颜色列表中返回一个随机颜色,并且该字符串通过 switch case 语句指示两个对象的颜色。

但是,对象的颜色不能相同。如何阻止重复?

这是我的代码:

前端

public partial class Front_End : Form
{
    RandomColourServiceReference.RandomColoursServiceClient ws = null;
    string BackGroundColour { get; set; }
    string TextColour { get; set; }

    public Front_End()
    {
        InitializeComponent();
    }

    private void Front_End_Load(object sender, EventArgs e)
    {
        ws = new RandomColourServiceReference.RandomColoursServiceClient();
    }

    private void BtnChangeBack_Click(object sender, EventArgs e)
    {
        BackGroundColour = ws.GenerateRandomColour();
        switch (BackGroundColour)
        {
            case "Red":
                this.BackColor = Color.Red;
                break;
            case "Blue":
                this.BackColor = Color.Blue;
                break;
            case "Black":
                this.BackColor = Color.Black;
                break;
            case "Purple":
                this.BackColor = Color.Purple;
                break;
            case "Green":
                this.BackColor = Color.Green;
                break;
        }
    }

    private void BtnChangeButton_Click(object sender, EventArgs e)
    {
        TextColour = ws.GenerateRandomColour();

        switch (TextColour)
        {
            case "Red":
                btnChangeButton.BackColor = Color.Red;
                btnChangeBack.BackColor = Color.Red;
                break;
            case "Blue":
                btnChangeButton.BackColor = Color.Blue;
                btnChangeBack.BackColor = Color.Blue;
                break;
            case "Black":
                btnChangeButton.BackColor = Color.Black;
                btnChangeBack.BackColor = Color.Black;
                break;
            case "Purple":
                btnChangeButton.BackColor = Color.Purple;
                btnChangeBack.BackColor = Color.Purple;
                break;
            case "Green":
                btnChangeButton.BackColor = Color.Green;
                btnChangeBack.BackColor = Color.Green;
                break;
        }
    }
}

RandomColourService

public class RandomColoursService : IRandomColoursService
{
    public string GenerateRandomColour()
    {
        //Declare and initialize a list of string colours
        List<String> colours = new List<String>();
        colours.AddRange(new String[]{ "Red", "Blue", "Green", "Pink", "Purple", "Black"});

        //create new instance of random
        Random rand = new Random();

        //return a random colour in array
        return colours[rand.Next(0, colours.Count)];
    }
}

IRandomColourService

[ServiceContract]
public interface IRandomColoursService
{
    [OperationContract]
    string GenerateRandomColour();
}

我觉得应该涉及一个 while 循环,但我不太确定。

或者也许我应该让 2 个对象从 wcf 返回,而不是只返回一个,然后检查它们在 wcf 中是否重复,如果是,则生成一个新对象?
所以它只会发送 2 种不同的颜色。那会是最好的吗?


*这是尝试添加更多属性后的更新代码

前端

public partial class Front_End : Form
{

    RandomColoursService.RandomColoursServiceClient ws = null;

    /*create two properties that can:385
    A. set the initial colours for the form objects. 
    B. be passed to wcf service as a used color to be removed from the list of colours that could potentially be returned next. */  
    Color BackGroundColour { get; set; } = Color.Blue;
    Color TextColour { get; set; } = Color.Red;
    Color ButtonColour { get; set; } = Color.Black;
    public Front_End()
    {
        //objects are initilized with colours. 
        InitializeComponent();
        btnChangeBack.BackColor = ButtonColour;
        btnChangeButton.BackColor = ButtonColour;
        btnChangeText.BackColor = ButtonColour;
        this.BackColor = BackGroundColour;
        lblTitle.ForeColor = TextColour;
        btnChangeBack.ForeColor = TextColour;
        btnChangeButton.ForeColor = TextColour;
        btnChangeText.ForeColor = TextColour;

    }

    private void Front_End_Load(object sender, EventArgs e)
    {
        //create new instance of wcf service
        ws = new RandomColoursService.RandomColoursServiceClient();

    }

    private void BtnChangeBack_Click(object sender, EventArgs e)
    {
        //This list is populated with the with current colours
        List<Color> UsedColours = new List<Color>() {TextColour, ButtonColour, BackGroundColour};
        //Call for another colour, pass in the current colour to be removed from list. 
        BackGroundColour = ws.GenerateRandomColour(UsedColours);
        //set object colour to returned colour
        this.BackColor = BackGroundColour;

    }

   private void BtnChangeButton_Click(object sender, EventArgs e)
    {
        //This list is populated with the with current colours
        List<Color> UsedColours = new List<Color>() {TextColour, BackGroundColour, ButtonColour};
        //Call for another colour, pass in the current colour to be removed from list. 
        ButtonColour = ws.GenerateRandomColour(UsedColours);
        //set object colour to returned colour
        btnChangeButton.BackColor = ButtonColour;
        btnChangeBack.BackColor = ButtonColour;
        btnChangeText.BackColor = ButtonColour;



    }

    private void BtnChangeText(object sender, EventArgs e)
    {
        //This list is populated with the with current colours
        List<Color> UsedColours = new List<Color>() { BackGroundColour, ButtonColour, TextColour};
        //Call for another colour, pass in the current colour to be removed from list. 
        TextColour = ws.GenerateRandomColour(UsedColours);
        //set object colour to returned colour
        btnChangeButton.ForeColor = TextColour;
        btnChangeBack.ForeColor = TextColour;
        btnChangeText.ForeColor = TextColour;
        lblTitle.ForeColor = TextColour;

    }
}
}

IRandomColoursService

[ServiceContract]
public interface IRandomColoursService
{
    [OperationContract]

    //As a parameter, pass in a list of coloured. 
    //The list will be populated with the current colours on the front end,
    //when a button is clicked a new call is made to wcf.
    Color GenerateRandomColour(List<Color> UsedColours);
}
}

RandomColoursService

    public class RandomColoursService : IRandomColoursService
{
    public Color GenerateRandomColour(List<Color> UsedColours)
    {
        //This is a list of potential colours that wcf can send. 
        List<Color> Colours = new List<Color>()
        {
            Color.Red, Color.Blue, Color.Black, Color.Green, Color.Indigo, Color.Orange
        };

        //This is a list of available colours once the current object colours are removed from the list.
        List<Color> AvailableColours = Colours.Except(UsedColours).ToList();
        Random rand = new Random();
        return Colours[rand.Next(0, AvailableColours.Count)];
    }


}

为了澄清,我应该在调用 wcf 时传递一个 UsedColours 列表。从颜色列表中扣除 UsedColors,然后可用颜色列表保存剩余的颜色。然后每次调用都应该返回可用颜色列表中的一个随机颜色?

我哪里出错了?

【问题讨论】:

    标签: c# winforms wcf random


    【解决方案1】:

    如果您的代码可以修改(包括接口),我建议进行以下更改

    由于您有两个引用所选颜色的属性,您可以分配默认值并使用这些值来设置表单和按钮的初始颜色。

    这些属性随后可用于引用 GenerateRandomColour([Color]) 方法无法选择的已使用颜色。
    传递给方法的 Color 参数在随机选择一个新颜色之前从颜色列表中删除:


    [ServiceContract]
    public interface IRandomColoursService
    {
        [OperationContract]
        Color GenerateRandomColour(Color UsedColor);
    }
    
    public class RandomColoursService : IRandomColoursService
    {
        public Color GenerateRandomColour(Color UsedColor)
        {
            List<Color> colours = new List<Color>() { 
                Color.Red, Color.Blue, Color.Green, Color.Pink, Color.Purple, Color.Black
            };
            colours.Remove(UsedColor);
            Random rand = new Random();
            return colours[rand.Next(0, colours.Count)];
        }
    }
    

    RandomColourServiceReference.RandomColoursServiceClient ws = null;
    
    Color BackGroundColour { get; set; } = Color.Red;
    Color TextColour { get; set; } = Color.Black;
    
    public Front_End()
    {
        InitializeComponent();
        btnChangeButton.BackColor = TextColour;
        btnChangeBack.BackColor = TextColour;
        this.BackColor = BackGroundColour;
    }
    
    private void BtnChangeButton_Click(object sender, EventArgs e)
    {
        TextColour = ws.GenerateRandomColour(BackGroundColour);
        btnChangeButton.BackColor = TextColour;
        btnChangeBack.BackColor = TextColour;
    }
    
    private void BtnChangeBack_Click(object sender, EventArgs e)
    {
        BackGroundColour = GenerateRandomColour(TextColour);
        this.BackColor = BackGroundColour;
    }
    


    更新
    如果要添加更多控件和相关属性,请更改 GenerateRandomColour 方法,使其接受 List&lt;Color&gt; 而不是单个颜色引用。
    (此处使用LINQExcept() 扩展方法来过滤使用另一个列表)
    例如:

    public Color GenerateRandomColour(List<Color> UsedColor)
    {
        List<Color> colours = new List<Color>() { 
            Color.Red, Color.Blue, Color.Green, Color.Pink, Color.Purple, Color.Black
        };
        List<Color> AvailableColours = colours.Except(UsedColor).ToList();
        Random rand = new Random();
        return AvailableColours[rand.Next(0, AvailableColours.Count)];
    }
    

    Color BackGroundColour { get; set; } = Color.Black;
    Color TextColour { get; set; } = Color.Red;
    Color AnotherColour { get; set; } = Color.Green;
    
    private void BtnChangeButton_Click(object sender, EventArgs e)
    {
        List<Color> UsedColors = new List<Color>() { BackGroundColour, AnotherColour };
        TextColour = ws.GenerateRandomColour(UsedColors);
        btnChangeButton.BackColor = TextColour;
        btnChangeBack.BackColor = TextColour;
    }
    
    //(...)
    

    等等。

    但是,如果有很多属性,这可能会变得太麻烦。
    您可以构建一个专门的类,将颜色映射到控件(使用它们的引用或名称),然后用于与GenerateRandomColour() 方法交换信息。

    【讨论】:

    • 天哪。你可以有一个列表或一组颜色!?很高兴知道!我尝试扩展并添加第三个属性,以便有一个按钮来更改背景、按钮和文本颜色。我基本上只是添加了一个额外的参数,但 colours.Remove 只能与 1 个参数一起使用。知道如何从列表中删除 2 个项目吗?还是不能做?
    • 列表可以包含任何内容。如果您需要更改更多属性,请参阅更新以了解可能的替代方法。此处使用List.Except(List) 扩展方法来过滤使用另一个列表。
    • 我得到 “参数 1:无法从 'System.Collections.Generic.List' 转换为 'System.Drawing.Color'” 用于前端每个按钮单击方法的 UsedColors。我已经更新了服务参考,但仍然出现错误。通过代码它应该是所有 List 。任何想法?谢谢吉米。
    • 好吧,再次检查一下 :) (我的意思是将您的代码与更新中的代码进行比较)。看起来您的 GenerateRandomColour() 方法试图返回 List&lt;Color&gt; 而不是 Color。或者类似的东西。
    • 好的,吉米。这应该如何?感觉好像我已经尝试了所有的组合。 :P 虽然老实说我对我的导师这么说然后她告诉我我很愚蠢。如果您好心,我已经对原始代码进行了编辑!
    猜你喜欢
    • 1970-01-01
    • 2020-11-11
    • 1970-01-01
    • 2019-10-31
    • 1970-01-01
    • 2014-10-14
    • 2021-03-16
    • 2011-11-11
    • 1970-01-01
    相关资源
    最近更新 更多