C# how to restart the console application - c#

I am a begginer, and Im trying to make a Tic-Tac-Toe console game.But when O player has won, it shows, only when X player has made a decision.So that, there can be a situation when 2 players have won.I tried to use if statement to stop aplication but it doesn't help. I think I don't need to restart the application, just start Main again. But how??
class Program
{
static void Main()
{
string Player1;
string Player2;
int turnPlayer1;
int turnPlayer2;
while (CheckTheWinner() == false)
{
BoardPlay();
Console.Clear();
BoardPlay();
for ( turnPlayer1 = 0; turnPlayer1 < 1; turnPlayer1++)
{
Console.Write("Player O: Choose your field:");
Player1 = Console.ReadLine();
Player1Choice(Player1);
}
CheckTheWinner();
Console.Clear();
BoardPlay();
for (int i = 0; i < 1; i++)
{
Console.Write("Player X: Choose your field:");
Player2 = Console.ReadLine();
Player2choice(Player2);
}
CheckTheWinner();
Console.Clear();
BoardPlay();
}
}
public static void Player1Choice(string P1)
{
string o = "O";
for (int i = 0; i < position.GetLength(0); i++)
{
Console.ForegroundColor = ConsoleColor.Red;
for (int j = 0; j <= 2; j++)
{
if (position[i, j] == P1)
{
position[i, j] = o;
}
}
};
}
public static void Player2choice(string P2)
{
string x = "X";
for (int i = 0; i < position.GetLength(0); i++)
{
Console.ForegroundColor = ConsoleColor.Red;
for (int j = 0; j <= 2; j++)
{
if (position[i, j] == P2)
{
position[i, j] = x;
}
}
};
}
static bool CheckTheWinner()
{
for (int i = 0; i < 3; i++)
{
if (position[i, 0] == position[i, 1] && position[i, 1] == position[i, 2])
{
return true;
}
if (position[0, i] == position[1, i] && position[1, i] == position[2, i])
{
return true;
}
}
if (position[0, 0] == position[1, 1] && position[1, 1] == position[2, 2])
{
return true;
}
if (position[0, 2] == position[1, 1] && position[1, 1] == position[2, 0])
{
return true;
}
return false;
}

"Starting a new game" is basically "repeating the operation of having a game". Use loops to repeat operations.
First, define the loop condition. For example, a boolean flag indicating to keep playing:
var keepPlaying = true;
Then loop as long as that flag is true:
var keepPlaying = true;
while (keepPlaying)
{
// all of the logic currently in your Main method
}
Then all you need to do is prompt the player if they want another game and update the variable accordingly. For example:
var keepPlaying = true;
while (keepPlaying)
{
// all of the logic currently in your Main method
Console.Write("Would you like to play again? (Y/N): ");
var playerReply = Console.ReadLine();
if (playerReply == "N")
keepPlaying = false;
}
You could perhaps simplify the logic a bit, this is mainly for demonstration. You can also add some logic to check the input, you can add a closing message if the player chooses to quit, add other options, etc.
But the point is that if you want to repeat the game, it's not a matter of restarting the application or re-invoking the Main method, it's just a matter of encapsulating what you want to repeat in a loop.

Related

How can I make an "item" disappear when the player once stands on it's position? C#

I make this little Escape Room game where the player needs to collect a key for getting out of the room. How can I make the Key disappear whenever the player steps on it? This is my code so far. I know I haven't used any methods because I haven't learned it in university so far.. So it would be great if anyone has a simple solution or help for me. Thanks in advance! <3
static void Main(string[] args)
{
ConsoleKeyInfo consoleKey;
int XPositionCursor = 5;
int YPositionCursor = 5;
int MapWidth = 20;
int MapHeight = 20;
char Wall = '█';
bool GameOver = true;
char Key = '#';
char Character = 'H';
int[,] MapGenerationArray = new int[MapWidth, MapHeight];
Random RandomKeyCoordinate = new Random();
Random RandomDoorCoordinate = new Random();
#region Instructions
Console.WriteLine("Wähle eine Breite für dein Spielfeld:");
string MapWidthString = Console.ReadLine();
MapWidth = int.Parse(MapWidthString);
Console.Clear();
Console.WriteLine("Wähle eine Höhe für dein Spielfeld:");
string MapHeightString = Console.ReadLine();
MapHeight = int.Parse(MapHeightString);
Console.Clear();
Console.WriteLine($"Dein Spielfeld wird {MapWidth} x {MapHeight} groß sein!");
Console.ReadLine();
#endregion
Vector2 KeyCoordinate = new Vector2();
KeyCoordinate.X = RandomKeyCoordinate.Next(1, MapWidth - 1);
KeyCoordinate.Y = RandomKeyCoordinate.Next(1, MapHeight - 1);
Vector2 DoorCoordinate1 = new Vector2();
DoorCoordinate1.X = RandomDoorCoordinate.Next(0, MapWidth);
DoorCoordinate1.Y = RandomDoorCoordinate.Next(0, 0);
bool PlayerIsOnKeyPosition = XPositionCursor == KeyCoordinate.X && YPositionCursor == KeyCoordinate.Y;
bool PlayerCarryingKey = false;
do
{
#region Map
Console.Clear();
for (int i = 0; i < MapWidth; i++)
{
Console.SetCursorPosition(i, 0);
Console.Write(Wall);
}
for (int i = 0; i < MapWidth; i++)
{
Console.SetCursorPosition(i, MapHeight);
Console.Write(Wall);
}
for (int i = 0; i < MapHeight; i++)
{
Console.SetCursorPosition(0, i);
Console.Write(Wall);
}
for (int i = 0; i < MapHeight; i++)
{
Console.SetCursorPosition(MapWidth, i);
Console.Write(Wall);
}
#endregion
Console.SetCursorPosition(XPositionCursor, YPositionCursor);
Console.CursorVisible = false;
Console.Beep(200, 100);
Console.Write(Character);
if (PlayerIsOnKeyPosition)
{
PlayerCarryingKey = true;
}
if (PlayerCarryingKey == true)
{
Console.SetCursorPosition((int)DoorCoordinate1.X, (int)DoorCoordinate1.Y);
Console.Write(' ');
}
else
{
Console.SetCursorPosition((int)KeyCoordinate.X, (int)KeyCoordinate.Y);
Console.Write(Key);
Console.SetCursorPosition((int)DoorCoordinate1.X, (int)DoorCoordinate1.Y);
Console.ForegroundColor = ConsoleColor.Red;
Console.Write(Wall);
Console.ResetColor();
}
#region CharacterMovement
consoleKey = Console.ReadKey(true);
Console.Clear();
switch (consoleKey.Key)
{
case ConsoleKey.UpArrow:
YPositionCursor--;
break;
case ConsoleKey.DownArrow:
YPositionCursor++;
break;
case ConsoleKey.LeftArrow:
XPositionCursor--;
break;
case ConsoleKey.RightArrow:
XPositionCursor++;
break;
}
if (YPositionCursor < 1) { YPositionCursor = 1; }
if (XPositionCursor < 1) { XPositionCursor = 1; }
if (YPositionCursor >= MapHeight - 1) { YPositionCursor = MapHeight - 1; };
if (XPositionCursor >= MapWidth - 1) { XPositionCursor = MapWidth - 1; };
#endregion
} while (GameOver == true);
}
}
As #doctorlove wrote, you are calculating whether player has a key before your main loop (do/while).
But you should do this inside main loop, every time player changes his position.
Replace line if (PlayerIsOnKeyPosition) with this if (XPositionCursor == KeyCoordinate.X && YPositionCursor == KeyCoordinate.Y).
P.S. Good idea is to use methods (functions) to split code into smaller chunks :)

for loop keeps looping when there is a break

I'm trying to make a carpark program and one of the functions is to move a vehicle. It is working, the object is changing position in the array, it's just that the loop continues and it crashes because parkingLot[i, j].RegNummer is null the second time it loops through it. How do I stop it from looping again after I have "moved" a car? I want it to break and go back to the menu. (This is in a switch case connected to a menu)
Console.WriteLine("Enter the licensenumber of the vehicle that you want to move: ");
string lNumber = Console.ReadLine();
for (int i = 0; i < 100; i++)
{
for (int j = 0; j < 2; j++)
{
if (lNumber == parkingLot[i, j].RegNummer)
{
Console.WriteLine("Enter the space you want to move it to: ");
int space = int.Parse(Console.ReadLine());
int space1 = space - 1;
if (parkingLot[space1, 0] == null)
{
parkingLot[space1, 0] = parkingLot[i, j];
parkingLot[i, j] = null;
Console.WriteLine("The vehicle with licensenumber {0} has been moved to space {1}", lNumber, space);
break;
}
}
else
{
Console.WriteLine("The vehicle with licensenumber {0} could not be found!", lNumber);
break;
}
}
}
Your break statements exit the inner for loop, if you need to exit the outer for loop, I'd suggest using a boolean, and checking if it's true to exit the outer loop. When you meet a condition on the inner for loop, set it to true:
string lNumber = Console.ReadLine();
bool exitOuter = false; //Use boolean to exit outer for loop
for (int i = 0; i < 100; i++)
{
for (int j = 0; j < 2; j++)
{
if (lNumber == parkingLot[i, j].RegNummer)
{
Console.WriteLine("Enter the space you want to move it to: ");
int space = int.Parse(Console.ReadLine());
int space1 = space - 1;
if (parkingLot[space1, 0] == null)
{
parkingLot[space1, 0] = parkingLot[i, j];
parkingLot[i, j] = null;
Console.WriteLine("The vehicle with licensenumber {0} has been moved to space {1}", lNumber, space);
exitOuter = true; //Set boolean to true to exit outer for loop
break;
}
}
else
{
Console.WriteLine("The vehicle with licensenumber {0} could not be found!", lNumber);
break;
}
}
//Check boolean to break outer for loop
if(exitOuter)
break;
}
So, the problem is that you break just from the inner loop.
if (parkingLot[space1, 0] == null)
{
parkingLot[space1, 0] = parkingLot[i, j];
parkingLot[i, j] = null;
Console.WriteLine("The vehicle with licensenumber {0} has been moved to space {1}", lNumber, space);
break;
}
You must inform the outer loop that the car has been parked and it must end the task.
You can implement a flag for that.
Console.WriteLine("Enter the licensenumber of the vehicle that you want to move: ");
string lNumber = Console.ReadLine();
bool carParked = false;
for (int i = 0; i < 100; i++)
{
for (int j = 0; j < 2; j++)
{
if (lNumber == parkingLot[i, j].RegNummer)
{
Console.WriteLine("Enter the space you want to move it to: ");
int space = int.Parse(Console.ReadLine());
int space1 = space - 1;
if (parkingLot[space1, 0] == null)
{
parkingLot[space1, 0] = parkingLot[i, j];
parkingLot[i, j] = null;
Console.WriteLine("The vehicle with licensenumber {0} has been moved to space {1}", lNumber, space);
carParked = true;
break;
}
}
else
{
Console.WriteLine("The vehicle with licensenumber {0} could not be found!", lNumber);
break;
}
}
if (carParked)
{
break;
}
}

C# Method called with a Switch statement - having troubles

I am new at programming and I'm trying to understand why the methods call inside a switch statement is not working. Basically I have a main menu and a submenu. Whem I press the Animal submenu , the switch statement is meant to call the methods for a CRUD (insert new, visualize by Id, update, etc) but none of these options are working. Is the method call/structure correct?
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace menu_clinica_veterinaria
{
class Program
{
public static int id = 1;
enum animalHeader { id, name, client_name, type_animal };
enum clientHeader { id, name, client_surname, adrress };
static void Main(string[] args)
{
string[,] animal = new string[20, 4];
string[,] client = new string[20, 6];
do { MenuOptions(animal); } while (true);
}
static void MenuOptions(string[,] animal)
{
int userChoice;
do
{
Console.Clear();
Console.WriteLine("\nChoose one of the following options:\n");
Console.WriteLine("[ 1 ] Animals");
Console.WriteLine("[ 2 ] Clients");
Console.WriteLine("[ 0 ] Quit application\n");
} while (!int.TryParse(Console.ReadLine(), out userChoice) || userChoice < 0 || userChoice > 2);
Console.Clear();
switch (userChoice)
{
case 1:
menuAnimal(animal);
break;
case 2:
//menuClient(client);
break;
case 0:
Environment.Exit(0);
break;
default:
Console.WriteLine("Try again!!");
break;
}
}
static void menuAnimal(string[,] animal)
{
int optAnimal;
while (true)
{
do
{
Console.Clear();
Console.WriteLine("\nInsert one of the following options:\n");
Console.WriteLine("[ 1 ] Insert animal");
Console.WriteLine("[ 2 ] See animal");
Console.WriteLine("[ 3 ] Alter animal");
Console.WriteLine("[ 4 ] Erase animal");
Console.WriteLine("[ 5 ] List animals");
Console.WriteLine("[ 0 ] Return to main menu\n");
} while (!int.TryParse(Console.ReadLine(), out optAnimal) || optAnimal < 0 || optAnimal > 5);
Console.Clear();
bool goBack = false;
switch (optAnimal)
{
case 1:
insertData(animal);
break;
case 2:
visualizeByid(animal);
break;
case 3:
updateById(animal);
break;
case 4:
deleteByid(animal);
break;
case 5:
listData(animal);
break;
case 0:
goBack = true;
break;
}
if (goBack) return;
}
}
static void mainMenu()
{
Console.Clear();
Console.ReadKey();
}
static void menuReturn(string[,] animal)
{
Console.Clear();
do { menuAnimal(animal); } while (true);
}
static int generateId()
{
return id++;
}
static int getInsertIndex(string[,] matrix)
{
for (int j = 0; j < matrix.GetLength(0) - 1; j++)
{
if (string.IsNullOrEmpty(matrix[j, 0])) return j;
}
return -1;
}
static void insertData(string[,] matrix)
{
int id = generateId();
int n = getInsertIndex(matrix);
matrix[n, 0] = Convert.ToString(id);
for (int j = 1; j < matrix.GetLength(1); j++)
{
do
{
Console.Write($"Insert {Enum.GetName(typeof(animalHeader), j)}: ");
matrix[n, j] = Console.ReadLine();
} while (String.IsNullOrEmpty(matrix[n, j]));
}
}
static int searchId(string[,] matrix)
{
int choosenId, index = -1;
do
{
Console.Write("Insert ID to continue: ");
} while (!int.TryParse(Console.ReadLine(), out choosenId));
for (int i = 0; i < matrix.GetLength(0); i++)
{
if (Convert.ToString(choosenId) == matrix[i, 0])
{
index = i;
}
}
return index;
}
static void visualizeByid(string[,] matrix)
{
int pos = searchId(matrix);
if (pos != -1)
{
for (int i = pos; i < pos + 1; i++)
{
for (int j = 0; j < matrix.GetLength(1); j++)
{
Console.Write($"{matrix[i, j]}\t");
}
Console.WriteLine();
}
}
else { Console.WriteLine("Wrong Id"); }
}
static void updateById(string[,] matrix)
{
int pos = searchId(matrix);
if (pos != -1)
{
for (int i = pos; i < pos + 1; i++)
{
for (int j = 1; j < matrix.GetLength(1); j++)
{
Console.Write($"Insert {Enum.GetName(typeof(animalHeader), j)}: ");
matrix[i, j] = Console.ReadLine();
}
Console.WriteLine();
}
}
else { Console.WriteLine("Id does not exist"); }
}
static void deleteByid(string[,] matrix)
{
int pos = searchId(matrix);
if (pos != -1)
{
for (int i = pos; i < pos + 1; i++)
{
for (int j = 0; j < matrix.GetLength(1); j++)
{
matrix[i, j] = null;
}
}
}
else { Console.WriteLine("Id does not exist"); }
}
static void listData(string[,] matrix)
{
for (int i = 0; i < matrix.GetLength(0); i++)
{
for (int j = 0; j < matrix.GetLength(1); j++)
{
Console.Write($"\t{matrix[i, j]}\t");
}
Console.WriteLine("\n\t");
}
}
}
}
It's a nifty little program for what it is.
However, you can't see an animal because:
searchId
for (var i = 0; i < matrix.GetLength(0); i++)
{
if (Convert.ToString(choosenId) == matrix[i, 0])
{
index = i;
// Though it's not the problem you could break here
// you could also just return from here
break;
}
}
Also, you'll need to Console.ReadKey() somewhere as your menu refreshes and overwrites the see animal routine.
menuAnimal
visualizeByid(animal);
// if you don't do something like this as the menu refreshes the animal away
Console.ReadKey();
The only other thing I'd suggest is to use lists and well-typed classes, instead of multidimensional arrays of strings; they are easier to work with, and you can use Linq.
Update
In regards to comments, given this:
private static string GetHeader<T>(int i) => Enum.GetName(typeof(T), i);
You could do something like this:
static void updateById<T>(string[,] matrix)
{
int pos = searchId(matrix);
if (pos != -1)
{
for (int i = pos; i < pos + 1; i++)
{
for (int j = 1; j < matrix.GetLength(1); j++)
{
Console.Write($"Insert {GetHeader<T>(j)}: ");
...
Usage:
updateById<animalHeader>(animal);
Basically this is some generics to reuse the updateById method and using your HeaderType.
Your program working Fine. You are using Console.Clear(). It will clear the screen which is displayed previously on the screen. Remove Console.Clear() in the program or Add Console.ReadKey() immediately after Switch block. I think it will work fine.

Implementing and using MinMax with four in row (connect4) game

I'm trying to implement the MinMax algorithm for four in a row (or connect4 or connect four) game.
I think I got the idea of it, it should build a tree of possible boards up to a certain depth, evaluate them and return their score, then we just take the max of those scores.
So, aiChooseCol() checks the score of every possible column by calling MinMax() and returns the column with the max score.
Now I wasn't sure, is this the right way to call MinMax()?
Is it right to check temp = Math.Max(temp, 1000);?
I still haven't made the heuristic function but this should at least recognize a winning column and choose it, but currently it just choose the first free column from the left... I can't figure out what am I doing wrong.
private int AiChooseCol()
{
int best = -1000;
int col=0;
for (int i = 0; i < m_Board.Cols; i++)
{
if (m_Board.CheckIfColHasRoom(i))
{
m_Board.FillSignInBoardAccordingToCol(i, m_Sign);
int t = MinMax(5, m_Board, board.GetOtherPlayerSign(m_Sign));
if (t > best)
{
best = t;
col = i;
}
m_Board.RemoveTopCoinFromCol(i);
}
}
return col;
}
private int MinMax(int Depth, board Board, char PlayerSign)
{
int temp=0;
if (Depth <= 0)
{
// return from heurisitic function
return temp;
}
char otherPlayerSign = board.GetOtherPlayerSign(PlayerSign);
char checkBoard = Board.CheckBoardForWin();
if (checkBoard == PlayerSign)
{
return 1000;
}
else if (checkBoard == otherPlayerSign)
{
return -1000;
}
else if (!Board.CheckIfBoardIsNotFull())
{
return 0; // tie
}
if (PlayerSign == m_Sign) // maximizing Player is myself
{
temp = -1000;
for (int i = 0; i < Board.Cols; i++)
{
if (Board.FillSignInBoardAccordingToCol(i, PlayerSign)) // so we don't open another branch in a full column
{
var v = MinMax(Depth - 1, Board, otherPlayerSign);
temp = Math.Max(temp, v);
Board.RemoveTopCoinFromCol(i);
}
}
}
else
{
temp = 1000;
for (int i = 0; i < Board.Cols; i++)
{
if (Board.FillSignInBoardAccordingToCol(i, PlayerSign)) // so we don't open another branch in a full column
{
var v = MinMax(Depth - 1, Board, otherPlayerSign);
temp = Math.Min(temp, v);
Board.RemoveTopCoinFromCol(i);
}
}
}
return temp;
}
Some notes:
FillSignInBoardAccordingToCol() returns a boolean if it was successful.
The board type has a char[,] array with the actual board and signs of the players.
This code is in the AI Player class.
So I decided to write my own MinMax Connect 4. I used the depth to determine the value of a win or loss so that a move that gets you closer to winning or blocking a loss will take precedence. I also decide that I will randomly pick the move if more than one has the same heuristic. Finally I stretched out the depth to 6 as that's how many moves are required to find possible win paths from the start.
private static void Main(string[] args)
{
var board = new Board(8,7);
var random = new Random();
while (true)
{
Console.WriteLine("Pick a column 1 -8");
int move;
if (!int.TryParse(Console.ReadLine(), out move) || move < 1 || move > 8)
{
Console.WriteLine("Must enter a number 1-8.");
continue;
}
if (!board.DropCoin(1, move-1))
{
Console.WriteLine("That column is full, pick another one");
continue;
}
if (board.Winner == 1)
{
Console.WriteLine(board);
Console.WriteLine("You win!");
break;
}
if (board.IsFull)
{
Console.WriteLine(board);
Console.WriteLine("Tie!");
break;
}
var moves = new List<Tuple<int, int>>();
for (int i = 0; i < board.Columns; i++)
{
if (!board.DropCoin(2, i))
continue;
moves.Add(Tuple.Create(i, MinMax(6, board, false)));
board.RemoveTopCoin(i);
}
int maxMoveScore = moves.Max(t => t.Item2);
var bestMoves = moves.Where(t => t.Item2 == maxMoveScore).ToList();
board.DropCoin(2, bestMoves[random.Next(0,bestMoves.Count)].Item1);
Console.WriteLine(board);
if (board.Winner == 2)
{
Console.WriteLine("You lost!");
break;
}
if (board.IsFull)
{
Console.WriteLine("Tie!");
break;
}
}
Console.WriteLine("DONE");
Console.ReadKey();
}
private static int MinMax(int depth, Board board, bool maximizingPlayer)
{
if (depth <= 0)
return 0;
var winner = board.Winner;
if (winner == 2)
return depth;
if (winner == 1)
return -depth;
if (board.IsFull)
return 0;
int bestValue = maximizingPlayer ? -1 : 1;
for (int i = 0; i < board.Columns; i++)
{
if (!board.DropCoin(maximizingPlayer ? 2 : 1, i))
continue;
int v = MinMax(depth - 1, board, !maximizingPlayer);
bestValue = maximizingPlayer ? Math.Max(bestValue, v) : Math.Min(bestValue, v);
board.RemoveTopCoin(i);
}
return bestValue;
}
public class Board
{
private readonly int?[,] _board;
private int? _winner;
private bool _changed;
public Board(int cols, int rows)
{
Columns = cols;
Rows = rows;
_board = new int?[cols, rows];
}
public int Columns { get; }
public int Rows { get; }
public bool ColumnFree(int column)
{
return !_board[column, 0].HasValue;
}
public bool DropCoin(int playerId, int column)
{
int row = 0;
while (row < Rows && !_board[column,row].HasValue)
{
row++;
}
if (row == 0)
return false;
_board[column, row - 1] = playerId;
_changed = true;
return true;
}
public bool RemoveTopCoin(int column)
{
int row = 0;
while (row < Rows && !_board[column, row].HasValue)
{
row++;
}
if (row == Rows)
return false;
_board[column, row] = null;
_changed = true;
return true;
}
public int? Winner
{
get
{
if (!_changed)
return _winner;
_changed = false;
for (int i = 0; i < Columns; i++)
{
for (int j = 0; j < Rows; j++)
{
if (!_board[i, j].HasValue)
continue;
bool horizontal = i + 3 < Columns;
bool vertical = j + 3 < Rows;
if (!horizontal && !vertical)
continue;
bool forwardDiagonal = horizontal && vertical;
bool backwardDiagonal = vertical && i - 3 >= 0;
for (int k = 1; k < 4; k++)
{
horizontal = horizontal && _board[i, j] == _board[i + k, j];
vertical = vertical && _board[i, j] == _board[i, j + k];
forwardDiagonal = forwardDiagonal && _board[i, j] == _board[i + k, j + k];
backwardDiagonal = backwardDiagonal && _board[i, j] == _board[i - k, j + k];
if (!horizontal && !vertical && !forwardDiagonal && !backwardDiagonal)
break;
}
if (horizontal || vertical || forwardDiagonal || backwardDiagonal)
{
_winner = _board[i, j];
return _winner;
}
}
}
_winner = null;
return _winner;
}
}
public bool IsFull
{
get
{
for (int i = 0; i < Columns; i++)
{
if (!_board[i, 0].HasValue)
return false;
}
return true;
}
}
public override string ToString()
{
var builder = new StringBuilder();
for (int j = 0; j < Rows; j++)
{
builder.Append('|');
for (int i = 0; i < Columns; i++)
{
builder.Append(_board[i, j].HasValue ? _board[i,j].Value.ToString() : " ").Append('|');
}
builder.AppendLine();
}
return builder.ToString();
}
}

Movement on the console in c#

I'm working on a snake game right now, and am having difficulty with making sure the tail follows my head. I'm currently trying to get it to work, and I've tried about a dozen different ideas, all of which either make it stall out completely (e.g. snake appears to be frozen in one place), or the vertical motion happens at all points of the tail at once, instead of one movement following another. I'm also having some trouble with the Console.Clear() method that seems inescapable. Either I do it too many times and it deletes everything but the first point of my snake, or I don't and the old positions don't get erased. Here's the code (it's a test code, split from the actual game as I need to make sure the code works):
class Program
{
const int size = 10;
struct Sprite
{
public char[] ch;
public int[,] posXY;
public int directionX;
public int directionY;
}
static void Main(string[] args)
{
int startX = 10;
int startY;
Sprite player = new Sprite();
player.ch = new char[7];
player.posXY = new int[7,2];
for (int i = 0; i < player.ch.Length; i++)
{
player.ch[i] = '*';
}
for (int i = 0; i < 7; i++)
{
startY = 10;
player.posXY[i, 0] = startX;
player.posXY[i, 1] = startY;
startX--;
}
ConsoleKeyInfo cki = new ConsoleKeyInfo();
while (true)
{
update(cki, ref player);
draw(player);
Thread.Sleep(200);
}//end while
}//end main
static void update(ConsoleKeyInfo cki, ref Sprite player)
{
if (Console.KeyAvailable)
{
cki = Console.ReadKey(true);
if (cki.Key == ConsoleKey.LeftArrow || cki.Key == ConsoleKey.A)
{
player.directionX = -1;
player.directionY = 0;
}
if (cki.Key == ConsoleKey.RightArrow || cki.Key == ConsoleKey.D)
{
player.directionX = 1;
player.directionY = 0;
}
if (cki.Key == ConsoleKey.UpArrow || cki.Key == ConsoleKey.W)
{
player.directionX = 0;
player.directionY = -1;
}
if (cki.Key == ConsoleKey.DownArrow || cki.Key == ConsoleKey.S)
{
player.directionX = 0;
player.directionY = 1;
}
}//endif
for (int i = 0; i < 7; i++)
{
player.posXY[i, 0] = player.posXY[i, 0] + player.directionX;
player.posXY[i, 1] = player.posXY[i, 1] + player.directionY;
}
}//end update
static void draw(Sprite player)
{
Console.Clear();
for (int i = 0; i < 7; i++)
{
Console.SetCursorPosition(player.posXY[i, 0], player.posXY[i, 1]);
Console.Write(player.ch[i]);
}
}//end draw
}
P.S. I need to use a struct for my snake, using a Class isn't an option.
IMHO the best datastructure to describe the "snake" game is a queue. So that you can dequeue ("undraw") 1 "item" from the tail and enqueue ("draw") a new one with the new coordinates as the head.
If it happens to be on the "apple" you just skip one dequeue operation or enqueue twice.
If you are not familiar with the Queue data structure take a look at this fist: http://en.wikipedia.org/wiki/Queue_(abstract_data_type)
Look at the default Queue of .net framework here: http://msdn.microsoft.com/en-us/library/7977ey2c.aspx

Categories