【发布时间】:2011-05-28 14:46:12
【问题描述】:
我有一些现有的 C# 代码,用于非常非常简单的 RogueLike 引擎。故意天真,因为我试图尽可能简单地做最少的数量。它所做的只是使用箭头键和 System.Console 在硬编码地图周围移动一个 @ 符号:
//define the map
var map = new List<string>{
" ",
" ",
" ",
" ",
" ############################### ",
" # # ",
" # ###### # ",
" # # # # ",
" #### #### # # # ",
" # # # # # # ",
" # # # # # # ",
" #### #### ###### # ",
" # = # ",
" # = # ",
" ############################### ",
" ",
" ",
" ",
" ",
" "
};
//set initial player position on the map
var playerX = 8;
var playerY = 6;
//clear the console
Console.Clear();
//send each row of the map to the Console
map.ForEach( Console.WriteLine );
//create an empty ConsoleKeyInfo for storing the last key pressed
var keyInfo = new ConsoleKeyInfo( );
//keep processing key presses until the player wants to quit
while ( keyInfo.Key != ConsoleKey.Q ) {
//store the player's current location
var oldX = playerX;
var oldY = playerY;
//change the player's location if they pressed an arrow key
switch ( keyInfo.Key ) {
case ConsoleKey.UpArrow:
playerY--;
break;
case ConsoleKey.DownArrow:
playerY++;
break;
case ConsoleKey.LeftArrow:
playerX--;
break;
case ConsoleKey.RightArrow:
playerX++;
break;
}
//check if the square that the player is trying to move to is empty
if( map[ playerY ][ playerX ] == ' ' ) {
//ok it was empty, clear the square they were standing on before
Console.SetCursorPosition( oldX, oldY );
Console.Write( ' ' );
//now draw them at the new square
Console.SetCursorPosition( playerX, playerY );
Console.Write( '@' );
} else {
//they can't move there, change their location back to the old location
playerX = oldX;
playerY = oldY;
}
//wait for them to press a key and store it in keyInfo
keyInfo = Console.ReadKey( true );
}
我在 F# 中玩弄它,最初我试图使用函数概念来编写它,但结果我有点过头了,所以我做了一个直接的移植 - 它不是真的 一个 F# 程序(尽管它可以编译和运行)它是一个用 F# 语法编写的过程程序:
open System
//define the map
let map = [ " ";
" ";
" ";
" ";
" ############################### ";
" # # ";
" # ###### # ";
" # # # # ";
" #### #### # # # ";
" # # # # # # ";
" # # # # # # ";
" #### #### ###### # ";
" # = # ";
" # = # ";
" ############################### ";
" ";
" ";
" ";
" ";
" " ]
//set initial player position on the map
let mutable playerX = 8
let mutable playerY = 6
//clear the console
Console.Clear()
//send each row of the map to the Console
map |> Seq.iter (printfn "%s")
//create an empty ConsoleKeyInfo for storing the last key pressed
let mutable keyInfo = ConsoleKeyInfo()
//keep processing key presses until the player wants to quit
while not ( keyInfo.Key = ConsoleKey.Q ) do
//store the player's current location
let mutable oldX = playerX
let mutable oldY = playerY
//change the player's location if they pressed an arrow key
if keyInfo.Key = ConsoleKey.UpArrow then
playerY <- playerY - 1
else if keyInfo.Key = ConsoleKey.DownArrow then
playerY <- playerY + 1
else if keyInfo.Key = ConsoleKey.LeftArrow then
playerX <- playerX - 1
else if keyInfo.Key = ConsoleKey.RightArrow then
playerX <- playerX + 1
//check if the square that the player is trying to move to is empty
if map.Item( playerY ).Chars( playerX ) = ' ' then
//ok it was empty, clear the square they were standing on
Console.SetCursorPosition( oldX, oldY )
Console.Write( ' ' )
//now draw them at the new square
Console.SetCursorPosition( playerX, playerY )
Console.Write( '@' )
else
//they can't move there, change their location back to the old location
playerX <- oldX
playerY <- oldY
//wait for them to press a key and store it in keyInfo
keyInfo <- Console.ReadKey( true )
所以我的问题是,为了更实用地重写它,我需要学习什么,你能给我一些提示,一个模糊的概述之类的东西。
我宁愿向正确的方向推进,而不是仅仅看到一些代码,但如果这是你向我解释它的最简单方法,那么很好,但在这种情况下,你能否也解释一下“为什么”而不是它的“如何”?
【问题讨论】:
-
这不是开始使用 F# 或一般函数式编程的最简单任务。状态是 @ 符号定位的固有属性,我认为以适当的函数形式执行此操作需要 monad 或其他箭头构造。
-
@jon_darkstar:完全有可能在不使用任何类似结构的情况下实现它。事实上,我建议您先自己实现该模式,以便在将其抽象到 monad 后面之前了解它在做什么。
-
是的,我想我有点想多了。现在我仔细阅读,似乎 OP 确实知道一些功能基础知识,而这个练习可能会成为过去的一个非常关键的障碍。通过nrkn遵循这一点,下面有一些很好的答案。这是 FP 更难的方面之一,但你会因此而变得更好。如果您真的想以认真的方式实现这一点,F# 可能不是最佳选择,但看起来您在这里设置了一个很好的练习。
-
好的,谢谢大家,我会记住你的建议。根据你们所说的,我正在做一些进一步的阅读:matthewmanela.com/blog/functional-stateful-program-in-f 和 stackoverflow.com/questions/3350644/… 如果没有你们有用的 cmets,我将无法找到这两个 :)
标签: f# functional-programming roguelike