我有一个我正在编写的程序,其工作原理是填充二维数组以检查获胜条件,它是noughts和crosses,所以只需点击一个按钮就可以填充二维数组,1代表一个圆圈, 2表示交叉,然后checkWin()将按照这个原则工作,而不是实际的代码...
if (myArray[0][0] == 1 && myArray[0][1] == 1 && myArray[0][2] == 1){
setBoolWinVal = true;
} else {
if(myArray[0][0] == 2 && myArray[0][1] == 2 && myArray[0][2] == 2){
setBoolWinVal = true;
}
你可以立即看到,对于每一个获胜条件,这将是凌乱的,有没有办法重写这个检查获胜,以缩短它?
答案 0 :(得分:7)
这看起来像是家庭作业,所以我不会完全放弃它。但请注意以下几点:
当你连续三次,一列或一条对角线上有三个相同的东西时,你就赢了。
这不是你需要检查一行中是否有三个零或三个十字架,而是一行中有三个相同的东西。
您可以从编写一个函数开始,该函数确定行,列或对角线是否具有三种相同类型的东西(并且该东西不是空白单元格)。然后为每行,每列和对角线调用该函数一次。
答案 1 :(得分:3)
这是(未经测试的)代码。它当然不是生产质量:)
请注意其他答案的一些优化:
int find_winner(int[][] arr) {
// check rows
for (int i = 0; i < 3; ++i) {
int player = arr[i][0];
if (player < 1) continue; // nb: prior version didn't check for empty cells
if (arr[i][1] == player && arr[i][2] == player) return player;
}
// check cols
for (int i = 0; i < 3; ++i) {
int player = arr[0][i];
if (player < 1) continue;
if (arr[1][i] == player && arr[2][i] == player) return player;
}
// check diagonals
int player = arr[1][1];
if (player < 1) return -1;
if ((arr[0][0] == player && arr[2][2] == player) ||
(arr[2][0] == player && arr[0][2] == player)) return player;
// no winner found
return -1;
}
答案 2 :(得分:2)
显而易见的方法是循环行,列或对角线中的3个元素并检查它们是否相同。
另一种方法是使用更紧凑的表示 - 例如,一个int,其中9个单元格每个由2位表示,或者两个短路,每个玩家一个。然后使用查找表或按位操作将状态映射到输赢。
如果单个位代表一个单元格,并且您有一个填充位,则每个玩家的磁贴都是3个十六进制数字0-7。
对角线是:
cells & 0x421 == 0x421
cells & 0x124 == 0x124
垂直线是:
cells & (cells>>4) & (cells>>8) != 0
水平线
cells & (cells>>1) & (cells>>2) != 0
使用类似的技术使用64位模式来表示国际象棋游戏中可能的移动。
答案 3 :(得分:1)
两个有趣的想法:(我假设基础1D数组因为它让生活更轻松。)
首先:对要测试的位置进行编码。就像你有一维数组描述你的领域一样:
diag[] = { { 0, 1, 2}, {3, 4, 5}, {6, 7, 8},
{ 0, 3, 6}, {1, 4, 7}, {2, 5, 8},
{ 0, 4, 8}, {6, 4, 2}};
然后循环遍历diag:对于它的每个元素,测试三个相应的字段(使用diag[i]
作为字段数组的索引)。
第二:使用位域来表示您的字段。像java.util.BitSet。然后将解编码为像{1,1,1,0,0,0,0,0,0},{0,0,0,1,1,1,0,0,0}等位域。然后你可以测试(循环)if (field & solution[i] == solution[i])
。对于第二个玩家,只需在if语句中使用!field
。
答案 4 :(得分:0)
做作业的气味。
小提示 - 用于循环,它适用于您想要的任何大小。如果您使用递归,则会获得奖励积分。
定义: 递归 - &gt;请参阅递归
答案 5 :(得分:0)
因此,如果您考虑一下,您正在检查以下条件:
www xxx xxx wxx
xxx www xxx xwx
xxx xxx www xxw
等
w是要检查胜利的人,而x是要忽略的。
(0,0),(0,1),(0,2)是第一个正确解中“w”的位置。 1,0,1,1和1,2是第二个,等等。
这让我觉得它应该是数据而不是代码。 诀窍是,如何有效地输入和存储数据。
请注意,此数据开始看起来像您的数组索引。
所以,假设您有一系列“解决方案”,其中包含8 x,y对(每个都表示一个成功的解决方案组合)
然后你要做的就是迭代这个集合,提取三个x,y对并测试它们。所以它与你拥有的相似,但是在你有数字的地方使用变量。
if(myArray[x0][y0] == 2 && myArray[x1][y1] == 2 && myArray[x2][y2] == 2){
win();
在迭代它时,索引变量将替换为数据的下一行。
由于您不想在获胜后报告损失,因此您将不得不稍微使用逻辑来确保您的循环停止,但这可能已经对家庭作业风格问题提供了太多帮助
答案 6 :(得分:0)
这听起来有点像家庭作业,但我会帮助解决行和列的简单问题,检查它们是否已满,对角线稍微硬一点,我还是留给你。 同样,我相信嵌套的for循环是最好的主意:
java.util.Arrays;
public yourClass{
public void findAnswer{
int initialVal = 0;
int copy = 0;
int column = 0;
boolean columnVal = true;
boolean rowVal = false;
for (int j = 0; j< myArray.length; j++){ //presuming myArray and myArray[] are same length
boolean firstRun = true;
for (int i = 0; i <myArray.length; i++){
initialVal = myArray[i][column];
if (firstRun == true){
copy = intialVal; //makes a copy for the first time, to compare
firstRun = false;
}
if (intialVal != copy){
columnVal = false; //realises this column isnt a full column i.e. 3 1's or 2's in column
return;
}else
columnVal = true;
}//end nested for loop
rowVal = findRow(j);
if(rowVal = true)
return;
}
public boolean findRow(int row){
int[] tempRow1, tempRow2;
Arrays.fill(tempRow1, 1);
Arrays.fill(tempRow2, 2); //fills temp arrays for comparison
boolean answer = false;
if (Arrays.equals(myArray[], tempRow1) || Arrays.equals(myArray[], tempRow2) //this tests either, || being logical OR
answer = true;
return answer;
}
}
n.b。这段代码没有经过测试,而且很快就被编码了,所以看起来不是很好,它可以很精致,而且我还没有实现对角线。 附:如果是家庭作业,可能最好在互联网上查找内容,并尝试自己解决,而不是通过要求其他人为你寻求帮助。
答案 7 :(得分:0)
答案 8 :(得分:0)
对于n X n矩阵......
//Check all horizontal rows
for(i=0; i<n && !setBoolWinVal; i++) //row
{
setBoolWinVal = true;
for(j=0; j<n-1; j++)
{
if( myArray[i][j] != myArray[i][j+1] ) //column
{
setBoolWinVal = false;
break;
}
}
if(setBoolWinVal) declareWinner(myArray[i][0]);
}
//Check all vertical columns
if(!setBoolWinVal)
{
for(i=0; i<n && !setBoolWinVal; i++) //column
{
setBoolWinVal = true;
for(j=0; j<n-1; j++) //row
{
if( myArray[j][i] != myArray[j+1][i] )
{
setBoolWinVal = false;
break;
}
}
}
if(setBoolWinVal) declareWinner(myArray[0][i]);
}
//Check forward diagonal
if(!setBoolWinVal)
{
setBoolWinVal = true;
for(i=0; i<n-1; i++)
{
if( myArray[i][i] != myArray[i+1][i+1])
{
setBoolWinVal = false;
break;
}
}
if(setBoolWinVal) declareWinner(myArray[0][0]);
}
//Check reverse diagonal
if(!setBoolWinVal)
{
setBoolWinVal = true;
for(i=0, j=n-1; i<n-1 && j>0; i++, j--)
{
if( myArray[i][j] != myArray[i+1][j-1])
{
setBoolWinVal = false;
break;
}
}
if(setBoolWinVal) declareWinner(myArray[0][n-1]);
}
答案 9 :(得分:0)
你也可以迭代地解决这个问题:
答案 10 :(得分:0)
一个简单而优雅的解决方案 - 您可以通过以下方式将数字1到9分配给您的电路板:
8 1 6
3 5 7
4 9 2
这个方块具有每行,每列和对角线的独特特征 总和为15,除非,否则无法从三个单元格获得15的总和 它们共用一行,一列或一条对角线。
对于每个玩家,你保留两个布尔数组:
boolean squarePairs[PAIRSMAXSUM+1];
boolean chosenSquares[NUMSQUARES+1];
其中PAIRSMAXSUM = 9 + 8且NUMSQUARES = 9
然后,您可以通过调用此功能轻松检查获胜动作:
boolean hasWon(int squareIndex) {
return squarePairs[WINNINGSUM - squareIndex];
}
其中WINNINGSUM为15.如果该函数返回false,则通过调用此函数来更新布尔数组:
void update(int squareIndex) {
for (int i = 1; i <= NUMSQUARES; i++) {
if (chosenSquares[i]) { {
squarePairs[i + squareIndex] = true;
}
}
chosenSquares[squareIndex] = true;
}
就这么简单!
答案 11 :(得分:-1)
如果数组长度相同,则以下内容应该有所帮助。
Arrays.equals(myArray[0], {1,1,1})
否则,编写一个循环遍历myArray[0]
中所有值的函数。