Inledning
3 i rad eller "Tic Tac Toe" som det kallas på engelska är en klassisk programmeringsuppgift. Vi tänker här presentera en lösning i Windows Forms där vi använder befintliga komponenter.
Man skulle kunna kalla artikeln för "Tic Tac Toe" på 10 minuter om man så vill.
Regler
Vi har nog alla spelat 3 i rad någon gång. Den som först får 3 i rad vinner! Detta kan ske på 8 olika sätt eftersom det finns 3 kolumner, 3 rader och 2 diagonaler.
Traditionellt sett spelar man "O" eller "X".
Implementation
Vi tänker oss en spelplan utav 3 x 3 Button-komponenter. Knapparna har ingen text förrän spelare "X" eller "O" trycker på dem.
Varje knapptryckning genererar ett Click-event som vi kopplar. Alla 9 knappar är kopplade till samma metod, dvs. alla knappar behandlas lika.
Den som "lägger en bricka" på spelplanen, alltså trycker på en knapp, är också den som kan vinna. Vi måste kolla alla kolumner, rader och diagonaler och se om denna spelare har 3 i rad. Om så är fallet så notifierar vi via MessageBox samt nollställer brädet. Det kan också vara så att ingen vunnit. I detta fall bör vi också notifiera samt nollställa brädet.
Det intressanta med implementationen är hur vi bearbetar data, dvs. Button-komponenterna. För att systematiskt bearbeta informationen om "X" eller "O" så väljer vi att lägga knapparna i en 2-dimensionell "array" (fält på svenska). Två dimensioner passar bra då vi får en bredd och en höjd som motsvarar brädets 3 x 3 knappar. Det kan tyckas en aning krångligt men en anledning till att göra på detta vis är att vi mycket lättare kan gå från ett 3 x 3 bräde till t.ex. ett 8 x 8 bräde.
Känner du dig osäker på fält så rekommenderas att först läsa Fält (array).
Video
Vi rekommenderar att se videon, i alla fall de första minuterna, för att hänga med på vilka ändringar som gjorts i den visuella editorn i Visual Studio.
Kod
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace TicTacToe
{
public partial class Form1 : Form
{
bool XTurn = false;
Button[,] array;
public Form1()
{
InitializeComponent();
array = new Button[,] { {button1, button2, button3 },
{button4, button5, button6 },
{button7, button8, button9 }};
}
private void ResetBoard()
{
int size = array.GetLength(0);
for (int x = 0; x < size; x++)
{
for (int y = 0; y < size; y++)
{
array[y, x].Text = string.Empty;
}
}
}
private void Button_Click(object sender, EventArgs e)
{
Button b = sender as Button;
if (b == null || !string.IsNullOrEmpty(b.Text))
return;
string player = (XTurn) ? "X" : "O";
b.Text = player;
XTurn = !XTurn;
int size = array.GetLength(0);
//Kolla om någon vann!
//kolumner
for (int x = 0; x < size; x++)
{
for (int y = 0; y < size && array[y, x].Text == player; y++)
{
if (y == size - 1)
{
MessageBox.Show(this, "Player " + player + " won!");
ResetBoard();
}
}
}
//rader
for (int y = 0; y < size; y++)
{
for (int x = 0; x < size && array[y, x].Text == player; x++)
{
if (x == size - 1)
{
MessageBox.Show(this, "Player " + player + " won!");
ResetBoard();
}
}
}
//Diagonal 1
for (int i = 0; i < size && array[i, i].Text == player; i++)
{
if (i == size - 1)
{
MessageBox.Show(this, "Player " + player + " won!");
ResetBoard();
}
}
//Diagonal 2
for (int i = 0; i < size && array[size - 1 - i, i].Text == player; i++)
{
if (i == size - 1)
{
MessageBox.Show(this, "Player " + player + " won!");
ResetBoard();
}
}
//Spelet slut?
bool finished = true;
for (int x = 0; x < size; x++)
{
for (int y = 0; y < size; y++)
{
if (string.IsNullOrEmpty(array[y, x].Text))
finished = false;
}
}
if (finished)
{
MessageBox.Show(this, "It's a draw!");
ResetBoard();
}
}
}
}
Övning 1
I exemplet ovan så är alla 9 knappar utplacerade manuellt. Detta är inte särskilt effektivt ifall vi vill utöka storleken på brädet.
Uppgiften går ut på att istället skapa de 9 knapparna i kod. Du måste alltså ställa in alla egenskaper som t.ex. storlek, bakgrundsfärg, Click-event, etc. Använd en loop som baseras på storleken.
Övning 2
Gör så att du kan ställa in storleken på brädet via en variabel i koden. Anpassa gärna storleken på knapparna samt storleken på typsnittet efter storleken på brädet.
Inför också en variabel som bestämmer "hur många i rad" som krävs för att vinna.
Du måste alltså justera algoritmerna för att bestämma vinnaren.