我创建了一个二维数组19,19的标签。在单击时,用户会根据迭代将标签的颜色更改为黑色或白色。当有五个颜色相同的标签水平排列时,我想要一个消息框弹出。这是不需要递归的。任何帮助都将不胜感激。
public partial class Form1 : Form
{
int labelCount = 0;
int iteration = 0;
public Label[,] board = new Label[19,19];
const int WinLength = 5;
const int BoardWidth = 19;
const int BoardHeight = 19;
gamePlay obj = new gamePlay();
public Form1()
{
InitializeComponent();
}
private void labelClick (object sender, EventArgs e)
{
Label x = (Label)sender;
if (x.BackColor == Color.Transparent)
{
if (iteration % 2 == 0)
{
x.BackColor = Color.Black;
}
else
{
x.BackColor = Color.White;
}
iteration++;
}
else
{
}
for (int r = 0; r < BoardHeight; r++)
{
for (int c = 0; c < BoardWidth; c++)
{
if (board[r, c] == x)
{
Color? winner = obj.CheckForWinner(board, r, c);
if (winner == Color.Black)
{
MessageBox.Show("Black is the winner!");
}
else if (winner == Color.White)
{
MessageBox.Show("White is the winner!");
}
// else winner is null, meaning no winner yet.
}
}
}
private int[] FindClickedLabelCoordinates(Label[,] board, Label label)
{
for (int r = 0; r < BoardHeight; r++)
{
for (int c = 0; c < BoardWidth; c++)
{
if (board[r, c] == label)
return new int[] { r, c };
}
}
return null;
}
}
class gamePlay
{
const int WinLength = 5;
const int BoardWidth = 19;
const int BoardHeight = 19;
private Color? CheckForWinner(Label[,] board, int r, int c)
{
Color startColor = board[r, c].BackColor;
for (int c1 = c - WinLength + 1; c1 <= c; c1++)
{
if (c1 >= 0 && c1 < BoardWidth && board[r, c1].BackColor == startColor)
{
MessageBox.Show("you win!");
bool win = true;
for (int c2 = c1 + 1; c2 < c1 + WinLength; c2++)
{
if (c2 < 0 || c2 >= BoardWidth || board[r, c2].BackColor != startColor)
{
win = false;
break;
}
}
if (win)
{
return startColor;
}
}
}
return null;
}发布于 2015-11-18 07:46:46
实际上,您不需要递归来解决这个问题;只是几个嵌套的循环。既然你说你只想从水平上的胜利开始,我就从那里开始。我将使用“石头”一词来表示一块已被点击的空格,使其变成黑色或白色。
如果董事会上没有石头,我们就知道没有获胜的礼物。这是游戏的默认状态。只有5块相同颜色的石头被放置在棋盘上,才能取得胜利。由于一次只放置一块石头,我们将在每次放置之后检查是否获胜,那么最后放置的石头必须是获胜移动的一部分,而获胜的颜色必须是该石头的颜色。这听起来很明显,但这意味着,没有必要检查整个董事会的一次胜利。我们只需要检查可能的胜利,可能涉及最后一块石头放置。此外,我们不需要单独检查它们是否都是黑色或白色的;我们只需要检查它们是否都是与最后一步相同的颜色,不管是什么颜色。
那么,如果唯一可能的获胜条件是横向的,我们需要检查哪些方块?好吧,假设最后一块石头放在一排中间。我们称其为正方形x。如果石头是一场胜利的一部分,而一场胜利是连续5场,那么就有5次可能的胜利,那石头可能是其中的一部分:
{x-4, x-3, x-2, x-1, x}{x-3, x-2, x-1, x, x+1}{x-2, x-1, x, x+1, x+2}{x-1, x, x+1, x+2, x+3}{x, x+1, x+2, x+3, x+4}因此,这表明了一种算法:
但是还有一件事要考虑。如果最后一块石头放在板子的左边或右边呢?例如,如果x是2,那么前两个可能的win序列,分别从x-4和x-3开始,都是无效的,因为它们部分脱离了董事会!因此,我们需要添加一些检查,以确保我们想要查看的空间实际上在边界内。
下面是上面的算法在代码中的样子。r和c参数是最后放置的石头的行和列:
const int WinLength = 5;
const int BoardWidth = 19;
const int BoardHeight = 19;
private Color? CheckForWinner(Label[,] board, int r, int c)
{
Color startColor = board[r, c].BackColor;
for (int c1 = c - WinLength + 1; c1 <= c; c1++)
{
if (c1 >= 0 && c1 < BoardWidth && board[r, c1].BackColor == startColor)
{
bool win = true;
for (int c2 = c1 + 1; c2 < c1 + WinLength; c2++)
{
if (c2 < 0 || c2 >= BoardWidth || board[r, c2].BackColor != startColor)
{
win = false;
break;
}
}
if (win) return startColor;
}
}
return null;
}下面是如何从单击处理程序调用上述方法:
private void labelClick(object sender, EventArgs e)
{
// set background color of clicked label here based on whose turn it is
int[] coords = FindClickedLabelCoordinates(board, (Label)sender);
Color? winner = CheckForWinner(board, coords[0], coords[1]);
if (winner == Color.Black)
{
MessageBox.Show("Black is the winner!");
}
else if (winner == Color.White)
{
MessageBox.Show("White is the winner!");
}
// else winner is null, meaning no winner yet.
}
private int[] FindClickedLabelCoordinates(Label[,] board, Label label)
{
for (int r = 0; r < BoardHeight; r++)
{
for (int c = 0; c < BoardWidth; c++)
{
if (board[r, c] == label)
return new int[] { r, c };
}
}
return null;
}希望这足以让你开始工作。
发布于 2015-11-18 02:05:16
在19x19,他们将需要点击大量的时间来减缓你的程序,即使你确实检查了整个董事会。想一想:,除非你能证明它对你的用例来说太慢,否则不要太早地优化,因为它浪费了你的精力。如果你有点击位置,并且可以找出位置,你可以从那里恢复,试图用同样的颜色找到相邻的位置。
基本的方法是从一个点开始,在保持计数器的同时,从左/右、上/下(或任何您的要求)开始。一旦你达到了成功的状态,你就会一直往上走。
发布于 2015-11-18 16:34:36
首先,定义“水平”。假设它是第一个数组边界x。
然后只需要一个函数来检查一行。
// Has the player won (5 horizontal ticks)?
public bool HasWinner(Label[,] board, Colour player)
{
for (int y = 0; y < 19; y++)
{
if (RowHasLine(y, board, player)
return true;
}
return false;
}
// Returns true if player has a winner in row y
private bool RowHasLine(int y, Label[,] board, Colour player)
{
for (int x = 0; x < 19; x++)
{
if (Ticked(x + 0, y, board, player) &&
Ticked(x + 1, y, board, player) &&
Ticked(x + 2, y, board, player) &&
Ticked(x + 3, y, board, player) &&
Ticked(x + 4, y, board, player))
{
return true;
}
}
return false;
}
// Has the player ticked this box?
private bool Ticked(int x, int y, Label[,] board, Colour player)
{
if (x >= 19 || y >= 19)
return false;
return (board[x][y].BackgroundColor == player);
}https://stackoverflow.com/questions/33770469
复制相似问题