我创建了一个二维数组[19,19]的标签。单击时,用户会根据迭代将标签的颜色更改为黑色或白色。当有五个相同颜色的标签水平,垂直或对角排列时,我想要弹出一个消息框。只有对角线检查不起作用,我不知道为什么。任何帮助将不胜感激。
class gamePlay
{
const int WinLength = 5;
const int BoardWidth = 19;
const int BoardHeight = 19;
const int kwinningCount = 5;
public Color? CheckWinner(Label[,] board)
{
int columnCount = board.GetLength(1), rowCount = board.GetLength(0);
for (int row = 0; row < rowCount; row++)
{
Color? lineResult = CheckWinnerForLine(board, 0, row, columnCount, 1, 0);
if (lineResult != null)
{
return lineResult;
}
if (rowCount - row >= kwinningCount)
{
lineResult = CheckWinnerForLine(board, 0, row, rowCount - row, 1, 1);
if (lineResult != null)
{
return lineResult;
}
}
}
for (int column = 0; column < columnCount; column++)
{
Color? lineResult = CheckWinnerForLine(board, column, 0, rowCount, 0, 1);
if (lineResult != null)
{
return lineResult;
}
if (column > 0 && columnCount - column >= kwinningCount)
{
lineResult =
CheckWinnerForLine(board, column, 0, columnCount - column, 1, 1);
if (lineResult != null)
{
return lineResult;
}
}
}
return null;
}
Color? CheckWinnerForLine(Label[,] board,
int column, int row, int count, int columnIncrement, int rowIncrement)
{
// Initialize from the first cell
int colorCount = 1;
Color currentColor = board[row, column].BackColor;
while (--count > 0)
{
column += columnIncrement;
row += rowIncrement;
Color cellColor = board[row, column].BackColor;
if (currentColor != cellColor)
{
// switched colors, so reset for this cell to be the first of the string
colorCount = 1;
currentColor = cellColor;
}
else if (++colorCount == kwinningCount && cellColor != Color.Transparent)
{
return cellColor;
}
}
return null;
}
public partial class Form1 : Form
{
int iteration = 0;
public Label[,] board = new Label[19,19];
int count;
int columnIncrement;
int rowIncrement;
const int WinLength = 5;
const int BoardWidth = 19;
const int BoardHeight = 19;
gamePlay WinCheck = new gamePlay();
public Form1()
{
InitializeComponent();
int x = this.Location.X + 10;
int y = this.Location.Y + 15;
// create 361 labels, set their properties
for (int i = 0; i < 19; i++)
{
for (int j = 0; j < 19; j++)
{
board[i,j] = new Label();
board[i,j].Parent = this;
board[i,j].Name = "label" + i;
//board[i,j].BackColor = System.Drawing.ColorTranslator.FromHtml("#DBB262");
board[i,j].BackColor = Color.Transparent;
//board[i, j].StyleChanged = Opacity
//set size of labels
board[i,j].Size = new Size(30, 30);
//initialize click event handler
this.board[i,j].Click += new System.EventHandler(this.labelClick);
this.Controls.Add(board[i,j]);
board[i,j].BringToFront();
}
}
// set the position of the label
for (int i = 0; i < 19; i++)
{
for (int j = 0; j < 19; j++)
{
board[i,j].Location = new Point(x, y);
//set distance between labels
if (x >= 755)
{
x = this.Location.X + 10;
y += 42;
}
else
{
x += 43;
}
}
}
}
private void labelClick (object sender, EventArgs e)
{
Label clickedLabel = (Label)sender;
if (clickedLabel.BackColor == Color.Transparent)
{
if (iteration % 2 == 0)
{
clickedLabel.BackColor = Color.Black;
}
else
{
clickedLabel.BackColor = Color.White;
}
iteration++;
}
else
{
}
for (int row = 0; row < BoardHeight; row++)
{
for (int column = 0; column < BoardWidth; column++)
{
if (board[row, column] == clickedLabel)
{
Color? winner = WinCheck.CheckWinner(board);
if (winner == Color.Black)
{
MessageBox.Show("Black is the winner!");
}
else if (winner == Color.White)
{
MessageBox.Show("White is the winner!");
}
}
}
}
}
private int[] FindClickedLabelCoordinates(Label[,] board, Label label)
{
for (int row = 0; row < BoardHeight; row++)
{
for (int column = 0; column < BoardWidth; column++)
{
if (board[row, column] == label)
return new int[] { row, column };
}
}
return null;
}
答案 0 :(得分:1)
你不需要复述,但有点修改循环:
private static Boolean IsWon(Label[,] board) {
if (null == board)
return false;
// Let code not be that rigid: "5" can be easily updated
const int atLeast = 5;
// Do not use magic numbers - i.e. "19"
for (int i = 0; i < board.GetLength(0); ++i) {
Color current = board[i, 0].BackColor;
int count = 1;
for (int j = 1; j < board.GetLength(1); ++j) { // note j = 1
if (current == board[i, j].BackColor) {
count += 1;
if (count >= atLeast)
return true;
}
else {
current = board[i, j].BackColor;
count = 1;
}
}
}
return false;
}
public void checkWinner(Label[,] board) {
if (IsWon(board))
MessageBox.Show("You Win!");
}
作为进一步改进,将模型(即游戏字段 - board [,])及其表示(Label
s分离在表单上)。
答案 1 :(得分:1)
<强>&LT;编辑&gt; 强>
正如您的后续问题Aligning labels in array of same backcolor diagonally in C#所表明的那样,您无法概括此处提供的解决方案,以便与您对计划感兴趣的其他两个方向一致。
所以我已经编辑了这个问题的答案,以更一般的方式在这里解决你的问题,这样它也可以修复你的对角线和垂直问题。请参阅下面的更新代码。
的&LT; /编辑&gt; 强>
当然,不需要递归。我还建议寻找具有扩展if
表达式的特定模式是浪费的,并且对于您编写的代码,无论如何都不会工作。事实上,避免像这样的复杂表达的一个原因是它们很容易出错。
这是一种方法,对于每一行,扫描行以查找相同颜色的五个字符串。一旦找到这样的字符串,它就会返回找到的Color
值(这样调用者就可以判断它是黑色还是白色)。如果未找到此类字符串,则返回null
。换句话说,一个非空值告诉你有人赢了,它也告诉你哪个牌手赢了。
<强>&LT;编辑&gt; 强>
这个新版本以一般方式完成上述操作。即上一段描述了扫描行时实现的工作原理。它将对角线和水平线进行类似的操作。它通过让main方法为您要检查的给定水平线,对角线和垂直线生成适当的起点和单元计数,然后调用实际工作以查找相同字符串的通用方法来实现此目的。颜色依次。
的&LT; /编辑&gt; 强>
<强> GamePlay.cs:强>
class GamePlay
{
private readonly int _winLength = 5;
public GamePlay(int winLength)
{
_winLength = winLength;
}
public Color? CheckWinner(Label[,] board)
{
return CheckWinnerIterator(board).FirstOrDefault(color => color != null);
}
private IEnumerable<Color?> CheckWinnerIterator(Label[,] board)
{
int columnCount = board.GetLength(1), rowCount = board.GetLength(0);
for (int row = 0; row < rowCount; row++)
{
// Horizontal
yield return CheckWinnerForLine(board, 0, row, columnCount, 1, 0);
// Diagonals starting in first column, upper-left to lower-right
yield return CheckWinnerForLine(board, 0, row, rowCount - row, 1, 1);
// Diagonals starting in first column, lower-left to upper-right
yield return CheckWinnerForLine(board, 0, row, row + 1, 1, -1);
}
for (int column = 0; column < columnCount; column++)
{
// Vertical
yield return CheckWinnerForLine(board, column, 0, rowCount, 0, 1);
// Diagonals starting in first row, upper-left to lower-right
yield return CheckWinnerForLine(board, column, 0, columnCount - column, 1, 1);
// Diagonals starting in last row, lower-left to upper-right
yield return CheckWinnerForLine(board, column, rowCount - 1, columnCount - column, 1, -1);
}
}
Color? CheckWinnerForLine(Label[,] board,
int column, int row, int count, int columnIncrement, int rowIncrement)
{
if (count < _winLength)
{
return null;
}
// Initialize from the first cell
int colorCount = 1;
Color currentColor = board[row, column].BackColor;
while (--count > 0)
{
column += columnIncrement;
row += rowIncrement;
Color cellColor = board[row, column].BackColor;
if (currentColor != cellColor)
{
// switched colors, so reset for this cell to be the first of the string
colorCount = 1;
currentColor = cellColor;
}
else if (++colorCount == _winLength && cellColor != Color.Transparent)
{
return cellColor;
}
}
return null;
}
}
<强> Form1.cs的强>
public partial class Form1 : Form
{
const int WinLength = 5;
const int BoardWidth = 19;
const int BoardHeight = 19;
private bool isBlackTurn = true;
private Label[,] board = new Label[BoardHeight, BoardWidth];
private GamePlay WinCheck = new GamePlay(WinLength);
public Form1()
{
InitializeComponent();
int x = this.Location.X + 10;
int y = this.Location.Y + 15;
// create 361 labels, set their properties
for (int i = 0; i < BoardHeight; i++)
{
for (int j = 0; j < BoardWidth; j++)
{
Label label = new Label();
label.Parent = this;
label.Name = "label" + i;
label.BackColor = Color.Transparent;
label.BorderStyle = BorderStyle.FixedSingle;
label.Size = new Size(30, 30);
label.Click += new System.EventHandler(this.labelClick);
this.Controls.Add(board[i, j]);
label.BringToFront();
board[i, j] = label;
}
}
// set the position of the label
for (int i = 0; i < BoardHeight; i++)
{
for (int j = 0; j < BoardWidth; j++)
{
board[i, j].Location = new Point(x, y);
//set distance between labels
if (x >= 755)
{
x = this.Location.X + 10;
y += 42;
}
else
{
x += 43;
}
}
}
}
private void labelClick(object sender, EventArgs e)
{
Label clickedLabel = (Label)sender;
if (clickedLabel.BackColor != Color.Transparent)
{
return;
}
clickedLabel.BackColor = isBlackTurn ? Color.Black : Color.White;
isBlackTurn = !isBlackTurn;
Color? winner = WinCheck.CheckWinner(board);
if (winner == Color.Black)
{
MessageBox.Show("Black is the winner!");
}
else if (winner == Color.White)
{
MessageBox.Show("White is the winner!");
}
else
{
return;
}
foreach (Label label in board)
{
label.BackColor = Color.Transparent;
}
}
}
<强>&LT;编辑&gt; 强>
注意:以上代码不仅代表了胜利测试的更正版本,而且代表了代码的重大清理:
FindClickedLabelCoordinates()
方法以及一些字段,因为它们都未使用过。labelClick()
方法的复杂性。它有相当多的冗余和过于冗长的实施细节;我已经将该方法减少到接近所需的最低代码。Label
周围添加了一个边框,以便我更容易看到我应该/可以点击的位置。最后,在您的评论中,您有以下问题:
宣布获胜者后,每增加一次点击白色赢得
后,就会弹出一个消息框
是的,在您的代码版本中,这将会发生,因为代码会在每次点击后检查获胜者,这会改变董事会状态(应该如此),一旦有胜利者,除非您有胜利者重置电路板。因此,每次点击都会导致检测到胜利者。我已经在labelClick()
中添加了上面的代码,如果找到了胜利者则继续重置电路板。
的&LT; /编辑&gt; 强>
对于笑嘻嘻(因此我可以仔细检查我的工作,因为OP没有提供完整的代码示例,可以通过测试来验证答案),这里是一个快速而肮脏的WPF程序,它包含了上述方法(稍加修改一下):
<强> XAML:强>
<Window x:Class="TestSO33773260FiveInARow.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:l="clr-namespace:TestSO33773260FiveInARow"
Title="MainWindow" Height="525" Width="525">
<ItemsControl ItemsSource="{Binding Board}" Background="AliceBlue">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<UniformGrid x:Name="uniformGrid1" Rows="{Binding Rows}" Columns="{Binding Columns}" IsItemsHost="True"/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate DataType="l:BoardCell">
<Rectangle Fill="{Binding Color}" MouseUp="Rectangle_MouseUp"/>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</Window>
<强> C#:强>
public partial class MainWindow : Window
{
private const int _kwinningCount = 5;
public int Rows { get; set; }
public int Columns { get; set; }
public List<BoardCell> Board { get; set; }
public MainWindow()
{
InitializeComponent();
Rows = 19;
Columns = 19;
Board = new List<BoardCell>(Enumerable.Range(0, Rows * Columns)
.Select(i => new BoardCell { Color = Brushes.Transparent }));
DataContext = this;
}
private void Rectangle_MouseUp(object sender, MouseButtonEventArgs e)
{
BoardCell boardCell = (BoardCell)((FrameworkElement)sender).DataContext;
boardCell.IncrementColor();
Color? winningColor = CheckWinner();
if (winningColor != null)
{
MessageBox.Show(winningColor.Value.GetFriendlyName() + " won!");
}
}
private Color _GetColorForBoardCell(int column, int row)
{
return Board[column + row * Rows].Color.Color;
}
public Color? CheckWinner()
{
return CheckWinnerIterator().FirstOrDefault(color => color != null);
}
private IEnumerable<Color?> CheckWinnerIterator()
{
int columnCount = Columns, rowCount = Rows;
for (int row = 0; row < rowCount; row++)
{
// Horizontal
yield return CheckWinnerForLine(0, row, columnCount, 1, 0);
// Diagonals starting in first column, upper-left to lower-right
yield return CheckWinnerForLine(0, row, rowCount - row, 1, 1);
// Diagonals starting in first column, lower-left to upper-right
yield return CheckWinnerForLine(0, row, row + 1, 1, -1);
}
for (int column = 0; column < columnCount; column++)
{
// Vertical
yield return CheckWinnerForLine(column, 0, rowCount, 0, 1);
// Diagonals starting in first row, upper-left to lower-right
yield return CheckWinnerForLine(column, 0, columnCount - column, 1, 1);
// Diagonals starting in last row, lower-left to upper-right
yield return CheckWinnerForLine(column, rowCount - 1, columnCount - column, 1, -1);
}
}
Color? CheckWinnerForLine(int column, int row, int count, int columnIncrement, int rowIncrement)
{
// Initialize from the first cell
int colorCount = 1;
Color currentColor = _GetColorForBoardCell(column, row);
while (--count > 0)
{
column += columnIncrement;
row += rowIncrement;
Color cellColor = _GetColorForBoardCell(column, row);
if (currentColor != cellColor)
{
// switched colors, so reset for this cell to be the first of the string
colorCount = 1;
currentColor = cellColor;
}
else if (++colorCount == _kwinningCount && cellColor != Colors.Transparent)
{
return cellColor;
}
}
return null;
}
}
public class BoardCell : INotifyPropertyChanged
{
private static readonly SolidColorBrush[] _colors =
{ Brushes.Transparent, Brushes.White, Brushes.Black };
private int _colorIndex;
public SolidColorBrush Color
{
get { return _colors[_colorIndex]; }
set
{
if (value != _colors[_colorIndex])
{
_SetColorIndex(Array.IndexOf(_colors, value));
}
}
}
public event PropertyChangedEventHandler PropertyChanged;
private void _OnPropertyChanged([CallerMemberName]string propertyName = null)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(propertyName));
}
}
public void IncrementColor()
{
_SetColorIndex(_colorIndex < _colors.Length - 1 ? _colorIndex + 1 : 0);
}
private void _SetColorIndex(int colorIndex)
{
_colorIndex = colorIndex;
_OnPropertyChanged("Color");
}
}
static class Extensions
{
private static readonly Lazy<Dictionary<Color, string>> _colorToName =
new Lazy<Dictionary<Color, string>>(() => GetColorToNameDictionary());
private static Dictionary<Color, string> GetColorToNameDictionary()
{
Dictionary<Color, string> colorToName = new Dictionary<Color, string>();
foreach (PropertyInfo pi in
typeof(Colors).GetProperties(BindingFlags.Static | BindingFlags.Public))
{
if (pi.PropertyType == typeof(Color))
{
colorToName[(Color)pi.GetValue(null)] = pi.Name;
}
}
return colorToName;
}
public static string GetFriendlyName(this Color color)
{
string name;
if (_colorToName.Value.TryGetValue(color, out name))
{
return name;
}
return color.ToString();
}
}
答案 2 :(得分:0)
private void Check(Label[,] board)
{
int Checker = 0;
for (int i = 0; i < 19; i++)
{
for (int j = 0; j < 19; j++)
{
if (board[i, j].BackColor == Color.Black)
Checker++;
else
Checker = 0;
if (Checker == 5)
{
MessageBox.Show("You WON....!");
return;
}
}
}
}
答案 3 :(得分:0)
它不仅仅是for循环可以得到那个结果。您也可以尝试一些linq
。我试图连续5次找到“1”..下面的代码工作正常。
int countItemNeed = 5;
string[,] arr = new string[7, 6]
{
{"0", "1", "1", "1", "0", "1"},
{"1", "0", "1", "1", "1", "0"},
{"1", "0", "1", "1", "1", "0"},
{"1", "0", "1", "1", "1", "0"},
{"1", "0", "1", "1", "1", "0"},
{"1", "0", "1", "1", "1", "0"},
{"1", "0", "1", "1", "1", "1"},
};
//convert the 2d array to list of object - List<new{string,index}>
var oneList = arr.Cast<string>()
.Select((s,i)=> new {s,i});
// convert the List to into sub list. one for each row in 2D array
var multipleList = new List<List<Tuple<string, int>>>();
//Size of the row - mean column in a row.
int size = arr.GetLength(1);
while (oneList.Any())
{
multipleList.Add(oneList
.Take(size)
.Select(c=>Tuple.Create(c.s, c.i%size)).ToList());
oneList = oneList.Skip(size).ToList();
}
// check each row. then check each item if we have all 5 items as same.
var foundContinueItems = multipleList.Any(list =>
{
return list.Any(c =>
{
if (c.Item2 > size - countItemNeed)
{
return false;
}
return list.Skip(c.Item2)
.Take(countItemNeed)
.All(d => d.Item1 == "1");
});
});