Check Sudoku - Unity Tutorial - 4. Setting values
In the previous step we have created app skeleton. In this one we will implement setting the values of board cells:
Implementation
In order to fill the board with 3x3 squares (we need 9 of those) and individual cells (we need 81) we create prefabs and use the
GridLayout to display them. We create one GroupRect for each 3x3 group and one CellImage for each cell:We follow the same pattern with the work cell, where we display possible values. We create
PossibilityRect to display possible cell value:After clicking the cell (
CellImage), we want something (???) to highlight the selected cell with a frame, and we want the work cell (WorkCellImage) to display current cell value. After clicking another cell, something (???) should deselect the previous cell, highlight the new one, and display the new cell value in the work cell.Question 1:
Which element should store the information about which cell is selected?
Options:
- The game manager (
GameManager) - The board (
BoardImage) - The work cell (
WorkCellImage)
Decision:
Since the work cell needs to already do something when a cell selection changes (show currently selected cell's value), it's easiest if it stores this information.
Question 2:
How to invoke a method in a work cell from the board cells (all 81 of them)?
Options:
- Making the work cell a Singleton, with all the pros and cons as described here.
- Adding a public field to each cell, and manually assign work cell to each cell using the editor.
Decision:
Since we don't expect to ever have two work cells at the same time, we chose the Singleton design pattern option in the WorkCellImage script.
public class WorkCellImage : MonoBehaviour
{
public static WorkCellImage Instance { get; private set; }
private void Awake()
{
if (Instance != null && Instance != this)
{
Destroy(this);
}
else
{
Instance = this;
}
}
...
}Question 3:
How to implement highlighting the cell?
Options:
- Adding a new UI element
SelectionImageto each cell, and adding "Select"/"Unselect" methods to activate/deactivate it. - Adding a new UI element
SelectionImageto the board. Make work cell display and move this element over the selected cell.
Decision:
Delegating the highlight to the cell seems easier, as there is no need to move any UI elements (some elements are just activated or deactivated).
Let's add a SelectionImage element, displaying a frame with #004D40 color to the
CellImage prefab, and let's add a "Selection Image" field, which we link with the SelectionImage object. In the script we implement the "Select" and "Unselect" methods, and add handling of "OnClick" to notify the work cell about a change of cell selection:
public class CellImage : MonoBehaviour
{
public GameObject selectionImage;
...
public void Select()
{
selectionImage.SetActive(true);
}
public void Unselect()
{
selectionImage.SetActive(false);
}
public void OnClick()
{
WorkCellImage.Instance.SelectCell(this);
}
}In the "SelectCell" method of the work cell, we unhighlight the previous cell, and highlight the new one:
public class WorkCellImage : MonoBehaviour
{
private CellImage selectedCell = null;
...
public void SelectCell(CellImage cell)
{
if (selectedCell != null)
{
selectedCell.Unselect();
}
selectedCell = cell;
if (selectedCell)
{
selectedCell.Select();
}
}
}In the same way we implement the selection of current cell's value. After clicking the possible value (
PossibilityRect), we want the work cell (WorkCellImage) to highlight the selected possible value with a frame, and the cell (CellImage) should display its value. After clicking another possible value, the work cell should unhighlight the previous value, highlight the new one, and display the new cell value.Let's add a SelectionImage element, displaying a frame with #004D40 color to the PossibilityRect prefab, and let's add a "Selection Image" field, which we link with the
SelectionImage object. In the script we implement the "Select" and "Unselect" methods, and add handling of "OnClick" to tell the work cell about a change in selected cell value:
public class PossibilityRect : MonoBehaviour
{
public GameObject selectionImage;
...
public void Select()
{
selectionImage.SetActive(true);
}
public void Unselect()
{
selectionImage.SetActive(false);
}
public void OnClick()
{
WorkCellImage.Instance.SelectPossibility(this);
}
}In the "SelectPossibility" method of the work cell, we unhighlight the previously selected value, and highlight the new one:
public class WorkCellImage : MonoBehaviour
{
private PossibilityRect selectedPossibility = null;
...
public void SelectPossibility(PossibilityRect possibility)
{
if (selectedPossibility != null)
{
selectedPossibility.Unselect();
}
selectedPossibility = possibility;
if (selectedPossibility != null)
{
selectedPossibility.Select();
}
if (selectedCell != null)
{
selectedCell.SetValue(possibility.Value);
}
}
}As you can see, in order for it to work, the cell (
CellImage) needs to contain a "SetValue" method, while the possible value (PossibilityRect) a "Value" property. We add those properties, making sure in the code, that their text fields will display their values:public class CellImage : MonoBehaviour
{
public int Value { get; private set; }
public TextMeshProUGUI valueText;
...
// Start is called before the first frame update
void Start()
{
SetValue(0);
}
...
public void SetValue(int value)
{
Value = value;
valueText.SetText(value != 0 ? value.ToString() : "");
}
}public class PossibilityRect : MonoBehaviour
{
[field: SerializeField]
public int Value { get; private set; } = 0;
public TextMeshProUGUI valueText;
...
// Start is called before the first frame update
void Start()
{
valueText.SetText(Value.ToString());
}
...
}Last, but not least, we update the "SelectCell" method of
WorkCellImage object so that when cell selection changes, the work cell displays new cell's value:public class WorkCellImage : MonoBehaviour
{
...
public void SelectCell(CellImage cell)
{
...
selectedPossibility = null;
foreach(PossibilityRect possibility in GetComponentsInChildren<PossibilityRect>())
{
if (selectedCell != null && possibility.Value == selectedCell.Value)
{
possibility.Select();
selectedPossibility = possibility;
}
else
{
possibility.Unselect();
}
}
}
...
}That's how we get the app from the introduction.
GitHub
Commits related to this step are here:
Next steps
In the next step we will add checking Sudoku rules, to prevent user from "clicking" illegal Sudoku board.
Polish | English











Comments
Post a Comment