Programming C
Tasks studies - laboratory
Project maintained by dawidolko
Hosted on GitHub Pages — Theme by dawidolko
Lab06 - Tic-Tac-Toe Game
Tic-Tac-Toe Game
https://drive.google.com/drive/folders/1-ceXITf1pQ7zAF0N5p8NqOXGnKtbVl4-?usp=sharing
Tasks
TicTacToe.exe
The current state of the game will be stored in a 2-dimensional array of characters.
The state should be a global variable so that every function has access to it.
In addition, information about the size of the board will be useful, which can also be stored in a global variable.
char tab[3][3] = { {' ', ' ', ' '},
{' ', ' ', ' '},
{' ', ' ', ' '} }
Step 1
Write a function renderboard()
that will print the current state of the game to the console in the following form:
The function should be able to render a board with dimensions from 3x3 to 26x26 squares.
Test the function.
on boards:
Test boards
```c
int const TAB_SIZE = 4;
char board[TAB_SIZE][TAB_SIZE] = { {' ', ' ', ' ', ' '},
{' ', ' ', ' ', ' '},
{' ', ' ', ' ', ' '},
{' ', ' ', ' ', ' '} };
```
```c
//Można zmienić rozmiar tablicy na mniejszy/więszy
int const TAB_SIZE = 26;
char board[TAB_SIZE][TAB_SIZE];
//w funkcji main ustawiane są wartośći w tablicy
int main(int argc, char const *argv[])
{
for (size_t i = 0; i < TAB_SIZE; i++)
{
for (size_t j = 0; j < TAB_SIZE; j++)
{
board[i][j] = ' ';
}
}
return 0;
}
```
Hint
```c
// The char type stores numbers from 0 to 255 which are decoded into characters visible in the console in the printf() function.
// A - 65
// Z - 90
// a - 97
// z - 122
for(char i = 65; i<91; i++){
printf("%c ", i);
}
```
Column headers can be printed before printing the board values.
Row headers can be printed before iterating over the second dimension of the array.
Solution:
The array can be initialized as a global variable, similarly to the size of the array:
int const TAB_SIZE = 3;
char board[3][3] = { {'X', 'O', 'O'},
{'X', 'X', 'O'},
{'O', ' ', 'X'} };
The size of the array must be known to us in order to efficiently iterate over subsequent values.
The renderboard function can use global information about the size of the array:
renderboard(){
for(int i= 0; i< TAB_SIZE; i++){
for(int j= 0; j< TAB_SIZE; j++){
printf("%c", tab[i][j]);
}
}
}
Step 2
Write a function makeMove()
that accepts a given player’s symbol on the board and returns the following codes:
- 0 - if the move is allowed (we occupy an empty square)
- 1 - if we go beyond the board area
- 2 - if we want to occupy another player’s square
- 3 - other errors
In the body of the function, implement queries to the user to select the square they want to occupy.
Hint
Using the scanf() instruction, we can read several values at once.
```c
char col;
int row;
printf("Enter the value of col and row, e.g. ", player);
scanf(" %c %i", &col, &row);
```
After reading the values, just convert them to indexes (numbered from 0) and check the appropriate conditions.
Step 3
Write a function score()
that checks vertically, horizontally and diagonally whether one of the players has won, and if so, returns their symbol.
Hint
You should check whether there are the same signs in the columns, rows and diagonals.
If you come across the ' ' sign, you can stop further searching in the column, row or diagonal. Similarly, if you come across another player's symbol.
Step 4
Implement the game logic in the main function.
*AdvancedTicTacToe.exe
Modify the TicTacToe game so that the user can define the size of the board, the number and symbols of players.
Hint
```c
#include
#include
// Zmienne globalne dostępne dla funkcji
// wskaźnik na pierwszy element tablicy
int *board;
// rozmiar tablicy
int BOARD_SIZE = 3;
int main(int argc, char const *argv[])
{
// Talice w pamięci są przechowyane w kolejnych adresach
int tab[2][3] = { {1,2,3},{4,5,6} };
int tab_size = sizeof(tab)/sizeof(int);
printf("tab_size = %i\n",tab_size);
int iterations = 0;
for (int *i = tab; iterations < (sizeof(tab)/sizeof(int)); i++)
{
printf("%i ", *i);
iterations++;
}
printf("\n");
// Rozmiar tablicy 2x3 typu int to (2*int)*(3*int) gdzie int to wielkość typu int.
int size = (BOARD_SIZE * sizeof(int)) * (BOARD_SIZE * sizeof(int));
// funkcja maloc() zarezerwuje w pamięci określoną liczbę bajtów i zwróci wskaźnik do pierwszego bajtu.
board = malloc(size);
// wiedząc że plansza ma rozmiar 3x3 co 3 komórka w pamięci będzie początkiem nowego wiersza.
int row = 0;
for (int *rowwsk = board; row < BOARD_SIZE; rowwsk + BOARD_SIZE)
{
int col = 0;
for (int *colwsk = rowwsk; col < BOARD_SIZE; colwsk++)
{
*colwsk = 0;
col++;
}
row++;
}
row = 0;
for (int *rowwsk = board; row < BOARD_SIZE; rowwsk + BOARD_SIZE)
{
int col = 0;
for (int *colwsk = rowwsk; col < BOARD_SIZE; colwsk++)
{
printf("board[%i][%i] = %i \t",row, col,*colwsk);
col++;
}
printf("\n");
row++;
}
// free zwalnia pamięć
free(board);
return 0;
}
```
```c
// +------+
// | | pointer to pointer to T
// +------+
// |
// v
// +------+------+------+
// | | | | pointers to T
// +------+------+------+
// | | | +-------------+-------------+-------------+
// | | +---->| | | | elements of type T
// | | +-------------+-------------+-------------+
// | | +-------------+-------------+
// | +---->| | | elements of type T
// | +-------------+-------------+
// |
// v
// +-------------+-------------+-------------+-------------+
// | | | | | elements of type T
// +-------------+-------------+-------------+-------------+
double **tab2;
tab2 = malloc(row * sizeof(double *));
for (int i = 0; i < 3; i++)
{
tab2[i] = calloc(col,sizeof(double));
}
// pzypisujemy wartości
tab2[0][0] = 0.0;
tab2[0][1] = 0.1;
tab2[1][0] = 1.0;
tab2[1][1] = 1.1;
tab2[2][0] = 2.0;
tab2[2][1] = 2.1;
// dla 3d array
int ***tab3d;
tab3d = malloc(2*sizeof(double **));
for (int i = 0; i < 2; i++)
{
tab3d[i] = malloc(2*sizeof(double *));
for (size_t j = 0; j < 2; j++)
{
tab3d[i][j] = calloc(2,sizeof(double));
}
}
```
</details>
### `Task3.exe`
Write a program that will print a spiral of a given size in the console - each subsequent arm, e.g.
```
Enter the size: 9
# # # # # # #
# # # #
# # # # #
# # # # #
# # # # #
# # # # # #
# # # # # # #
```
The length of the line creating the spiral increases by 1.
How to calculate the size of the array storing the spiral of sizes: 5, 6, 7, 8?
How to determine the beginning of drawing the spiral?
Which array indices to change moving north, east, south, west?