【问题标题】:List changes when I assign it to a variable c#当我将其分配给变量 c# 时列表更改
【发布时间】:2016-06-25 19:08:25
【问题描述】:

我遇到了一个问题。我正在尝试制作一个井字游戏,您可以在其中与 ai 对战。但它并不真正关心这个问题。该板是一个 2D 列表女巫,看起来像这样:

[0, 1, 0]
[1, 2, 0]
[0, 2, 0]

0 是空位
1 是玩家一(圆圈)
2 是玩家二(十字)

但是我有一个问题,我需要遍历所有点,所以我做了这个 for 循环。

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

这是我在运行此代码时看到的。

【问题讨论】:

    标签: c# winforms list variables


    【解决方案1】:

    当你这样做时:

    boardTry = board;
    

    它不会创建新列表。 boardTryboard 现在都是引用同一个列表的变量。因此,对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()));
    }
    

    【讨论】:

    • 感谢您的精彩解释!我真的很感激。
    【解决方案2】:

    试试这个井字游戏控制(你可以修改它):

    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);
    

    外观:

    【讨论】:

      猜你喜欢
      • 2021-06-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-01-01
      • 2012-01-05
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多