C#
1020个字符。
1088个字符(添加了来自控制台的输入)。
925个字符(重构变量)。
875个字符(删除冗余的字典初始化程序;改为二进制&运算符)
在发布之前,我特意没有查看其他人的代码。我相信它可以使用LINQ进行优化。而且,在可读版本中,整个FindLaser方法似乎非常可疑。但是,它能够工作,而且现在已经很晚了 :)
请注意,可读类包括一个额外的方法,该方法在激光移动时打印出当前竞技场。
class L{static void Main(){
A=new Dictionary<Point,string>();
var l=Console.ReadLine();int y=0;
while(l!=""){var a=l.ToCharArray();
for(int x=0;x<a.Count();x++)
A.Add(new Point(x,y),l[x].ToString());
y++;l=Console.ReadLine();}new L();}
static Dictionary<Point,string>A;Point P,O,N,S,W,E;
public L(){N=S=W=E=new Point(0,-1);S.Offset(0,2);
W.Offset(-1,1);E.Offset(1,1);D();
Console.WriteLine(F());}bool F(){
var l=A[P];int m=O.X,n=O.Y,o=P.X,p=P.Y;
bool x=o==m,y=p==n,a=x&p<n,b=x&p>n,c=y&o>m,d=y&o<m;
if(l=="\\"){if(a)T(W);if(b)T(E);if(c)T(S);
if(d)T(N);if(F())return true;}
if(l=="/"){if(a)T(E);if(b)T(W);if(c)T(N);
if(d)T(S);if(F())return true;}return l=="x";}
void T(Point p){O=P;do P.Offset(p);
while(!("\\,/,#,x".Split(',')).Contains(A[P]));}
void D(){P=A.Where(x=>("^,v,>,<".Split(',')).
Contains(x.Value)).First().Key;var c=A[P];
if(c=="^")T(N);if(c=="v")T(S);if(c=="<")T(W);
if(c==">")T(E);}}
可读版本(不是最终的高尔夫版本,但基本相同):
class Laser
{
private Dictionary<Point, string> Arena;
private readonly List<string> LaserChars;
private readonly List<string> OtherChars;
private Point Position;
private Point OldPosition;
private readonly Point North;
private readonly Point South;
private readonly Point West;
private readonly Point East;
public Laser( List<string> arena )
{
SplitArena( arena );
LaserChars = new List<string> { "^", "v", ">", "<" };
OtherChars = new List<string> { "\\", "/", "#", "x" };
North = new Point( 0, -1 );
South = new Point( 0, 1 );
West = new Point( -1, 0 );
East = new Point( 1, 0 );
FindLaser();
Console.WriteLine( FindTarget() );
}
private void SplitArena( List<string> arena )
{
Arena = new Dictionary<Point, string>();
int y = 0;
foreach( string str in arena )
{
var line = str.ToCharArray();
for( int x = 0; x < line.Count(); x++ )
{
Arena.Add( new Point( x, y ), line[x].ToString() );
}
y++;
}
}
private void DrawArena()
{
Console.Clear();
var d = new Dictionary<Point, string>( Arena );
d[Position] = "*";
foreach( KeyValuePair<Point, string> p in d )
{
if( p.Key.X == 0 )
Console.WriteLine();
Console.Write( p.Value );
}
System.Threading.Thread.Sleep( 400 );
}
private bool FindTarget()
{
DrawArena();
string chr = Arena[Position];
switch( chr )
{
case "\\":
if( ( Position.X == Position.X ) && ( Position.Y < OldPosition.Y ) )
{
OffSet( West );
}
else if( ( Position.X == Position.X ) && ( Position.Y > OldPosition.Y ) )
{
OffSet( East );
}
else if( ( Position.Y == Position.Y ) && ( Position.X > OldPosition.X ) )
{
OffSet( South );
}
else
{
OffSet( North );
}
if( FindTarget() )
{
return true;
}
break;
case "/":
if( ( Position.X == Position.X ) && ( Position.Y < OldPosition.Y ) )
{
OffSet( East );
}
else if( ( Position.X == Position.X ) && ( Position.Y > OldPosition.Y ) )
{
OffSet( West );
}
else if( ( Position.Y == Position.Y ) && ( Position.X > OldPosition.X ) )
{
OffSet( North );
}
else
{
OffSet( South );
}
if( FindTarget() )
{
return true;
}
break;
case "x":
return true;
case "#":
return false;
}
return false;
}
private void OffSet( Point p )
{
OldPosition = Position;
do
{
Position.Offset( p );
} while( !OtherChars.Contains( Arena[Position] ) );
}
private void FindLaser()
{
Position = Arena.Where( x => LaserChars.Contains( x.Value ) ).First().Key;
switch( Arena[Position] )
{
case "^":
OffSet( North );
break;
case "v":
OffSet( South );
break;
case "<":
OffSet( West );
break;
case ">":
OffSet( East );
break;
}
}
}