我遇到了一个问题。我正在尝试制作一个tic tac toe游戏,你可以对抗ai。但它并没有真正关心这个问题。董事会是一个2D列表女巫看起来像这样:
[0,1,0]
[1,2,0]左[0,2,0]
0是空白点
1是玩家1(圆圈)
2是玩家2(交叉)
但我有一个问题,我需要通过所有的点迭代,所以我做了这个循环。
List<List<int>> boardTry;
List<List<int>> board = new List<List<int>> { new List<int> { 0, 0, 0 }, new List<int> { 0, 0, 0, }, new List<int> { 0, 0, 0 } };
for (int rowNum = 0; rowNum < 3; rowNum ++)
{
for (int colNum = 0; colNum < 3; colNum++)
{
// Check if spot is empty
if (board[rowNum][colNum] == 0)
{
boardTry = board;
showBoard(board);
boardTry[rowNum][colNum] = 2;
}
}
}
我创建了一个名为showBoard的方法来查看列表的外观。
void showBoard(List<List<int>> board)
{
StringBuilder sb = new StringBuilder();
foreach (List<int> row in board)
{
sb.Append("[");
foreach(int col in row)
{
sb.Append(col.ToString() + " ");
}
sb.Append("]");
}
MessageBox.Show(sb.ToString(0, 8) + "\n" + sb.ToString(8, 8) + "\n" + sb.ToString(16, 8));
}
但问题是,当我运行此代码时,board
列表随boardTry
而变化。因此,每次我将boardTry
分配给board
时,board
都会等同于boardTry
。
答案 0 :(得分:4)
执行此操作时:
boardTry = board;
它不会创建新列表。 boardTry
和board
现在都是引用相同列表的变量。因此,对boardTry
所做的任何更改也会对board
进行。
Here's a very recent question and answer讨论几乎相同的问题以及如何解决它。简短的版本是您不希望仅将现有列表分配给新变量。您想要创建一个新列表,该列表是现有列表的副本。
这是一个将现有电路板复制到新电路板的功能示例。这有点冗长:
List<List<int>> CopyBoard(List<List<int>> original)
{
var copied = new List<List<int>>();
foreach (var innerList in original)
{
copied.Add(new List<int>(innerList));
}
return copied;
}
这与LINQ表达式相同。我们这样做是因为如果我们把原来的功能和填充到一行中稍微难以阅读,那么我们对自己感觉良好。
List<List<int>> CopyBoard(List<List<int>> original)
{
return new List<List<int>>(original.Select(innerList=> innerList.ToList()));
}
答案 1 :(得分:0)
尝试这个tic tac toe控件(你可以修改它):
using System;
using System.Linq;
using System.Drawing;
using System.Windows.Forms;
using System.Collections.Generic;
public class TicTacToe : Panel
{
public TicTacToe()
{
// You can change these properties.
this.Size = new Size(281, 360);
this.BackColor = Color.White;
// Add the labels.
this.Controls.AddRange(new Control[] { wins, losses, turn });
// To generate random numbers for the A.I
Random opponentPlay = new Random();
// A.I turn
opponentDelay.Tick += delegate
{
opponentDelay.Interval = 20;
Point opponentPos = new Point(opponentPlay.Next(0, 3), opponentPlay.Next(0, 3));
if (board[opponentPos.X][opponentPos.Y].Text.Length == 0)
{
board[opponentPos.X][opponentPos.Y].Text = "X";
opponentDelay.Interval = 500;
opponentDelay.Stop();
UpdateGame();
}
};
// Setup board.
for (int x = 0; x < board.Count; x++)
{
for (int y = 0; y < board.Count; y++)
{
board[x][y].Location = new Point(4 + (x * 92), 4 + (y * 92));
// Add player turn event.
board[x][y].Click += delegate (object sender, EventArgs e)
{
if (turn.Name == "1")
{
if (((Button)sender).Text.Length == 0)
{
((Button)sender).Text = "0";
UpdateGame();
}
}
};
this.Controls.Add(board[x][y]);
}
}
}
// Check game for wins, losses, and draws.
public void UpdateGame()
{
// Check if player won.
if (board[0][0].Text == "0" && board[1][0].Text == "0" && board[2][0].Text == "0")
EndGame(0);
else if (board[0][1].Text == "0" && board[1][1].Text == "0" && board[2][1].Text == "0")
EndGame(0);
else if (board[0][2].Text == "0" && board[1][2].Text == "0" && board[2][2].Text == "0")
EndGame(0);
else if (board[0][0].Text == "0" && board[0][1].Text == "0" && board[0][2].Text == "0")
EndGame(0);
else if (board[1][0].Text == "0" && board[1][1].Text == "0" && board[1][2].Text == "0")
EndGame(0);
else if (board[2][0].Text == "0" && board[2][1].Text == "0" && board[2][2].Text == "0")
EndGame(0);
else if (board[0][0].Text == "0" && board[1][1].Text == "0" && board[2][2].Text == "0")
EndGame(0);
else if (board[0][2].Text == "0" && board[1][1].Text == "0" && board[2][0].Text == "0")
EndGame(0);
// Check if opponent won.
if (board[0][0].Text == "X" && board[1][0].Text == "X" && board[2][0].Text == "X")
EndGame(1);
else if (board[0][1].Text == "X" && board[1][1].Text == "X" && board[2][1].Text == "X")
EndGame(1);
else if (board[0][2].Text == "X" && board[1][2].Text == "X" && board[2][2].Text == "X")
EndGame(1);
else if (board[0][0].Text == "X" && board[0][1].Text == "X" && board[0][2].Text == "X")
EndGame(1);
else if (board[1][0].Text == "X" && board[1][1].Text == "X" && board[1][2].Text == "X")
EndGame(1);
else if (board[2][0].Text == "X" && board[2][1].Text == "X" && board[2][2].Text == "X")
EndGame(1);
else if (board[0][0].Text == "X" && board[1][1].Text == "X" && board[2][2].Text == "X")
EndGame(1);
else if (board[0][2].Text == "X" && board[1][1].Text == "X" && board[2][0].Text == "X")
EndGame(1);
// Check if nobody won.
if (board[0][0].Text != "" && board[0][1].Text != "" && board[0][2].Text != "" && board[1][0].Text != "" && board[1][1].Text != "" && board[1][2].Text != "" && board[2][0].Text != "" && board[2][1].Text != "" && board[2][2].Text != "")
EndGame(2);
// Change turn.
if (turn.Name == "2")
{
turn.Name = "1";
turn.Text = "Your turn";
}
else
{
turn.Name = "2";
turn.Text = "Opponents turn";
opponentDelay.Start();
}
}
// End game (or end round).
public void EndGame(int win)
{
if (win == 0)
{
MessageBox.Show("You Win!", "Tic Tac Toe");
wins.Name = (Convert.ToInt32(wins.Name) + 1).ToString();
wins.Text = "Wins: " + wins.Name;
}
else if (win == 1)
{
MessageBox.Show("Sorry but you lost, better luck next time...", "Tic Tac Toe");
losses.Name = (Convert.ToInt32(losses.Name) + 1).ToString();
losses.Text = "Losses: " + losses.Name;
}
else
{
MessageBox.Show("Draw! No one won...", "Tic Tac Toe");
}
// Reset board.
for (int x = 0; x < board.Count; x++)
{
for (int y = 0; y < board.Count; y++)
{
board[x][y].Text = "";
}
}
// Set the turn.
turn.Name = "2";
}
// Variables
public Label wins = new Label() { Text = "Wins: 0", Name = "0", Location = new Point(30, 310), AutoSize = false, Size = new Size(54, 17) };
public Label losses = new Label() { Text = "Losses: 0", Name = "0", Location = new Point(95, 310), AutoSize = false, Size = new Size(66, 17) };
public Label turn = new Label() { Text = "Your turn", Name = "1", Location = new Point(175, 310) };
public Timer opponentDelay = new Timer() { Interval = 500 };
// Instead of buttons and int lists, where you have to add click event and get button index to change int list and button text, just use a button list and click evnt which read the button text and changes it.
public List<List<Button>> board = new List<List<Button>>
{
new List<Button>
{
new Button() { Text = "", Font = new Font(SystemFonts.DefaultFont.Name, 26f, FontStyle.Bold), UseVisualStyleBackColor = true, TabStop = false, Size = new Size(90, 90) },
new Button() { Text = "", Font = new Font(SystemFonts.DefaultFont.Name, 26f, FontStyle.Bold), UseVisualStyleBackColor = true, TabStop = false, Size = new Size(90, 90) },
new Button() { Text = "", Font = new Font(SystemFonts.DefaultFont.Name, 26f, FontStyle.Bold), UseVisualStyleBackColor = true, TabStop = false, Size = new Size(90, 90) }
},
new List<Button>
{
new Button() { Text = "", Font = new Font(SystemFonts.DefaultFont.Name, 26f, FontStyle.Bold), UseVisualStyleBackColor = true, TabStop = false, Size = new Size(90, 90) },
new Button() { Text = "", Font = new Font(SystemFonts.DefaultFont.Name, 26f, FontStyle.Bold), UseVisualStyleBackColor = true, TabStop = false, Size = new Size(90, 90) },
new Button() { Text = "", Font = new Font(SystemFonts.DefaultFont.Name, 26f, FontStyle.Bold), UseVisualStyleBackColor = true, TabStop = false, Size = new Size(90, 90) }
},
new List<Button>
{
new Button() { Text = "", Font = new Font(SystemFonts.DefaultFont.Name, 26f, FontStyle.Bold), UseVisualStyleBackColor = true, TabStop = false, Size = new Size(90, 90) },
new Button() { Text = "", Font = new Font(SystemFonts.DefaultFont.Name, 26f, FontStyle.Bold), UseVisualStyleBackColor = true, TabStop = false, Size = new Size(90, 90) },
new Button() { Text = "", Font = new Font(SystemFonts.DefaultFont.Name, 26f, FontStyle.Bold), UseVisualStyleBackColor = true, TabStop = false, Size = new Size(90, 90) }
}
};
}
<强>用法:强>
TicTacToe TicTacToeGame = new TicTacToe();
...Controls.Add(TicTacToeGame);
它看起来像什么: