I have made a simple tic tac toe game and need help tweaking it to fit the bill of object oriented design. Any suggestions most welcome. I basically want it safer, and more "best practice-like" It is a game consisting of four classes, and I'm pretty happy with it as I am new to programming, but maybe it is worthless seen from your perspective. Any pointers, tips and concrete examples would be greatly appreciated!
Board class:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Drawing;
namespace TicTac
{
class Board
{
private int movesMade = 0; //Keeps tracks of how many moves made
private Holder[,] holders = new Holder[3, 3]; //Creates an array of 3x3
private const int X = 0; //Whatever X presses becomes a 0 in the array
private const int O = 1; //Whatever O presses becomes a 1 in the array
public const int B = 2; //Whatever space is unclicked is a 2 in the array
public void initBoard() //Iniates the board
{
for (int x = 0; x < 3; x++) //Vertical row
{
for (int y = 0; y < 3; y++) //Horizontal row
{
holders[x, y] = new Holder();
holders[x, y].setValue(B);
holders[x, y].setLocation(new Point(x, y));
}
}
}
public void detectHit(Point loc) //Checks what space was hit and draws either an O or X depending on whos turn it is
{
if (loc.Y <= 500)
{
int x = 0;
int y = 0;
if (loc.X < 167)
{
x = 0;
}
else if (loc.X > 167 && loc.X < 334)
{
x = 1;
}
else if (loc.X > 334)
{
x = 2;
}
if (loc.Y < 167)
{
y = 0;
}
else if (loc.Y > 167 && loc.Y < 334)
{
y = 1;
}
else if (loc.Y > 334 && loc.Y < 500)
{
y = 2;
}
movesMade++;
if (movesMade % 2 == 0) //If even number X turns to act
{
GFX.putX(new Point(x, y));
holders[x, y].setValue(X);
if (checkWinner(X))
{
MessageBox.Show("Player 'X' won");
}
}
else
{
GFX.putO(new Point(x, y)); //Calls "Put O" method when its his turn
holders[x, y].setValue(O);
if (checkWinner(O))
{
MessageBox.Show("Player 'O' Won!");
}
}
// MessageBox.Show(x.ToString() + "," + y.ToString());
}
}
private bool checkWinner(int Z)
{
bool winner = false;
for (int x = 0; x < 3; x++)
{
if (holders[x, 0].getValue() == Z && holders[x, 1].getValue() == Z && holders[x, 2].getValue() == Z) //Checks if board is won horizontally
{
return true;
}
if (holders[0, x].getValue() == Z && holders[1, x].getValue() == Z && holders[2, x].getValue() == Z) //Checks if board is won vertically
{
return true;
}
switch (x) //Checks if board is won diagnonally
{
case 0:
if (holders[0, 0].getValue() == Z && holders[1, 1].getValue() == Z && holders[2, 2].getValue() == Z)
{
return true;
}
break;
case 1:
if (holders[0, 2].getValue() == Z && holders[1, 1].getValue() == Z && holders[0, 2].getValue() == Z)
{
return true;
}
break;
}
}
return winner;
}
}
}
Holder class:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Drawing;
using System.Windows.Forms;
namespace TicTac
{
public class Holder
{
private Point loc;
public int value = Board.B;
internal void setLocation(Point p)
{
loc = p;
}
internal Point getLocation()
{
return loc;
}
internal void setValue(int i)
{
value = i;
}
internal int getValue()
{
return value;
}
}
}
Graphics class:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Drawing;
using System.Windows.Forms;
namespace TicTac
{
class GFX
{
private static Graphics gObject;
public GFX(Graphics g)
{
gObject = g;
initBoard();
}
public void initBoard() //Method that initiates the boaard
{
Pen lines = new Pen(Color.Chocolate, 6);
Brush bg = new SolidBrush(Color.White);
gObject.FillRectangle(bg, new Rectangle(0, 0, 500, 600)); //Draws the background
gObject.DrawLine(lines, new Point(167, 0), new Point(167, 500)); //Draws the lines
gObject.DrawLine(lines, new Point(334, 0), new Point(334, 500)); //Draws the lines
gObject.DrawLine(lines, new Point(0, 167), new Point(500, 167)); //Draws the lines
gObject.DrawLine(lines, new Point(0, 334), new Point(500, 334)); //Draws the lines
}
public static void putX(Point loc) //Method that writes out an X
{
Pen xObjekt = new Pen(Color.Blue, 4);
int xAbs = loc.X * 167;
int yAbs = loc.Y * 167;
gObject.DrawLine(xObjekt, xAbs + 20, yAbs + 20, xAbs + 157, yAbs + 157); //Makes an X when board is clicked, adjusted to not intervene with next square
gObject.DrawLine(xObjekt, xAbs + 157, yAbs + 20, xAbs + 20, yAbs + 157); //Makes an X when board is clicked, adjusted to not intervene with next square
}
public static void putO(Point loc) //Method that writes out an O
{
Pen oObjekt = new Pen(Color.Green, 4);
int xAbs = loc.X * 167;
int yAbs = loc.Y * 167;
gObject.DrawEllipse(oObjekt, xAbs + 20, yAbs + 20, 120, 120); //Makes an O when board is clicked, adjusted to not intervene with next square
}
}
}
UI_FORM1:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Drawing;
namespace TicTac
{
public partial class Form1 : Form
{
Board board;
GFX engine;
public Form1()
{
InitializeComponent();
}
private void panel1_Paint(object sender, PaintEventArgs e)
{
}
private void panel1_Click(object sender, EventArgs e) //When player interacts with the board
{
Point mouse = Cursor.Position;
mouse = panel1.PointToClient(mouse);
board.detectHit(mouse);
}
private void gameToolStripMenuItem_Click(object sender, EventArgs e) //When a singleplayermode is selected
{
Graphics toPass = panel1.CreateGraphics();
engine = new GFX(toPass);
board = new Board();
board.initBoard();
}
}
}