https://simmer.io/#JammerLamma/~c09dd45e-0528-01ce-e641-e4a56fb9cfed
https://github.com/JammerLamma/Number-Muncher-Clone
I'm creating a number munchers clone, and the integer variables are not getting properly assigned. It works for a few games, but after a few times of winning, and/or clicking quit, and choosing another game it appears the for loop goes through properly. The game says there are 5 maxCorrect, and correctOnBoard is also set to 5, so I assume the loop goes through 5 times, however, only 4 tiles get set as correct, then sometimes 2, or 4, but never 5 again. It always works as intended the first game.
If I comment out //AssignRest(); the problem still persists.
public void GenerateEven()
{
//GameObject smasher = Instantiate(smasherPF, transform.position, transform.rotation);
remainingNumbers = totalTiles - maxCorrect;
GetLists();
GetTiles();
AssignEven();
RemoveDuplicates(evenNumbers);
AssignRest();
}
private void AssignEven()
{
int maxCorrect = 5;
for (int i = 1; i <= maxCorrect; i++)
{
randomChild = children[UnityEngine.Random.Range(0, children.Count)];
int maxLength = evenNumbers.Count;
int tempTileNum = evenNumbers[UnityEngine.Random.Range(0, maxLength)];
randomChild.GetComponent<Tile>()._TileNumber = tempTileNum;
randomChild.GetComponent<Tile>()._IsCorrect = true;
correctOnBoard++;
randomChild.GetComponent<SpriteRenderer>().sprite = numberSprite[tempTileNum - 1];
Debug.Log(tempTileNum);
}
}
Some things are serialized for debugging purposes. All of the lists get generated correctly.
Changed the code to
private void AssignEven()
{
for (int i = 1; i <= maxCorrect;)
{
randomChild = children[UnityEngine.Random.Range(0, children.Count)];
if(randomChild.GetComponent<Tile>()._IsCorrect == false)
{
int maxLength = evenNumbers.Count;
int tempTileNum = evenNumbers[UnityEngine.Random.Range(0, maxLength)];
randomChild.GetComponent<Tile>()._TileNumber = tempTileNum;
randomChild.GetComponent<Tile>()._IsCorrect = true;
correctOnBoard++;
randomChild.GetComponent<SpriteRenderer>().sprite = numberSprite[tempTileNum - 1];
Debug.Log(tempTileNum);
i++;
}
}
}
Thanks to John Wu!
Related
I'm making a simple game in C# where the player fights until they have no more health:
public void FightLoop(int currentHealth) {
bool death = false;
do{
hit = false;
if(currentHealth == 0){
death = true;
}
turn = turn + 1;
string turnRecord = turn.ToString();
string firstPlayerChoiceString = GetPlayerInput();
string secondPlayerChoiceString = GetRandomWeapon ();
string gameResult = DetermineWinner(firstPlayerChoiceString, secondPlayerChoiceString, currentHealth, turnRecord);
if(hit == true){
currentHealth = currentHealth - 1;
}
FightRecord();
AddRecord(firstPlayerChoiceString, secondPlayerChoiceString, gameResult, turnRecord, turn);
}while (death == false);
DisplayFightHistory ();
}
At the end of each fight, a summary of the whole thing should be shown (array with turns, attacks and results).
public void FightRecord(int recordSize = 100)
{
try
{
fightRecordSize = recordSize;
fightRecord = new string[fightRecordSize, 4];
}
catch (OverflowException e)
{
System.Console.WriteLine("OverflowException during FightRecord initialization: \"{0}\"\nrecordSize given was [{1}]\nSetting recordSize to 10", e.Message, recordSize);
fightRecordSize = 100;
fightRecord = new string[fightRecordSize, 4];
}
fightRecordCurrentSize = fightRecordCurrentSize++;
}
public void AddRecord(string playerOneChoice, string playerTwoChoice, string gameResult, string turnRecord, int turn)
{
// Insert the record data
fightRecord[fightRecordCurrentIndex, 0] = playerOneChoice;
fightRecord[fightRecordCurrentIndex, 1] = playerTwoChoice;
fightRecord[fightRecordCurrentIndex, 2] = gameResult;
fightRecord[fightRecordCurrentIndex, 3] = turnRecord;
// Increment the fight index counter and current history size
fightRecordCurrentIndex = (fightRecordCurrentIndex + 1) % fightRecordSize;
if (fightRecordCurrentSize < fightRecordSize)
{
fightRecordCurrentSize++;
}
}
public void DisplayFightHistory () {
System.Console.WriteLine ("\nPodsumowanie:");
for (int i = 0; i < fightRecordCurrentSize; i++){
System.Console.WriteLine ("Tura #{0}:\t{1}\t-\t{2},\t{3} {4}",
fightRecord[i,3], fightRecord[i,0], fightRecord[i,1], fightRecord[i,2], i);
}
}
However, every time I get only the last value, like this:
Summary:
Turn #: - ,
Turn #: - ,
Turn #: - ,
Turn #: - ,
Turn #: - ,
Turn #: - ,
Turn #8: Sword - Spear, You lose
By following the whole process of creating the array, it seems like the values are being put in it correctly at first, but with each new turn, only the last value remains.
Does anyone have any idea why it's happening?
Use the loop variable as the index.
Change
fightRecord[displayRecordIndex,3], fightRecord[displayRecordIndex,0], fightRecord[displayRecordIndex,1], fightRecord[displayRecordIndex,2], displayRecordIndex);
To
fightRecord[i,3], fightRecord[i,0], fightRecord[i,1], fightRecord[i,2], i);
Just as the title says, I have a waveManaging system that spawnsEnemies based on enemies that are yet to spawn and remain alive.
for (int enemiesRemainingToSpawn = currentWaveNumber ; enemiesRemainingToSpawn > 0;enemiesRemainingToSpawn -- , enemiesRemainingAlive ++)
{
print("enemies spawning" + enemiesRemainingToSpawn);
print("enemies alive" + enemiesRemainingAlive);
}
This is just a test right now, but it seems that 'enemiesRemaingToSpawn --' is not working while 'enemiesRemainingAlive ++' is.
On the GameDev Discord, no one has found anything wrong with it which is why I am here. It looks fine to me as well. I have tried putting it within the body of the loop but that does not work as well. i have specified it within the initializing(first) section of the for loop and again this does not work.
What is the problem at hand?
edit:
public int enemiesRemainingToSpawn;
public int enemiesRemainingAlive;
public float afterWavePrepTime = 5f;
public GameObject basicEnemyPreFab;
public Transform[] spawnPoints;
private bool isWaveFinished = false;
private bool startNewWave = false;
public int currentWaveNumber;
void spawnEnemies ()
{
int spawnPointIndex = Random.Range(0, spawnPoints.Length);
for (int enemiesRemainingToSpawn = currentWaveNumber ; enemiesRemainingToSpawn > 0;enemiesRemainingToSpawn -- , enemiesRemainingAlive ++)
{
print("enemies spawning" + enemiesRemainingToSpawn);
print("enemies alive" + enemiesRemainingAlive);
}
}
The output is that enemiesRemainingAlive constantly goes up because EnemiesRemainingToSpawn does not go down, concluding in an endless loop.
remainingtospawn = 1, enemiesremainingalive ++
Hi I try to run your code in locally by excluding your objects .Its running well
public static void spawnEnemies()
{
int enemiesRemainingAlive = 0;
double afterWavePrepTime = 5.0;
bool isWaveFinished = false;
bool startNewWave = false;
int currentWaveNumber;
Random x = new Random();
currentWaveNumber = x.Next(1, 7);
for (int enemiesRemainingToSpawn = currentWaveNumber; enemiesRemainingToSpawn > 0; enemiesRemainingToSpawn--, enemiesRemainingAlive++)
{
Console.WriteLine("enemies spawning" + enemiesRemainingToSpawn);
Console.WriteLine("enemies alive" + enemiesRemainingAlive);
}
Console.ReadLine();
}
//out put
// enemies spawning2
//enemies alive0
//enemies spawning1
//enemies alive1
So I am trying to figure out why filling sudoku board in order of how I generate fields is many times faster then filling it which shuffled order, and I can't come to any reasonable conclusions.
Speed of filling and checking should be about the same no matter if fields are shuffled or not, only noticeable difference is the fact that filling boxes in a shuffled order causes the main loop to easily go for 60.000.000+ iterations not sure how many on average as I am not patient enough to check. And filling them in order of how they were generated gets finished in usually < 1.000 iterations rarely going over it and basically never going over 5.000.
I do understand that code doesn't follow C# standards too strictly but it's a project I am supposed to make and it's not my main language there are probably some possible optimizations but it's not what I am interested in all i want to know why shuffling the order of fill the boxes causes the process to take this much longer.
Edit: forgot to attach order of creating/filling boxes order of filling/creating boxes:
Edit2: more concise rephrased question:
The question is why generating an valid fully filled sudoku board in order from image creates a lot less invalid boards from which there is required backtracking, as compared to generating a board in a random order of choosing fields?
example of random order
Here is the code used for the project https://github.com/Piterm21/sudoku
And here are all the parts used in generation.
filledBox class:
public class filledBox
{
public int textBoxIndex;
public int value;
public int nextIndexToTry;
public int[] values;
public int lineIndex;
public int columnIndex;
public int groupIndex;
}
Here is a main loop:
filledBox[] boxes = this.shuffleBoxesCreateCheckingLists();
long iter = 0;
int nextIndexToFill = 0;
while (nextIndexToFill != 81) {
for (; boxes[nextIndexToFill].nextIndexToTry < 9; boxes[nextIndexToFill].nextIndexToTry++) {
// check if is valid
if (!createsError(boxes[nextIndexToFill])) {
boxes[nextIndexToFill].value = boxes[nextIndexToFill].values[boxes[nextIndexToFill].nextIndexToTry];
nextIndexToFill++;
break;
}
if (boxes[nextIndexToFill].nextIndexToTry == 8) {
boxes[nextIndexToFill].nextIndexToTry = 0;
boxes[nextIndexToFill].value = 0;
nextIndexToFill--;
boxes[nextIndexToFill].nextIndexToTry++;
while (boxes[nextIndexToFill].nextIndexToTry == 9) {
boxes[nextIndexToFill].nextIndexToTry = 0;
boxes[nextIndexToFill].value = 0;
nextIndexToFill--;
boxes[nextIndexToFill].nextIndexToTry++;
}
break;
}
}
iter++;
}
System.Diagnostics.Debug.WriteLine(iter);
Generation of boxes with setting of lists used for checking for errors:
List<filledBox>[] generationLines;
List<filledBox>[] generationColumns;
List<filledBox>[] generationGroups;
public filledBox[] shuffleBoxesCreateCheckingLists()
{
filledBox[] boxes = new filledBox[81];
for (int i = 0; i < 81; i++) {
boxes[i] = new filledBox();
boxes[i].values = new int[9]{ 1, 2, 3, 4, 5, 6, 7, 8, 9 };
boxes[i].values = shuffle(boxes[i].values, true);
}
generationLines = new List<filledBox>[9];
generationColumns = new List<filledBox>[9];
generationGroups = new List<filledBox>[9];
for (int i = 0; i < 9; i++) {
generationLines[i] = new List<filledBox>();
generationColumns[i] = new List<filledBox>();
generationGroups[i] = new List<filledBox>();
}
int boxIndex = 0;
for (int y = 0; y < 3; y++) {
for (int x = 0; x < 3; x++) {
for (int innerY = 0; innerY < 3; innerY++) {
for (int innerX = 0; innerX < 3; innerX++) {
int subPanelIndex = x + y * 3;
int lineIndex = innerY + y * 3;
int columnIndex = innerX + x * 3;
boxes[boxIndex].textBoxIndex = boxIndex;
boxes[boxIndex].groupIndex = subPanelIndex;
boxes[boxIndex].columnIndex = columnIndex;
boxes[boxIndex].lineIndex = lineIndex;
boxes[boxIndex].nextIndexToTry = 0;
boxes[boxIndex].value = 0;
generationLines[lineIndex].Add(boxes[boxIndex]);
generationColumns[columnIndex].Add(boxes[boxIndex]);
generationGroups[subPanelIndex].Add(boxes[boxIndex]);
boxIndex++;
}
}
}
}
#if !fast
boxes = shuffle(boxes);
#endif
return boxes;
}
Shuffling code:
public T[] shuffle<T> (T[] array)
{
int i = array.Length;
while (i > 1) {
i--;
int j = rnd.Next(0, i - 1);
T temp = array[i];
array[i] = array[j];
array[j] = temp;
}
return array;
}
And code responsible for checking for errors:
public bool hasError (List<filledBox> list, filledBox box)
{
bool result = false;
foreach (filledBox filledBoxToCheck in list) {
if (filledBoxToCheck.value == box.values[box.nextIndexToTry]) {
if (box.lineIndex != filledBoxToCheck.lineIndex ||
box.columnIndex != filledBoxToCheck.columnIndex) {
result = true;
break;
}
}
}
return result;
}
public bool createsError (filledBox box)
{
bool result = false;
if (hasError(generationGroups[box.groupIndex], box)) {
result = true;
} else if (hasError(generationLines[box.lineIndex], box)) {
result = true;
} else if (hasError(generationColumns[box.columnIndex], box)) {
result = true;
}
return result;
}
The reason the shuffled order of visiting boxes is worse is that, for the first few boxes, you've increased the odds of filling them in independently. I'm calling a 3x3 region a box. You could visit each little square randomly, but I'll confine my analysis to fillng in one 3x3 box at a time. It should illustrate the problem.
Lets assume, whether you used the in-order or random method, you filled in the top left box first.
VISITING BOXES IN ORDER:
Now consider filling in the box next to it, that is, the top middle box. Just look at filling in the top row of that box, there are 6x5x4 = 120 ways to fill it in.
VISITING BOXES RANDOMLY:
Now consider instead choosing any box to fill in next. If you happen to choose a box that is not in the top row or left column, filling it in is unaffected by the way the first box was filled. The top row of that box can be filled in 9x8x7 = 504 ways.
Taking this further, if you fill in the boxes sequentially, say, across the top, the third box (the top right one), begins with only 3x2x1 = 6 ways to fill in the top row of it. Whereas, if you select the next box randomly, you might, at worst, select a box that is not in the same row or column of either of the first 2 boxes, which means that the top row of that box has yet again 9x8x7 = 504 ways of being filled in.
If you tried randomly selecting the order for each little square to be filled in, the first few might all be in different rows and columns. At worst, none of the first 9 squares will align meaning there will be 9^9 = 387,420,489 options. But filling them in across the top row, the choices are guaranteed to be 9! = 362,880.
This illustrates one of the strategies for how to approach backtracking. Ideally, you first solve parts of the problem that most tightly constrain the rest of the problem. For some problems sequential is better, and for some random is better.
As the title suggests I am initializing objects in a list through a loop. But they all become identical when the loop exits. I can see during the loop that they are not the same. but when the loop exits they change to the last object entered.
public List<ElevationLayout> layoutList = new List<ElevationLayout>();
public int layoutNumber { get; set; }
public int worldWidth { get; set; }
public Random seed { get; set; }
public XYSize dimLeft { get; set; }
//I have narrowed down the problem to this method
//==========================================================================================================================================================
//==========================================================================================================================================================
//==========================================================================================================================================================
public void init(World world) {
dimLeft = new XYSize();
ElevationLayout layout = new ElevationLayout();
dimLeft.y = 0;
dimLeft.x = world.size.x;
seed = new Random((int)DateTime.Now.Ticks);
worldWidth = (int)((world.size.x / 6.4) + (world.size.x / 64) - 1);
layoutNumber = worldWidth + seed.Next(-2, 3);
for (int i = 0; i < layoutNumber; i++)
{
layout.type = seed.Next(0, 2);
layout.width = (world.size.x / layoutNumber) + seed.Next(0, ((dimLeft.x / layoutNumber) / 2) + 1);
if (layout.width > dimLeft.x)
{
layout.width = dimLeft.x;
}
dimLeft.x -= layout.width;
layout.height = seed.Next(world.size.y / 16, (world.size.y / 4) + 1);
if (layout.height > dimLeft.y)
{
layout.height = dimLeft.y;
}
this.layoutList.Add(layout);
Console.Write(this.layoutList[i].type); // here the objects are different
if ((world.size.y -= layout.height) > dimLeft.y)
{
dimLeft.y = (world.size.y - layout.height);
}
if (dimLeft.x <= 0)
{
layoutNumber = i;
}
}
Console.WriteLine();
for (int y = 0; y < layoutNumber; y++)
Console.Write(this.layoutList[y].type); //but as soon as i exit the loop they are the same
}
//==============================================================================================================
//==============================================================================================================
//==============================================================================================================
Someone had a similar problem here: Why is my list of objects all the same?
and here: Why are all the values in my list the same?
Initially my list of objects was static, but i have since removed that and the problem remains.
The problem is that you only create one instance of the object before the loop and set the properties of that one object.
Fix:
for (int i = 0; i < layoutNumber; i++)
{
ElevationLayout layout = new ElevationLayout();
Basically create your object inside the loop, so that on every iteration you allocate a new object.
You're adding the same layout to the list over and over, rather than creating a new instance of layout each time. Move the code to create the layout object inside the loop.
In my code I have a nested loop which does not iterate with the exception of an if statement that always occurs no matter what the condition. Without the if statement the portion of the for loop's code which iterates the loop becomes unreachable. No matter what I have tried I have not been able to get the inside loop to iterate.
class Map
{
public int Width { get; set; }
public int Height { get; set; }
public Vector2[] positions = new Vector2[500*500];
private GroundVoxel[,] map = new GroundVoxel[500, 500];
private Vector2 voxelPosition = new Vector2(0,0);
private static int sizeX = 499, sizeY = 499, airLevel = 425;
private int positionX = 0, positionY = 0, vectorNumber = 0;
public Map()
{
}
public Vector2[] Initialize()
{
for (int i = 0; i <= sizeY; i++)
{
for (int j = 0; j <= sizeX; j++) <-- This does not iterate.
{
map[positionX, positionY] = new GroundVoxel(voxelPosition);
voxelPosition.X += 80;
positions[vectorNumber] = voxelPosition;
vectorNumber += 1;
if (j == sizeX) <-- This always executes even though j != sizeX.
{
break;
}
}
voxelPosition.Y += 80;
voxelPosition.X = 0;
}
return positions;
}
}
}
You have to use the fully qualified name to refer to a static class member variable like your sizeX and sizeY. Here is an article on the subject.
Hope this helps!
I think we'll need more code. I've copied your code into a basic winforms test application and both of my loops iterates as expected.
I'm not familiar with XNA or what a "VoxelPosition" is, but I think you have a lurking bug here:
voxelPosition.X += 80;
positions[vectorNumber] = voxelPosition;
You are simply storing the same pointer in a very large array -- all of the entries will be pointing to the same object.
You will need to declare another object every time through the loop to store individal vector entries.
Hope this helps?