井字游戏提前结束



我尝试创建一个井字游戏,但是X通常在它应该之前获胜,例如:第1行第2列在第一步结束程序,但如果我先写第2行第3列,它在大多数情况下工作得很好。有些事情显然可以做得更好(O或X替换已经占用的贴图等等),但我宁愿先通过稍微改变代码来修复这部分。

代码如下:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Tic_Tac_Toe
{
class Program
{
static void Field(List<char[]> p) { 
Console.WriteLine("-------------------------------------------------");
Console.WriteLine(p[0]);
Console.WriteLine(p[1]);
Console.WriteLine(p[2]);
Console.WriteLine(p[3]);
Console.WriteLine(p[4]);
Console.WriteLine("-------------------------------------------------");
}
static List<char[]> read(char player, List<char[]> p) {
bool end = true;
int row = 0;
int column = 0;
do {
Console.WriteLine("Which row would you like to pick?(1,2,3)");
row = Convert.ToInt32(Console.ReadLine());
Console.WriteLine("Which column would you like to pick?(1,2,3)");
column = Convert.ToInt32(Console.ReadLine());

if (row == 1)
{
row = 0;
end = true;
}
else if (row == 2)
{
row = 2;
end = true;
}
else if (row == 3)
{
row = 4;
end = true;
}
else {
Console.WriteLine("There is no such row");
end = false;
}
if (column == 1)
{
column = 0;
end = true;
}
else if (column == 2) {
end = true;
}
else if (column == 3) {
column = 4;
end = true;
}
else
{
Console.WriteLine("There is no such column");
end = false;
}
} while (!end);
p = write(player,p,row,column);
return p;
}
static List<char[]> write(char player, List<char[]> p, int row, int column) {
p[row][column] = player;
Field(p);
return p;
}
static bool Test(List<char[]> p) {
for (int i = 0; i <= 4; i=i+2)
{
if ((p[i][0] == 'X' || p[i][0] == 'O')|| (p[0][i]=='X' || p[0][i] =='O'))
{            
if (p[i][0] == p[i][2] && p[i][2] == p[i][4]) 
{
return true;
}
else if (p[0][i] == p[2][i] && p[2][i] == p[4][i])
{
return true;
}
}
}
if (p[0][0] == 'X' || p[0][0] == 'O'  )
{            
if (p[0][0] == p[2][2] && p[2][2] == p[4][4])
{
return true;
}
}
if (p[0][4] == 'X' || p[0][4] == 'O')
{
if (p[0][4] == p[2][2] && p[2][2] == p[4][0])
{
return true;
}
}

return false;
}
static void run(List<char[]>p) {
int i = 0;
Field(p);
bool end = Test(p);
for (i = 0; i < 9  && !end; i++)
{
if (i % 2 == 0) 
{
p=read('X',p);
end = Test(p);
}
else
{
p=read('O', p);
end = Test(p);
}
}
if (Test(p))
{
i--;
if (i % 2 == 0) 
{
Console.WriteLine("Player X won!");
}
else
{
Console.WriteLine("Player O won!");
}
}
}
static void Main(string[] args)
{
List<char[]> Field = new List<char[]>();
char[] row1 = {' ','|',' ','|',' '};
char[] row2 = { ' ', '|', ' ', '|', ' ' };
char[] row3 = { ' ', '|', ' ', '|', ' ' };
char[] sep1 = { '_', ' ', '_', ' ', '_'};
char[] sep2 = { '_', ' ', '_', ' ', '_' };
Field.Add(row1);
Field.Add(sep1);
Field.Add(row2);
Field.Add(sep2);
Field.Add(row3);
run(Field);
Console.ReadKey();
}
}
}

我试着重写了一些关于行和列的部分,但这并没有真正帮助。我认为问题可能是在程序决定谁赢的部分,但我不太确定如何解决这个部分。如有任何帮助,我将不胜感激。

我要建议你,首先要试着写更干净的代码,你的代码很难读,我很确定它包含了很多逻辑错误。

然而,在快速查看您的Test函数与输入(行:1,列:2)之后,我发现了以下内容:

  1. i = 2
  2. 时,返回if((p[i][0] == 'X' || p[i][0] == 'O') || (p[0][i] == 'X' || p[0][i] == 'O'))true
  3. 所以下一行if (p[i][0] == p[i][2] && p[i][2] == p[i][4])特别是在p[i][0] == p[i][2]部分比较两个空字符,这总是正确的。

最后注意:不要在输入数组中包含字段行'|',这会使事情变得更加困难。

从程序维护/调试的角度来看,你很好地说明了为什么OOP编程比函数式编程更好。

很难遵循逻辑,这部分是因为你的整个游戏模型由List<char[]>组成,这实际上是游戏的可视化。

那么如何检查是否有人赢了呢?这是在2D数组中创建带有某种玩家位置表示的class TicTacToe { }的部分,这将更容易检查结束条件(填充棋盘),如果任何玩家都有一个(三个)标记。

在上面的代码中,有一个带有条件结束条件的for循环,这不是for循环设计的使用方式。使用while()循环并在每次迭代时检查结束条件

最后输入&一旦开发出游戏模型,验证就可以简化。


游戏模型的例子可以是

public class TicTacToe
{
// 2D array holding 0 for empty spot
// 1 for player one, and 2 for player 2
public int[,] Board = new int[3,3];
public bool HasPlayerWon(int player)
{
// with a loop you can check if any row or column
// of the Board contains the number in `player`.
// Don't forget to check the diagonals also.
}
public bool IsBoardFull()
{
// check if any spots in `Board[,]` are still zero
// if they are then return false, otherwise return true
}
public bool TryPlayerTurn(int player, int row, int column)
{
// try to mark row,column with player
// return true if spot was empty, false if illegal move
}

public override string ToString()
{
// Visualization code here   
// Use StringBuilder to add grid and player marks
}
}

游戏逻辑应该是这样的

static class Program
{
static void Main(string[] args)
{
var game = new TicTacToe();
int player = 1, turn = 0, row, column;
while(true)
{ 
turn++;
// Show the game board
Console.WriteLine(game);
do
{
// Process user input
row = ...
column = ...
}
while(!game.TryPlayerTurn(player,row,column));
if(game.HasPlayerWon(player))
{
// player just won
break;
}
if(game.IsBoardFull())
{
// game is a tie
break;
}
// Switch players
player = 3-player;
}
}
}

最新更新