How to display a simple hollow asterisk rectangle in console? - c#

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();
}

Related

c# I cannot print a message from a loop

I am trying to make a simple program that takes in 2 integers: a number and a width. I want it to print a triangle with that width using that number. Should I use a double for loop instead if not can it be done my way?
class Program
{
public static int readInt()
{
int result;
string resultString = Console.ReadLine();
result = int.Parse(resultString);
return result;
}
static void Main(string[] args)
{
int number, width;
Console.WriteLine("Enter a number: ");
number = readInt();
Console.WriteLine("Enter a width: ");
width = readInt();
do {
for (int i = width; i < 0; i--)
{
Console.Write(number);
width--;
Console.WriteLine();
}
} while (width < 0);
Console.ReadLine();
}
}
Output:
number:7
width:4
7777
777
77
7
Just for fun, this version will print a rectangle centered
int space = 0;
do
{
// Prints initial spaces
for(int x = 0; x < space; x++)
Console.Write("-");
// Print the number for the current value of width
for (int i = 0; i < width; i++)
Console.Write(number);
// Print final spaces -
// Not really needed
for (int x = 0; x < space; x++)
Console.Write("-");
// Start the new line
Console.WriteLine();
//Decrease width by one space for each end (2)
width-=2;
// Increment the spaces to print before and after
space++;
} while (width > 0);
A part from the logic completely rewritten note that Console.WriteLine appends a newline, so you need to use Console.Write

Where's the mistake in my Spiral Matrix algorithm? Size of matrix = input N^2

So I'm creating a spiral matrix using C#.
A spiral array is a square arrangement of the first N^2 natural numbers, where the numbers increase sequentially as you go around the edges of the array spiralling inwards.
For example:
I'm supposed to do this using an algorithm however my final results look like this:
My code is below:
private static void FillMatrix (int[ , ] matrix, int n)
{
int positionX = 0;
int positionY = 0;
int direction = 0; // The initial direction is "right"
int stepsCount = n - 1; // stepsCount decrements after 3/2/2/2/2...
int stepPosition = 0; // 0 steps already performed
int counter = 1; // counter increments after every turn
for (int i = 1; i < n * n; i++)
{
matrix[positionY, positionX] = i;
//moving logic:
if (stepPosition < stepsCount)
{
stepPosition++;
}
else
{
counter++;
stepPosition = 1;
if (counter <= 3)
{
direction = (direction + 1) % 4;
}
else if (counter % 2 != 0 && counter >= 5 || counter == 4)
{
stepsCount = stepsCount - 1;
direction = (direction + 1) % 4;
}
}
// Move to the next cell in the current direction
switch (direction)
{
case 0:
// right
positionX++;
break;
case 1:
// down
positionY++;
break;
case 2:
// left
positionX--;
break;
case 3:
// up
positionY--;
break;
}
}
}
private static void PrintMatrix (int[ , ] matrix, int n)
{
for (int i = 0; i < n; i++)
{
for (int j = 0; j < n; j++)
{
Console.Write("{0,3}", matrix[i, j]);
}
Console.WriteLine();
}
}
static void Main(string[] args)
{
int n;
Console.WriteLine("Please enter N: ");
bool checkN = int.TryParse(Console.ReadLine(), out n);
if (checkN)
{
int[,] spiralMatrix = new int[n,n];
FillMatrix(spiralMatrix, n);
PrintMatrix(spiralMatrix, n);
}
Console.ReadKey();
}
}
}
Any help much appreciated!
Your logic for deciding when to make a turn and how many steps to take has a bug, and it is more complicated than necessary. A better way of making a decision on when to turn is to check the matrix itself. Pre-fill the matrix with -1, then start filling it at the top-left corner. When you see -1, continue straight; if you reached one of the ends of the matrix, or the next position has -1 in it, then make a turn. This makes your stepPosition and stepCount variables unnecessary, and shortens your code quite a bit.
Another useful trick is turning right: rather than keeping a direction as a single variable, keep two "delta" variables - dx and dy
if (positionX < 0 || positionX == n || positionY < 0 || positionY == N || matrix[positionX][positionY] != -1) {
int temp = dy;
dy = dx;
dx = -temp;
}
positionX += dx;
positionY += dy;
I've solved this problem.
There was an issue with my algorithm. The number pattern for the size of sequential line when filling in a matrix from the outside in is N, N-1, N-1, N-2, N-2, N-3, N-3... and so on.
For example in a spiral matrix of N size 4 the pattern goes like this:
4 right.
3 down.
3 left.
2 up.
2 right.
1 down.
1 left.
I originally thought the pattern started:
3 right.
3 down.
3 left.
I forgot to include the one more element of movement resulting in a algorithm that wouldn't fill out correctly.
Once I changed my conditional statements to the following code it allowed for the correct output. To clarify I am supposed to be starting from 1 in my 0 element of the array. Apologies for the confusion.
Code below:
int positionX = 0;
int positionY = 0;
int direction = 0; // The initial direction is "right"
int stepsCount = n - 1; // stepsCount decrements after 1/2/2/2/2... turns
int stepPosition = 1; // 1 steps already performed
int counter = 0; // counter increments after every change in direction
for (int i = 1; i < n * n + 1; i++)
{
matrix[positionY, positionX] = i;
//moving logic:
if (stepPosition <= stepsCount)
{
stepPosition++;
}
else
{
counter++;
stepPosition = 1;
if (counter % 2 != 0)
{
stepsCount = stepsCount - 1;
direction = (direction + 1) % 4;
}
else if (counter % 2 == 0)
{
direction = (direction + 1) % 4;
}
}
The result is a much simpler way than checking for zero and turning based on that rule as it is absolutely infallable.
Example results below:

how can I draw a triangle of asterisks using the while statement?

here is the (not working code) and it should print the shape below but its not :
static void Main(string[] args)
{
int i = 1;
int k = 5;
int h = 1;
while (i <= 5)
{
Console.WriteLine("");
while (k > i)
{
Console.Write(" ");
k--;
}
while (h <= i)
{
Console.Write("**");
h++;
}
i++;
}
Console.ReadLine();
}
but when I try to do the same using the while statement the shape gets totally messed up.
any help ?
You have to declare k and h within the loop:
static void Main(string[] args)
{
int i = 1;
while (i <= 5)
{
int k = 5;
int h = 1;
Console.WriteLine("");
while (k > i)
{
Console.Write(" ");
k--;
}
while (h <= i)
{
Console.Write("**");
h++;
}
i++;
}
Console.ReadLine();
}
With your current solution, after first outer loop iteration, inner loops do nothing.
int NumberOfLines = 5;
int count = 1;
while (NumberOfLines-- != 0)
{
int c = count;
while (c-- != 0)
{
Console.Write("*");
}
Console.WriteLine();
count = count + 2;
}
That's it, simplest implementation.
The problem is that i, k and h are initialised before the outermost loop is entered. Within the outer loop k and h are altered by the inner loops. On the second execution of the outer loop k and h have the same values as were left after running the inner loops previously. As i increments in the outer loop, the k loop will not be entered and the h loop will only run once.
Think about what values h and k should have inside the outermost loop on the second execution.
I'll not solve for you just will give you hint only:
Use 3 loop statements
1. for line change
2. for spaces (reverse loop)
3. for printing * (odd series in this case) i.e. 2n-1
check in third while statement h <= 2*i - 1;
and print only one * in place of **
Check here:
http://ideone.com/xOB2OI
Actually I've done this via 'for' loop, z is height and x is equal to length of side.
Isosceles triangle (x>z):
public void Print(int x, int z)
{
var peakStart = x;
var peakEnd = x;
for (int i = 0; i < z; i++)
{
for (int j = 0; j < 2 * x + 1; j++)
{
if (peakStart < 1.5 * x && j >= peakStart && j <= peakEnd)
Console.Write("*");
else
Console.Write(" ");
}
peakStart--;
peakEnd++;
Console.WriteLine("");
}
}

Sudoku generator algorithm using a recursive method

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;
}

keeping array in an array

i want to save kingarray[x1+1,y1-1],king array[x1+1,y1],etc in an array(ways that king in chess game can go).how can i do it?or if its not possible what do you suggest me to keep the ways that king can go?thanks
int[,] kingarray = new int[8, 8];
for (i = 0; i < 1; i++)
{
return kingarray[x1 + 1, y1];
}
for (i = 1; i > 0; i--)
{
return kingarray[x1 - 1, y1];
}
for (j = 0; j < 1; j++)
{
return kingarray[x1, y1 + 1];
}
for (j = 1; j > 0; j--)
{
return kingarray[x1, y1 - 1];
}
for (i = 0; i < 1; i++)
for (j = 1; j > 0; j--)
{
return kingarray[x1 + 1, y1 - 1];
}
for (i = 1; i > 0; i--)
for (j = 0; j < 1; j++)
{
return kingarray[x1 - 1, y1 + 1];
}
for (i = 0; i < 1; i++)
for (j = 0; j < 1; j++)
{
return kingarray[x1 + 1, y1 + 1];
}
for (i = 1; i > 0; i--)
for (j = 1; j > 0; j--)
{
return kingarray[x1 - 1, y1 - 1];
}
what do you suggest me to keep the ways that king can go?
This may not answer your question directly, and that you have already marked the correct answer. But just to answer the above.
Rather than keeping the all the positions a king can go, I would keep the positions it is allowed to go and calculate the possible routes during run-time.
For any piece(King, Pawn, etc), there are 8 places that it can move. Left, right, up, down, top-left, top-right, bottom-left, bottom-right. Based upon the type of piece, you can control the movement.
For You can create a ChessPiece class. Declare 8 positional flags, bool flags probably, that would define the possible positions that a piece can move.
Declare the number of blocks a piece can skip, for instance directions(; and drive the types from the ChessPiece and allow.
--EDIT--
For instance, following:
//Class that contains the position of the Piece over the Tile
class PiecePosition
{
//Set the bounds an image/vector can move.
public int X, Y;
public PiecePosition(int x, int y) { this.X = x; this.Y = y; }
public PiecePosition(int x, int y, int width, int height) { this.X = x; this.Y = y; }
}
//Base ChessPeice class that shall be used to drive all types of chess pieces.
//Sixteen pieces: one king, one queen, two rooks, two knights, two bishops, and eight pawns
//http://en.wikipedia.org/wiki/Chess
abstract class ChessPiece
{
public object Image;//This is an "optional" object that contains the Picture of the Peice,
//alternatively, it may contain vector of the image that you want
//to draw. Right now this is object is here just for the sake of
//understanding that you can use this object here to Draw() it
//based upon its position.
//Possible movements of the unhindered piece=8
protected const int MaxDirectionsCount = 8;
public enum PieceType { King, Pawn, SomeOtherType }//Types of chess peice.
public enum Moves { Up, Down, Left, Right, TopLeft, Etc }//Possible positions a piece can move
protected PieceType Type; //Contains type of piece
protected Moves MoveableDirections;//Shall contain the allowable directions
public List<PiecePosition> listPositions;//List of possible positions to be calculated during runtime
//Defines a piece can skip
protected int SkippableBlocks;
public abstract void PossiblePositions(PiecePosition CurrentPosition);//Calculates possible positions
public abstract void Draw();//Draws the piece
}
//The King Chess piece
//http://en.wikipedia.org/wiki/King_%28chess%29
class King : ChessPiece
{
//Constructor that sets the type of piece
public King()
{
//Set the directions a King can move.
base.MoveableDirections = Moves.Down | Moves.Left | Moves.Right;
base.Type = PieceType.King;
SkippableBlocks = 1; //Max a king can move is one block in the base.Directions set above.
}
//Calculates possible available positions to move to, during runtime; based upon current position.
public override void PossiblePositions(PiecePosition CurrentPosition)
{
//Calculate position
//Since you know this is king piece, you can calculate the possible positions
//And add that the list of possible positions.
//For instance, a King can move
int X = 0; int Y = 0;
for (int i = 0; i < MaxDirectionsCount; i++)
{
//Calculate directions.
if (base.MoveableDirections == Moves.Down) { X = CurrentPosition.X - 1; Y = CurrentPosition.Y; }
if (base.MoveableDirections == Moves.Up) { X = CurrentPosition.X + 1; Y = CurrentPosition.Y; }
//Rest of the directions go here...
//...Btw, what would you do for cross directions?
//One way could be to pass a Rectangle in the ChessTile(x,y,width,height) constructor
//Add to list of possible directions.
listPositions.Add(new PiecePosition(X, Y));
}
}
public override void Draw()
{
//You can actually draw/redraw using the Image object
//based upon the current/moved position.
}
}
Btw, if you just started writing the code, I would suggest you stop. Look around for Chess class designs first, and see if you want make sense out of Chess Objects. For instance, ChessBoard, Game, Players, Piece, Movements, AllowablePositions, etc.
Take a look at questions related to Chess/Google abit, and see if the questions/answers and your logic is already inline.
Array?
It is rather easy to determine a King's possible movement.
class position { public int x, y }
...
public ArrayList<position> KingPossibleMove(position current)
{
var list = new ArrayList();
if (current.x>0) {
list.add(new position() { x= current.x - 1, y = current.y });
if (current.x<8) {
list.add(new position() { x= current.x + 1, y = current.y });
// The rest follows, try to determine if the move is within bound
// you can also look for if the move will cause immediate checkmate.
return list;
}
int[,][] declares a 1D array containing a 2D array of int. Is that what you want?
And the kingmoves can simply be calculated as:
IEnumerable<Position> ValidKingTargets(Position p)
{
int top=Math.Max(0,y-1);
int left=Math.Max(0,x-1);
int bottom=Math.Min(8,y+2);
int right=Math.Min(8,x+2);
for(int y=top;y<bottom;y++)
for(int x=left;x<right;x++)
if(x!=p.X || y!=p.Y)
yield return new Position(x,y);
}

Categories