I am working on a program in ASP.NET MVC where my goal is to make an golf scorecard.
In golf every player have an handicap which give them a number of extra strokes on each golf course they play. these number are then distributed over the 18 holes depending on the index on the hole (how hard it is) So for example if you get 25 extra strokes you get one stroke on hole 1-18 and then one extra on index hole 1-7 (so you have two extra strokes on these holes).
My scorecard is presented in the view with an field next to the hole number where i want to present how many extra strokes you have on this hole. So now i want to make a function that distribute these extra strokes.
My idea for the functions is that i pass in the players scorecard and the number of strokes as a parameter and then in some kind of for loop distribute the numbers of strokes over the 18 hole. And then return the list so i can present it in the view.
Anyone who can help me how to write this function?
/ Mike
This is how i started but got stuck..
public static List<Result> DistributeStrokes (int stroke,List<Result>MyList)
{
for(int i=0; i< MyList.count; i--;)
{
//do some code to add the strokes on the list
}
return MyList;
}
This is my class
public Class Result
{
public int Id {get;set}
public int Stroke{get;set} //number of strokes on the hole
public int Score {get;set} //number of extra stroke on the hole
public int Point {get;set}
}
Something along the lines of the below code should help, even if it's not 100% correct (I'm replying from my phone). Using the modulus operator to loop through your list, incrementing the result stroke while decrementing the stroke parameter.
int index = 0;
while (stroke > 0)
{
stroke--;
MyList[index].Stroke++;
index = (index + 1) % MyList.Count;
}
You'll also want to consider handling the case where the list is empty, etc.
Related
I have been trying to work with Unity's pure ECS approach to make a basic nxn grid of tiles.
Before using ECS I would just use a 2d array Tiles[,] grid where I can simply index (x,y) to find the tile I want.
Now moving into ECS, I want to create an entity for each tile using an IComponentData struct like so:
public struct Tile : IComponentData
{
public int xIndex;
public int yIndex;
public int isValid;
}
Somewhere during the start of my game I create the tile entities
for (int i = 0; i < tilesInMap; i++)
{
Entity tileEntity = entityManager.CreateEntity(tileArchetype);
int xIndex = i % terrainSize;
int yIndex = i / terrainSize;
entityManager.SetComponentData(tileEntity, new Position { Value = new float3(xIndex , 0, yIndex) });
Tile newTile;
newTile.xIndex = xIndex;
newTIle.yIndex = yIndex;
newTile.isValid = 1;
entityManager.SetComponentData(tileEntity, newTile);
}
Now somewhere else in my code I have a ComponentSystem that pulls in the tiles using a group struct
public struct TileGroup
{
public readonly int Length;
public EntityArray entity;
public ComponentDataArray<Tile> tile;
}
[Inject] TileGroup m_tileGroup;
As far as I'm aware, as long as I don't change the archetype of any of those entities in the TileGroup (for instance by calling AddComponent or RemoveComponent), the ordering of that injected array will be preserved (I'm not even sure of that!)
So say in my OnUpdate method I want to "get the tile at grid coordinate (23, 43)". I can calculate this (assuming a 1d array of tiles with the order preserved) by
int arrayIndex = yIndex * tilesPerMapWidth + xIndex;
But this only works as long as the injected array order of tiles is preserved which I doubt it will be eventually.
So a few questions:
1. Should I ever rely on the order of an injected array for behaviour logic?
2. Are there any better methods in achieving what I want using ECS?
From the Unity forums, "Order of Entities":
ComponentDataArray<> / ComponentGroup makes zero gurantees on the actual ordering of your entities except for that its deterministic. But generally the indices are not stable. (E.g. Adding a component to an entity, will change the index in ComponentDataArray of that entity and likely of another one) The only stable id is the "Entity" ID.
To answer your questions:
So a few questions: 1. Should I ever rely on the order of an injected array for behaviour logic?
Based on "...makes zero guarantees on the actual ordering of your entities..." I would say no.
Are there any better methods in achieving what I want using ECS?
You don't need arrayIndex to access entities in your tile group. You can iterate through the entities and access x and y for each to perform the required behavior. Depending on your actual functionality you may want to use the job system as well.
for (int i = 0; i < m_tileGroup.Length; i++) {
int x = m_tileGroup.tile[i].xIndex;
int y = m_tileGroup.tile[i].yIndex;
// do something with x and y
}
I want lines as many as the width of the console to simultaneously write downwards one char to the height of the console. I've done most of it, but it goes from top to bottom to right etc...
If you need help picturing what I mean, think of the matrix code rain.
int w = Console.WindowWidth;
int h = Console.WindowHeight;
int i = 0;
while (i < w)
{
int j = 0;
while (j < h)
{
Thread.Sleep(1);
Console.SetCursorPosition(i, j);
Console.Write(".");
j++;
}
i++;
}
What I would do is construct a List<string> lines; that would contain the lines you want to write to the console window, where each line is as wide as the console width. Then just print the list out to the console window in reverse order, so the first line (at lines[0]) will always be the last one printed, and will always be at the bottom of the console window.
Sample Implementation -- someone mentioned this might be homework. I did not think so, but if it is, then please try your own implementation of the above idea first.
We can add new items to the list in the same loop that we use to print out its items. Before we add a line, however, we first check to see if there are already as many lines in the list as there are in the console window (Console.WindowHeight). If there are, then we just remove the line at lines[0] before we add a new one. In this way, the List<string> lines is "scrolling" along with the console window.
The scrolling speed is controlled by a Thread.Sleep, but this code could easily be added to a Timer instead, so that other work could happen in the background (like if this was intended to be a "screensaver", and you wanted to wait for user input to "wake up"). But no matter how we decide to implement the speed, I decided to create an enum with values that represent the number of milliseconds a Thread.Sleep implementation would use:
class Program
{
enum MatrixCodeSpeed
{
Fastest = 0,
Faster = 33,
Fast = 67,
Normal = 100,
Slow = 333,
Slower = 667,
Slowest = 1000
}
I would also create a helper method that creates a "random" line for you. It could take in an integer that specifies the "density", which means how many characters you'd want in the line. density represents a percentage, so if 10 is specified, then we pick a random number between 0 and 99, and if it's less than 10 then we add a random matrix character to the string (otherwise we add a space character).
Also, in order to replicate the matrix a little closer, I've also chosen 4 different characters to print, each one slightly darker than the previous. This adds to the three dimensional effect, where the faded blocks look further away than the solid ones:
private static Random rnd = new Random();
// Add whatever 'matrix' characters you want to this array. If you prefer to have one
// character chosen more often than the others, you can write code to favor a specific
// index, or just add more instances of that character to the array below:
private static char[] matrixChars = new[] { '░', '▒', '▓', '█' };
static string GetMatrixLine(int density)
{
var line = new StringBuilder();
for (int i = 0; i < Console.WindowWidth; i++)
{
// Choose a random number from 0-99 and see if it's greater than density
line.Append(rnd.Next(100) > density
? ' ' // If it is, add a space to reduce line density
: matrixChars[rnd.Next(matrixChars.Length)]); // Pick a random character
}
return line.ToString();
}
Next, we have the main method, which populates a list with random lines (using a density of 10%), then prints them out one at a time, in reverse order, in an endless loop (removing the first line if we need to):
static void Main()
{
var lines = new List<string>();
var density = 10; // (10% of each line will be a matrix character)
var speed = MatrixCodeSpeed.Normal;
// Hide the cursor - set this to 'true' again before accepting user input
Console.CursorVisible = false;
Console.ForegroundColor = ConsoleColor.DarkGreen;
while (true)
{
// Once the lines count is greater than the window height,
// remove the first item, so that the list "scrolls" also
if (lines.Count >= Console.WindowHeight)
{
lines.Remove(lines[0]);
}
// Add a new random line to the list, which will be the new topmost line.
lines.Add(GetMatrixLine(density));
Console.SetCursorPosition(0, 0);
// Print the lines out to the console in reverse order so the
// first line is always last, or on the bottom of the window
for (int i = lines.Count - 1; i >= 0; i--)
{
Console.Write(lines[i]);
}
Thread.Sleep(TimeSpan.FromMilliseconds((int)speed));
}
}
}
Here's a gif of it in action, up to the point where the screen is full (then the gif repeats, but the code version continues to scroll normally):
The task smells like an assignment, so I'm guiding you instead feeding the implementation. It is not ethical to feed you with an answer if it is a homework.
You are looking for a better fit of algorithm. The stated algorithm fill the console from top to bottom, as it iterate to fill through the Y-axis first (the nested loop) and followed by the X-axis (the outer loop).
What is needed is to iterate x-axis and y-axis alternatively so that it looks like it fills from the top left corner to the bottom right corner.
// 1 step to (0,0)
*
// 3 steps to (1,1)
**
**
// 5 steps for reaching (2,2)
***
***
***
// 7 steps for reaching (3,3)
****
****
****
// 9 steps for reaching (4,4) and 11 steps for (5,5)...
// I do think everyone could get this pattern
This draft would also be the final outcome of what it looks like.
Instead of filling them all at the same time, what you need is actually get the thread sleep after it reach the next square point.
(Computers are so fast that it probably do all its work to feed your screen within a second and the black console window is gone without any notice.)
At the time you posted the question, I'm also solving it from the very beginning. I thought of filling X and Y axis alternatively is the solution, but stopping at each time that the square expands is far more important to get the effect.
It is not a threading problem tag either at my point of view.
Let's sum up the above pattern:
Assume i and j are x and y coordinates respectively.
Each iteration takes you from (i, j) and n*2+1 steps to reach
(i+1,j+1)
Note that we are zero-based in this example.
We are about to construct the loop:
The n*2+1 step number is useful. It means you need to fill x-axis for
n times and y-axis for n times, and finally get the diagonal grid
(n+1,n+1) done.
In each inner loop, we first render the X frontier along y-axis and
then render the Y frontier along x-axis.
Let say the cycle start with the checkpoint (n,n), where n=3, and we
slept for a while, so we are in n=4 now.
To achieve this, we'd better first navigate to (n+1,0) then fill up
to (n+1,n)
Afterwards we navigate to (0,n+1) and fill to (n+1,n+1)
Then we are in m=n+1 now (sounds like a mathematical proving :(
The loop would be
//calculate how many checkpoints (n)
int checkpoints = 1080;
//n should indicate the actual turn we are instead of naming the total turns like sucks
//The main, the outermost For-loop
for (int n=0;n<checkpoints;n++)
{
// The nested step
for (int y=0;y<n;y++)
{
// Just fill in (n+1, y) grid
Console.SetCursorPosition(n+1, y);
Console.Write(".");
}
for (int x=0;x<n+1;x++)
{
// Just fill in (x, n+1) grid
Console.SetCursorPosition(x, n+1);
Console.Write(".");
}
// Upon completion of each main cycle we have a sleep, yah
Thread.Sleep(100);
}
Well, I expect the program to crash when the console size is smaller than 1080x1080.
This algorithm could only get you a square to fill, and a typical monitor with resolution 1920x1080 just fails as it is 16:9. This is intentional, if you're doing homework you need to configure it before shipping it to your teacher. (I've got no chance to do an assignment as I self learned programming :(
(The site continuously urging me to format my code, this has been half an hour and I just didn't do things wrong. So I decided to post it bit by bit to debug that. Finally I've got the job done...)
If you just want to write one line at a time you can use this:
int w = Console.WindowWidth;
int h = Console.WindowHeight;
int i = 0;
while (i < h)
{
Console.WriteLine(new string('.', w-1));
Thread.Sleep(20);
i++;
}
Just a bit of modification allow the code to simulate the matrix code rain.
int w = Console.WindowWidth;
int h = Console.WindowHeight;
int i = 0;
while (i < h)
{
int j = 0;
string s = "";
Thread.Sleep(10);
while (j < w)
{
Console.SetCursorPosition(j, i);
s += ".";
j++;
}
Console.Write(s);
i++;
}
basically what i did here is just some restructuring of the logic and putting in the proper delays at the right position. Hope it helps.
I am trying to improve myself on probabilities with a task but couldn't figure it out:
On a backgammon game, I have four (dynamic) rows of placements.
So lets say row 5,7,11,13. I am throwing dynamic number of dice. I am trying to find the probabilities of each gameplay. As an example:
I have thrown 4 dice and result is 1,3,4,6
So
I can play from the 5. row-1,3,4,6 dice
I can play from the 5. row-1,3,4 dice and from the 7. row-6 dice
I can play from the 5. row-3,1 dice and from the 11. row-6 dice and from the 13. row-4 dice
etc etc.
The dice have to be dynamic, the rows have to be dynamic, the dice can be played mixed like 1,3,4,6 or 6,1,4,3 or 3,1,6,4. And it has to calculate all the possibilities of different variations of dice spread on the rows.
Simply I am trying to calculate the possibilities of play on a backgammon with unlimited dice. The method I am trying to use it to have a resizable possible moves class and inside of this class, there are the resizable rows class. Inside the rows class, there is resizable List moves variable. I am adding one move for each variation. This is the codes for non dynamic 4 dice.
public List<int> dice;
public List<int> places;
[System.Serializable]
public class arrayData
{
public List<arrayData2> places = new List<arrayData2>();
}
public List<arrayData> pos = new List<arrayData>();
[System.Serializable]
public class arrayData2
{
public List<int> moves = new List<int> {};
}
void Start()
{
vs();
}
void vs()
{
for (int i = 0; i < places.Count; i++)
{
for (int a = 0; a < dice.Count; a++)
{
for (int b = 0; b < dice.Count; b++)
{
for (int c = 0; c < dice.Count; c++)
{
for (int d = 0; d < dice.Count; d++)
{
if (a == b || a == c || a == d || b == c || b == d || c == d)
{
continue;
}
pos.Add(new arrayData());
for (int s = 0; s < places.Count; s++)
{
pos[pos.Count - 1].places.Add(new arrayData2());
}
pos[pos.Count - 1].places[i].moves.Add(dice[a]);
pos[pos.Count - 1].places[i].moves.Add(dice[b]);
pos[pos.Count - 1].places[i].moves.Add(dice[c]);
pos[pos.Count - 1].places[i].moves.Add(dice[d]);
}
}
}
}
}
}
What I couldn't figure out:
-Firstly, I tried to make it a recursive loop but I couldn't figure out the structure
-Second, the output is giving me missing values for the variation of spread between rows: It gives such values: 5. row-1,3,4,6 dices but not such values: 5. row-3,1 dices and from the 11. row-6 dice and from the 13. row-4 dice
I know it is a big question to ask but any kind of pointing out the mistake or correct direction leading would be so appreciated.
Thanks
It might be useful to think about your moves as part of a game tree. The basic idea is that all games start in a particular state. We'll call it x. A move then changes the state of the game to x1, the next move to x2, and so on. Most moves involve a choice and, depending on the choice made, each move pushes the game into a different state. From the starting state, all possible moves form a gigantic tree. This is handy because we can use tree traversal algorithms to explore our tree. That's where the recursion comes in.
Backgammon is conceptually a little trickier than a game like chess or checkers because you have to account for the randomness of the dice as well as the behavior of your opponent. That adds even more choices during a move. In pseudo-code, I might tackle the problem like this:
function get_next_move (current_state):
dice = roll_dice()
possible_states = an empty collection
get_possible_states (dice, current_state, possible_states)
return decide_best_state (possible_states)
function get_possible_states (dice, state, possible_states):
// If we've exhausted all dice, we're done.
// Add the state we've reached to our possible outcomes.
if dice are empty:
add state to possible_states
return
for each die in dice:
dice_without_die = remove die from dice
for each next_state in get_legal_states (state, die):
// Here's the recursion. Go a level deeper in our tree.
get_possible_states (dice_without_die , next_state, possible_states)
function get_legal_states (state, die):
// Here's where you determine legal moves based on the
// die rolled and the current state of the game.
Put another way, to determine my next move I have to:
Roll the dice.
With each die rolled, generate all of its legal moves (states).
Repeat the process using a new state and without the die already used.
When there are no dice left, add the final state to the list of possible states.
Finally, determine which move is best. Keep in mind that some generated states may be duplicates. There's more than one way to move your pieces to the same locations.
The nice thing about this approach is there are no hard-coded numbers. It can handle any number of legal moves or dice. (Though I'm not sure when Backgammon would use a variable number of dice.) One detail I left out is that you need to know who's turn it is. The legal moves will depend on who's making them.
I've stored a list of colors in my program. I am after an object in my scene to one of the colors in the list. So far, I have done the followings:
if(Input.GetKeyDown(KeyCode.O))
{
for(int i = 0; i < claddingColor.Count; i++)
{
claddingMaterial.color = claddingColor[i];
}
}
This isn't working due to a reason I know (and you can probably spot) but I lack to the verbal fortitude to write it down.
As opposed to have a multiple lines of the following:
claddingMaterial.color = claddingColor[0];
Each tied to different buttons, I like a way I can emulate the above but tie it to a single button press. Thus, if I hit the 0 button 5 times, it will loop through each color stored in the list. If I hit it for a sixth time, it will go back to the first color in the list.
Could someone please help me implement this? Or point me to something that I may learn how to do it for myself?
Define LastColor property as class member:
int LastColor;
In your function use modulo
if(Input.GetKeyDown(KeyCode.O))
{
claddingMaterial.color = claddingColor[(LastColor++) % claddingColor.Count];
}
Note: Depending on the type of claddingColor use Count for a List or Length for Array.
You won't need a for loop
int lastStep = 0;
if(Input.GetKeyDown(KeyCode.O))
{
claddingMaterial.color = claddingColor[lastStep++];
if (lastStep == claddingColor.Count)
lastStep = 0;
}
Related question: Getting a string index based on a pixel offset
I know this is close to that question, but this isn't asking how to do it directly, it's asking how to fake it best.
I am implementing my own text box for Windows Forms (because RichTextBox sucks) and I am trying to find the best way to, given strings that have been drawn on the screen, calculate what character the mouse is over. The problem is that characters can be variable-width.
I have come up with two possibilities:
Do Graphics.MeasureCharacterRange every time the mouse moves in a binary search fashion on the line that the mouse is over (as suggested in the question linked at the top)
Keep a list of the offset of every character of every line.
(1) Will have bad performance, and
(2) will be memory-inefficient plus make typing a character become a O(n) operation (because you have to adjust the offset of every character after it) plus impossible to do precisely because Graphics.MeasureCharacterRange isn't precise (it returns one value for one character, another value for another character, and a totally different value [that does not equal the two previous values added together] for both of them together in one string. E.g. W will be 16 pixels wide and f will be 5 pixels wide, but Wf is 20 pixels wide. Those numbers are from an actual test.).
So I am looking for a better strategy to do this, preferably one that requires minimal space and O(1) computational complexity (though I will gladly trade off a little memory efficiency for speed efficiency).
I don't think you have to do O(1). O(1) is assuming that every additional character has an affect on ALL previous characters, which it would not. At best I would see an O(1) for each word which should be crazy fast. It sounds like what you need is a way to store; 1 the location of each word, 2 each unique word, and 3 the width of each letter in the word. This would significantly reduce the storage and increase look up speed. Maybe something like:
IEnumerable<TextLocation> TextLocations = ...;
internal class TextLocation
{
public RectF BoundingBox { get; set; } //this is relative to the textbox
public TextWord TextWord { get; set; }
}
internal class TextWord
{
public string Text { get; set; }
public IEnumerable<LetterInfo> Letters { get; set; }
}
internal class LetterInfo
{
public char Letter { get; set; }
public float left { get; set; } //these would be relative to the bounding box
public float right { get; set; } //not to the textbox
}
Then you might be able to do something like
var tl = TextLocations.FirstOrDefault(x => x.BoundingBox.Left < Mouse.X
&& x.BoundingBox.Right > Mouse.X
&& x.BoundingBox.Top < Mouse.Y
&& x.BoundingBox.Bottom > Mouse.Y)
if (tl != null)
{
//tl.TextWord.Text is the Word ("The", "Lazy", "Dog"...)
var letter = tl.TextWord.Letters
.FirstOrDefault(x => Mouse.x - tl.BoundingBox.left > x.left
Mouse.x - tl.BoundingBox.left < x.right);
if (letter != null)
{
// you get the idea
}
}