Right now I have a snake game that is working but I need a way to make my code look better and work better.
A method I named GameSense
is very long and I need a way to make it more object-oriented. I want to use enums.
This is what my teacher sent back to me:
The game is very nice and nicely working tail! The test you have also follows the right idea but uses an
UpdatePosition
method that you have not implemented. I'm also thinking about your class pixel - you do not use it for anything in the rest of the game. You should use it instead of e.g.berryx
,berryy
. What I am trying to access is more use of object orientation and division into methods, and not a single long method likeGameSense
right now. Also want to see you use enum / bool instead of strings for e.g. the variablesmovement
andbuttonpressed
. However, I'm glad you got an interface on a corner
As you can see… I feel pretty suck right now.
What do I need to do here in order to make the program be more object-oriented?
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Threading;
namespace Snake
{
/// <summary>
/// Start class, everything goes from here.
/// Made by Karwan!
/// </summary>
public class Starter : InterF
{
public static object Key { get; private set; }
/// <summary>
/// Main method.
/// </summary>
/// <param name="args"></param>
static void Main(string[] args)
{
//Making the text green and also given a player
//options to chose from.
Console.ForegroundColor = ConsoleColor.Green;
bool loopC = true;
while (loopC)
{
string mystring = null; Console.WriteLine("Welcome to Snake.\nPress S+Enter to start or press Q+Enter to exit.");
mystring = Console.ReadLine();
switch (mystring)
{
case "Q":
Environment.Exit(0);
break;
case "S":
Console.WriteLine("Starting game!");
System.Threading.Thread.Sleep(4000);
loopC = false;
break;
default:
Console.WriteLine("Invalid Entry.. Try again.");
break;
}
}
//Call for GameSense if
//they want to play.
GameSense();
}
/// <summary>
/// Game object!
/// </summary>
public static void GameSense()
{
//Game console height/width.
Console.WindowHeight = 30;
Console.WindowWidth = 70;
int screenwidth = Console.WindowWidth;
int screenheight = Console.WindowHeight;
Random randomnummer = new Random();
//Lenght of tail == current score.
int score = 2;
int gameover = 0;
//Gather positions from pixel class.
pixel positions = new pixel();
positions.xpos = screenwidth / 2;
positions.ypos = screenheight / 2;
positions.Black = ConsoleColor.Red;
string movement = "RIGHT";
//Position manegment.
List<int> xpos = new List<int>();
List<int> ypos = new List<int>();
int berryx = randomnummer.Next(0, screenwidth);
int berryy = randomnummer.Next(0, screenheight);
//Time manegment.
DateTime time1 = DateTime.Now;
DateTime time2 = DateTime.Now;
string buttonpressed = "no";
//Draw world from GameWorld.cs.
GameWorld.DrawBorder(screenwidth, screenheight);
while (true)
{
GameWorld.ClearConsole(screenwidth, screenheight);
if (positions.xpos == screenwidth - 1 || positions.xpos == 0 || positions.ypos == screenheight - 1 || positions.ypos == 0)
{
gameover = 1;
}
Console.ForegroundColor = ConsoleColor.Green;
if (berryx == positions.xpos && berryy == positions.ypos)
{
score++;
berryx = randomnummer.Next(1, screenwidth - 2);
berryy = randomnummer.Next(1, screenheight - 2);
}
for (int i = 0; i < xpos.Count(); i++)
{
Console.SetCursorPosition(xpos[i], ypos[i]);
Console.Write("*");
if (xpos[i] == positions.xpos && ypos[i] == positions.ypos)
{
gameover = 1;
}
}
if (gameover == 1)
{
break;
}
Console.SetCursorPosition(positions.xpos, positions.ypos);
Console.ForegroundColor = positions.Black;
Console.Write("*");
//Food color & position.
Console.SetCursorPosition(berryx, berryy);
Console.ForegroundColor = ConsoleColor.Cyan;
Console.Write("*");
Console.CursorVisible = false;
time1 = DateTime.Now;
buttonpressed = "no";
while (true)
{
time2 = DateTime.Now;
if (time2.Subtract(time1).TotalMilliseconds > 500) { break; }
if (Console.KeyAvailable)
{
ConsoleKeyInfo info = Console.ReadKey(true);
//Connecting the buttons to the x/y movments.
if (info.Key.Equals(ConsoleKey.UpArrow) && movement != "DOWN" && buttonpressed == "no")
{
movement = "UP";
buttonpressed = "yes";
}
if (info.Key.Equals(ConsoleKey.DownArrow) && movement != "UP" && buttonpressed == "no")
{
movement = "DOWN";
buttonpressed = "yes";
}
if (info.Key.Equals(ConsoleKey.LeftArrow) && movement != "RIGHT" && buttonpressed == "no")
{
movement = "LEFT";
buttonpressed = "yes";
}
if (info.Key.Equals(ConsoleKey.RightArrow) && movement != "LEFT" && buttonpressed == "no")
{
movement = "RIGHT";
buttonpressed = "yes";
}
}
}
//Giving the connections value
//to change x/y to make the movment happen.
xpos.Add(positions.xpos);
ypos.Add(positions.ypos);
switch (movement)
{
case "UP":
positions.ypos--;
break;
case "DOWN":
positions.ypos++;
break;
case "LEFT":
positions.xpos--;
break;
case "RIGHT":
positions.xpos++;
break;
}
if (xpos.Count() > score)
{
xpos.RemoveAt(0);
ypos.RemoveAt(0);
}
}
Console.SetCursorPosition(screenwidth / 5, screenheight / 2);
Console.WriteLine("Game over, Score: " + score);
Console.SetCursorPosition(screenwidth / 5, screenheight / 2 + 1);
System.Threading.Thread.Sleep(1000);
restart();
}
/// <summary>
/// Restarter.
/// </summary>
public static void restart()
{
string Over = null; Console.WriteLine("\nWould you like to start over? Y/N");
bool O = true;
while (O)
{
Over = Console.ReadLine();
switch (Over)
{
case "Y":
Console.WriteLine("\nRestarting!");
System.Threading.Thread.Sleep(2000);
break;
case "N":
Console.WriteLine("\nThank you for playing!");
Environment.Exit(0);
break;
default:
Console.WriteLine("Invalid Entry.. Try again.");
break;
}
}
}
/// <summary>
/// Set/get pixel position.
/// </summary>
public class pixel
{
public int xpos { get; set; }
public int ypos { get; set; }
public ConsoleColor Black { get; set; }
}
}
}
My test class
using Microsoft.VisualStudio.TestTools.UnitTesting;
using NUnit.Framework;
using Snake;
using System;
using System.Collections.Generic;
using System.Text;
using static Snake.Starter;
namespace Snake.Tests
{
[TestClass()]
public class StarterTests
{
/// <summary>
/// Testing the movment.
/// </summary>
[TestMethod()]
public void test()
{
var pos = new pixel();
pos.xpos = 10;
pos.ypos = 10;
// this is the operation:
UpdatePosition(pos, "UP");
// check the results
NUnit.Framework.Assert.That(pos.xpos, Is.EqualTo(10));
NUnit.Framework.Assert.That(pos.ypos, Is.EqualTo(9));
}
/// <summary>
/// Updating pixel class.
/// </summary>
/// <param name="pos"></param>
/// <param name="v"></param>
private void UpdatePosition(pixel pos, string v)
{
throw new NotImplementedException();
}
}
}
This is just the gameworld:
using System;
using System.Linq;
public class GameWorld
{
/// <summary>
/// Clear console for snake.
/// </summary>
/// <param name="screenwidth"></param>
/// <param name="screenheight"></param>
public static void ClearConsole(int screenwidth, int screenheight)
{
var blackLine = string.Join("", new byte[screenwidth - 2].Select(b => " ").ToArray());
Console.ForegroundColor = ConsoleColor.Black;
for (int i = 1; i < screenheight - 1; i++)
{
Console.SetCursorPosition(1, i);
Console.Write(blackLine);
}
}
/// <summary>
/// Draw boared.
/// </summary>
/// <param name="screenwidth"></param>
/// <param name="screenheight"></param>
public static void DrawBorder(int screenwidth, int screenheight)
{
var horizontalBar = string.Join("", new byte[screenwidth].Select(b => "■").ToArray());
Console.SetCursorPosition(0, 0);
Console.Write(horizontalBar);
Console.SetCursorPosition(0, screenheight - 1);
Console.Write(horizontalBar);
for (int i = 0; i < screenheight; i++)
{
Console.SetCursorPosition(0, i);
Console.Write("■");
Console.SetCursorPosition(screenwidth - 1, i);
Console.Write("■");
}
}
}
switch (mystring.ToUpper())
andswitch (Over.ToUpper())
will allow input in lower case. \$\endgroup\$