我正在做一个井字游戏项目,我遇到了一些困难。我只是对收藏品松懈,所以你可以看到问题。
事情是,我创建了9个按钮,在单击时更改了背景图像,并禁用它们自己。我已经设法让它为2名玩家运行,但我的愿望是创建某种AI。
我需要一个按钮集合,以便我可以比较它们的属性,并避免通常的逐一比较和大量的If语句。
我真正想要的是能够测试同一行或列中的按钮是否具有相同的值(背景图像)。到目前为止我使用的是一个描述符号值的字符串数组,但它完全脱离了按钮,并且输入所有代码需要花费大量时间。
如果无法按照我想象的方式完成,请告诉我们。我愿意接受建议,并将非常感激。
哦,如果您需要任何代码或更多详细信息,请与我们联系。
答案 0 :(得分:5)
您需要分隔数据(数组)和演示文稿(按钮)。
更新
编译并运行的I published a sample console project 它的模型与表示是分开的,因此您可以使用
TicTacToe.cs
并为其编写GUI。
你不需要字符串;布尔都适用于两个州 事实上,有一个第三个状态,它是空的,所以你可以使用一个可以为空的布尔值。
因此X对应true
,O对应false
,空对应null
。
我创建了一个封装可空布尔方形数组的类:
class TicTacToe {
const int Length = 3;
private bool? [][] _data;
private bool? _winner;
public TicTacToe ()
{
_data = Enumerable
.Range (0, Length)
.Select (_ => new bool? [Length])
.ToArray ();
}
}
然后我将行,列和对角线表示为向量:
public bool? GetCell (int row, int column)
{
return _data [row][column];
}
public IEnumerable<bool?> GetRow (int index)
{
return _data [index];
}
IEnumerable<int> GetIndices ()
{
return Enumerable.Range (0, Length);
}
public IEnumerable<bool?> GetColumn (int index)
{
return GetIndices ()
.Select (GetRow)
.Select (row => row.ElementAt (index));
}
public IEnumerable<bool?> GetDiagonal (bool ltr)
{
return GetIndices ()
.Select (i => Tuple.Create (i, ltr ? i : Length - 1 - i))
.Select (pos => GetCell (pos.Item1, pos.Item2));
}
public IEnumerable<IEnumerable<bool?>> GetRows ()
{
return GetIndices ()
.Select (GetRow);
}
public IEnumerable<IEnumerable<bool?>> GetColumns ()
{
return GetIndices ()
.Select (GetColumn);
}
public IEnumerable<IEnumerable<bool?>> GetDiagonals ()
{
return new [] { true, false }
.Select (GetDiagonal);
}
public IEnumerable<IEnumerable<bool?>> GetVectors ()
{
return GetDiagonals ()
.Concat (GetRows ())
.Concat (GetColumns ());
}
然后我会编写一个带矢量的函数,并说它是否是一个胜利者:
static bool? FindWinner (IEnumerable<bool?> vector)
{
try {
return vector
.Distinct ()
.Single ();
} catch (InvalidOperationException) {
return null;
}
}
static bool? FindWinner (IEnumerable<IEnumerable<bool?>> vectors)
{
return vectors
.Select (FindWinner)
.FirstOrDefault (winner => winner.HasValue);
}
public bool? FindWinner ()
{
return FindWinner (GetVectors ());
}
现在我们可以致电GetWinner
查看是否有人赢了
然后我会写一个方法来采取行动:
public bool MakeMove (int row, int column, bool move)
{
if (_winner.HasValue)
throw new InvalidOperationException ("The game is already won.");
if (_data [row][column].HasValue)
throw new InvalidOperationException ("This cell is already taken.");
_data [row][column] = move;
_winner = FindWinner ();
return move == _winner;
}
public bool? Winner {
get { return _winner; }
}
这都在TicTacToe
级内
您的GUI应该创建它并调用它的方法。
点击按钮时,您可以这样做:
private TicTacToe _game = new TicTacToe ();
private Button [][] _buttons = new Button [][3];
const bool HumanPlayer = true;
const bool AIPlayer = false;
public void HandleButtonClick (object sender, EventArgs e)
{
// Assuming you put a Tuple with row and column in button's Tag property
var position = (Tuple<int, int>) ((Button) sender).Tag;
var row = position.Item1;
var column = position.Item2;
// Sanity check
Debug.Asset (sender == _buttons [row][column]);
bool won = _game.MakeMove (row, column, HumanPlayer);
if (won) {
MessageBox.Show ("You won.");
}
RefreshButtons ();
}
void RefreshButtons ()
{
for (var i = 0; i < 3; i++) {
for (var j = 0; j < 3; j++) {
var btn = _buttons [i][j];
var cell = _game.GetCell (i, j);
btn.Enabled = !cell.HasValue;
btn.Text = cell.HasValue
? (cell.Value ? "X" : "O")
: string.Empty;
}
}
}
您的AI还应拨打MakeMove
并根据来自GetRow
,GetColumn
和GetDiagonal
的信息进行计算。
我没有检查代码,它只是一个草图。 (但是console project应该运行得很好。)
答案 1 :(得分:1)
我将使用的是包含游戏当前状态的游戏状态类。例如:
public class Game
{
// These will have null for unselected, true for circle, false for cross, or something like that
public bool?[][] SquareStates = new bool?[3][3];
// Maybe a property to show a game is in progress
public bool GameInProgress = false;
// Maybe a function to restart game
public void Restart() { ... }
// And maybe a function to check for a winner
public string CheckWinner() { ... }
// Maybe another function to make AI make its next move
// and updates SquareStates.
public void AINextMove(out int row, out int column) { ... }
}
一旦你有这样的课程,你的表格只会包含一个游戏的内容,然后在按下按钮时更新SquareStates数组,然后检查获胜者,调用AINextMove,再次检查获胜者,然后更新自己的按钮使用新的SquareStates进行陈述。