gpt4 book ai didi

f# - 在 F# 中非常简单的 RogueLike,使它更 "functional"

转载 作者:行者123 更新时间:2023-12-04 10:05:49 25 4
gpt4 key购买 nike

我有一些现有的 C# 代码,用于一个非常非常简单的 RogueLike 引擎。故意天真,因为我试图尽可能简单地做最少的事情。它所做的只是使用箭头键和 System.Console 在硬编码 map 周围移动 @ 符号:

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

所以我的问题是,我需要学习什么才能更有效地重写它,你能给我一些提示,一个模糊的概述,那种东西。

我更喜欢朝正确的方向推进,而不是只看一些代码,但如果这是你向我解释的最简单方法,那很好,但在这种情况下,你能不能解释一下“为什么”而不是“如何” ”的吗?

最佳答案

一般而言,游戏编程将测试您管理复杂性的能力。我发现函数式编程鼓励您将解决的问题分解成更小的部分。

您要做的第一件事是通过分离所有不同的关注点,将您的脚本变成一堆函数。我知道这听起来很愚蠢,但这样做的行为将使代码更具功能性(双关语)。您主要关注的是状态管理。我用一个记录来管理位置状态,用一个元组来管理运行状态。随着您的代码变得更高级,您将需要对象来干净地管理状态。

尝试在此游戏中添加更多内容,并随着功能的增长不断分解这些功能。最终,您将需要对象来管理所有功能。

在游戏编程笔记上,不要将状态更改为其他内容,如果未通过某些测试,则将其更改回来。你想要最小的状态变化。因此,例如下面我计算了 newPosition然后只更改 playerPosition如果这个 future 的职位过去了。

open System

// use a third party vector class for 2D and 3D positions
// or write your own for pratice
type Pos = {x: int; y: int}
with
static member (+) (a, b) =
{x = a.x + b.x; y = a.y + b.y}

let drawBoard map =
//clear the console
Console.Clear()
//send each row of the map to the Console
map |> List.iter (printfn "%s")

let movePlayer (keyInfo : ConsoleKeyInfo) =
match keyInfo.Key with
| ConsoleKey.UpArrow -> {x = 0; y = -1}
| ConsoleKey.DownArrow -> {x = 0; y = 1}
| ConsoleKey.LeftArrow -> {x = -1; y = 0}
| ConsoleKey.RightArrow -> {x = 1; y = 0}
| _ -> {x = 0; y = 0}

let validPosition (map:string list) position =
map.Item(position.y).Chars(position.x) = ' '

//clear the square player was standing on
let clearPlayer position =
Console.SetCursorPosition(position.x, position.y)
Console.Write( ' ' )

//draw the square player is standing on
let drawPlayer position =
Console.SetCursorPosition(position.x, position.y)
Console.Write( '@' )

let takeTurn map playerPosition =
let keyInfo = Console.ReadKey true
// check to see if player wants to keep playing
let keepPlaying = keyInfo.Key <> ConsoleKey.Q
// get player movement from user input
let movement = movePlayer keyInfo
// calculate the players new position
let newPosition = playerPosition + movement
// check for valid move
let validMove = newPosition |> validPosition map
// update drawing if move was valid
if validMove then
clearPlayer playerPosition
drawPlayer newPosition
// return state
if validMove then
keepPlaying, newPosition
else
keepPlaying, playerPosition

// main game loop
let rec gameRun map playerPosition =
let keepPlaying, newPosition = playerPosition |> takeTurn map
if keepPlaying then
gameRun map newPosition

// setup game
let startGame map playerPosition =
drawBoard map
drawPlayer playerPosition
gameRun map playerPosition


//define the map
let map = [ " ";
" ";
" ";
" ";
" ############################### ";
" # # ";
" # ###### # ";
" # # # # ";
" #### #### # # # ";
" # # # # # # ";
" # # # # # # ";
" #### #### ###### # ";
" # = # ";
" # = # ";
" ############################### ";
" ";
" ";
" ";
" ";
" " ]

//initial player position on the map
let playerPosition = {x = 8; y = 6}

startGame map playerPosition

关于f# - 在 F# 中非常简单的 RogueLike,使它更 "functional",我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4495993/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com