我有这个方法来检查在Reversi中是否可以移动。这个方法可以正常工作,但由于某些原因,它感觉不太正确。感觉很重复。我试图通过其他方法来减少重复,但这并没有让它变得更好。
public bool MovePossible(int y, int x)
{
//check if position is in field
if (y > 7 || x > 7 || y < 0 || x < 0)
{
return false;
}
//check if spot is not occupied
if(Bord[y, x] != Color.None)
{
return false;
}
//get color of current turn
Color color = InTurn;
//set oppesite color
Color oppositeColor = Color.Black;
if (color == Color.Black) oppositeColor = Color.White;
//check: X, Y + 1
if (y + 1 <= 7)
{
if(Bord[y + 1, x] == oppositeColor)
{
for (int i = y + 2; i <= 7; i++)
{
if(Bord[i, x] == color)
{
return true;
}
}
}
}
//check: X, Y - 1
if (y - 1 >= 0)
{
if (Bord[y - 1, x] == oppositeColor)
{
for (int i = y - 2; i >= 0; i--)
{
if (Bord[i, x] == color)
{
return true;
}
}
}
}
//check: X + 1, Y
if (x + 1 <= 7)
{
if (Bord[y, x + 1] == oppositeColor)
{
for (int i = x + 2; i <= 7; i++)
{
if (Bord[y, i] == color)
{
return true;
}
}
}
}
//check: X - 1, Y
if (x - 1 >= 0)
{
if (Bord[y, x - 1] == oppositeColor)
{
for (int i = x - 2; i >= 0; i--)
{
if (Bord[y, i] == color)
{
return true;
}
}
}
}
//check: X + 1, Y + 1
if (y + 1 <= 7 && x + 1 <= 7)
{
if (Bord[y + 1, x + 1] == oppositeColor)
{
var i = y + 2;
var j = x + 2;
while (i <= 7 && j <= 7)
{
if (Bord[i, j] == color)
{
return true;
}
i++;
j++;
}
}
}
//check: X - 1, Y - 1
if (y - 1 >= 0 && x - 1 >= 0)
{
if (Bord[y - 1, x - 1] == oppositeColor)
{
var i = y - 2;
var j = x - 2;
while (i >= 0 && j >= 0)
{
if (Bord[i, j] == color)
{
return true;
}
i--;
j--;
}
}
}
//check: X - 1, Y + 1
if (y + 1 <= 7 && x - 1 >= 0)
{
if (Bord[y + 1, x - 1] == oppositeColor)
{
var i = y + 2;
var j = x - 2;
while(i <= 7 && j >= 0)
{
if (Bord[i, j] == color)
{
return true;
}
i++;
j--;
}
}
}
//check: X + 1, Y - 1
if (x + 1 <= 7 && y - 1 >= 0)
{
if (Bord[y - 1, x + 1] == oppositeColor)
{
var i = y - 2;
var j = x + 2;
while (i >= 0 && j <= 7)
{
if (Bord[i, j] == color)
{
return true;
}
i--;
j++;
}
}
}
return false;
}我想得到一些关于我的代码的反馈,以及如何改进它,减少重复。
编辑:
代码应该做什么?
该方法必须检查磁盘是否可以放置在网格上。这是奥赛罗(或Reversi)比赛的一部分。当以下情况下,该方法必须返回true:
3, 3上放置一个黑色磁盘,下面的一个或多个坐标必须是白色的:2, 2、2, 3、2, 4、3, 2、3, 4、4, 2、4, 3、4, 4。举个例子:
0 1 2 3 4 5 6 7
0 0 0 0 0 0 0 0 0
1 0 0 0 0 0 0 0 0
2 0 0 0 0 0 0 0 0
3 0 0 0 2 1 0 0 0
4 0 0 0 1 2 0 0 0
5 0 0 0 0 0 0 0 0
6 0 0 0 0 0 0 0 0
7 0 0 0 0 0 0 0 0我想把一个白色的磁盘放在Y: 2,X: 3。这是有效的,因为光点是空的,它在黑色(2)磁盘旁边,黑色磁盘现在被包围了。当磁盘被放置时,网格如下所示:
0 1 2 3 4 5 6 7
0 0 0 0 0 0 0 0 0
1 0 0 0 0 0 0 0 0
2 0 0 0 1 0 0 0 0
3 0 0 0 2 1 0 0 0
4 0 0 0 1 2 0 0 0
5 0 0 0 0 0 0 0 0
6 0 0 0 0 0 0 0 0
7 0 0 0 0 0 0 0 0由于黑色磁盘现在被白色磁盘包围,所以磁盘变成了一个白色磁盘(3, 3上的那个),但是更改磁盘发生在另一个函数中,对这个问题并不重要。
另一个例子是:
0 1 2 3 4 5 6 7
0 0 0 0 0 0 0 0 0
1 0 0 0 0 0 0 0 0
2 0 0 0 0 0 0 0 0
3 0 0 0 2 2 2 0 0
4 0 0 0 1 1 0 0 0
5 0 0 0 0 1 0 0 0
6 0 0 0 0 0 0 0 0
7 0 0 0 0 0 0 0 0在Y: 4,X: 5放置白色(1)磁盘无效。它在黑色(2)磁盘旁边,但是黑色磁盘不会被包围,因此它是无效的。Y: 2,X: 2将是一个有效的移动,因为在Y: 3,X: 3处的黑盘被Y: 2,X: 2和Y: 4包围。
发布于 2020-02-06 15:54:58
我还没有检查您在//check: X, Y + 1注释后面的逻辑是否正确,但可以如下所示进行重构。你基本上是在检查8个方向(N,NE,E,SE,S,SW,W,NW),每个方向都是由一个dx和一个dy在-1和1之间唯一识别的。你需要排除dx和dy都是0的情况。
dx -1 0 +1
dy -1 NW N NE
0 W . E
+1 SW S SE这会给出这样的代码:
for (int dx = -1; dx <= 1; dx++) {
for (int dy = -1; dy <= 1; dy++) {
if (dx == 0 && dy == 0)
continue;
if (x + dx < 0 || x + dx > 7 || y + dy < 0 || y + dy > 7)
continue;
if (Bord[y + dy, x + dx] != oppositeColor)
continue;
int i = 2;
while (i <= 7)
{
if (x + i * dx < 0 || x + i * dx > 7 || y + i * dy < 0 || y + i * dy > 7)
break;
if (Bord[y + i * dy, x + i * dx] == Color.None)
break;
if (Bord[y + i * dy, x + i * dx] == color)
{
return true;
}
i++;
}
}
}https://codereview.stackexchange.com/questions/236759
复制相似问题