I'm trying to create a Sudoku generator that saves the puzzle in a 2D string array.
I created a recursive method that returns the puzzle at the end, but as soon as it returns the puzzle it continues with the recursion and so I can never break out of this method.
The recursive method code is below:
static string[,] RecursiveFill(int digit, int px, int py, string[,] grid)
{
// Create a new test grid
string[,] testGrid = new string[9, 9];
// Fill it with the current main grid
for (int i = 0; i < 9; i++)
{
for (int j = 0; j < 9; j++)
testGrid[j, i] = grid[j, i];
}
// Place the digit to be entered into the test grid
testGrid[px, py] = digit.ToString();
// Find a new digit to enter
for (int x = 0; x < 9; x++) // Iterate through the grid by x
{
for (int y = 0; y < 9; y++) // And by y
{
if (testGrid[x, y] == 0.ToString() || testGrid[x, y] == null) // If an empty slot
{
for (int val = 1; val <= 9; val++) // 1-9 as these are the numbers to enter
{
if (CheckMove(y, x, val, testGrid)) // If the move is valid
RecursiveFill(val, x, y, testGrid); // Use recursion and go back around
}
return null; // Otherwise return null
}
}
}
return testGrid; // This gets returned but then it carries on with the RecursiveFill method and never exits this method?
}
Here's how I'm calling this method:
sudokuGrid = RecursiveFill(0, 0, 0, sudokuGrid);
If anyone has any suggestions as to what I need to modify in order to get this method to return a complete sudoku puzzle that'd be awesome. I've had this bug for a few days now and I can't figure out why. :/
You probably need to check if the return value from RecursiveFill() is non-null, and return it if it is.
In your inner loop:
if (CheckMove(y, x, val, testGrid)) // If the move is valid
{
var result = RecursiveFill(val, x, y, testGrid); // Use recursion and go back around
if (result != null)
return result;
}
Related
I'm trying to make a scan of an array where it follows the index with the numbers inside and I don't understand why it gives me this exception. I cant add any more details its a pretty straight forward question.
using System;
public class Program
{
public static bool IsPerfect(int[] arr)
{
int next=0, done=0,i;
while (done == 0)
{
i = arr[next];
arr[next] = 10;
next = arr[i];
if (i == 0)
done = 1;
}
for(int j = 0; j < arr.Length; j++)
if (arr[j] != 10)
return false;
return true;
}
public static void Main()
{
int[] arr = { 3, 0, 1, 4, 2 };
if (IsPerfect(arr) == true)
Console.WriteLine("is perfect");
if (IsPerfect(arr) == false)
Console.WriteLine("boooo");
}
}
You are not specifying the functioning for duplicates... Use a method to check for duplicates and as soon as you encounter a duplicate element exit the loop... It will work fine! 👍
ok for anyone intrested the problem was lying in the second if, and the "next = arr[i];" the first i changed because it made more sense and the second and main problem was the other if. because i had the second condition it ran the method twice and with the changed values it returned an error.
the solution was to put else instead.
Reverse engineering: we mark visited items and if all items are visted, then we have a "Perfect" array.
Problem: we mark item with 10 which can be an index (what if array has, say, 15 items)?
Solution: let's mark by -1 (definitely not an index - an array can have negative number of items) and check if item has been marked:
Tricky moment: we should assign -1 to the current arr[i] item but use its initial value to be assigned to i. Sure, we can save i and put it as
for (int i = 0; i >= 0 && i < arr.Length; ) {
int nextI = arr[i];
arr[i] = i;
i = nextI;
}
but let's put in a short modern way: (i, arr[i]) = (arr[i], -1);
Code:
public static bool IsPerfect(int[] arr) {
// In public method we must be ready for any input; null included
if (arr == null)
return false; // or throw new ArgumentNullException(nameof(arr));
// Do we have a valid array?
for (int i = 0; i < arr.Length; ++i)
if (arr[i] < 0 || arr[i] >= arr.Length)
return false;
// Note the condition: we read the next item - arr[i] -
// if and only if i is within range
// Note, that we have nothing to increment / decrement
for (int i = 0; i >= 0 && i < arr.Length; )
(i, arr[i]) = (arr[i], -1); // note the assignment: both i and arr[i] in one go
// We have marked all that we could.
// Do we have unmarked items?
for (int i = 0; i < arr.Length; ++i)
if (arr[i] != -1) // ... yes, we have and thus
return false; // arr is not perfect
return true;
}
Please, fiddle
I have a 2d boolean array that checks if the row of the columns are all true. right now I want to check that if a row is filled with all true. I want that row to go all false. and then I take the value above me. and shove it down. just like tetris. this is my pseudo code i made. can someone give me a hint and explanation about how to do it? and btw. if i filled the SECOND column with true. I'm afraid that the first column will also shift down regardless of his lowest column value.
[SerializeField]private int columns;
[SerializeField]private int rows;
private bool[,] grid;
private bool isRowTrue = true;
private int gridColumnCount = 0;
private int gridRowCount = 0;
private int combo = 0;
// Start is called before the first frame update
void Start()
{
grid = new bool[columns, rows];
for (int y = 0; y < grid.GetLength(1); y++)
{
for (int x = 0; x < grid.GetLength(0); x++)
{
grid[y, x] = false;
}
}
}
// Update is called once per frame
void Update()
{
CheckArrays();
}
private void CheckArrays()
{
for (int y = 0; y < grid.GetLength(1); y++)
{
for (int x = 0; x < grid.GetLength(0); x++)
{
if (grid[y, x] == false)
{
isRowTrue = false;
break;
}
}
if (isRowTrue == true)
{
Debug.Log(y + "TH Row Are All True");
for (int x = 0; x < grid.GetLength(0); x++)
{
grid[y, x] = false;
Debug.Log(grid[y, x]);
}
for (int yc = 0; yc < grid.GetLength(1); yc++)
{
for (int xc = 0; xc < grid.GetLength(0); xc++)
{
grid[yc, xc] = grid[yc - 1, xc - 1];
}
}
}
else
{
isRowTrue = true;
}
}
}
If you don't have a specific requirement to build this as a 2d array, this may be easier to reason about in a more object oriented way. For example, create a Row class that will hold an array of bool and have a method IsFull() which returns true if the entire array is true. Then you can hold a ArrayList of Row in your code above. Then, you can iterate over the rows and simply delete the row from the list whenever row.IsFull()==true, this should give you the effect that you are looking for.
This may be a silly question and I couldn't find an answer around for a while.
Basically: I got a method that creates a thread that calls a method that calls a recursion, ....does this recursion run? because what I get from it is garbage...
I code in c# for unity3d. the script I want to run on a separate thread does not contain unity api methods.
Elaboration:
This is what I have:
The method GetPCNextTurn creates the thread like this:
Thread myThread = new Thread(() => CompPlayTurn(MinMaxBoard, weights));
myThread.Start();
Then CompPlayTurn should start right?
CompPlayTurn calls ScoreBoard which returns a value.
then after some condition CompPlayTurn calls a recursion which calls ScoreBoard recursivly
I would assume at this point it returns to the first method after the thread start lines right?
Something does not seem to happen the way I wish it would it seems. Can someone please enlighten me with behavior of threads and recursions?
I need 1 thread for this recursion all I need is to separate it from the main thread.
This is the code:
this is the main method in the script:
public int GetPCNextTurn(int[][] board, int height, int width, int sequence)
{
this.done = false;
this.height = height;
this.width = width;
this.sequence = sequence;
int[][] MinMaxBoard = CopyBoard(board);
weights = GetWeights(sequence);
Thread myThread = new Thread(() => CompPlayTurn(MinMaxBoard, weights));
myThread.Start();
return ans;
}
public void CompPlayTurn(int[][] MinMaxBoard, int[] weights)
{
int scoreOrig = ScoreBoard(MinMaxBoard);
if (scoreOrig == orangeWins) winner = (int)Winner.pc;
// Debug.Log("I win\n");
else if (scoreOrig == yellowWins) winner = (int)Winner.player;
// Debug.Log("You win\n");
else
{
int move, score;
Minimax(true, (int)Mycell.Orange, maxDepth, MinMaxBoard, out move, out score);
ans = move;
if (move != -1)
{
ans = move;
// dropDisk(board, move, (int)Mycell.Orange);
scoreOrig = ScoreBoard(MinMaxBoard);
if (scoreOrig == orangeWins) { winner = (int)Winner.pc; }//Debug.Log("I win\n"); }
else if (scoreOrig == yellowWins) { winner = (int)Winner.player; }//Debug.Log("You win\n"); }
}
else winner = (int)Winner.draw;
}
}
public int ScoreBoard(int[][] scores)
{
int[] counters;
int x, y, count = 0, size = (2 * sequence + 1);
counters = new int[size];
Array.Clear(counters, 0, counters.Length); //needed?
// Horizontal spans
for (y = 0; y < height; y++)
{
int score = 0;
for (int i = 0; i <= sequence - 2; i++)
score += scores[y][i];
for (x = (sequence - 1); x < width; x++)
{
score += scores[y][x];
counters[score + sequence]++;
score -= scores[y][x - (sequence - 1)];
}
}
// Vertical spans
for (x = 0; x < width; x++)
{
int score = 0;
for (int i = 0; i <= sequence - 2; i++)
score += scores[i][x];
for (y = (sequence - 1); y < height; y++)
{
score += scores[y][x];
counters[score + sequence]++;
score -= scores[y - (sequence - 1)][x];
}
}
// Down-right (and up-left) diagonals
for (y = 0; y < height - (sequence - 1); y++)
{
for (x = 0; x < width - (sequence - 1); x++)
{
int score = 0, idx = 0;
for (idx = 0; idx < sequence; idx++)
{
score += scores[y + idx][x + idx];
}
counters[(score + sequence)]++;
}
}
// up-right (and down-left) diagonals
for (y = (sequence - 1); y < height; y++)
{
for (x = 0; x < width - (sequence - 1); x++)
{
int score = 0, idx = 0;
for (idx = 0; idx < sequence; idx++)
{
score += scores[y - idx][x + idx];
}
counters[(score + sequence)]++;
}
}
if (counters[0] != 0)
return yellowWins;
else if (counters[(sequence * 2)] != 0)
return orangeWins;
else
{
for (int i = 1; i < size - 1; i++)
{ count += weights[i] * counters[i]; }
return count;
}
}
public void Minimax(bool maximizeOrMinimize, int color, int depth, int[][] MinMaxBoard, out int move, out int score)
{
if (0 == depth)
{
move = -1;
score = ScoreBoard(MinMaxBoard);
}
else
{
int bestScore = maximizeOrMinimize ? -10000000 : 10000000;
int bestMove = -1;
for (int column = 0; column < width; column++)
{
if (MinMaxBoard[0][column] != (int)Mycell.Barren)
continue;
int rowFilled = dropDisk(MinMaxBoard, column, color); // damage the state
if (rowFilled == -1)
continue;
int s = ScoreBoard(MinMaxBoard);
if (s == (maximizeOrMinimize ? orangeWins : yellowWins))
{
bestMove = column;
bestScore = s;
MinMaxBoard[rowFilled][column] = (int)Mycell.Barren;
break;
}
int moveInner, scoreInner;
Minimax(!maximizeOrMinimize, color == (int)Mycell.Orange ? (int)Mycell.Yellow : (int)Mycell.Orange,
depth - 1, MinMaxBoard, out moveInner, out scoreInner);
MinMaxBoard[rowFilled][column] = (int)Mycell.Barren; // Undo the damage
// No need for lists and sorting - just keep the best value you meet.
if (maximizeOrMinimize)
{
if (scoreInner >= bestScore)
{
bestScore = scoreInner;
bestMove = column;
}
}
else
{
if (scoreInner <= bestScore)
{
bestScore = scoreInner;
bestMove = column;
}
}
}
move = bestMove;
score = bestScore;
}
}
public int dropDisk(int[][] MinMaxBoard, int column, int color)
{
int y;
for (y = height - 1; y >= 0; y--)
if (MinMaxBoard[y][column] == (int)Mycell.Barren)
{
MinMaxBoard[y][column] = color;
return y;
}
return -1;
}
edit:
I tried adding a method to tell whether the thread finished running:
public bool TryGetValue(out int val)
{
val = ans;
this.done = false;
if (done==true)
return true;
return false;
}
The thread has a public bool variable that gets initialized in CompPlayTurn so the thread initializes it with false for the first time
And just for testing it out, I set its value to true inside CompPlayTurn, the first thing it does (before the recursion and everything, right after the method signature).
And for the main thread I added:
while (!(minimaxscript.TryGetValue(out column)))
{ StartCoroutine(wait(count)); }
and
public IEnumerator wait(int count)
{
Debug.Log("not done yet");
count++;
if (count == 7)
{
Application.Quit();
yield break;
}
yield return new WaitForSeconds(3f);
}
I started with yield return new WaitForEndOfFrame(); then yield return new waitforseconds and finally I added Application.Quit()
It freezes....I don;t think it is the thread, since he does't call the recourse...can;t be the main thread logic can it? it runs without the thread recursion ai just fine.
I even tried updating the bool variable to: done=true right after thread was created (after the thread.start) so it should be the main thread updating the variable before leaving the script, but it still freezes. as if the variable is never set....but without this protection I do get values, where are they coming from then?.
Nvm just lack of sleep -.- I am stupid...
this is the method I wanted to write and no idea what crossed my mind when I wrote what I did:
public bool TryGetValue(out int val)
{
val = ans;
return done;
}
edit:
I changed the done=false to be the first thing the thead does (first line in invoked method) and done=false, at the end of it.
Then main thread invokes waitforseconds(1f) and a debug msg to make sure it waits.
using this:
bool ok = (minimaxscript.TryGetValue(out column));
while (ok == false)
{
ok = (minimaxscript.TryGetValue(out column));
StartCoroutine( wait());
}
And it freezes...
final solution:
Adding the polling and protecting the method from invoking while it hasn;t finished yet seems to solve the problem.
The problem was eventually in unity, I kept calling the method again and again.
I was checking if it finished or not and coroutine it, but kept calling it regardless via a method that is called in update method so I didn;t notice that.
To answer your question, yes you can recursively call a function and it will stay in the thread you just created. Once you start that thread it no matter what function you call it will stay on that thread until it no longer has any code to execute.
However it looks like you are assigning a value to "ans" inside your CompPlayTurn function and then returning that value from GetPCNextTurn
The problem is that you can't guarantee that ans will be assigned before you return from that function (and most likely wont be). When you create a new thread you have no guarantees of when each thread will finish doing work. Which means that ans could be set before or after your return function, therefore making your return value no longer valid.
If you want to be able to return a value from a separate thread you will need to either pass a delegate to the function, or create a seperate function to poll when the value is set. However be warned, anything that is unity specific can only be used from the main thread, so i would recommend using the polling function to return the value
public void GetPCNextTurn(int[][] board, int height, int width, int sequence)
{
this.done = false;
this.height = height;
this.width = width;
this.sequence = sequence;
int[][] MinMaxBoard = CopyBoard(board);
weights = GetWeights(sequence);
Thread myThread = new Thread(() => CompPlayTurn(MinMaxBoard, weights));
myThread.Start();
}
public bool TryGetValue(out int val)
{
//return true if you have a value and set that to val
}
This is a very rough implementation, as with anything multithreaded you will want to make this a lot more robust, I mainly wrote this to show you the concept
Could someone advise me on a simple way to implement hollow rectangles in C#?
I have been able to make a simple rectangle, but hollow rectangle programs I've looked at either contained or arrays or were pretty convoluted. For instance, the solution on another forum that seems too challenging, and this answer on CodeReview.SE is too difficult to understand.
This is what I've done, which displays a simple (filled) rectangle. How to output a hollow rectangle using if logic if possible?
class Nested_Loops_Hollow_Rectangles
{
public void RunExercise()
{
// how are now supposed to make this hollow?
// columns are side by side, rows is number of top to bottom
// see tut
Console.WriteLine("Welcome to the HollowRectanglePrinter Program.");
Console.WriteLine("How many columns wide should the rectangle be?"); //i.e. 4
int iColMax, iRowMax;
string userChoiceC = Console.ReadLine();
Int32.TryParse(userChoiceC, out iColMax);
Console.WriteLine("How many rows tall should the rectangle be? "); //i.e. 4
string userChoiceR = Console.ReadLine();
Int32.TryParse(userChoiceR, out iRowMax);
Console.WriteLine("Here you go:");
if (iRowMax > 0 || iColMax > 0)
{
for (int iRow = 0; iRow < iRowMax; iRow++)
{
for (int iCol = 0; iCol < iColMax; iCol++)
{
Console.Write("*");
}
Console.WriteLine();
}
}
}
}
The essential part of your application can be reduced to:
private void DrawFillRectangle(int width, int height)
{
for (int y = 0; y < height; y++)
{
for (int x = 0; x < width; x++)
{
Console.Write("*");
}
Console.WriteLine();
}
}
This, by the way (separating the logic and the input by putting the logic in a dedicated method) is what you should be doing. See Separation of concerns for more information.
The previous method draws a filled rectangle, so how can you draw a hollow one?
Start looking at the output. For instance, for (5, 3), the output is:
*****
*****
*****
and what you want is to have:
*****
* *
*****
How can you do that? Probably by replacing stars by spaces in some cases. Which ones?
Well, look again at the output. The first row is untouched, so the condition where you use spaces instead of stars is limited to rows other than the first one, that is:
private void DrawRectangle(int width, int height)
{
for (int y = 0; y < height; y++)
{
for (int x = 0; x < width; x++)
{
if (y > 0)
{
// Print either a star or a space.
}
else
{
Console.Write("*");
}
}
Console.WriteLine();
}
}
Now you must include the other cases in your condition: the first column, and the last column and row.
In order to combine conditions, you can use && and || operators. The first one means that the condition is true if both operands are true, and the second one means that either the first or the second operand is true.
It might be that your final condition will become too difficult to read. There are two things you can do. The first thing is to use intermediary variables. For instance:
if (a && b && c && d)
{
}
can be refactored into:
var e = a && b;
var f = c && d;
if (e && f)
{
}
if it makes sense to regroup a with b and c with d. A second thing you can do is to put the condition in a separate method, which may improve readability if you find a good name for the method:
private void DrawRectangle(int width, int height)
{
for (int y = 0; y < height; y++)
{
for (int x = 0; x < width; x++)
{
if (this.IsInsideRectangle(x, y))
{
// Print either a star or a space.
}
else
{
Console.Write("*");
}
}
Console.WriteLine();
}
}
private bool IsInsideRectangle(int x, int y)
{
return y > 0 && ...
}
This is hopefully all you need to do the exercise. Depending of your progression in the course, you may also be interested in those aspects:
You may avoid repeating code in an if/else block, so instead of:
if (...)
{
Console.Write(" ");
}
else
{
Console.Write("*");
}
you may end up writing only only Write():
Console.Write(...)
What C# operator can you use for that?
It is a good practice for a method to validate its input before doing its job. If you've already learnt what exceptions are, how can they be used to validate width and height? Why in the current situation it may make sense to not filter negative and zero values (in other words, would the application crash if, for instance, width is equal to -5)?
class emptyRectangle:Shape
{
byte width;
byte height;
public emptyRectangle(byte width,byte height)
{
this.width = width;
this.height = height;
}
public override void area()
{
Console.WriteLine("\n----------");
for (int i = 0; i < height; i++)
{
Console.WriteLine("");
for (int k = 0; k < width; k++)
{
if (i > 0 && k > 0)
{
if (i < height - 1 && k < width - 1)
{
Console.Write(" ");
}
else
Console.Write('*');
}
else
Console.Write("*");
}
}
}
}
Add a single IF statement where you are drawing the character:
if it is the first or last row or the first or last column, write the *
else the space.
For more fun, make a variable sized rectangular "hole" in the rectangle.
static void Main()
{
int width = 0, height = 0;
width = int.Parse(Console.ReadLine());
height = int.Parse(Console.ReadLine());
for (int i = 1; i <= height; i++)
{
for (int j = 1; j <= width; j++)
{
if ((i == 1 || i == height || j == 1 || j == width))
Console.Write("*");
else
Console.Write(" ");
}
Console.WriteLine();
}
Console.ReadKey();
}
Basically my first task was to save the position of the '0' in an integer. Real simple with a standard array. This code loops through an array (Size: 8) until it locates the 0, then save that as the position. See code below:
p.s: n is a reference to an array saved somewhere else.
int position = 0;
this.nodesExpanded++;
// Loop through the array to get the position of where '0' is
for (int i = 0; i < n.getPuzzle().length; i++){
if (n.getPuzzle()[i] == 0){
position = i;
break;
}
}
My ultimate task was to make this possible for a multidimensional array (Size: [3, 3]). So here's what I've created thus far:
for (int x = 0; x < 3; x++)
{
for (int y = 0; y < 3; y++)
{
if (n.getPuzzle()[x,y] == 0)
{
**position = ;**
break;
}
}//end y loop
}//end x loop
So how do I go about saving an array reference to a location to a value?
'position' will need to be something other than int I'm guessing..
If you need more clarification be sure to comment, sorry in advance & thank you!
You can use a Tuple to store that position. Or you can create your own data structure.
Example: at the end you can see how to access tuple items.
var positions = new List<Tuple<int, int>>();
for (int x = 0; x < 3; x++)
{
for (int y = 0; y < 3; y++)
{
if (n.getPuzzle()[x,y] == 0)
{
positions.Add(new Tuple<int, int>(x,y));
break;
}
}//end y loop
}//end x loop
if(positions.Any())
{
var xpos = positions[0].Item1;
var ypos = positions[0].Item2;
}
I find a natural way to store a multidimensional array index is to use a single dimensional array whose size is the number of dimensions.
So if you have a object[,,] A and index int[] i you would index into A with the expression A[i[0],i[1],i[2]].
It works the same way as your one-dimensional array, but you have two position values to keep. I've used ints for the example, but you may want to use a custom structure or Tuple (as AD.Net) said.
int xpos = -1;
int ypos = -1;
for (int x = 0; x < 3; x++)
{
for (int y = 0; y < 3; y++)
{
if (n.getPuzzle()[x,y] == 0)
{
xpos = x;
ypos = y;
break;
}
}//end y loop
}//end x loop
if (!(xpos > -1 && ypos > -1)) ; // 0 was not found