-
Notifications
You must be signed in to change notification settings - Fork 2
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Enumoji implementation in C# 14.0 #2
base: master
Are you sure you want to change the base?
Changes from 1 commit
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -3,4 +3,5 @@ obj/ | |
/packages/ | ||
riderModule.iml | ||
/_ReSharper.Caches/ | ||
.idea | ||
.idea | ||
.ionide |
This file was deleted.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,67 @@ | ||
module GameOfLife.Program | ||
open System | ||
open System.Security.Cryptography | ||
open System.Text | ||
open System.Threading | ||
|
||
let rows = 15 | ||
let columns = 15 | ||
let timeout = 500 | ||
Comment on lines
+7
to
+9
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We can infer types on our statically scoped variables! |
||
let mutable runSimulation = true | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. F# requires you to qualify any variable you want to mutate. You save so much boiler plate with type inference, adding this extra 6 let word hardly seems like a thing, and makes it easier to reason about variables. Notice we only have to use the keyword 3 times in this program ported directly from C#. |
||
|
||
type Status = ``💀`` = 0 | ``😁`` = 1 | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Using Enumoji's we don't have to use conditional expressions for the 3 data types needed for two states Alive|Dead in this port. We can then use the F# operators |
||
|
||
let private nextGeneration (currentGrid: Status [,]) = | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Although there is a recursive modifier ( |
||
let nextGeneration = Array2D.zeroCreate rows columns | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. F# has functions to create arrays, rather than syntax. While an F# |
||
// Loop through every cell | ||
for row in 1..(rows-2) do | ||
for column in 1..(columns-2) do | ||
Comment on lines
+17
to
+18
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. F# doesn't have a post increment operator, so you can use a range operator in a for loop instead. F# ranges are inclusive at start and end, and can be used as a sequence, unlike new C# ranges. While imperative for loops are not the preferred F# method, this is how you would do them in F#. If you want to decrement from 10 to 1 the syntax is |
||
// find your alive neighbor | ||
let mutable ``😁Neighbors`` = 0 | ||
for i in -1..1 do | ||
for j in -1..1 do | ||
``😁Neighbors`` <- ``😁Neighbors`` + int currentGrid.[row+i, column+i] | ||
let currentCell = currentGrid.[row, column] | ||
// The cell needs to be subtracted | ||
// from its neighbours as it was | ||
// counted before | ||
``😁Neighbors`` <- ``😁Neighbors`` - int currentCell | ||
// Implementing the Rules of Life | ||
nextGeneration.[row,column] <- | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. While we didn't declare the variable |
||
match currentCell with | ||
// Cell is lonely and dies OR Cell dies due to over population | ||
| Status.``😁`` when ``😁Neighbors`` < 2 || ``😁Neighbors`` > 3 -> Status.``💀`` | ||
// A new cell is born | ||
| Status.``💀`` when ``😁Neighbors`` = 3 -> Status.``😁`` | ||
// stays the same | ||
| _ -> currentCell | ||
jbtule marked this conversation as resolved.
Show resolved
Hide resolved
|
||
nextGeneration | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. In F# the last line in an expression is the returned value. No |
||
|
||
let private print (future: Status[,]) = | ||
let sb = StringBuilder() | ||
for row in 0..(rows-1) do | ||
for column in 0..(columns-1) do | ||
future.[row, column] |> string |> sb.Append |> ignore | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The pipe operator ignore(sb.Append(string(future.[row, column]))) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The |
||
sb.AppendLine() |> ignore | ||
Console.BackgroundColor <- ConsoleColor.Black | ||
Console.CursorVisible <- false | ||
Console.SetCursorPosition(0,0) | ||
sb.ToString() |> Console.Write |> ignore | ||
Thread.Sleep(timeout) | ||
|
||
[<EntryPoint>] | ||
let main _ = | ||
// randomly initialize our grid | ||
let mutable grid = Array2D.init rows columns (fun _ _ -> RandomNumberGenerator.GetInt32(0, 2) |> enum<Status>) | ||
Console.CancelKeyPress.Add( | ||
fun _ -> | ||
runSimulation <- false | ||
Console.WriteLine("\n👋 Ending simulation.")) | ||
Comment on lines
+56
to
+59
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think I read somewhere that C# designers wished they never special cased |
||
// let's give our console | ||
// a good scrubbing | ||
Console.Clear(); | ||
// Displaying the grid | ||
while runSimulation do | ||
print grid | ||
grid <- nextGeneration(grid) | ||
0 | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Main function is expected to return an integer. So last line is a zero. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Although you can do C# style static classes in F# with some boilerplate. A module is the preferred vehicle for static functions. CLI wise it will look like a static class in C#.